ip6tables.c 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921
  1. /* Code to take an ip6tables-style command line and do it. */
  2. /*
  3. * Author: Paul.Russell@rustcorp.com.au and mneuling@radlogic.com.au
  4. *
  5. * (C) 2000-2002 by the netfilter coreteam <coreteam@netfilter.org>:
  6. * Paul 'Rusty' Russell <rusty@rustcorp.com.au>
  7. * Marc Boucher <marc+nf@mbsi.ca>
  8. * James Morris <jmorris@intercode.com.au>
  9. * Harald Welte <laforge@gnumonks.org>
  10. * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
  11. *
  12. * This program is free software; you can redistribute it and/or modify
  13. * it under the terms of the GNU General Public License as published by
  14. * the Free Software Foundation; either version 2 of the License, or
  15. * (at your option) any later version.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with this program; if not, write to the Free Software
  24. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  25. */
  26. #include <getopt.h>
  27. #include <string.h>
  28. #include <netdb.h>
  29. #include <errno.h>
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <ctype.h>
  33. #include <stdarg.h>
  34. #include <stdbool.h>
  35. #include <limits.h>
  36. #include <ip6tables.h>
  37. #include <xtables.h>
  38. #include <arpa/inet.h>
  39. #include <unistd.h>
  40. #include <fcntl.h>
  41. #include <sys/types.h>
  42. #include <sys/socket.h>
  43. #include "ip6tables-multi.h"
  44. #include "xshared.h"
  45. #ifndef TRUE
  46. #define TRUE 1
  47. #endif
  48. #ifndef FALSE
  49. #define FALSE 0
  50. #endif
  51. #define CMD_NONE 0x0000U
  52. #define CMD_INSERT 0x0001U
  53. #define CMD_DELETE 0x0002U
  54. #define CMD_DELETE_NUM 0x0004U
  55. #define CMD_REPLACE 0x0008U
  56. #define CMD_APPEND 0x0010U
  57. #define CMD_LIST 0x0020U
  58. #define CMD_FLUSH 0x0040U
  59. #define CMD_ZERO 0x0080U
  60. #define CMD_NEW_CHAIN 0x0100U
  61. #define CMD_DELETE_CHAIN 0x0200U
  62. #define CMD_SET_POLICY 0x0400U
  63. #define CMD_RENAME_CHAIN 0x0800U
  64. #define CMD_LIST_RULES 0x1000U
  65. #define CMD_ZERO_NUM 0x2000U
  66. #define CMD_CHECK 0x4000U
  67. #define NUMBER_OF_CMD 16
  68. static const char cmdflags[] = { 'I', 'D', 'D', 'R', 'A', 'L', 'F', 'Z',
  69. 'N', 'X', 'P', 'E', 'S', 'Z', 'C' };
  70. #define NUMBER_OF_OPT ARRAY_SIZE(optflags)
  71. static const char optflags[]
  72. = { 'n', 's', 'd', 'p', 'j', 'v', 'x', 'i', 'o', '0', 'c'};
  73. static struct option original_opts[] = {
  74. {.name = "append", .has_arg = 1, .val = 'A'},
  75. {.name = "delete", .has_arg = 1, .val = 'D'},
  76. {.name = "check" , .has_arg = 1, .val = 'C'},
  77. {.name = "insert", .has_arg = 1, .val = 'I'},
  78. {.name = "replace", .has_arg = 1, .val = 'R'},
  79. {.name = "list", .has_arg = 2, .val = 'L'},
  80. {.name = "list-rules", .has_arg = 2, .val = 'S'},
  81. {.name = "flush", .has_arg = 2, .val = 'F'},
  82. {.name = "zero", .has_arg = 2, .val = 'Z'},
  83. {.name = "new-chain", .has_arg = 1, .val = 'N'},
  84. {.name = "delete-chain", .has_arg = 2, .val = 'X'},
  85. {.name = "rename-chain", .has_arg = 1, .val = 'E'},
  86. {.name = "policy", .has_arg = 1, .val = 'P'},
  87. {.name = "source", .has_arg = 1, .val = 's'},
  88. {.name = "destination", .has_arg = 1, .val = 'd'},
  89. {.name = "src", .has_arg = 1, .val = 's'}, /* synonym */
  90. {.name = "dst", .has_arg = 1, .val = 'd'}, /* synonym */
  91. {.name = "protocol", .has_arg = 1, .val = 'p'},
  92. {.name = "in-interface", .has_arg = 1, .val = 'i'},
  93. {.name = "jump", .has_arg = 1, .val = 'j'},
  94. {.name = "table", .has_arg = 1, .val = 't'},
  95. {.name = "match", .has_arg = 1, .val = 'm'},
  96. {.name = "numeric", .has_arg = 0, .val = 'n'},
  97. {.name = "out-interface", .has_arg = 1, .val = 'o'},
  98. {.name = "verbose", .has_arg = 0, .val = 'v'},
  99. {.name = "exact", .has_arg = 0, .val = 'x'},
  100. {.name = "version", .has_arg = 0, .val = 'V'},
  101. {.name = "help", .has_arg = 2, .val = 'h'},
  102. {.name = "line-numbers", .has_arg = 0, .val = '0'},
  103. {.name = "modprobe", .has_arg = 1, .val = 'M'},
  104. {.name = "set-counters", .has_arg = 1, .val = 'c'},
  105. {.name = "goto", .has_arg = 1, .val = 'g'},
  106. {.name = "ipv4", .has_arg = 0, .val = '4'},
  107. {.name = "ipv6", .has_arg = 0, .val = '6'},
  108. {NULL},
  109. };
  110. void ip6tables_exit_error(enum xtables_exittype status, const char *msg, ...) __attribute__((noreturn, format(printf,2,3)));
  111. struct xtables_globals ip6tables_globals = {
  112. .option_offset = 0,
  113. .program_version = IPTABLES_VERSION,
  114. .orig_opts = original_opts,
  115. .exit_err = ip6tables_exit_error,
  116. };
  117. /* Table of legal combinations of commands and options. If any of the
  118. * given commands make an option legal, that option is legal (applies to
  119. * CMD_LIST and CMD_ZERO only).
  120. * Key:
  121. * + compulsory
  122. * x illegal
  123. * optional
  124. */
  125. static const char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] =
  126. /* Well, it's better than "Re: Linux vs FreeBSD" */
  127. {
  128. /* -n -s -d -p -j -v -x -i -o --line -c */
  129. /*INSERT*/ {'x',' ',' ',' ',' ',' ','x',' ',' ','x',' '},
  130. /*DELETE*/ {'x',' ',' ',' ',' ',' ','x',' ',' ','x','x'},
  131. /*DELETE_NUM*/{'x','x','x','x','x',' ','x','x','x','x','x'},
  132. /*REPLACE*/ {'x',' ',' ',' ',' ',' ','x',' ',' ','x',' '},
  133. /*APPEND*/ {'x',' ',' ',' ',' ',' ','x',' ',' ','x',' '},
  134. /*LIST*/ {' ','x','x','x','x',' ',' ','x','x',' ','x'},
  135. /*FLUSH*/ {'x','x','x','x','x',' ','x','x','x','x','x'},
  136. /*ZERO*/ {'x','x','x','x','x',' ','x','x','x','x','x'},
  137. /*ZERO_NUM*/ {'x','x','x','x','x',' ','x','x','x','x','x'},
  138. /*NEW_CHAIN*/ {'x','x','x','x','x',' ','x','x','x','x','x'},
  139. /*DEL_CHAIN*/ {'x','x','x','x','x',' ','x','x','x','x','x'},
  140. /*SET_POLICY*/{'x','x','x','x','x',' ','x','x','x','x',' '},
  141. /*RENAME*/ {'x','x','x','x','x',' ','x','x','x','x','x'},
  142. /*LIST_RULES*/{'x','x','x','x','x',' ','x','x','x','x','x'},
  143. /*CHECK*/ {'x',' ',' ',' ',' ',' ','x',' ',' ','x','x'},
  144. };
  145. static const unsigned int inverse_for_options[NUMBER_OF_OPT] =
  146. {
  147. /* -n */ 0,
  148. /* -s */ IP6T_INV_SRCIP,
  149. /* -d */ IP6T_INV_DSTIP,
  150. /* -p */ XT_INV_PROTO,
  151. /* -j */ 0,
  152. /* -v */ 0,
  153. /* -x */ 0,
  154. /* -i */ IP6T_INV_VIA_IN,
  155. /* -o */ IP6T_INV_VIA_OUT,
  156. /*--line*/ 0,
  157. /* -c */ 0,
  158. };
  159. #define opts ip6tables_globals.opts
  160. #define prog_name ip6tables_globals.program_name
  161. #define prog_vers ip6tables_globals.program_version
  162. /* A few hardcoded protocols for 'all' and in case the user has no
  163. /etc/protocols */
  164. struct pprot {
  165. const char *name;
  166. uint8_t num;
  167. };
  168. static void __attribute__((noreturn))
  169. exit_tryhelp(int status)
  170. {
  171. if (line != -1)
  172. fprintf(stderr, "Error occurred at line: %d\n", line);
  173. fprintf(stderr, "Try `%s -h' or '%s --help' for more information.\n",
  174. prog_name, prog_name);
  175. xtables_free_opts(1);
  176. exit(status);
  177. }
  178. static void
  179. exit_printhelp(const struct xtables_rule_match *matches)
  180. {
  181. printf("%s v%s\n\n"
  182. "Usage: %s -[ACD] chain rule-specification [options]\n"
  183. " %s -I chain [rulenum] rule-specification [options]\n"
  184. " %s -R chain rulenum rule-specification [options]\n"
  185. " %s -D chain rulenum [options]\n"
  186. " %s -[LS] [chain [rulenum]] [options]\n"
  187. " %s -[FZ] [chain] [options]\n"
  188. " %s -[NX] chain\n"
  189. " %s -E old-chain-name new-chain-name\n"
  190. " %s -P chain target [options]\n"
  191. " %s -h (print this help information)\n\n",
  192. prog_name, prog_vers, prog_name, prog_name,
  193. prog_name, prog_name, prog_name, prog_name,
  194. prog_name, prog_name, prog_name, prog_name);
  195. printf(
  196. "Commands:\n"
  197. "Either long or short options are allowed.\n"
  198. " --append -A chain Append to chain\n"
  199. " --check -C chain Check for the existence of a rule\n"
  200. " --delete -D chain Delete matching rule from chain\n"
  201. " --delete -D chain rulenum\n"
  202. " Delete rule rulenum (1 = first) from chain\n"
  203. " --insert -I chain [rulenum]\n"
  204. " Insert in chain as rulenum (default 1=first)\n"
  205. " --replace -R chain rulenum\n"
  206. " Replace rule rulenum (1 = first) in chain\n"
  207. " --list -L [chain [rulenum]]\n"
  208. " List the rules in a chain or all chains\n"
  209. " --list-rules -S [chain [rulenum]]\n"
  210. " Print the rules in a chain or all chains\n"
  211. " --flush -F [chain] Delete all rules in chain or all chains\n"
  212. " --zero -Z [chain [rulenum]]\n"
  213. " Zero counters in chain or all chains\n"
  214. " --new -N chain Create a new user-defined chain\n"
  215. " --delete-chain\n"
  216. " -X [chain] Delete a user-defined chain\n"
  217. " --policy -P chain target\n"
  218. " Change policy on chain to target\n"
  219. " --rename-chain\n"
  220. " -E old-chain new-chain\n"
  221. " Change chain name, (moving any references)\n"
  222. "Options:\n"
  223. " --ipv4 -4 Error (line is ignored by ip6tables-restore)\n"
  224. " --ipv6 -6 Nothing (line is ignored by iptables-restore)\n"
  225. "[!] --proto -p proto protocol: by number or name, eg. `tcp'\n"
  226. "[!] --source -s address[/mask][,...]\n"
  227. " source specification\n"
  228. "[!] --destination -d address[/mask][,...]\n"
  229. " destination specification\n"
  230. "[!] --in-interface -i input name[+]\n"
  231. " network interface name ([+] for wildcard)\n"
  232. " --jump -j target\n"
  233. " target for rule (may load target extension)\n"
  234. #ifdef IP6T_F_GOTO
  235. " --goto -g chain\n"
  236. " jump to chain with no return\n"
  237. #endif
  238. " --match -m match\n"
  239. " extended match (may load extension)\n"
  240. " --numeric -n numeric output of addresses and ports\n"
  241. "[!] --out-interface -o output name[+]\n"
  242. " network interface name ([+] for wildcard)\n"
  243. " --table -t table table to manipulate (default: `filter')\n"
  244. " --verbose -v verbose mode\n"
  245. " --line-numbers print line numbers when listing\n"
  246. " --exact -x expand numbers (display exact values)\n"
  247. /*"[!] --fragment -f match second or further fragments only\n"*/
  248. " --modprobe=<command> try to insert modules using this command\n"
  249. " --set-counters PKTS BYTES set the counter during insert/append\n"
  250. "[!] --version -V print package version.\n");
  251. print_extension_helps(xtables_targets, matches);
  252. exit(0);
  253. }
  254. void
  255. ip6tables_exit_error(enum xtables_exittype status, const char *msg, ...)
  256. {
  257. va_list args;
  258. va_start(args, msg);
  259. fprintf(stderr, "%s v%s: ", prog_name, prog_vers);
  260. vfprintf(stderr, msg, args);
  261. va_end(args);
  262. fprintf(stderr, "\n");
  263. if (status == PARAMETER_PROBLEM)
  264. exit_tryhelp(status);
  265. if (status == VERSION_PROBLEM)
  266. fprintf(stderr,
  267. "Perhaps ip6tables or your kernel needs to be upgraded.\n");
  268. /* On error paths, make sure that we don't leak memory */
  269. xtables_free_opts(1);
  270. exit(status);
  271. }
  272. static void
  273. generic_opt_check(int command, int options)
  274. {
  275. int i, j, legal = 0;
  276. /* Check that commands are valid with options. Complicated by the
  277. * fact that if an option is legal with *any* command given, it is
  278. * legal overall (ie. -z and -l).
  279. */
  280. for (i = 0; i < NUMBER_OF_OPT; i++) {
  281. legal = 0; /* -1 => illegal, 1 => legal, 0 => undecided. */
  282. for (j = 0; j < NUMBER_OF_CMD; j++) {
  283. if (!(command & (1<<j)))
  284. continue;
  285. if (!(options & (1<<i))) {
  286. if (commands_v_options[j][i] == '+')
  287. xtables_error(PARAMETER_PROBLEM,
  288. "You need to supply the `-%c' "
  289. "option for this command\n",
  290. optflags[i]);
  291. } else {
  292. if (commands_v_options[j][i] != 'x')
  293. legal = 1;
  294. else if (legal == 0)
  295. legal = -1;
  296. }
  297. }
  298. if (legal == -1)
  299. xtables_error(PARAMETER_PROBLEM,
  300. "Illegal option `-%c' with this command\n",
  301. optflags[i]);
  302. }
  303. }
  304. static char
  305. opt2char(int option)
  306. {
  307. const char *ptr;
  308. for (ptr = optflags; option > 1; option >>= 1, ptr++);
  309. return *ptr;
  310. }
  311. static char
  312. cmd2char(int option)
  313. {
  314. const char *ptr;
  315. for (ptr = cmdflags; option > 1; option >>= 1, ptr++);
  316. return *ptr;
  317. }
  318. static void
  319. add_command(unsigned int *cmd, const int newcmd, const int othercmds,
  320. int invert)
  321. {
  322. if (invert)
  323. xtables_error(PARAMETER_PROBLEM, "unexpected '!' flag");
  324. if (*cmd & (~othercmds))
  325. xtables_error(PARAMETER_PROBLEM, "Cannot use -%c with -%c\n",
  326. cmd2char(newcmd), cmd2char(*cmd & (~othercmds)));
  327. *cmd |= newcmd;
  328. }
  329. /*
  330. * All functions starting with "parse" should succeed, otherwise
  331. * the program fails.
  332. * Most routines return pointers to static data that may change
  333. * between calls to the same or other routines with a few exceptions:
  334. * "host_to_addr", "parse_hostnetwork", and "parse_hostnetworkmask"
  335. * return global static data.
  336. */
  337. /* These are invalid numbers as upper layer protocol */
  338. static int is_exthdr(uint16_t proto)
  339. {
  340. return (proto == IPPROTO_ROUTING ||
  341. proto == IPPROTO_FRAGMENT ||
  342. proto == IPPROTO_AH ||
  343. proto == IPPROTO_DSTOPTS);
  344. }
  345. /* Can't be zero. */
  346. static int
  347. parse_rulenumber(const char *rule)
  348. {
  349. unsigned int rulenum;
  350. if (!xtables_strtoui(rule, NULL, &rulenum, 1, INT_MAX))
  351. xtables_error(PARAMETER_PROBLEM,
  352. "Invalid rule number `%s'", rule);
  353. return rulenum;
  354. }
  355. static const char *
  356. parse_target(const char *targetname)
  357. {
  358. const char *ptr;
  359. if (strlen(targetname) < 1)
  360. xtables_error(PARAMETER_PROBLEM,
  361. "Invalid target name (too short)");
  362. if (strlen(targetname) >= XT_EXTENSION_MAXNAMELEN)
  363. xtables_error(PARAMETER_PROBLEM,
  364. "Invalid target name `%s' (%u chars max)",
  365. targetname, XT_EXTENSION_MAXNAMELEN - 1);
  366. for (ptr = targetname; *ptr; ptr++)
  367. if (isspace(*ptr))
  368. xtables_error(PARAMETER_PROBLEM,
  369. "Invalid target name `%s'", targetname);
  370. return targetname;
  371. }
  372. static void
  373. set_option(unsigned int *options, unsigned int option, uint8_t *invflg,
  374. int invert)
  375. {
  376. if (*options & option)
  377. xtables_error(PARAMETER_PROBLEM, "multiple -%c flags not allowed",
  378. opt2char(option));
  379. *options |= option;
  380. if (invert) {
  381. unsigned int i;
  382. for (i = 0; 1 << i != option; i++);
  383. if (!inverse_for_options[i])
  384. xtables_error(PARAMETER_PROBLEM,
  385. "cannot have ! before -%c",
  386. opt2char(option));
  387. *invflg |= inverse_for_options[i];
  388. }
  389. }
  390. static void
  391. print_header(unsigned int format, const char *chain, struct xtc_handle *handle)
  392. {
  393. struct xt_counters counters;
  394. const char *pol = ip6tc_get_policy(chain, &counters, handle);
  395. printf("Chain %s", chain);
  396. if (pol) {
  397. printf(" (policy %s", pol);
  398. if (!(format & FMT_NOCOUNTS)) {
  399. fputc(' ', stdout);
  400. xtables_print_num(counters.pcnt, (format|FMT_NOTABLE));
  401. fputs("packets, ", stdout);
  402. xtables_print_num(counters.bcnt, (format|FMT_NOTABLE));
  403. fputs("bytes", stdout);
  404. }
  405. printf(")\n");
  406. } else {
  407. unsigned int refs;
  408. if (!ip6tc_get_references(&refs, chain, handle))
  409. printf(" (ERROR obtaining refs)\n");
  410. else
  411. printf(" (%u references)\n", refs);
  412. }
  413. if (format & FMT_LINENUMBERS)
  414. printf(FMT("%-4s ", "%s "), "num");
  415. if (!(format & FMT_NOCOUNTS)) {
  416. if (format & FMT_KILOMEGAGIGA) {
  417. printf(FMT("%5s ","%s "), "pkts");
  418. printf(FMT("%5s ","%s "), "bytes");
  419. } else {
  420. printf(FMT("%8s ","%s "), "pkts");
  421. printf(FMT("%10s ","%s "), "bytes");
  422. }
  423. }
  424. if (!(format & FMT_NOTARGET))
  425. printf(FMT("%-9s ","%s "), "target");
  426. fputs(" prot ", stdout);
  427. if (format & FMT_OPTIONS)
  428. fputs("opt", stdout);
  429. if (format & FMT_VIA) {
  430. printf(FMT(" %-6s ","%s "), "in");
  431. printf(FMT("%-6s ","%s "), "out");
  432. }
  433. printf(FMT(" %-19s ","%s "), "source");
  434. printf(FMT(" %-19s "," %s "), "destination");
  435. printf("\n");
  436. }
  437. static int
  438. print_match(const struct xt_entry_match *m,
  439. const struct ip6t_ip6 *ip,
  440. int numeric)
  441. {
  442. const struct xtables_match *match =
  443. xtables_find_match(m->u.user.name, XTF_TRY_LOAD, NULL);
  444. if (match) {
  445. if (match->print)
  446. match->print(ip, m, numeric);
  447. else
  448. printf("%s ", match->name);
  449. } else {
  450. if (m->u.user.name[0])
  451. printf("UNKNOWN match `%s' ", m->u.user.name);
  452. }
  453. /* Don't stop iterating. */
  454. return 0;
  455. }
  456. /* e is called `fw' here for historical reasons */
  457. static void
  458. print_firewall(const struct ip6t_entry *fw,
  459. const char *targname,
  460. unsigned int num,
  461. unsigned int format,
  462. struct xtc_handle *const handle)
  463. {
  464. const struct xtables_target *target = NULL;
  465. const struct xt_entry_target *t;
  466. char buf[BUFSIZ];
  467. if (!ip6tc_is_chain(targname, handle))
  468. target = xtables_find_target(targname, XTF_TRY_LOAD);
  469. else
  470. target = xtables_find_target(XT_STANDARD_TARGET,
  471. XTF_LOAD_MUST_SUCCEED);
  472. t = ip6t_get_target((struct ip6t_entry *)fw);
  473. if (format & FMT_LINENUMBERS)
  474. printf(FMT("%-4u ", "%u "), num);
  475. if (!(format & FMT_NOCOUNTS)) {
  476. xtables_print_num(fw->counters.pcnt, format);
  477. xtables_print_num(fw->counters.bcnt, format);
  478. }
  479. if (!(format & FMT_NOTARGET))
  480. printf(FMT("%-9s ", "%s "), targname);
  481. fputc(fw->ipv6.invflags & XT_INV_PROTO ? '!' : ' ', stdout);
  482. {
  483. const char *pname = proto_to_name(fw->ipv6.proto, format&FMT_NUMERIC);
  484. if (pname)
  485. printf(FMT("%-5s", "%s "), pname);
  486. else
  487. printf(FMT("%-5hu", "%hu "), fw->ipv6.proto);
  488. }
  489. if (format & FMT_OPTIONS) {
  490. if (format & FMT_NOTABLE)
  491. fputs("opt ", stdout);
  492. fputc(' ', stdout); /* Invert flag of FRAG */
  493. fputc(' ', stdout); /* -f */
  494. fputc(' ', stdout);
  495. }
  496. if (format & FMT_VIA) {
  497. char iface[IFNAMSIZ+2];
  498. if (fw->ipv6.invflags & IP6T_INV_VIA_IN) {
  499. iface[0] = '!';
  500. iface[1] = '\0';
  501. }
  502. else iface[0] = '\0';
  503. if (fw->ipv6.iniface[0] != '\0') {
  504. strcat(iface, fw->ipv6.iniface);
  505. }
  506. else if (format & FMT_NUMERIC) strcat(iface, "*");
  507. else strcat(iface, "any");
  508. printf(FMT(" %-6s ","in %s "), iface);
  509. if (fw->ipv6.invflags & IP6T_INV_VIA_OUT) {
  510. iface[0] = '!';
  511. iface[1] = '\0';
  512. }
  513. else iface[0] = '\0';
  514. if (fw->ipv6.outiface[0] != '\0') {
  515. strcat(iface, fw->ipv6.outiface);
  516. }
  517. else if (format & FMT_NUMERIC) strcat(iface, "*");
  518. else strcat(iface, "any");
  519. printf(FMT("%-6s ","out %s "), iface);
  520. }
  521. fputc(fw->ipv6.invflags & IP6T_INV_SRCIP ? '!' : ' ', stdout);
  522. if (!memcmp(&fw->ipv6.smsk, &in6addr_any, sizeof in6addr_any)
  523. && !(format & FMT_NUMERIC))
  524. printf(FMT("%-19s ","%s "), "anywhere");
  525. else {
  526. if (format & FMT_NUMERIC)
  527. strcpy(buf, xtables_ip6addr_to_numeric(&fw->ipv6.src));
  528. else
  529. strcpy(buf, xtables_ip6addr_to_anyname(&fw->ipv6.src));
  530. strcat(buf, xtables_ip6mask_to_numeric(&fw->ipv6.smsk));
  531. printf(FMT("%-19s ","%s "), buf);
  532. }
  533. fputc(fw->ipv6.invflags & IP6T_INV_DSTIP ? '!' : ' ', stdout);
  534. if (!memcmp(&fw->ipv6.dmsk, &in6addr_any, sizeof in6addr_any)
  535. && !(format & FMT_NUMERIC))
  536. printf(FMT("%-19s ","-> %s"), "anywhere");
  537. else {
  538. if (format & FMT_NUMERIC)
  539. strcpy(buf, xtables_ip6addr_to_numeric(&fw->ipv6.dst));
  540. else
  541. strcpy(buf, xtables_ip6addr_to_anyname(&fw->ipv6.dst));
  542. strcat(buf, xtables_ip6mask_to_numeric(&fw->ipv6.dmsk));
  543. printf(FMT("%-19s ","-> %s"), buf);
  544. }
  545. if (format & FMT_NOTABLE)
  546. fputs(" ", stdout);
  547. #ifdef IP6T_F_GOTO
  548. if(fw->ipv6.flags & IP6T_F_GOTO)
  549. printf("[goto] ");
  550. #endif
  551. IP6T_MATCH_ITERATE(fw, print_match, &fw->ipv6, format & FMT_NUMERIC);
  552. if (target) {
  553. if (target->print)
  554. /* Print the target information. */
  555. target->print(&fw->ipv6, t, format & FMT_NUMERIC);
  556. } else if (t->u.target_size != sizeof(*t))
  557. printf("[%u bytes of unknown target data] ",
  558. (unsigned int)(t->u.target_size - sizeof(*t)));
  559. if (!(format & FMT_NONEWLINE))
  560. fputc('\n', stdout);
  561. }
  562. static void
  563. print_firewall_line(const struct ip6t_entry *fw,
  564. struct xtc_handle *const h)
  565. {
  566. struct xt_entry_target *t;
  567. t = ip6t_get_target((struct ip6t_entry *)fw);
  568. print_firewall(fw, t->u.user.name, 0, FMT_PRINT_RULE, h);
  569. }
  570. static int
  571. append_entry(const xt_chainlabel chain,
  572. struct ip6t_entry *fw,
  573. unsigned int nsaddrs,
  574. const struct in6_addr saddrs[],
  575. const struct in6_addr smasks[],
  576. unsigned int ndaddrs,
  577. const struct in6_addr daddrs[],
  578. const struct in6_addr dmasks[],
  579. int verbose,
  580. struct xtc_handle *handle)
  581. {
  582. unsigned int i, j;
  583. int ret = 1;
  584. for (i = 0; i < nsaddrs; i++) {
  585. fw->ipv6.src = saddrs[i];
  586. fw->ipv6.smsk = smasks[i];
  587. for (j = 0; j < ndaddrs; j++) {
  588. fw->ipv6.dst = daddrs[j];
  589. fw->ipv6.dmsk = dmasks[j];
  590. if (verbose)
  591. print_firewall_line(fw, handle);
  592. ret &= ip6tc_append_entry(chain, fw, handle);
  593. }
  594. }
  595. return ret;
  596. }
  597. static int
  598. replace_entry(const xt_chainlabel chain,
  599. struct ip6t_entry *fw,
  600. unsigned int rulenum,
  601. const struct in6_addr *saddr, const struct in6_addr *smask,
  602. const struct in6_addr *daddr, const struct in6_addr *dmask,
  603. int verbose,
  604. struct xtc_handle *handle)
  605. {
  606. fw->ipv6.src = *saddr;
  607. fw->ipv6.dst = *daddr;
  608. fw->ipv6.smsk = *smask;
  609. fw->ipv6.dmsk = *dmask;
  610. if (verbose)
  611. print_firewall_line(fw, handle);
  612. return ip6tc_replace_entry(chain, fw, rulenum, handle);
  613. }
  614. static int
  615. insert_entry(const xt_chainlabel chain,
  616. struct ip6t_entry *fw,
  617. unsigned int rulenum,
  618. unsigned int nsaddrs,
  619. const struct in6_addr saddrs[],
  620. const struct in6_addr smasks[],
  621. unsigned int ndaddrs,
  622. const struct in6_addr daddrs[],
  623. const struct in6_addr dmasks[],
  624. int verbose,
  625. struct xtc_handle *handle)
  626. {
  627. unsigned int i, j;
  628. int ret = 1;
  629. for (i = 0; i < nsaddrs; i++) {
  630. fw->ipv6.src = saddrs[i];
  631. fw->ipv6.smsk = smasks[i];
  632. for (j = 0; j < ndaddrs; j++) {
  633. fw->ipv6.dst = daddrs[j];
  634. fw->ipv6.dmsk = dmasks[j];
  635. if (verbose)
  636. print_firewall_line(fw, handle);
  637. ret &= ip6tc_insert_entry(chain, fw, rulenum, handle);
  638. }
  639. }
  640. return ret;
  641. }
  642. static unsigned char *
  643. make_delete_mask(const struct xtables_rule_match *matches,
  644. const struct xtables_target *target)
  645. {
  646. /* Establish mask for comparison */
  647. unsigned int size;
  648. const struct xtables_rule_match *matchp;
  649. unsigned char *mask, *mptr;
  650. size = sizeof(struct ip6t_entry);
  651. for (matchp = matches; matchp; matchp = matchp->next)
  652. size += XT_ALIGN(sizeof(struct xt_entry_match)) + matchp->match->size;
  653. mask = xtables_calloc(1, size
  654. + XT_ALIGN(sizeof(struct xt_entry_target))
  655. + target->size);
  656. memset(mask, 0xFF, sizeof(struct ip6t_entry));
  657. mptr = mask + sizeof(struct ip6t_entry);
  658. for (matchp = matches; matchp; matchp = matchp->next) {
  659. memset(mptr, 0xFF,
  660. XT_ALIGN(sizeof(struct xt_entry_match))
  661. + matchp->match->userspacesize);
  662. mptr += XT_ALIGN(sizeof(struct xt_entry_match)) + matchp->match->size;
  663. }
  664. memset(mptr, 0xFF,
  665. XT_ALIGN(sizeof(struct xt_entry_target))
  666. + target->userspacesize);
  667. return mask;
  668. }
  669. static int
  670. delete_entry(const xt_chainlabel chain,
  671. struct ip6t_entry *fw,
  672. unsigned int nsaddrs,
  673. const struct in6_addr saddrs[],
  674. const struct in6_addr smasks[],
  675. unsigned int ndaddrs,
  676. const struct in6_addr daddrs[],
  677. const struct in6_addr dmasks[],
  678. int verbose,
  679. struct xtc_handle *handle,
  680. struct xtables_rule_match *matches,
  681. const struct xtables_target *target)
  682. {
  683. unsigned int i, j;
  684. int ret = 1;
  685. unsigned char *mask;
  686. mask = make_delete_mask(matches, target);
  687. for (i = 0; i < nsaddrs; i++) {
  688. fw->ipv6.src = saddrs[i];
  689. fw->ipv6.smsk = smasks[i];
  690. for (j = 0; j < ndaddrs; j++) {
  691. fw->ipv6.dst = daddrs[j];
  692. fw->ipv6.dmsk = dmasks[j];
  693. if (verbose)
  694. print_firewall_line(fw, handle);
  695. ret &= ip6tc_delete_entry(chain, fw, mask, handle);
  696. }
  697. }
  698. free(mask);
  699. return ret;
  700. }
  701. static int
  702. check_entry(const xt_chainlabel chain, struct ip6t_entry *fw,
  703. unsigned int nsaddrs, const struct in6_addr *saddrs,
  704. const struct in6_addr *smasks, unsigned int ndaddrs,
  705. const struct in6_addr *daddrs, const struct in6_addr *dmasks,
  706. bool verbose, struct xtc_handle *handle,
  707. struct xtables_rule_match *matches,
  708. const struct xtables_target *target)
  709. {
  710. unsigned int i, j;
  711. int ret = 1;
  712. unsigned char *mask;
  713. mask = make_delete_mask(matches, target);
  714. for (i = 0; i < nsaddrs; i++) {
  715. fw->ipv6.src = saddrs[i];
  716. fw->ipv6.smsk = smasks[i];
  717. for (j = 0; j < ndaddrs; j++) {
  718. fw->ipv6.dst = daddrs[j];
  719. fw->ipv6.dmsk = dmasks[j];
  720. if (verbose)
  721. print_firewall_line(fw, handle);
  722. ret &= ip6tc_check_entry(chain, fw, mask, handle);
  723. }
  724. }
  725. free(mask);
  726. return ret;
  727. }
  728. int
  729. for_each_chain6(int (*fn)(const xt_chainlabel, int, struct xtc_handle *),
  730. int verbose, int builtinstoo, struct xtc_handle *handle)
  731. {
  732. int ret = 1;
  733. const char *chain;
  734. char *chains;
  735. unsigned int i, chaincount = 0;
  736. chain = ip6tc_first_chain(handle);
  737. while (chain) {
  738. chaincount++;
  739. chain = ip6tc_next_chain(handle);
  740. }
  741. chains = xtables_malloc(sizeof(xt_chainlabel) * chaincount);
  742. i = 0;
  743. chain = ip6tc_first_chain(handle);
  744. while (chain) {
  745. strcpy(chains + i*sizeof(xt_chainlabel), chain);
  746. i++;
  747. chain = ip6tc_next_chain(handle);
  748. }
  749. for (i = 0; i < chaincount; i++) {
  750. if (!builtinstoo
  751. && ip6tc_builtin(chains + i*sizeof(xt_chainlabel),
  752. handle) == 1)
  753. continue;
  754. ret &= fn(chains + i*sizeof(xt_chainlabel), verbose, handle);
  755. }
  756. free(chains);
  757. return ret;
  758. }
  759. int
  760. flush_entries6(const xt_chainlabel chain, int verbose,
  761. struct xtc_handle *handle)
  762. {
  763. if (!chain)
  764. return for_each_chain6(flush_entries6, verbose, 1, handle);
  765. if (verbose)
  766. fprintf(stdout, "Flushing chain `%s'\n", chain);
  767. return ip6tc_flush_entries(chain, handle);
  768. }
  769. static int
  770. zero_entries(const xt_chainlabel chain, int verbose,
  771. struct xtc_handle *handle)
  772. {
  773. if (!chain)
  774. return for_each_chain6(zero_entries, verbose, 1, handle);
  775. if (verbose)
  776. fprintf(stdout, "Zeroing chain `%s'\n", chain);
  777. return ip6tc_zero_entries(chain, handle);
  778. }
  779. int
  780. delete_chain6(const xt_chainlabel chain, int verbose,
  781. struct xtc_handle *handle)
  782. {
  783. if (!chain)
  784. return for_each_chain6(delete_chain6, verbose, 0, handle);
  785. if (verbose)
  786. fprintf(stdout, "Deleting chain `%s'\n", chain);
  787. return ip6tc_delete_chain(chain, handle);
  788. }
  789. static int
  790. list_entries(const xt_chainlabel chain, int rulenum, int verbose, int numeric,
  791. int expanded, int linenumbers, struct xtc_handle *handle)
  792. {
  793. int found = 0;
  794. unsigned int format;
  795. const char *this;
  796. format = FMT_OPTIONS;
  797. if (!verbose)
  798. format |= FMT_NOCOUNTS;
  799. else
  800. format |= FMT_VIA;
  801. if (numeric)
  802. format |= FMT_NUMERIC;
  803. if (!expanded)
  804. format |= FMT_KILOMEGAGIGA;
  805. if (linenumbers)
  806. format |= FMT_LINENUMBERS;
  807. for (this = ip6tc_first_chain(handle);
  808. this;
  809. this = ip6tc_next_chain(handle)) {
  810. const struct ip6t_entry *i;
  811. unsigned int num;
  812. if (chain && strcmp(chain, this) != 0)
  813. continue;
  814. if (found) printf("\n");
  815. if (!rulenum)
  816. print_header(format, this, handle);
  817. i = ip6tc_first_rule(this, handle);
  818. num = 0;
  819. while (i) {
  820. num++;
  821. if (!rulenum || num == rulenum)
  822. print_firewall(i,
  823. ip6tc_get_target(i, handle),
  824. num,
  825. format,
  826. handle);
  827. i = ip6tc_next_rule(i, handle);
  828. }
  829. found = 1;
  830. }
  831. errno = ENOENT;
  832. return found;
  833. }
  834. /* This assumes that mask is contiguous, and byte-bounded. */
  835. static void
  836. print_iface(char letter, const char *iface, const unsigned char *mask,
  837. int invert)
  838. {
  839. unsigned int i;
  840. if (mask[0] == 0)
  841. return;
  842. printf("%s -%c ", invert ? " !" : "", letter);
  843. for (i = 0; i < IFNAMSIZ; i++) {
  844. if (mask[i] != 0) {
  845. if (iface[i] != '\0')
  846. printf("%c", iface[i]);
  847. } else {
  848. /* we can access iface[i-1] here, because
  849. * a few lines above we make sure that mask[0] != 0 */
  850. if (iface[i-1] != '\0')
  851. printf("+");
  852. break;
  853. }
  854. }
  855. }
  856. /* The ip6tables looks up the /etc/protocols. */
  857. static void print_proto(uint16_t proto, int invert)
  858. {
  859. if (proto) {
  860. unsigned int i;
  861. const char *invertstr = invert ? " !" : "";
  862. const struct protoent *pent = getprotobynumber(proto);
  863. if (pent) {
  864. printf("%s -p %s",
  865. invertstr, pent->p_name);
  866. return;
  867. }
  868. for (i = 0; xtables_chain_protos[i].name != NULL; ++i)
  869. if (xtables_chain_protos[i].num == proto) {
  870. printf("%s -p %s",
  871. invertstr, xtables_chain_protos[i].name);
  872. return;
  873. }
  874. printf("%s -p %u", invertstr, proto);
  875. }
  876. }
  877. static int print_match_save(const struct xt_entry_match *e,
  878. const struct ip6t_ip6 *ip)
  879. {
  880. const struct xtables_match *match =
  881. xtables_find_match(e->u.user.name, XTF_TRY_LOAD, NULL);
  882. if (match) {
  883. printf(" -m %s",
  884. match->alias ? match->alias(e) : e->u.user.name);
  885. /* some matches don't provide a save function */
  886. if (match->save)
  887. match->save(ip, e);
  888. } else {
  889. if (e->u.match_size) {
  890. fprintf(stderr,
  891. "Can't find library for match `%s'\n",
  892. e->u.user.name);
  893. exit(1);
  894. }
  895. }
  896. return 0;
  897. }
  898. /* print a given ip including mask if neccessary */
  899. static void print_ip(const char *prefix, const struct in6_addr *ip,
  900. const struct in6_addr *mask, int invert)
  901. {
  902. char buf[51];
  903. int l = ipv6_prefix_length(mask);
  904. if (l == 0 && !invert)
  905. return;
  906. printf("%s %s %s",
  907. invert ? " !" : "",
  908. prefix,
  909. inet_ntop(AF_INET6, ip, buf, sizeof buf));
  910. if (l == -1)
  911. printf("/%s", inet_ntop(AF_INET6, mask, buf, sizeof buf));
  912. else
  913. printf("/%d", l);
  914. }
  915. /* We want this to be readable, so only print out neccessary fields.
  916. * Because that's the kind of world I want to live in. */
  917. void print_rule6(const struct ip6t_entry *e,
  918. struct xtc_handle *h, const char *chain, int counters)
  919. {
  920. const struct xt_entry_target *t;
  921. const char *target_name;
  922. /* print counters for iptables-save */
  923. if (counters > 0)
  924. printf("[%llu:%llu] ", (unsigned long long)e->counters.pcnt, (unsigned long long)e->counters.bcnt);
  925. /* print chain name */
  926. printf("-A %s", chain);
  927. /* Print IP part. */
  928. print_ip("-s", &(e->ipv6.src), &(e->ipv6.smsk),
  929. e->ipv6.invflags & IP6T_INV_SRCIP);
  930. print_ip("-d", &(e->ipv6.dst), &(e->ipv6.dmsk),
  931. e->ipv6.invflags & IP6T_INV_DSTIP);
  932. print_iface('i', e->ipv6.iniface, e->ipv6.iniface_mask,
  933. e->ipv6.invflags & IP6T_INV_VIA_IN);
  934. print_iface('o', e->ipv6.outiface, e->ipv6.outiface_mask,
  935. e->ipv6.invflags & IP6T_INV_VIA_OUT);
  936. print_proto(e->ipv6.proto, e->ipv6.invflags & XT_INV_PROTO);
  937. #if 0
  938. /* not definied in ipv6
  939. * FIXME: linux/netfilter_ipv6/ip6_tables: IP6T_INV_FRAG why definied? */
  940. if (e->ipv6.flags & IPT_F_FRAG)
  941. printf("%s -f",
  942. e->ipv6.invflags & IP6T_INV_FRAG ? " !" : "");
  943. #endif
  944. if (e->ipv6.flags & IP6T_F_TOS)
  945. printf("%s -? %d",
  946. e->ipv6.invflags & IP6T_INV_TOS ? " !" : "",
  947. e->ipv6.tos);
  948. /* Print matchinfo part */
  949. if (e->target_offset) {
  950. IP6T_MATCH_ITERATE(e, print_match_save, &e->ipv6);
  951. }
  952. /* print counters for iptables -R */
  953. if (counters < 0)
  954. printf(" -c %llu %llu", (unsigned long long)e->counters.pcnt, (unsigned long long)e->counters.bcnt);
  955. /* Print target name and targinfo part */
  956. target_name = ip6tc_get_target(e, h);
  957. t = ip6t_get_target((struct ip6t_entry *)e);
  958. if (t->u.user.name[0]) {
  959. struct xtables_target *target =
  960. xtables_find_target(t->u.user.name, XTF_TRY_LOAD);
  961. if (!target) {
  962. fprintf(stderr, "Can't find library for target `%s'\n",
  963. t->u.user.name);
  964. exit(1);
  965. }
  966. printf(" -j %s", target->alias ? target->alias(t) : target_name);
  967. if (target->save)
  968. target->save(&e->ipv6, t);
  969. else {
  970. /* If the target size is greater than xt_entry_target
  971. * there is something to be saved, we just don't know
  972. * how to print it */
  973. if (t->u.target_size !=
  974. sizeof(struct xt_entry_target)) {
  975. fprintf(stderr, "Target `%s' is missing "
  976. "save function\n",
  977. t->u.user.name);
  978. exit(1);
  979. }
  980. }
  981. } else if (target_name && (*target_name != '\0'))
  982. #ifdef IP6T_F_GOTO
  983. printf(" -%c %s", e->ipv6.flags & IP6T_F_GOTO ? 'g' : 'j', target_name);
  984. #else
  985. printf(" -j %s", target_name);
  986. #endif
  987. printf("\n");
  988. }
  989. static int
  990. list_rules(const xt_chainlabel chain, int rulenum, int counters,
  991. struct xtc_handle *handle)
  992. {
  993. const char *this = NULL;
  994. int found = 0;
  995. if (counters)
  996. counters = -1; /* iptables -c format */
  997. /* Dump out chain names first,
  998. * thereby preventing dependency conflicts */
  999. if (!rulenum) for (this = ip6tc_first_chain(handle);
  1000. this;
  1001. this = ip6tc_next_chain(handle)) {
  1002. if (chain && strcmp(this, chain) != 0)
  1003. continue;
  1004. if (ip6tc_builtin(this, handle)) {
  1005. struct xt_counters count;
  1006. printf("-P %s %s", this, ip6tc_get_policy(this, &count, handle));
  1007. if (counters)
  1008. printf(" -c %llu %llu", (unsigned long long)count.pcnt, (unsigned long long)count.bcnt);
  1009. printf("\n");
  1010. } else {
  1011. printf("-N %s\n", this);
  1012. }
  1013. }
  1014. for (this = ip6tc_first_chain(handle);
  1015. this;
  1016. this = ip6tc_next_chain(handle)) {
  1017. const struct ip6t_entry *e;
  1018. int num = 0;
  1019. if (chain && strcmp(this, chain) != 0)
  1020. continue;
  1021. /* Dump out rules */
  1022. e = ip6tc_first_rule(this, handle);
  1023. while(e) {
  1024. num++;
  1025. if (!rulenum || num == rulenum)
  1026. print_rule6(e, handle, this, counters);
  1027. e = ip6tc_next_rule(e, handle);
  1028. }
  1029. found = 1;
  1030. }
  1031. errno = ENOENT;
  1032. return found;
  1033. }
  1034. static struct ip6t_entry *
  1035. generate_entry(const struct ip6t_entry *fw,
  1036. struct xtables_rule_match *matches,
  1037. struct xt_entry_target *target)
  1038. {
  1039. unsigned int size;
  1040. struct xtables_rule_match *matchp;
  1041. struct ip6t_entry *e;
  1042. size = sizeof(struct ip6t_entry);
  1043. for (matchp = matches; matchp; matchp = matchp->next)
  1044. size += matchp->match->m->u.match_size;
  1045. e = xtables_malloc(size + target->u.target_size);
  1046. *e = *fw;
  1047. e->target_offset = size;
  1048. e->next_offset = size + target->u.target_size;
  1049. size = 0;
  1050. for (matchp = matches; matchp; matchp = matchp->next) {
  1051. memcpy(e->elems + size, matchp->match->m, matchp->match->m->u.match_size);
  1052. size += matchp->match->m->u.match_size;
  1053. }
  1054. memcpy(e->elems + size, target, target->u.target_size);
  1055. return e;
  1056. }
  1057. static void command_jump(struct iptables_command_state *cs)
  1058. {
  1059. size_t size;
  1060. set_option(&cs->options, OPT_JUMP, &cs->fw6.ipv6.invflags, cs->invert);
  1061. cs->jumpto = parse_target(optarg);
  1062. /* TRY_LOAD (may be chain name) */
  1063. cs->target = xtables_find_target(cs->jumpto, XTF_TRY_LOAD);
  1064. if (cs->target == NULL)
  1065. return;
  1066. size = XT_ALIGN(sizeof(struct xt_entry_target)) + cs->target->size;
  1067. cs->target->t = xtables_calloc(1, size);
  1068. cs->target->t->u.target_size = size;
  1069. if (cs->target->real_name == NULL) {
  1070. strcpy(cs->target->t->u.user.name, cs->jumpto);
  1071. } else {
  1072. strcpy(cs->target->t->u.user.name, cs->target->real_name);
  1073. if (!(cs->target->ext_flags & XTABLES_EXT_ALIAS))
  1074. fprintf(stderr, "Notice: The %s target is converted into %s target "
  1075. "in rule listing and saving.\n",
  1076. cs->jumpto, cs->target->real_name);
  1077. }
  1078. cs->target->t->u.user.revision = cs->target->revision;
  1079. xs_init_target(cs->target);
  1080. if (cs->target->x6_options != NULL)
  1081. opts = xtables_options_xfrm(ip6tables_globals.orig_opts, opts,
  1082. cs->target->x6_options,
  1083. &cs->target->option_offset);
  1084. else
  1085. opts = xtables_merge_options(ip6tables_globals.orig_opts, opts,
  1086. cs->target->extra_opts,
  1087. &cs->target->option_offset);
  1088. if (opts == NULL)
  1089. xtables_error(OTHER_PROBLEM, "can't alloc memory!");
  1090. }
  1091. static void command_match(struct iptables_command_state *cs)
  1092. {
  1093. struct xtables_match *m;
  1094. size_t size;
  1095. if (cs->invert)
  1096. xtables_error(PARAMETER_PROBLEM,
  1097. "unexpected ! flag before --match");
  1098. m = xtables_find_match(optarg, XTF_LOAD_MUST_SUCCEED, &cs->matches);
  1099. size = XT_ALIGN(sizeof(struct xt_entry_match)) + m->size;
  1100. m->m = xtables_calloc(1, size);
  1101. m->m->u.match_size = size;
  1102. if (m->real_name == NULL) {
  1103. strcpy(m->m->u.user.name, m->name);
  1104. } else {
  1105. strcpy(m->m->u.user.name, m->real_name);
  1106. if (!(m->ext_flags & XTABLES_EXT_ALIAS))
  1107. fprintf(stderr, "Notice: The %s match is converted into %s match "
  1108. "in rule listing and saving.\n", m->name, m->real_name);
  1109. }
  1110. m->m->u.user.revision = m->revision;
  1111. xs_init_match(m);
  1112. if (m == m->next)
  1113. return;
  1114. /* Merge options for non-cloned matches */
  1115. if (m->x6_options != NULL)
  1116. opts = xtables_options_xfrm(ip6tables_globals.orig_opts, opts,
  1117. m->x6_options, &m->option_offset);
  1118. else if (m->extra_opts != NULL)
  1119. opts = xtables_merge_options(ip6tables_globals.orig_opts, opts,
  1120. m->extra_opts, &m->option_offset);
  1121. }
  1122. int do_command6(int argc, char *argv[], char **table, struct xtc_handle **handle)
  1123. {
  1124. struct iptables_command_state cs;
  1125. struct ip6t_entry *e = NULL;
  1126. unsigned int nsaddrs = 0, ndaddrs = 0;
  1127. struct in6_addr *saddrs = NULL, *daddrs = NULL;
  1128. struct in6_addr *smasks = NULL, *dmasks = NULL;
  1129. int verbose = 0;
  1130. const char *chain = NULL;
  1131. const char *shostnetworkmask = NULL, *dhostnetworkmask = NULL;
  1132. const char *policy = NULL, *newname = NULL;
  1133. unsigned int rulenum = 0, command = 0;
  1134. const char *pcnt = NULL, *bcnt = NULL;
  1135. int ret = 1;
  1136. struct xtables_match *m;
  1137. struct xtables_rule_match *matchp;
  1138. struct xtables_target *t;
  1139. unsigned long long cnt;
  1140. memset(&cs, 0, sizeof(cs));
  1141. cs.jumpto = "";
  1142. cs.argv = argv;
  1143. /* re-set optind to 0 in case do_command6 gets called
  1144. * a second time */
  1145. optind = 0;
  1146. /* clear mflags in case do_command6 gets called a second time
  1147. * (we clear the global list of all matches for security)*/
  1148. for (m = xtables_matches; m; m = m->next)
  1149. m->mflags = 0;
  1150. for (t = xtables_targets; t; t = t->next) {
  1151. t->tflags = 0;
  1152. t->used = 0;
  1153. }
  1154. /* Suppress error messages: we may add new options if we
  1155. demand-load a protocol. */
  1156. opterr = 0;
  1157. opts = xt_params->orig_opts;
  1158. while ((cs.c = getopt_long(argc, argv,
  1159. "-:A:C:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:bvnt:m:xc:g:46",
  1160. opts, NULL)) != -1) {
  1161. switch (cs.c) {
  1162. /*
  1163. * Command selection
  1164. */
  1165. case 'A':
  1166. add_command(&command, CMD_APPEND, CMD_NONE,
  1167. cs.invert);
  1168. chain = optarg;
  1169. break;
  1170. case 'C':
  1171. add_command(&command, CMD_CHECK, CMD_NONE,
  1172. cs.invert);
  1173. chain = optarg;
  1174. break;
  1175. case 'D':
  1176. add_command(&command, CMD_DELETE, CMD_NONE,
  1177. cs.invert);
  1178. chain = optarg;
  1179. if (optind < argc && argv[optind][0] != '-'
  1180. && argv[optind][0] != '!') {
  1181. rulenum = parse_rulenumber(argv[optind++]);
  1182. command = CMD_DELETE_NUM;
  1183. }
  1184. break;
  1185. case 'R':
  1186. add_command(&command, CMD_REPLACE, CMD_NONE,
  1187. cs.invert);
  1188. chain = optarg;
  1189. if (optind < argc && argv[optind][0] != '-'
  1190. && argv[optind][0] != '!')
  1191. rulenum = parse_rulenumber(argv[optind++]);
  1192. else
  1193. xtables_error(PARAMETER_PROBLEM,
  1194. "-%c requires a rule number",
  1195. cmd2char(CMD_REPLACE));
  1196. break;
  1197. case 'I':
  1198. add_command(&command, CMD_INSERT, CMD_NONE,
  1199. cs.invert);
  1200. chain = optarg;
  1201. if (optind < argc && argv[optind][0] != '-'
  1202. && argv[optind][0] != '!')
  1203. rulenum = parse_rulenumber(argv[optind++]);
  1204. else rulenum = 1;
  1205. break;
  1206. case 'L':
  1207. add_command(&command, CMD_LIST,
  1208. CMD_ZERO | CMD_ZERO_NUM, cs.invert);
  1209. if (optarg) chain = optarg;
  1210. else if (optind < argc && argv[optind][0] != '-'
  1211. && argv[optind][0] != '!')
  1212. chain = argv[optind++];
  1213. if (optind < argc && argv[optind][0] != '-'
  1214. && argv[optind][0] != '!')
  1215. rulenum = parse_rulenumber(argv[optind++]);
  1216. break;
  1217. case 'S':
  1218. add_command(&command, CMD_LIST_RULES,
  1219. CMD_ZERO | CMD_ZERO_NUM, cs.invert);
  1220. if (optarg) chain = optarg;
  1221. else if (optind < argc && argv[optind][0] != '-'
  1222. && argv[optind][0] != '!')
  1223. chain = argv[optind++];
  1224. if (optind < argc && argv[optind][0] != '-'
  1225. && argv[optind][0] != '!')
  1226. rulenum = parse_rulenumber(argv[optind++]);
  1227. break;
  1228. case 'F':
  1229. add_command(&command, CMD_FLUSH, CMD_NONE,
  1230. cs.invert);
  1231. if (optarg) chain = optarg;
  1232. else if (optind < argc && argv[optind][0] != '-'
  1233. && argv[optind][0] != '!')
  1234. chain = argv[optind++];
  1235. break;
  1236. case 'Z':
  1237. add_command(&command, CMD_ZERO, CMD_LIST|CMD_LIST_RULES,
  1238. cs.invert);
  1239. if (optarg) chain = optarg;
  1240. else if (optind < argc && argv[optind][0] != '-'
  1241. && argv[optind][0] != '!')
  1242. chain = argv[optind++];
  1243. if (optind < argc && argv[optind][0] != '-'
  1244. && argv[optind][0] != '!') {
  1245. rulenum = parse_rulenumber(argv[optind++]);
  1246. command = CMD_ZERO_NUM;
  1247. }
  1248. break;
  1249. case 'N':
  1250. if (optarg && (*optarg == '-' || *optarg == '!'))
  1251. xtables_error(PARAMETER_PROBLEM,
  1252. "chain name not allowed to start "
  1253. "with `%c'\n", *optarg);
  1254. if (xtables_find_target(optarg, XTF_TRY_LOAD))
  1255. xtables_error(PARAMETER_PROBLEM,
  1256. "chain name may not clash "
  1257. "with target name\n");
  1258. add_command(&command, CMD_NEW_CHAIN, CMD_NONE,
  1259. cs.invert);
  1260. chain = optarg;
  1261. break;
  1262. case 'X':
  1263. add_command(&command, CMD_DELETE_CHAIN, CMD_NONE,
  1264. cs.invert);
  1265. if (optarg) chain = optarg;
  1266. else if (optind < argc && argv[optind][0] != '-'
  1267. && argv[optind][0] != '!')
  1268. chain = argv[optind++];
  1269. break;
  1270. case 'E':
  1271. add_command(&command, CMD_RENAME_CHAIN, CMD_NONE,
  1272. cs.invert);
  1273. chain = optarg;
  1274. if (optind < argc && argv[optind][0] != '-'
  1275. && argv[optind][0] != '!')
  1276. newname = argv[optind++];
  1277. else
  1278. xtables_error(PARAMETER_PROBLEM,
  1279. "-%c requires old-chain-name and "
  1280. "new-chain-name",
  1281. cmd2char(CMD_RENAME_CHAIN));
  1282. break;
  1283. case 'P':
  1284. add_command(&command, CMD_SET_POLICY, CMD_NONE,
  1285. cs.invert);
  1286. chain = optarg;
  1287. if (optind < argc && argv[optind][0] != '-'
  1288. && argv[optind][0] != '!')
  1289. policy = argv[optind++];
  1290. else
  1291. xtables_error(PARAMETER_PROBLEM,
  1292. "-%c requires a chain and a policy",
  1293. cmd2char(CMD_SET_POLICY));
  1294. break;
  1295. case 'h':
  1296. if (!optarg)
  1297. optarg = argv[optind];
  1298. /* ip6tables -p icmp -h */
  1299. if (!cs.matches && cs.protocol)
  1300. xtables_find_match(cs.protocol, XTF_TRY_LOAD,
  1301. &cs.matches);
  1302. exit_printhelp(cs.matches);
  1303. /*
  1304. * Option selection
  1305. */
  1306. case 'p':
  1307. set_option(&cs.options, OPT_PROTOCOL, &cs.fw6.ipv6.invflags,
  1308. cs.invert);
  1309. /* Canonicalize into lower case */
  1310. for (cs.protocol = optarg; *cs.protocol; cs.protocol++)
  1311. *cs.protocol = tolower(*cs.protocol);
  1312. cs.protocol = optarg;
  1313. cs.fw6.ipv6.proto = xtables_parse_protocol(cs.protocol);
  1314. cs.fw6.ipv6.flags |= IP6T_F_PROTO;
  1315. if (cs.fw6.ipv6.proto == 0
  1316. && (cs.fw6.ipv6.invflags & XT_INV_PROTO))
  1317. xtables_error(PARAMETER_PROBLEM,
  1318. "rule would never match protocol");
  1319. if (is_exthdr(cs.fw6.ipv6.proto)
  1320. && (cs.fw6.ipv6.invflags & XT_INV_PROTO) == 0)
  1321. fprintf(stderr,
  1322. "Warning: never matched protocol: %s. "
  1323. "use extension match instead.\n",
  1324. cs.protocol);
  1325. break;
  1326. case 's':
  1327. set_option(&cs.options, OPT_SOURCE, &cs.fw6.ipv6.invflags,
  1328. cs.invert);
  1329. shostnetworkmask = optarg;
  1330. break;
  1331. case 'd':
  1332. set_option(&cs.options, OPT_DESTINATION, &cs.fw6.ipv6.invflags,
  1333. cs.invert);
  1334. dhostnetworkmask = optarg;
  1335. break;
  1336. #ifdef IP6T_F_GOTO
  1337. case 'g':
  1338. set_option(&cs.options, OPT_JUMP, &cs.fw6.ipv6.invflags,
  1339. cs.invert);
  1340. cs.fw6.ipv6.flags |= IP6T_F_GOTO;
  1341. cs.jumpto = parse_target(optarg);
  1342. break;
  1343. #endif
  1344. case 'j':
  1345. command_jump(&cs);
  1346. break;
  1347. case 'i':
  1348. if (*optarg == '\0')
  1349. xtables_error(PARAMETER_PROBLEM,
  1350. "Empty interface is likely to be "
  1351. "undesired");
  1352. set_option(&cs.options, OPT_VIANAMEIN, &cs.fw6.ipv6.invflags,
  1353. cs.invert);
  1354. xtables_parse_interface(optarg,
  1355. cs.fw6.ipv6.iniface,
  1356. cs.fw6.ipv6.iniface_mask);
  1357. break;
  1358. case 'o':
  1359. if (*optarg == '\0')
  1360. xtables_error(PARAMETER_PROBLEM,
  1361. "Empty interface is likely to be "
  1362. "undesired");
  1363. set_option(&cs.options, OPT_VIANAMEOUT, &cs.fw6.ipv6.invflags,
  1364. cs.invert);
  1365. xtables_parse_interface(optarg,
  1366. cs.fw6.ipv6.outiface,
  1367. cs.fw6.ipv6.outiface_mask);
  1368. break;
  1369. case 'v':
  1370. if (!verbose)
  1371. set_option(&cs.options, OPT_VERBOSE,
  1372. &cs.fw6.ipv6.invflags, cs.invert);
  1373. verbose++;
  1374. break;
  1375. case 'm':
  1376. command_match(&cs);
  1377. break;
  1378. case 'n':
  1379. set_option(&cs.options, OPT_NUMERIC, &cs.fw6.ipv6.invflags,
  1380. cs.invert);
  1381. break;
  1382. case 't':
  1383. if (cs.invert)
  1384. xtables_error(PARAMETER_PROBLEM,
  1385. "unexpected ! flag before --table");
  1386. *table = optarg;
  1387. break;
  1388. case 'x':
  1389. set_option(&cs.options, OPT_EXPANDED, &cs.fw6.ipv6.invflags,
  1390. cs.invert);
  1391. break;
  1392. case 'V':
  1393. if (cs.invert)
  1394. printf("Not %s ;-)\n", prog_vers);
  1395. else
  1396. printf("%s v%s\n",
  1397. prog_name, prog_vers);
  1398. exit(0);
  1399. case '0':
  1400. set_option(&cs.options, OPT_LINENUMBERS, &cs.fw6.ipv6.invflags,
  1401. cs.invert);
  1402. break;
  1403. case 'M':
  1404. xtables_modprobe_program = optarg;
  1405. break;
  1406. case 'c':
  1407. set_option(&cs.options, OPT_COUNTERS, &cs.fw6.ipv6.invflags,
  1408. cs.invert);
  1409. pcnt = optarg;
  1410. bcnt = strchr(pcnt + 1, ',');
  1411. if (bcnt)
  1412. bcnt++;
  1413. if (!bcnt && optind < argc && argv[optind][0] != '-'
  1414. && argv[optind][0] != '!')
  1415. bcnt = argv[optind++];
  1416. if (!bcnt)
  1417. xtables_error(PARAMETER_PROBLEM,
  1418. "-%c requires packet and byte counter",
  1419. opt2char(OPT_COUNTERS));
  1420. if (sscanf(pcnt, "%llu", &cnt) != 1)
  1421. xtables_error(PARAMETER_PROBLEM,
  1422. "-%c packet counter not numeric",
  1423. opt2char(OPT_COUNTERS));
  1424. cs.fw6.counters.pcnt = cnt;
  1425. if (sscanf(bcnt, "%llu", &cnt) != 1)
  1426. xtables_error(PARAMETER_PROBLEM,
  1427. "-%c byte counter not numeric",
  1428. opt2char(OPT_COUNTERS));
  1429. cs.fw6.counters.bcnt = cnt;
  1430. break;
  1431. case '4':
  1432. /* This is not the IPv4 iptables */
  1433. if (line != -1)
  1434. return 1; /* success: line ignored */
  1435. fprintf(stderr, "This is the IPv6 version of ip6tables.\n");
  1436. exit_tryhelp(2);
  1437. case '6':
  1438. /* This is indeed the IPv6 ip6tables */
  1439. break;
  1440. case 1: /* non option */
  1441. if (optarg[0] == '!' && optarg[1] == '\0') {
  1442. if (cs.invert)
  1443. xtables_error(PARAMETER_PROBLEM,
  1444. "multiple consecutive ! not"
  1445. " allowed");
  1446. cs.invert = TRUE;
  1447. optarg[0] = '\0';
  1448. continue;
  1449. }
  1450. fprintf(stderr, "Bad argument `%s'\n", optarg);
  1451. exit_tryhelp(2);
  1452. default:
  1453. if (command_default(&cs, &ip6tables_globals) == 1)
  1454. /*
  1455. * If new options were loaded, we must retry
  1456. * getopt immediately and not allow
  1457. * cs.invert=FALSE to be executed.
  1458. */
  1459. continue;
  1460. break;
  1461. }
  1462. cs.invert = FALSE;
  1463. }
  1464. for (matchp = cs.matches; matchp; matchp = matchp->next)
  1465. xtables_option_mfcall(matchp->match);
  1466. if (cs.target != NULL)
  1467. xtables_option_tfcall(cs.target);
  1468. /* Fix me: must put inverse options checking here --MN */
  1469. if (optind < argc)
  1470. xtables_error(PARAMETER_PROBLEM,
  1471. "unknown arguments found on commandline");
  1472. if (!command)
  1473. xtables_error(PARAMETER_PROBLEM, "no command specified");
  1474. if (cs.invert)
  1475. xtables_error(PARAMETER_PROBLEM,
  1476. "nothing appropriate following !");
  1477. if (command & (CMD_REPLACE | CMD_INSERT | CMD_DELETE | CMD_APPEND | CMD_CHECK)) {
  1478. if (!(cs.options & OPT_DESTINATION))
  1479. dhostnetworkmask = "::0/0";
  1480. if (!(cs.options & OPT_SOURCE))
  1481. shostnetworkmask = "::0/0";
  1482. }
  1483. if (shostnetworkmask)
  1484. xtables_ip6parse_multiple(shostnetworkmask, &saddrs,
  1485. &smasks, &nsaddrs);
  1486. if (dhostnetworkmask)
  1487. xtables_ip6parse_multiple(dhostnetworkmask, &daddrs,
  1488. &dmasks, &ndaddrs);
  1489. if ((nsaddrs > 1 || ndaddrs > 1) &&
  1490. (cs.fw6.ipv6.invflags & (IP6T_INV_SRCIP | IP6T_INV_DSTIP)))
  1491. xtables_error(PARAMETER_PROBLEM, "! not allowed with multiple"
  1492. " source or destination IP addresses");
  1493. if (command == CMD_REPLACE && (nsaddrs != 1 || ndaddrs != 1))
  1494. xtables_error(PARAMETER_PROBLEM, "Replacement rule does not "
  1495. "specify a unique address");
  1496. generic_opt_check(command, cs.options);
  1497. if (chain != NULL && strlen(chain) >= XT_EXTENSION_MAXNAMELEN)
  1498. xtables_error(PARAMETER_PROBLEM,
  1499. "chain name `%s' too long (must be under %u chars)",
  1500. chain, XT_EXTENSION_MAXNAMELEN);
  1501. /* only allocate handle if we weren't called with a handle */
  1502. if (!*handle)
  1503. *handle = ip6tc_init(*table);
  1504. /* try to insmod the module if iptc_init failed */
  1505. if (!*handle && xtables_load_ko(xtables_modprobe_program, false) != -1)
  1506. *handle = ip6tc_init(*table);
  1507. if (!*handle)
  1508. xtables_error(VERSION_PROBLEM,
  1509. "can't initialize ip6tables table `%s': %s",
  1510. *table, ip6tc_strerror(errno));
  1511. if (command == CMD_APPEND
  1512. || command == CMD_DELETE
  1513. || command == CMD_CHECK
  1514. || command == CMD_INSERT
  1515. || command == CMD_REPLACE) {
  1516. if (strcmp(chain, "PREROUTING") == 0
  1517. || strcmp(chain, "INPUT") == 0) {
  1518. /* -o not valid with incoming packets. */
  1519. if (cs.options & OPT_VIANAMEOUT)
  1520. xtables_error(PARAMETER_PROBLEM,
  1521. "Can't use -%c with %s\n",
  1522. opt2char(OPT_VIANAMEOUT),
  1523. chain);
  1524. }
  1525. if (strcmp(chain, "POSTROUTING") == 0
  1526. || strcmp(chain, "OUTPUT") == 0) {
  1527. /* -i not valid with outgoing packets */
  1528. if (cs.options & OPT_VIANAMEIN)
  1529. xtables_error(PARAMETER_PROBLEM,
  1530. "Can't use -%c with %s\n",
  1531. opt2char(OPT_VIANAMEIN),
  1532. chain);
  1533. }
  1534. if (cs.target && ip6tc_is_chain(cs.jumpto, *handle)) {
  1535. fprintf(stderr,
  1536. "Warning: using chain %s, not extension\n",
  1537. cs.jumpto);
  1538. if (cs.target->t)
  1539. free(cs.target->t);
  1540. cs.target = NULL;
  1541. }
  1542. /* If they didn't specify a target, or it's a chain
  1543. name, use standard. */
  1544. if (!cs.target
  1545. && (strlen(cs.jumpto) == 0
  1546. || ip6tc_is_chain(cs.jumpto, *handle))) {
  1547. size_t size;
  1548. cs.target = xtables_find_target(XT_STANDARD_TARGET,
  1549. XTF_LOAD_MUST_SUCCEED);
  1550. size = sizeof(struct xt_entry_target)
  1551. + cs.target->size;
  1552. cs.target->t = xtables_calloc(1, size);
  1553. cs.target->t->u.target_size = size;
  1554. strcpy(cs.target->t->u.user.name, cs.jumpto);
  1555. xs_init_target(cs.target);
  1556. }
  1557. if (!cs.target) {
  1558. /* it is no chain, and we can't load a plugin.
  1559. * We cannot know if the plugin is corrupt, non
  1560. * existant OR if the user just misspelled a
  1561. * chain. */
  1562. #ifdef IP6T_F_GOTO
  1563. if (cs.fw6.ipv6.flags & IP6T_F_GOTO)
  1564. xtables_error(PARAMETER_PROBLEM,
  1565. "goto '%s' is not a chain\n",
  1566. cs.jumpto);
  1567. #endif
  1568. xtables_find_target(cs.jumpto, XTF_LOAD_MUST_SUCCEED);
  1569. } else {
  1570. e = generate_entry(&cs.fw6, cs.matches, cs.target->t);
  1571. free(cs.target->t);
  1572. }
  1573. }
  1574. switch (command) {
  1575. case CMD_APPEND:
  1576. ret = append_entry(chain, e,
  1577. nsaddrs, saddrs, smasks,
  1578. ndaddrs, daddrs, dmasks,
  1579. cs.options&OPT_VERBOSE,
  1580. *handle);
  1581. break;
  1582. case CMD_DELETE:
  1583. ret = delete_entry(chain, e,
  1584. nsaddrs, saddrs, smasks,
  1585. ndaddrs, daddrs, dmasks,
  1586. cs.options&OPT_VERBOSE,
  1587. *handle, cs.matches, cs.target);
  1588. break;
  1589. case CMD_DELETE_NUM:
  1590. ret = ip6tc_delete_num_entry(chain, rulenum - 1, *handle);
  1591. break;
  1592. case CMD_CHECK:
  1593. ret = check_entry(chain, e,
  1594. nsaddrs, saddrs, smasks,
  1595. ndaddrs, daddrs, dmasks,
  1596. cs.options&OPT_VERBOSE,
  1597. *handle, cs.matches, cs.target);
  1598. break;
  1599. case CMD_REPLACE:
  1600. ret = replace_entry(chain, e, rulenum - 1,
  1601. saddrs, smasks, daddrs, dmasks,
  1602. cs.options&OPT_VERBOSE, *handle);
  1603. break;
  1604. case CMD_INSERT:
  1605. ret = insert_entry(chain, e, rulenum - 1,
  1606. nsaddrs, saddrs, smasks,
  1607. ndaddrs, daddrs, dmasks,
  1608. cs.options&OPT_VERBOSE,
  1609. *handle);
  1610. break;
  1611. case CMD_FLUSH:
  1612. ret = flush_entries6(chain, cs.options&OPT_VERBOSE, *handle);
  1613. break;
  1614. case CMD_ZERO:
  1615. ret = zero_entries(chain, cs.options&OPT_VERBOSE, *handle);
  1616. break;
  1617. case CMD_ZERO_NUM:
  1618. ret = ip6tc_zero_counter(chain, rulenum, *handle);
  1619. break;
  1620. case CMD_LIST:
  1621. case CMD_LIST|CMD_ZERO:
  1622. case CMD_LIST|CMD_ZERO_NUM:
  1623. ret = list_entries(chain,
  1624. rulenum,
  1625. cs.options&OPT_VERBOSE,
  1626. cs.options&OPT_NUMERIC,
  1627. cs.options&OPT_EXPANDED,
  1628. cs.options&OPT_LINENUMBERS,
  1629. *handle);
  1630. if (ret && (command & CMD_ZERO))
  1631. ret = zero_entries(chain,
  1632. cs.options&OPT_VERBOSE, *handle);
  1633. if (ret && (command & CMD_ZERO_NUM))
  1634. ret = ip6tc_zero_counter(chain, rulenum, *handle);
  1635. break;
  1636. case CMD_LIST_RULES:
  1637. case CMD_LIST_RULES|CMD_ZERO:
  1638. case CMD_LIST_RULES|CMD_ZERO_NUM:
  1639. ret = list_rules(chain,
  1640. rulenum,
  1641. cs.options&OPT_VERBOSE,
  1642. *handle);
  1643. if (ret && (command & CMD_ZERO))
  1644. ret = zero_entries(chain,
  1645. cs.options&OPT_VERBOSE, *handle);
  1646. if (ret && (command & CMD_ZERO_NUM))
  1647. ret = ip6tc_zero_counter(chain, rulenum, *handle);
  1648. break;
  1649. case CMD_NEW_CHAIN:
  1650. ret = ip6tc_create_chain(chain, *handle);
  1651. break;
  1652. case CMD_DELETE_CHAIN:
  1653. ret = delete_chain6(chain, cs.options&OPT_VERBOSE, *handle);
  1654. break;
  1655. case CMD_RENAME_CHAIN:
  1656. ret = ip6tc_rename_chain(chain, newname, *handle);
  1657. break;
  1658. case CMD_SET_POLICY:
  1659. ret = ip6tc_set_policy(chain, policy, cs.options&OPT_COUNTERS ? &cs.fw6.counters : NULL, *handle);
  1660. break;
  1661. default:
  1662. /* We should never reach this... */
  1663. exit_tryhelp(2);
  1664. }
  1665. if (verbose > 1)
  1666. dump_entries6(*handle);
  1667. xtables_rule_matches_free(&cs.matches);
  1668. if (e != NULL) {
  1669. free(e);
  1670. e = NULL;
  1671. }
  1672. free(saddrs);
  1673. free(smasks);
  1674. free(daddrs);
  1675. free(dmasks);
  1676. xtables_free_opts(1);
  1677. return ret;
  1678. }