iptables.c 51 KB

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