You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

809 lines
20 KiB

  1. /*
  2. * virsh-nwfilter.c: Commands to manage network filters
  3. *
  4. * Copyright (C) 2005, 2007-2016 Red Hat, Inc.
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library. If not, see
  18. * <http://www.gnu.org/licenses/>.
  19. */
  20. #include <config.h>
  21. #include "virsh-nwfilter.h"
  22. #include "internal.h"
  23. #include "virbuffer.h"
  24. #include "viralloc.h"
  25. #include "virfile.h"
  26. #include "vsh-table.h"
  27. virNWFilterPtr
  28. virshCommandOptNWFilterBy(vshControl *ctl, const vshCmd *cmd,
  29. const char **name, unsigned int flags)
  30. {
  31. virNWFilterPtr nwfilter = NULL;
  32. const char *n = NULL;
  33. const char *optname = "nwfilter";
  34. virshControlPtr priv = ctl->privData;
  35. virCheckFlags(VIRSH_BYUUID | VIRSH_BYNAME, NULL);
  36. if (vshCommandOptStringReq(ctl, cmd, optname, &n) < 0)
  37. return NULL;
  38. vshDebug(ctl, VSH_ERR_INFO, "%s: found option <%s>: %s\n",
  39. cmd->def->name, optname, n);
  40. if (name)
  41. *name = n;
  42. /* try it by UUID */
  43. if ((flags & VIRSH_BYUUID) && strlen(n) == VIR_UUID_STRING_BUFLEN-1) {
  44. vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as nwfilter UUID\n",
  45. cmd->def->name, optname);
  46. nwfilter = virNWFilterLookupByUUIDString(priv->conn, n);
  47. }
  48. /* try it by NAME */
  49. if (!nwfilter && (flags & VIRSH_BYNAME)) {
  50. vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as nwfilter NAME\n",
  51. cmd->def->name, optname);
  52. nwfilter = virNWFilterLookupByName(priv->conn, n);
  53. }
  54. if (!nwfilter)
  55. vshError(ctl, _("failed to get nwfilter '%s'"), n);
  56. return nwfilter;
  57. }
  58. /*
  59. * "nwfilter-define" command
  60. */
  61. static const vshCmdInfo info_nwfilter_define[] = {
  62. {.name = "help",
  63. .data = N_("define or update a network filter from an XML file")
  64. },
  65. {.name = "desc",
  66. .data = N_("Define a new network filter or update an existing one.")
  67. },
  68. {.name = NULL}
  69. };
  70. static const vshCmdOptDef opts_nwfilter_define[] = {
  71. VIRSH_COMMON_OPT_FILE(N_("file containing an XML network "
  72. "filter description")),
  73. {.name = NULL}
  74. };
  75. static bool
  76. cmdNWFilterDefine(vshControl *ctl, const vshCmd *cmd)
  77. {
  78. virNWFilterPtr nwfilter;
  79. const char *from = NULL;
  80. bool ret = true;
  81. char *buffer;
  82. virshControlPtr priv = ctl->privData;
  83. if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0)
  84. return false;
  85. if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0)
  86. return false;
  87. nwfilter = virNWFilterDefineXML(priv->conn, buffer);
  88. VIR_FREE(buffer);
  89. if (nwfilter != NULL) {
  90. vshPrintExtra(ctl, _("Network filter %s defined from %s\n"),
  91. virNWFilterGetName(nwfilter), from);
  92. virNWFilterFree(nwfilter);
  93. } else {
  94. vshError(ctl, _("Failed to define network filter from %s"), from);
  95. ret = false;
  96. }
  97. return ret;
  98. }
  99. /*
  100. * "nwfilter-undefine" command
  101. */
  102. static const vshCmdInfo info_nwfilter_undefine[] = {
  103. {.name = "help",
  104. .data = N_("undefine a network filter")
  105. },
  106. {.name = "desc",
  107. .data = N_("Undefine a given network filter.")
  108. },
  109. {.name = NULL}
  110. };
  111. static const vshCmdOptDef opts_nwfilter_undefine[] = {
  112. {.name = "nwfilter",
  113. .type = VSH_OT_DATA,
  114. .flags = VSH_OFLAG_REQ,
  115. .help = N_("network filter name or uuid"),
  116. .completer = virshNWFilterNameCompleter,
  117. },
  118. {.name = NULL}
  119. };
  120. static bool
  121. cmdNWFilterUndefine(vshControl *ctl, const vshCmd *cmd)
  122. {
  123. virNWFilterPtr nwfilter;
  124. bool ret = true;
  125. const char *name;
  126. if (!(nwfilter = virshCommandOptNWFilter(ctl, cmd, &name)))
  127. return false;
  128. if (virNWFilterUndefine(nwfilter) == 0) {
  129. vshPrintExtra(ctl, _("Network filter %s undefined\n"), name);
  130. } else {
  131. vshError(ctl, _("Failed to undefine network filter %s"), name);
  132. ret = false;
  133. }
  134. virNWFilterFree(nwfilter);
  135. return ret;
  136. }
  137. /*
  138. * "nwfilter-dumpxml" command
  139. */
  140. static const vshCmdInfo info_nwfilter_dumpxml[] = {
  141. {.name = "help",
  142. .data = N_("network filter information in XML")
  143. },
  144. {.name = "desc",
  145. .data = N_("Output the network filter information as an XML dump to stdout.")
  146. },
  147. {.name = NULL}
  148. };
  149. static const vshCmdOptDef opts_nwfilter_dumpxml[] = {
  150. {.name = "nwfilter",
  151. .type = VSH_OT_DATA,
  152. .flags = VSH_OFLAG_REQ,
  153. .help = N_("network filter name or uuid"),
  154. .completer = virshNWFilterNameCompleter,
  155. },
  156. {.name = NULL}
  157. };
  158. static bool
  159. cmdNWFilterDumpXML(vshControl *ctl, const vshCmd *cmd)
  160. {
  161. virNWFilterPtr nwfilter;
  162. bool ret = true;
  163. char *dump;
  164. if (!(nwfilter = virshCommandOptNWFilter(ctl, cmd, NULL)))
  165. return false;
  166. dump = virNWFilterGetXMLDesc(nwfilter, 0);
  167. if (dump != NULL) {
  168. vshPrint(ctl, "%s", dump);
  169. VIR_FREE(dump);
  170. } else {
  171. ret = false;
  172. }
  173. virNWFilterFree(nwfilter);
  174. return ret;
  175. }
  176. static int
  177. virshNWFilterSorter(const void *a, const void *b)
  178. {
  179. virNWFilterPtr *fa = (virNWFilterPtr *) a;
  180. virNWFilterPtr *fb = (virNWFilterPtr *) b;
  181. if (*fa && !*fb)
  182. return -1;
  183. if (!*fa)
  184. return *fb != NULL;
  185. return vshStrcasecmp(virNWFilterGetName(*fa),
  186. virNWFilterGetName(*fb));
  187. }
  188. struct virshNWFilterList {
  189. virNWFilterPtr *filters;
  190. size_t nfilters;
  191. };
  192. typedef struct virshNWFilterList *virshNWFilterListPtr;
  193. static void
  194. virshNWFilterListFree(virshNWFilterListPtr list)
  195. {
  196. size_t i;
  197. if (list && list->filters) {
  198. for (i = 0; i < list->nfilters; i++) {
  199. if (list->filters[i])
  200. virNWFilterFree(list->filters[i]);
  201. }
  202. VIR_FREE(list->filters);
  203. }
  204. VIR_FREE(list);
  205. }
  206. static virshNWFilterListPtr
  207. virshNWFilterListCollect(vshControl *ctl,
  208. unsigned int flags)
  209. {
  210. virshNWFilterListPtr list = vshMalloc(ctl, sizeof(*list));
  211. size_t i;
  212. int ret;
  213. virNWFilterPtr filter;
  214. bool success = false;
  215. size_t deleted = 0;
  216. int nfilters = 0;
  217. char **names = NULL;
  218. virshControlPtr priv = ctl->privData;
  219. /* try the list with flags support (0.10.2 and later) */
  220. if ((ret = virConnectListAllNWFilters(priv->conn,
  221. &list->filters,
  222. flags)) >= 0) {
  223. list->nfilters = ret;
  224. goto finished;
  225. }
  226. /* check if the command is actually supported */
  227. if (last_error && last_error->code == VIR_ERR_NO_SUPPORT) {
  228. vshResetLibvirtError();
  229. goto fallback;
  230. }
  231. /* there was an error during the call */
  232. vshError(ctl, "%s", _("Failed to list network filters"));
  233. goto cleanup;
  234. fallback:
  235. /* fall back to old method (0.9.13 and older) */
  236. vshResetLibvirtError();
  237. nfilters = virConnectNumOfNWFilters(priv->conn);
  238. if (nfilters < 0) {
  239. vshError(ctl, "%s", _("Failed to count network filters"));
  240. goto cleanup;
  241. }
  242. if (nfilters == 0)
  243. return list;
  244. names = vshMalloc(ctl, sizeof(char *) * nfilters);
  245. nfilters = virConnectListNWFilters(priv->conn, names, nfilters);
  246. if (nfilters < 0) {
  247. vshError(ctl, "%s", _("Failed to list network filters"));
  248. goto cleanup;
  249. }
  250. list->filters = vshMalloc(ctl, sizeof(virNWFilterPtr) * nfilters);
  251. list->nfilters = 0;
  252. /* get the network filters */
  253. for (i = 0; i < nfilters; i++) {
  254. if (!(filter = virNWFilterLookupByName(priv->conn, names[i])))
  255. continue;
  256. list->filters[list->nfilters++] = filter;
  257. }
  258. /* truncate network filters that weren't found */
  259. deleted = nfilters - list->nfilters;
  260. finished:
  261. /* sort the list */
  262. if (list->filters && list->nfilters)
  263. qsort(list->filters, list->nfilters,
  264. sizeof(*list->filters), virshNWFilterSorter);
  265. /* truncate the list for not found filter objects */
  266. if (deleted)
  267. VIR_SHRINK_N(list->filters, list->nfilters, deleted);
  268. success = true;
  269. cleanup:
  270. for (i = 0; nfilters != -1 && i < nfilters; i++)
  271. VIR_FREE(names[i]);
  272. VIR_FREE(names);
  273. if (!success) {
  274. virshNWFilterListFree(list);
  275. list = NULL;
  276. }
  277. return list;
  278. }
  279. /*
  280. * "nwfilter-list" command
  281. */
  282. static const vshCmdInfo info_nwfilter_list[] = {
  283. {.name = "help",
  284. .data = N_("list network filters")
  285. },
  286. {.name = "desc",
  287. .data = N_("Returns list of network filters.")
  288. },
  289. {.name = NULL}
  290. };
  291. static const vshCmdOptDef opts_nwfilter_list[] = {
  292. {.name = NULL}
  293. };
  294. static bool
  295. cmdNWFilterList(vshControl *ctl, const vshCmd *cmd G_GNUC_UNUSED)
  296. {
  297. size_t i;
  298. char uuid[VIR_UUID_STRING_BUFLEN];
  299. bool ret = false;
  300. virshNWFilterListPtr list = NULL;
  301. vshTablePtr table = NULL;
  302. if (!(list = virshNWFilterListCollect(ctl, 0)))
  303. return false;
  304. table = vshTableNew(_("UUID"), _("Name"), NULL);
  305. if (!table)
  306. goto cleanup;
  307. for (i = 0; i < list->nfilters; i++) {
  308. virNWFilterPtr nwfilter = list->filters[i];
  309. virNWFilterGetUUIDString(nwfilter, uuid);
  310. if (vshTableRowAppend(table,
  311. uuid,
  312. virNWFilterGetName(nwfilter),
  313. NULL) < 0)
  314. goto cleanup;
  315. }
  316. vshTablePrintToStdout(table, ctl);
  317. ret = true;
  318. cleanup:
  319. vshTableFree(table);
  320. virshNWFilterListFree(list);
  321. return ret;
  322. }
  323. /*
  324. * "nwfilter-edit" command
  325. */
  326. static const vshCmdInfo info_nwfilter_edit[] = {
  327. {.name = "help",
  328. .data = N_("edit XML configuration for a network filter")
  329. },
  330. {.name = "desc",
  331. .data = N_("Edit the XML configuration for a network filter.")
  332. },
  333. {.name = NULL}
  334. };
  335. static const vshCmdOptDef opts_nwfilter_edit[] = {
  336. {.name = "nwfilter",
  337. .type = VSH_OT_DATA,
  338. .flags = VSH_OFLAG_REQ,
  339. .help = N_("network filter name or uuid"),
  340. .completer = virshNWFilterNameCompleter,
  341. },
  342. {.name = NULL}
  343. };
  344. static bool
  345. cmdNWFilterEdit(vshControl *ctl, const vshCmd *cmd)
  346. {
  347. bool ret = false;
  348. virNWFilterPtr nwfilter = NULL;
  349. virNWFilterPtr nwfilter_edited = NULL;
  350. virshControlPtr priv = ctl->privData;
  351. nwfilter = virshCommandOptNWFilter(ctl, cmd, NULL);
  352. if (nwfilter == NULL)
  353. goto cleanup;
  354. #define EDIT_GET_XML virNWFilterGetXMLDesc(nwfilter, 0)
  355. #define EDIT_NOT_CHANGED \
  356. do { \
  357. vshPrintExtra(ctl, _("Network filter %s XML " \
  358. "configuration not changed.\n"), \
  359. virNWFilterGetName(nwfilter)); \
  360. ret = true; \
  361. goto edit_cleanup; \
  362. } while (0)
  363. #define EDIT_DEFINE \
  364. (nwfilter_edited = virNWFilterDefineXML(priv->conn, doc_edited))
  365. #include "virsh-edit.c"
  366. vshPrintExtra(ctl, _("Network filter %s XML configuration edited.\n"),
  367. virNWFilterGetName(nwfilter_edited));
  368. ret = true;
  369. cleanup:
  370. if (nwfilter)
  371. virNWFilterFree(nwfilter);
  372. if (nwfilter_edited)
  373. virNWFilterFree(nwfilter_edited);
  374. return ret;
  375. }
  376. virNWFilterBindingPtr
  377. virshCommandOptNWFilterBindingBy(vshControl *ctl,
  378. const vshCmd *cmd,
  379. const char **name,
  380. unsigned int flags)
  381. {
  382. virNWFilterBindingPtr binding = NULL;
  383. const char *n = NULL;
  384. const char *optname = "binding";
  385. virshControlPtr priv = ctl->privData;
  386. virCheckFlags(0, NULL);
  387. if (vshCommandOptStringReq(ctl, cmd, optname, &n) < 0)
  388. return NULL;
  389. vshDebug(ctl, VSH_ERR_INFO, "%s: found option <%s>: %s\n",
  390. cmd->def->name, optname, n);
  391. if (name)
  392. *name = n;
  393. vshDebug(ctl, VSH_ERR_DEBUG, "%s: <%s> trying as nwfilter binding port dev\n",
  394. cmd->def->name, optname);
  395. binding = virNWFilterBindingLookupByPortDev(priv->conn, n);
  396. if (!binding)
  397. vshError(ctl, _("failed to get nwfilter binding '%s'"), n);
  398. return binding;
  399. }
  400. /*
  401. * "nwfilter-binding-create" command
  402. */
  403. static const vshCmdInfo info_nwfilter_binding_create[] = {
  404. {.name = "help",
  405. .data = N_("create a network filter binding from an XML file")
  406. },
  407. {.name = "desc",
  408. .data = N_("Create a new network filter binding.")
  409. },
  410. {.name = NULL}
  411. };
  412. static const vshCmdOptDef opts_nwfilter_binding_create[] = {
  413. VIRSH_COMMON_OPT_FILE(N_("file containing an XML network "
  414. "filter binding description")),
  415. {.name = NULL}
  416. };
  417. static bool
  418. cmdNWFilterBindingCreate(vshControl *ctl, const vshCmd *cmd)
  419. {
  420. virNWFilterBindingPtr binding;
  421. const char *from = NULL;
  422. bool ret = true;
  423. char *buffer;
  424. virshControlPtr priv = ctl->privData;
  425. if (vshCommandOptStringReq(ctl, cmd, "file", &from) < 0)
  426. return false;
  427. if (virFileReadAll(from, VSH_MAX_XML_FILE, &buffer) < 0)
  428. return false;
  429. binding = virNWFilterBindingCreateXML(priv->conn, buffer, 0);
  430. VIR_FREE(buffer);
  431. if (binding != NULL) {
  432. vshPrintExtra(ctl, _("Network filter binding on %s created from %s\n"),
  433. virNWFilterBindingGetPortDev(binding), from);
  434. virNWFilterBindingFree(binding);
  435. } else {
  436. vshError(ctl, _("Failed to create network filter from %s"), from);
  437. ret = false;
  438. }
  439. return ret;
  440. }
  441. /*
  442. * "nwfilter-binding-delete" command
  443. */
  444. static const vshCmdInfo info_nwfilter_binding_delete[] = {
  445. {.name = "help",
  446. .data = N_("delete a network filter binding")
  447. },
  448. {.name = "desc",
  449. .data = N_("Delete a given network filter binding.")
  450. },
  451. {.name = NULL}
  452. };
  453. static const vshCmdOptDef opts_nwfilter_binding_delete[] = {
  454. {.name = "binding",
  455. .type = VSH_OT_DATA,
  456. .flags = VSH_OFLAG_REQ,
  457. .help = N_("network filter binding port dev"),
  458. .completer = virshNWFilterBindingNameCompleter,
  459. },
  460. {.name = NULL}
  461. };
  462. static bool
  463. cmdNWFilterBindingDelete(vshControl *ctl, const vshCmd *cmd)
  464. {
  465. virNWFilterBindingPtr binding;
  466. bool ret = true;
  467. const char *portdev;
  468. if (!(binding = virshCommandOptNWFilterBinding(ctl, cmd, &portdev)))
  469. return false;
  470. if (virNWFilterBindingDelete(binding) == 0) {
  471. vshPrintExtra(ctl, _("Network filter binding on %s deleted\n"), portdev);
  472. } else {
  473. vshError(ctl, _("Failed to delete network filter binding on %s"), portdev);
  474. ret = false;
  475. }
  476. virNWFilterBindingFree(binding);
  477. return ret;
  478. }
  479. /*
  480. * "nwfilter-binding-dumpxml" command
  481. */
  482. static const vshCmdInfo info_nwfilter_binding_dumpxml[] = {
  483. {.name = "help",
  484. .data = N_("network filter information in XML")
  485. },
  486. {.name = "desc",
  487. .data = N_("Output the network filter information as an XML dump to stdout.")
  488. },
  489. {.name = NULL}
  490. };
  491. static const vshCmdOptDef opts_nwfilter_binding_dumpxml[] = {
  492. {.name = "binding",
  493. .type = VSH_OT_DATA,
  494. .flags = VSH_OFLAG_REQ,
  495. .help = N_("network filter binding portdev"),
  496. .completer = virshNWFilterBindingNameCompleter,
  497. },
  498. {.name = NULL}
  499. };
  500. static bool
  501. cmdNWFilterBindingDumpXML(vshControl *ctl, const vshCmd *cmd)
  502. {
  503. virNWFilterBindingPtr binding;
  504. bool ret = true;
  505. char *dump;
  506. if (!(binding = virshCommandOptNWFilterBinding(ctl, cmd, NULL)))
  507. return false;
  508. dump = virNWFilterBindingGetXMLDesc(binding, 0);
  509. if (dump != NULL) {
  510. vshPrint(ctl, "%s", dump);
  511. VIR_FREE(dump);
  512. } else {
  513. ret = false;
  514. }
  515. virNWFilterBindingFree(binding);
  516. return ret;
  517. }
  518. static int
  519. virshNWFilterBindingSorter(const void *a, const void *b)
  520. {
  521. virNWFilterBindingPtr *fa = (virNWFilterBindingPtr *) a;
  522. virNWFilterBindingPtr *fb = (virNWFilterBindingPtr *) b;
  523. if (*fa && !*fb)
  524. return -1;
  525. if (!*fa)
  526. return *fb != NULL;
  527. return vshStrcasecmp(virNWFilterBindingGetPortDev(*fa),
  528. virNWFilterBindingGetPortDev(*fb));
  529. }
  530. struct virshNWFilterBindingList {
  531. virNWFilterBindingPtr *bindings;
  532. size_t nbindings;
  533. };
  534. typedef struct virshNWFilterBindingList *virshNWFilterBindingListPtr;
  535. static void
  536. virshNWFilterBindingListFree(virshNWFilterBindingListPtr list)
  537. {
  538. size_t i;
  539. if (list && list->bindings) {
  540. for (i = 0; i < list->nbindings; i++) {
  541. if (list->bindings[i])
  542. virNWFilterBindingFree(list->bindings[i]);
  543. }
  544. VIR_FREE(list->bindings);
  545. }
  546. VIR_FREE(list);
  547. }
  548. static virshNWFilterBindingListPtr
  549. virshNWFilterBindingListCollect(vshControl *ctl,
  550. unsigned int flags)
  551. {
  552. virshNWFilterBindingListPtr list = vshMalloc(ctl, sizeof(*list));
  553. int ret;
  554. bool success = false;
  555. virshControlPtr priv = ctl->privData;
  556. if ((ret = virConnectListAllNWFilterBindings(priv->conn,
  557. &list->bindings,
  558. flags)) < 0) {
  559. /* there was an error during the call */
  560. vshError(ctl, "%s", _("Failed to list network filter bindings"));
  561. goto cleanup;
  562. }
  563. list->nbindings = ret;
  564. /* sort the list */
  565. if (list->bindings && list->nbindings > 1)
  566. qsort(list->bindings, list->nbindings,
  567. sizeof(*list->bindings), virshNWFilterBindingSorter);
  568. success = true;
  569. cleanup:
  570. if (!success) {
  571. virshNWFilterBindingListFree(list);
  572. list = NULL;
  573. }
  574. return list;
  575. }
  576. /*
  577. * "nwfilter-binding-list" command
  578. */
  579. static const vshCmdInfo info_nwfilter_binding_list[] = {
  580. {.name = "help",
  581. .data = N_("list network filter bindings")
  582. },
  583. {.name = "desc",
  584. .data = N_("Returns list of network filter bindings.")
  585. },
  586. {.name = NULL}
  587. };
  588. static const vshCmdOptDef opts_nwfilter_binding_list[] = {
  589. {.name = NULL}
  590. };
  591. static bool
  592. cmdNWFilterBindingList(vshControl *ctl, const vshCmd *cmd G_GNUC_UNUSED)
  593. {
  594. size_t i;
  595. bool ret = false;
  596. virshNWFilterBindingListPtr list = NULL;
  597. vshTablePtr table = NULL;
  598. if (!(list = virshNWFilterBindingListCollect(ctl, 0)))
  599. return false;
  600. table = vshTableNew(_("Port Dev"), _("Filter"), NULL);
  601. if (!table)
  602. goto cleanup;
  603. for (i = 0; i < list->nbindings; i++) {
  604. virNWFilterBindingPtr binding = list->bindings[i];
  605. if (vshTableRowAppend(table,
  606. virNWFilterBindingGetPortDev(binding),
  607. virNWFilterBindingGetFilterName(binding),
  608. NULL) < 0)
  609. goto cleanup;
  610. }
  611. vshTablePrintToStdout(table, ctl);
  612. ret = true;
  613. cleanup:
  614. vshTableFree(table);
  615. virshNWFilterBindingListFree(list);
  616. return ret;
  617. }
  618. const vshCmdDef nwfilterCmds[] = {
  619. {.name = "nwfilter-define",
  620. .handler = cmdNWFilterDefine,
  621. .opts = opts_nwfilter_define,
  622. .info = info_nwfilter_define,
  623. .flags = 0
  624. },
  625. {.name = "nwfilter-dumpxml",
  626. .handler = cmdNWFilterDumpXML,
  627. .opts = opts_nwfilter_dumpxml,
  628. .info = info_nwfilter_dumpxml,
  629. .flags = 0
  630. },
  631. {.name = "nwfilter-edit",
  632. .handler = cmdNWFilterEdit,
  633. .opts = opts_nwfilter_edit,
  634. .info = info_nwfilter_edit,
  635. .flags = 0
  636. },
  637. {.name = "nwfilter-list",
  638. .handler = cmdNWFilterList,
  639. .opts = opts_nwfilter_list,
  640. .info = info_nwfilter_list,
  641. .flags = 0
  642. },
  643. {.name = "nwfilter-undefine",
  644. .handler = cmdNWFilterUndefine,
  645. .opts = opts_nwfilter_undefine,
  646. .info = info_nwfilter_undefine,
  647. .flags = 0
  648. },
  649. {.name = "nwfilter-binding-create",
  650. .handler = cmdNWFilterBindingCreate,
  651. .opts = opts_nwfilter_binding_create,
  652. .info = info_nwfilter_binding_create,
  653. .flags = 0
  654. },
  655. {.name = "nwfilter-binding-delete",
  656. .handler = cmdNWFilterBindingDelete,
  657. .opts = opts_nwfilter_binding_delete,
  658. .info = info_nwfilter_binding_delete,
  659. .flags = 0
  660. },
  661. {.name = "nwfilter-binding-dumpxml",
  662. .handler = cmdNWFilterBindingDumpXML,
  663. .opts = opts_nwfilter_binding_dumpxml,
  664. .info = info_nwfilter_binding_dumpxml,
  665. .flags = 0
  666. },
  667. {.name = "nwfilter-binding-list",
  668. .handler = cmdNWFilterBindingList,
  669. .opts = opts_nwfilter_binding_list,
  670. .info = info_nwfilter_binding_list,
  671. .flags = 0
  672. },
  673. {.name = NULL}
  674. };