iptables.c 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939
  1. /*
  2. * firewall3 - 3rd OpenWrt UCI firewall implementation
  3. *
  4. * Copyright (C) 2013 Jo-Philipp Wich <jo@mein.io>
  5. *
  6. * Permission to use, copy, modify, and/or distribute this software for any
  7. * purpose with or without fee is hereby granted, provided that the above
  8. * copyright notice and this permission notice appear in all copies.
  9. *
  10. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. #define _GNU_SOURCE /* RTLD_NEXT */
  19. /* include userspace headers */
  20. #include <dlfcn.h>
  21. #include <unistd.h>
  22. #include <getopt.h>
  23. #include <net/if.h>
  24. #include <netinet/in.h>
  25. #include <sys/utsname.h>
  26. #include <sys/socket.h>
  27. /* prevent indirect inclusion of kernel headers */
  28. #define _LINUX_IF_H
  29. #define _LINUX_IN_H
  30. #define _LINUX_IN6_H
  31. /* prevent libiptc from including kernel headers */
  32. #define _FWCHAINS_KERNEL_HEADERS_H
  33. /* finally include libiptc and xtables */
  34. #include <libiptc/libiptc.h>
  35. #include <libiptc/libip6tc.h>
  36. #include <xtables.h>
  37. #include <setjmp.h>
  38. #include "options.h"
  39. /* xtables interface */
  40. #if (XTABLES_VERSION_CODE >= 10)
  41. # include "xtables-10.h"
  42. #elif (XTABLES_VERSION_CODE == 5)
  43. # include "xtables-5.h"
  44. #else
  45. # error "Unsupported xtables version"
  46. #endif
  47. #include "iptables.h"
  48. #define XT_LOCK_NAME "/var/run/xtables.lock"
  49. static int xt_lock_fd = -1;
  50. struct fw3_ipt_rule {
  51. struct fw3_ipt_handle *h;
  52. union {
  53. struct ipt_entry e;
  54. struct ip6t_entry e6;
  55. };
  56. struct xtables_rule_match *matches;
  57. struct xtables_target *target;
  58. int argc;
  59. char **argv;
  60. uint32_t protocol;
  61. bool protocol_loaded;
  62. };
  63. static struct option base_opts[] = {
  64. { .name = "match", .has_arg = 1, .val = 'm' },
  65. { .name = "jump", .has_arg = 1, .val = 'j' },
  66. { .name = "in-interface", .has_arg = 1, .val = 'i' },
  67. { .name = "out-interface", .has_arg = 1, .val = 'o' },
  68. { .name = "source", .has_arg = 1, .val = 's' },
  69. { .name = "destination", .has_arg = 1, .val = 'd' },
  70. { NULL }
  71. };
  72. static jmp_buf fw3_ipt_error_jmp;
  73. static __attribute__((noreturn))
  74. void fw3_ipt_error_handler(enum xtables_exittype status,
  75. const char *fmt, ...)
  76. {
  77. va_list args;
  78. fprintf(stderr, " ! Exception: ");
  79. va_start(args, fmt);
  80. vfprintf(stderr, fmt, args);
  81. va_end(args);
  82. longjmp(fw3_ipt_error_jmp, status);
  83. }
  84. static struct xtables_globals xtg = {
  85. .option_offset = 0,
  86. .program_version = "4",
  87. .orig_opts = base_opts,
  88. .exit_err = fw3_ipt_error_handler,
  89. #if XTABLES_VERSION_CODE > 10
  90. .compat_rev = xtables_compatible_revision,
  91. #endif
  92. };
  93. static struct xtables_globals xtg6 = {
  94. .option_offset = 0,
  95. .program_version = "6",
  96. .orig_opts = base_opts,
  97. .exit_err = fw3_ipt_error_handler,
  98. #if XTABLES_VERSION_CODE > 10
  99. .compat_rev = xtables_compatible_revision,
  100. #endif
  101. };
  102. static struct {
  103. bool retain;
  104. int mcount, tcount;
  105. struct xtables_match **matches;
  106. struct xtables_target **targets;
  107. void (*register_match)(struct xtables_match *);
  108. void (*register_target)(struct xtables_target *);
  109. } xext;
  110. /* Required by certain extensions like SNAT and DNAT */
  111. int kernel_version = 0;
  112. void
  113. get_kernel_version(void)
  114. {
  115. static struct utsname uts;
  116. int x = 3, y = 0, z = 0;
  117. if (uname(&uts) != -1)
  118. sscanf(uts.release, "%d.%d.%d", &x, &y, &z);
  119. kernel_version = 0x10000 * x + 0x100 * y + z;
  120. }
  121. static void fw3_init_extensions(void)
  122. {
  123. init_extensions();
  124. init_extensions4();
  125. #ifndef DISABLE_IPV6
  126. init_extensions6();
  127. #endif
  128. }
  129. struct fw3_ipt_handle *
  130. fw3_ipt_open(enum fw3_family family, enum fw3_table table)
  131. {
  132. int i;
  133. struct fw3_ipt_handle *h;
  134. h = fw3_alloc(sizeof(*h));
  135. xtables_init();
  136. while (!fw3_lock_path(&xt_lock_fd, XT_LOCK_NAME)) {
  137. warn("Currently busy xtables.lock - wait 1 second");
  138. sleep(1);
  139. }
  140. if (family == FW3_FAMILY_V6)
  141. {
  142. #ifndef DISABLE_IPV6
  143. h->family = FW3_FAMILY_V6;
  144. h->table = table;
  145. h->handle = ip6tc_init(fw3_flag_names[table]);
  146. xtables_set_params(&xtg6);
  147. xtables_set_nfproto(NFPROTO_IPV6);
  148. #endif
  149. }
  150. else
  151. {
  152. h->family = FW3_FAMILY_V4;
  153. h->table = table;
  154. h->handle = iptc_init(fw3_flag_names[table]);
  155. xtables_set_params(&xtg);
  156. xtables_set_nfproto(NFPROTO_IPV4);
  157. }
  158. if (!h->handle)
  159. {
  160. free(h);
  161. fw3_unlock_path(&xt_lock_fd, XT_LOCK_NAME);
  162. return NULL;
  163. }
  164. fw3_xt_reset();
  165. fw3_init_extensions();
  166. if (xext.register_match)
  167. for (i = 0; i < xext.mcount; i++)
  168. xext.register_match(xext.matches[i]);
  169. if (xext.register_target)
  170. for (i = 0; i < xext.tcount; i++)
  171. xext.register_target(xext.targets[i]);
  172. return h;
  173. }
  174. static void
  175. debug(struct fw3_ipt_handle *h, const char *fmt, ...)
  176. {
  177. va_list ap;
  178. printf("%s -t %s ", (h->family == FW3_FAMILY_V6) ? "ip6tables" : "iptables",
  179. fw3_flag_names[h->table]);
  180. va_start(ap, fmt);
  181. vprintf(fmt, ap);
  182. va_end(ap);
  183. }
  184. void
  185. fw3_ipt_set_policy(struct fw3_ipt_handle *h, const char *chain,
  186. enum fw3_flag policy)
  187. {
  188. if (fw3_pr_debug)
  189. debug(h, "-P %s %s\n", chain, fw3_flag_names[policy]);
  190. #ifndef DISABLE_IPV6
  191. if (h->family == FW3_FAMILY_V6)
  192. ip6tc_set_policy(chain, fw3_flag_names[policy], NULL, h->handle);
  193. else
  194. #endif
  195. iptc_set_policy(chain, fw3_flag_names[policy], NULL, h->handle);
  196. }
  197. void
  198. fw3_ipt_flush_chain(struct fw3_ipt_handle *h, const char *chain)
  199. {
  200. if (fw3_pr_debug)
  201. debug(h, "-F %s\n", chain);
  202. #ifndef DISABLE_IPV6
  203. if (h->family == FW3_FAMILY_V6)
  204. ip6tc_flush_entries(chain, h->handle);
  205. else
  206. #endif
  207. iptc_flush_entries(chain, h->handle);
  208. }
  209. static void
  210. delete_rules(struct fw3_ipt_handle *h, const char *target)
  211. {
  212. unsigned int num;
  213. const struct ipt_entry *e;
  214. const char *chain;
  215. const char *t;
  216. bool found;
  217. #ifndef DISABLE_IPV6
  218. if (h->family == FW3_FAMILY_V6)
  219. {
  220. for (chain = ip6tc_first_chain(h->handle);
  221. chain != NULL;
  222. chain = ip6tc_next_chain(h->handle))
  223. {
  224. do {
  225. found = false;
  226. const struct ip6t_entry *e6;
  227. for (num = 0, e6 = ip6tc_first_rule(chain, h->handle);
  228. e6 != NULL;
  229. num++, e6 = ip6tc_next_rule(e6, h->handle))
  230. {
  231. t = ip6tc_get_target(e6, h->handle);
  232. if (*t && !strcmp(t, target))
  233. {
  234. if (fw3_pr_debug)
  235. debug(h, "-D %s %u\n", chain, num + 1);
  236. ip6tc_delete_num_entry(chain, num, h->handle);
  237. found = true;
  238. break;
  239. }
  240. }
  241. } while (found);
  242. }
  243. }
  244. else
  245. #endif
  246. {
  247. for (chain = iptc_first_chain(h->handle);
  248. chain != NULL;
  249. chain = iptc_next_chain(h->handle))
  250. {
  251. do {
  252. found = false;
  253. for (num = 0, e = iptc_first_rule(chain, h->handle);
  254. e != NULL;
  255. num++, e = iptc_next_rule(e, h->handle))
  256. {
  257. t = iptc_get_target(e, h->handle);
  258. if (*t && !strcmp(t, target))
  259. {
  260. if (fw3_pr_debug)
  261. debug(h, "-D %s %u\n", chain, num + 1);
  262. iptc_delete_num_entry(chain, num, h->handle);
  263. found = true;
  264. break;
  265. }
  266. }
  267. } while (found);
  268. }
  269. }
  270. }
  271. static bool
  272. is_referenced(struct fw3_ipt_handle *h, const char *target)
  273. {
  274. const struct ipt_entry *e;
  275. const char *chain;
  276. const char *t;
  277. #ifndef DISABLE_IPV6
  278. if (h->family == FW3_FAMILY_V6)
  279. {
  280. for (chain = ip6tc_first_chain(h->handle);
  281. chain != NULL;
  282. chain = ip6tc_next_chain(h->handle))
  283. {
  284. const struct ip6t_entry *e6;
  285. for (e6 = ip6tc_first_rule(chain, h->handle);
  286. e6 != NULL;
  287. e6 = ip6tc_next_rule(e6, h->handle))
  288. {
  289. t = ip6tc_get_target(e6, h->handle);
  290. if (*t && !strcmp(t, target))
  291. return true;
  292. }
  293. }
  294. }
  295. else
  296. #endif
  297. {
  298. for (chain = iptc_first_chain(h->handle);
  299. chain != NULL;
  300. chain = iptc_next_chain(h->handle))
  301. {
  302. for (e = iptc_first_rule(chain, h->handle);
  303. e != NULL;
  304. e = iptc_next_rule(e, h->handle))
  305. {
  306. t = iptc_get_target(e, h->handle);
  307. if (*t && !strcmp(t, target))
  308. return true;
  309. }
  310. }
  311. }
  312. return false;
  313. }
  314. void
  315. fw3_ipt_delete_chain(struct fw3_ipt_handle *h, bool if_unused,
  316. const char *chain)
  317. {
  318. if (if_unused && is_referenced(h, chain))
  319. return;
  320. delete_rules(h, chain);
  321. if (fw3_pr_debug)
  322. debug(h, "-X %s\n", chain);
  323. #ifndef DISABLE_IPV6
  324. if (h->family == FW3_FAMILY_V6)
  325. ip6tc_delete_chain(chain, h->handle);
  326. else
  327. #endif
  328. iptc_delete_chain(chain, h->handle);
  329. }
  330. static bool
  331. has_rule_tag(const void *base, unsigned int start, unsigned int end)
  332. {
  333. unsigned int i;
  334. const struct xt_entry_match *em;
  335. for (i = start; i < end; i += em->u.match_size)
  336. {
  337. em = base + i;
  338. if (strcmp(em->u.user.name, "comment"))
  339. continue;
  340. if (!memcmp(em->data, "!fw3", 4))
  341. return true;
  342. }
  343. return false;
  344. }
  345. void
  346. fw3_ipt_delete_id_rules(struct fw3_ipt_handle *h, const char *chain)
  347. {
  348. unsigned int num;
  349. const struct ipt_entry *e;
  350. bool found;
  351. #ifndef DISABLE_IPV6
  352. if (h->family == FW3_FAMILY_V6)
  353. {
  354. if (!ip6tc_is_chain(chain, h->handle))
  355. return;
  356. do {
  357. found = false;
  358. const struct ip6t_entry *e6;
  359. for (num = 0, e6 = ip6tc_first_rule(chain, h->handle);
  360. e6 != NULL;
  361. num++, e6 = ip6tc_next_rule(e6, h->handle))
  362. {
  363. if (has_rule_tag(e6, sizeof(*e6), e6->target_offset))
  364. {
  365. if (fw3_pr_debug)
  366. debug(h, "-D %s %u\n", chain, num + 1);
  367. ip6tc_delete_num_entry(chain, num, h->handle);
  368. found = true;
  369. break;
  370. }
  371. }
  372. } while (found);
  373. }
  374. else
  375. #endif
  376. {
  377. if (!iptc_is_chain(chain, h->handle))
  378. return;
  379. do {
  380. found = false;
  381. for (num = 0, e = iptc_first_rule(chain, h->handle);
  382. e != NULL;
  383. num++, e = iptc_next_rule(e, h->handle))
  384. {
  385. if (has_rule_tag(e, sizeof(*e), e->target_offset))
  386. {
  387. if (fw3_pr_debug)
  388. debug(h, "-D %s %u\n", chain, num + 1);
  389. iptc_delete_num_entry(chain, num, h->handle);
  390. found = true;
  391. break;
  392. }
  393. }
  394. } while (found);
  395. }
  396. }
  397. static bool
  398. is_chain(struct fw3_ipt_handle *h, const char *name)
  399. {
  400. #ifndef DISABLE_IPV6
  401. if (h->family == FW3_FAMILY_V6)
  402. return ip6tc_is_chain(name, h->handle);
  403. else
  404. #endif
  405. return iptc_is_chain(name, h->handle);
  406. }
  407. void
  408. fw3_ipt_create_chain(struct fw3_ipt_handle *h, bool ignore_existing,
  409. const char *chain)
  410. {
  411. if (ignore_existing && is_chain(h, chain))
  412. return;
  413. if (fw3_pr_debug)
  414. debug(h, "-N %s\n", chain);
  415. iptc_create_chain(chain, h->handle);
  416. }
  417. void
  418. fw3_ipt_flush(struct fw3_ipt_handle *h)
  419. {
  420. const char *chain;
  421. #ifndef DISABLE_IPV6
  422. if (h->family == FW3_FAMILY_V6)
  423. {
  424. for (chain = ip6tc_first_chain(h->handle);
  425. chain != NULL;
  426. chain = ip6tc_next_chain(h->handle))
  427. {
  428. ip6tc_flush_entries(chain, h->handle);
  429. }
  430. for (chain = ip6tc_first_chain(h->handle);
  431. chain != NULL;
  432. chain = ip6tc_next_chain(h->handle))
  433. {
  434. ip6tc_delete_chain(chain, h->handle);
  435. }
  436. }
  437. else
  438. #endif
  439. {
  440. for (chain = iptc_first_chain(h->handle);
  441. chain != NULL;
  442. chain = iptc_next_chain(h->handle))
  443. {
  444. iptc_flush_entries(chain, h->handle);
  445. }
  446. for (chain = iptc_first_chain(h->handle);
  447. chain != NULL;
  448. chain = iptc_next_chain(h->handle))
  449. {
  450. iptc_delete_chain(chain, h->handle);
  451. }
  452. }
  453. }
  454. static bool
  455. chain_is_empty(struct fw3_ipt_handle *h, const char *chain)
  456. {
  457. #ifndef DISABLE_IPV6
  458. if (h->family == FW3_FAMILY_V6)
  459. return (!ip6tc_builtin(chain, h->handle) &&
  460. !ip6tc_first_rule(chain, h->handle));
  461. #endif
  462. return (!iptc_builtin(chain, h->handle) &&
  463. !iptc_first_rule(chain, h->handle));
  464. }
  465. void
  466. fw3_ipt_gc(struct fw3_ipt_handle *h)
  467. {
  468. const char *chain;
  469. bool found;
  470. #ifndef DISABLE_IPV6
  471. if (h->family == FW3_FAMILY_V6)
  472. {
  473. do {
  474. found = false;
  475. for (chain = ip6tc_first_chain(h->handle);
  476. chain != NULL;
  477. chain = ip6tc_next_chain(h->handle))
  478. {
  479. if (!chain_is_empty(h, chain))
  480. continue;
  481. fw3_ipt_delete_chain(h, false, chain);
  482. found = true;
  483. break;
  484. }
  485. } while(found);
  486. }
  487. else
  488. #endif
  489. {
  490. do {
  491. found = false;
  492. for (chain = iptc_first_chain(h->handle);
  493. chain != NULL;
  494. chain = iptc_next_chain(h->handle))
  495. {
  496. warn("C=%s\n", chain);
  497. if (!chain_is_empty(h, chain))
  498. continue;
  499. warn("D=%s\n", chain);
  500. fw3_ipt_delete_chain(h, false, chain);
  501. found = true;
  502. break;
  503. }
  504. } while (found);
  505. }
  506. }
  507. void
  508. fw3_ipt_commit(struct fw3_ipt_handle *h)
  509. {
  510. int rv;
  511. #ifndef DISABLE_IPV6
  512. if (h->family == FW3_FAMILY_V6)
  513. {
  514. rv = ip6tc_commit(h->handle);
  515. if (!rv)
  516. warn("ip6tc_commit(): %s", ip6tc_strerror(errno));
  517. }
  518. else
  519. #endif
  520. {
  521. rv = iptc_commit(h->handle);
  522. if (!rv)
  523. warn("iptc_commit(): %s", iptc_strerror(errno));
  524. }
  525. }
  526. void
  527. fw3_ipt_close(struct fw3_ipt_handle *h)
  528. {
  529. fw3_unlock_path(&xt_lock_fd, XT_LOCK_NAME);
  530. free(h);
  531. }
  532. struct fw3_ipt_rule *
  533. fw3_ipt_rule_new(struct fw3_ipt_handle *h)
  534. {
  535. struct fw3_ipt_rule *r;
  536. r = fw3_alloc(sizeof(*r));
  537. r->h = h;
  538. r->argv = fw3_alloc(sizeof(char *));
  539. r->argv[r->argc++] = "fw3";
  540. return r;
  541. }
  542. static char *
  543. get_protoname(struct fw3_ipt_rule *r)
  544. {
  545. const struct xtables_pprot *pp;
  546. if (r->protocol)
  547. for (pp = xtables_chain_protos; pp->name; pp++)
  548. if (pp->num == r->protocol)
  549. return (char *)pp->name;
  550. return NULL;
  551. }
  552. static struct xtables_match *
  553. find_match(struct fw3_ipt_rule *r, const char *name)
  554. {
  555. struct xtables_match *m;
  556. xext.retain = true;
  557. m = xtables_find_match(name, XTF_TRY_LOAD, &r->matches);
  558. xext.retain = false;
  559. return m;
  560. }
  561. static void
  562. init_match(struct fw3_ipt_rule *r, struct xtables_match *m, bool no_clone)
  563. {
  564. size_t s;
  565. struct xtables_globals *g;
  566. if (!m)
  567. return;
  568. s = XT_ALIGN(sizeof(struct xt_entry_match)) + m->size;
  569. m->m = fw3_alloc(s);
  570. fw3_xt_set_match_name(m);
  571. m->m->u.user.revision = m->revision;
  572. m->m->u.match_size = s;
  573. /* free previous userspace data */
  574. fw3_xt_free_match_udata(m);
  575. if (m->init)
  576. m->init(m->m);
  577. /* don't merge options if no_clone is set and this match is a clone */
  578. if (no_clone && (m == m->next))
  579. return;
  580. /* merge option table */
  581. g = (r->h->family == FW3_FAMILY_V6) ? &xtg6 : &xtg;
  582. fw3_xt_merge_match_options(g, m);
  583. }
  584. static bool
  585. need_protomatch(struct fw3_ipt_rule *r, const char *pname)
  586. {
  587. struct xtables_match *match;
  588. if (!pname)
  589. return false;
  590. match = xtables_find_match(pname, XTF_DONT_LOAD, NULL);
  591. if (!match)
  592. return true;
  593. /* Free any kind of clone from xtables_find_match */
  594. if (match == match->next)
  595. free(match);
  596. return !r->protocol_loaded;
  597. }
  598. static struct xtables_match *
  599. load_protomatch(struct fw3_ipt_rule *r)
  600. {
  601. const char *pname = get_protoname(r);
  602. if (!need_protomatch(r, pname))
  603. return NULL;
  604. return find_match(r, pname);
  605. }
  606. static struct xtables_target *
  607. find_target(struct fw3_ipt_rule *r, const char *name)
  608. {
  609. struct xtables_target *t;
  610. xext.retain = true;
  611. if (is_chain(r->h, name))
  612. t = xtables_find_target(XT_STANDARD_TARGET, XTF_TRY_LOAD);
  613. else
  614. t = xtables_find_target(name, XTF_TRY_LOAD);
  615. xext.retain = false;
  616. return t;
  617. }
  618. static struct xtables_target *
  619. get_target(struct fw3_ipt_rule *r, const char *name)
  620. {
  621. size_t s;
  622. struct xtables_target *t;
  623. struct xtables_globals *g;
  624. t = find_target(r, name);
  625. if (!t)
  626. return NULL;
  627. s = XT_ALIGN(sizeof(struct xt_entry_target)) + t->size;
  628. t->t = fw3_alloc(s);
  629. fw3_xt_set_target_name(t, name);
  630. t->t->u.user.revision = t->revision;
  631. t->t->u.target_size = s;
  632. /* free previous userspace data */
  633. fw3_xt_free_target_udata(t);
  634. if (t->init)
  635. t->init(t->t);
  636. /* merge option table */
  637. g = (r->h->family == FW3_FAMILY_V6) ? &xtg6 : &xtg;
  638. fw3_xt_merge_target_options(g, t);
  639. r->target = t;
  640. return t;
  641. }
  642. void
  643. fw3_ipt_rule_proto(struct fw3_ipt_rule *r, struct fw3_protocol *proto)
  644. {
  645. uint32_t pr;
  646. if (!proto || proto->any)
  647. return;
  648. pr = proto->protocol;
  649. #ifndef DISABLE_IPV6
  650. if (r->h->family == FW3_FAMILY_V6)
  651. {
  652. if (pr == 1)
  653. pr = 58;
  654. r->e6.ipv6.proto = pr;
  655. r->e6.ipv6.flags |= IP6T_F_PROTO;
  656. if (proto->invert)
  657. r->e6.ipv6.invflags |= XT_INV_PROTO;
  658. }
  659. else
  660. #endif
  661. {
  662. r->e.ip.proto = pr;
  663. if (proto->invert)
  664. r->e.ip.invflags |= XT_INV_PROTO;
  665. }
  666. r->protocol = pr;
  667. }
  668. void
  669. fw3_ipt_rule_in_out(struct fw3_ipt_rule *r,
  670. struct fw3_device *in, struct fw3_device *out)
  671. {
  672. #ifndef DISABLE_IPV6
  673. if (r->h->family == FW3_FAMILY_V6)
  674. {
  675. if (in && !in->any)
  676. {
  677. xtables_parse_interface(in->name, r->e6.ipv6.iniface,
  678. r->e6.ipv6.iniface_mask);
  679. if (in->invert)
  680. r->e6.ipv6.invflags |= IP6T_INV_VIA_IN;
  681. }
  682. if (out && !out->any)
  683. {
  684. xtables_parse_interface(out->name, r->e6.ipv6.outiface,
  685. r->e6.ipv6.outiface_mask);
  686. if (out->invert)
  687. r->e6.ipv6.invflags |= IP6T_INV_VIA_OUT;
  688. }
  689. }
  690. else
  691. #endif
  692. {
  693. if (in && !in->any)
  694. {
  695. xtables_parse_interface(in->name, r->e.ip.iniface,
  696. r->e.ip.iniface_mask);
  697. if (in->invert)
  698. r->e.ip.invflags |= IPT_INV_VIA_IN;
  699. }
  700. if (out && !out->any)
  701. {
  702. xtables_parse_interface(out->name, r->e.ip.outiface,
  703. r->e.ip.outiface_mask);
  704. if (out->invert)
  705. r->e.ip.invflags |= IPT_INV_VIA_OUT;
  706. }
  707. }
  708. }
  709. void
  710. fw3_ipt_rule_src_dest(struct fw3_ipt_rule *r,
  711. struct fw3_address *src, struct fw3_address *dest)
  712. {
  713. if ((src && src->range) || (dest && dest->range))
  714. {
  715. fw3_ipt_rule_addarg(r, false, "-m", "iprange");
  716. }
  717. if (src && src->set)
  718. {
  719. if (src->range)
  720. {
  721. fw3_ipt_rule_addarg(r, src->invert, "--src-range",
  722. fw3_address_to_string(src, false, false));
  723. }
  724. #ifndef DISABLE_IPV6
  725. else if (r->h->family == FW3_FAMILY_V6)
  726. {
  727. r->e6.ipv6.src = src->address.v6;
  728. r->e6.ipv6.smsk = src->mask.v6;
  729. int i;
  730. for (i = 0; i < 4; i++)
  731. r->e6.ipv6.src.s6_addr32[i] &= r->e6.ipv6.smsk.s6_addr32[i];
  732. if (src->invert)
  733. r->e6.ipv6.invflags |= IP6T_INV_SRCIP;
  734. }
  735. #endif
  736. else
  737. {
  738. r->e.ip.src = src->address.v4;
  739. r->e.ip.smsk = src->mask.v4;
  740. r->e.ip.src.s_addr &= r->e.ip.smsk.s_addr;
  741. if (src->invert)
  742. r->e.ip.invflags |= IPT_INV_SRCIP;
  743. }
  744. }
  745. if (dest && dest->set)
  746. {
  747. if (dest->range)
  748. {
  749. fw3_ipt_rule_addarg(r, dest->invert, "--dst-range",
  750. fw3_address_to_string(dest, false, false));
  751. }
  752. #ifndef DISABLE_IPV6
  753. else if (r->h->family == FW3_FAMILY_V6)
  754. {
  755. r->e6.ipv6.dst = dest->address.v6;
  756. r->e6.ipv6.dmsk = dest->mask.v6;
  757. int i;
  758. for (i = 0; i < 4; i++)
  759. r->e6.ipv6.dst.s6_addr32[i] &= r->e6.ipv6.dmsk.s6_addr32[i];
  760. if (dest->invert)
  761. r->e6.ipv6.invflags |= IP6T_INV_DSTIP;
  762. }
  763. #endif
  764. else
  765. {
  766. r->e.ip.dst = dest->address.v4;
  767. r->e.ip.dmsk = dest->mask.v4;
  768. r->e.ip.dst.s_addr &= r->e.ip.dmsk.s_addr;
  769. if (dest->invert)
  770. r->e.ip.invflags |= IPT_INV_DSTIP;
  771. }
  772. }
  773. }
  774. void
  775. fw3_ipt_rule_sport_dport(struct fw3_ipt_rule *r,
  776. struct fw3_port *sp, struct fw3_port *dp)
  777. {
  778. char buf[sizeof("65535:65535")];
  779. if ((!sp || !sp->set) && (!dp || !dp->set))
  780. return;
  781. if (!get_protoname(r))
  782. return;
  783. if (sp && sp->set)
  784. {
  785. if (sp->port_min == sp->port_max)
  786. snprintf(buf, sizeof(buf), "%u", sp->port_min);
  787. else
  788. snprintf(buf, sizeof(buf), "%u:%u", sp->port_min, sp->port_max);
  789. fw3_ipt_rule_addarg(r, sp->invert, "--sport", buf);
  790. }
  791. if (dp && dp->set)
  792. {
  793. if (dp->port_min == dp->port_max)
  794. snprintf(buf, sizeof(buf), "%u", dp->port_min);
  795. else
  796. snprintf(buf, sizeof(buf), "%u:%u", dp->port_min, dp->port_max);
  797. fw3_ipt_rule_addarg(r, dp->invert, "--dport", buf);
  798. }
  799. }
  800. void
  801. fw3_ipt_rule_device(struct fw3_ipt_rule *r, const char *device, bool out)
  802. {
  803. struct fw3_device dev = { .any = false };
  804. if (device) {
  805. snprintf(dev.name, sizeof(dev.name), "%s", device);
  806. fw3_ipt_rule_in_out(r, (out) ? NULL : &dev, (out) ? &dev : NULL);
  807. }
  808. }
  809. void
  810. fw3_ipt_rule_mac(struct fw3_ipt_rule *r, struct fw3_mac *mac)
  811. {
  812. char buf[sizeof("ff:ff:ff:ff:ff:ff")];
  813. uint8_t *addr = mac->mac.ether_addr_octet;
  814. if (!mac)
  815. return;
  816. snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
  817. addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
  818. fw3_ipt_rule_addarg(r, false, "-m", "mac");
  819. fw3_ipt_rule_addarg(r, mac->invert, "--mac-source", buf);
  820. }
  821. void
  822. fw3_ipt_rule_icmptype(struct fw3_ipt_rule *r, struct fw3_icmptype *icmp)
  823. {
  824. char buf[sizeof("255/255")];
  825. if (!icmp)
  826. return;
  827. #ifndef DISABLE_IPV6
  828. if (r->h->family == FW3_FAMILY_V6)
  829. {
  830. if (icmp->code6_min == 0 && icmp->code6_max == 0xFF)
  831. snprintf(buf, sizeof(buf), "%u", icmp->type6);
  832. else
  833. snprintf(buf, sizeof(buf), "%u/%u", icmp->type6, icmp->code6_min);
  834. fw3_ipt_rule_addarg(r, icmp->invert, "--icmpv6-type", buf);
  835. }
  836. else
  837. #endif
  838. {
  839. if (icmp->code_min == 0 && icmp->code_max == 0xFF)
  840. snprintf(buf, sizeof(buf), "%u", icmp->type);
  841. else
  842. snprintf(buf, sizeof(buf), "%u/%u", icmp->type, icmp->code_min);
  843. fw3_ipt_rule_addarg(r, icmp->invert, "--icmp-type", buf);
  844. }
  845. }
  846. void
  847. fw3_ipt_rule_limit(struct fw3_ipt_rule *r, struct fw3_limit *limit)
  848. {
  849. char buf[sizeof("-4294967296/second")];
  850. if (!limit || limit->rate <= 0)
  851. return;
  852. fw3_ipt_rule_addarg(r, false, "-m", "limit");
  853. snprintf(buf, sizeof(buf), "%u/%s", limit->rate, fw3_limit_units[limit->unit]);
  854. fw3_ipt_rule_addarg(r, limit->invert, "--limit", buf);
  855. if (limit->burst > 0)
  856. {
  857. snprintf(buf, sizeof(buf), "%u", limit->burst);
  858. fw3_ipt_rule_addarg(r, limit->invert, "--limit-burst", buf);
  859. }
  860. }
  861. void
  862. fw3_ipt_rule_ipset(struct fw3_ipt_rule *r, struct fw3_setmatch *match)
  863. {
  864. char buf[sizeof("dst,dst,dst")];
  865. char *p = buf;
  866. int i = 0, len;
  867. size_t rem = sizeof(buf);
  868. struct fw3_ipset *set;
  869. struct fw3_ipset_datatype *type;
  870. if (!match || !match->set || !match->ptr)
  871. return;
  872. set = match->ptr;
  873. list_for_each_entry(type, &set->datatypes, list)
  874. {
  875. if (i >= 3)
  876. break;
  877. if (p > buf) {
  878. if (rem <= 1)
  879. break;
  880. *p++ = ',';
  881. *p = 0;
  882. rem--;
  883. }
  884. len = snprintf(p, rem, "%s", match->dir[i] ? match->dir[i] : type->dir);
  885. if (len < 0 || len >= rem)
  886. break;
  887. rem -= len;
  888. p += len;
  889. i++;
  890. }
  891. fw3_ipt_rule_addarg(r, false, "-m", "set");
  892. fw3_ipt_rule_addarg(r, match->invert, "--match-set",
  893. set->external ? set->external : set->name);
  894. fw3_ipt_rule_addarg(r, false, buf, NULL);
  895. }
  896. void
  897. fw3_ipt_rule_helper(struct fw3_ipt_rule *r, struct fw3_cthelpermatch *match)
  898. {
  899. if (!match || !match->set || !match->ptr)
  900. return;
  901. fw3_ipt_rule_addarg(r, false, "-m", "helper");
  902. fw3_ipt_rule_addarg(r, match->invert, "--helper", match->ptr->name);
  903. }
  904. void
  905. fw3_ipt_rule_time(struct fw3_ipt_rule *r, struct fw3_time *time)
  906. {
  907. int i, len;
  908. struct tm empty = { 0 };
  909. char buf[84]; /* sizeof("1,2,3,...,30,31") */
  910. char *p;
  911. bool d1 = memcmp(&time->datestart, &empty, sizeof(empty));
  912. bool d2 = memcmp(&time->datestop, &empty, sizeof(empty));
  913. size_t rem;
  914. if (!d1 && !d2 && !time->timestart && !time->timestop &&
  915. !(time->monthdays & 0xFFFFFFFE) && !(time->weekdays & 0xFE))
  916. {
  917. return;
  918. }
  919. fw3_ipt_rule_addarg(r, false, "-m", "time");
  920. if (!time->utc)
  921. fw3_ipt_rule_addarg(r, false, "--kerneltz", NULL);
  922. if (d1)
  923. {
  924. strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", &time->datestart);
  925. fw3_ipt_rule_addarg(r, false, "--datestart", buf);
  926. }
  927. if (d2)
  928. {
  929. strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", &time->datestop);
  930. fw3_ipt_rule_addarg(r, false, "--datestop", buf);
  931. }
  932. if (time->timestart)
  933. {
  934. snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
  935. time->timestart / 3600,
  936. time->timestart % 3600 / 60,
  937. time->timestart % 60);
  938. fw3_ipt_rule_addarg(r, false, "--timestart", buf);
  939. }
  940. if (time->timestop)
  941. {
  942. snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
  943. time->timestop / 3600,
  944. time->timestop % 3600 / 60,
  945. time->timestop % 60);
  946. fw3_ipt_rule_addarg(r, false, "--timestop", buf);
  947. }
  948. if (time->monthdays & 0xFFFFFFFE)
  949. {
  950. for (i = 1, p = buf, rem = sizeof(buf); i < 32; i++)
  951. {
  952. if (fw3_hasbit(time->monthdays, i))
  953. {
  954. if (p > buf) {
  955. if (rem <= 1)
  956. break;
  957. *p++ = ',';
  958. *p = 0;
  959. rem--;
  960. }
  961. len = snprintf(p, rem, "%u", i);
  962. if (len < 0 || len >= rem)
  963. break;
  964. rem -= len;
  965. p += len;
  966. }
  967. }
  968. fw3_ipt_rule_addarg(r, fw3_hasbit(time->monthdays, 0), "--monthdays", buf);
  969. }
  970. if (time->weekdays & 0xFE)
  971. {
  972. for (i = 1, p = buf, rem = sizeof(buf); i < 8; i++)
  973. {
  974. if (fw3_hasbit(time->weekdays, i))
  975. {
  976. if (p > buf) {
  977. if (rem <= 1)
  978. break;
  979. *p++ = ',';
  980. *p = 0;
  981. rem--;
  982. }
  983. len = snprintf(p, rem, "%u", i);
  984. if (len < 0 || len >= rem)
  985. break;
  986. rem -= len;
  987. p += len;
  988. }
  989. }
  990. fw3_ipt_rule_addarg(r, fw3_hasbit(time->weekdays, 0), "--weekdays", buf);
  991. }
  992. }
  993. void
  994. fw3_ipt_rule_mark(struct fw3_ipt_rule *r, struct fw3_mark *mark)
  995. {
  996. char buf[sizeof("0xFFFFFFFF/0xFFFFFFFF")];
  997. if (!mark || !mark->set)
  998. return;
  999. if (mark->mask < 0xFFFFFFFF)
  1000. snprintf(buf, sizeof(buf), "0x%x/0x%x", mark->mark, mark->mask);
  1001. else
  1002. snprintf(buf, sizeof(buf), "0x%x", mark->mark);
  1003. fw3_ipt_rule_addarg(r, false, "-m", "mark");
  1004. fw3_ipt_rule_addarg(r, mark->invert, "--mark", buf);
  1005. }
  1006. void
  1007. fw3_ipt_rule_dscp(struct fw3_ipt_rule *r, struct fw3_dscp *dscp)
  1008. {
  1009. char buf[sizeof("0xFF")];
  1010. if (!dscp || !dscp->set)
  1011. return;
  1012. snprintf(buf, sizeof(buf), "0x%x", dscp->dscp);
  1013. fw3_ipt_rule_addarg(r, false, "-m", "dscp");
  1014. fw3_ipt_rule_addarg(r, dscp->invert, "--dscp", buf);
  1015. }
  1016. void
  1017. fw3_ipt_rule_comment(struct fw3_ipt_rule *r, const char *fmt, ...)
  1018. {
  1019. va_list ap;
  1020. char buf[256];
  1021. if (!fmt || !*fmt)
  1022. return;
  1023. va_start(ap, fmt);
  1024. vsnprintf(buf, sizeof(buf), fmt, ap);
  1025. va_end(ap);
  1026. fw3_ipt_rule_addarg(r, false, "-m", "comment");
  1027. fw3_ipt_rule_addarg(r, false, "--comment", buf);
  1028. }
  1029. void
  1030. fw3_ipt_rule_extra(struct fw3_ipt_rule *r, const char *extra)
  1031. {
  1032. char *p, **tmp, *s;
  1033. if (!extra || !*extra)
  1034. return;
  1035. s = fw3_strdup(extra);
  1036. for (p = strtok(s, " \t"); p; p = strtok(NULL, " \t"))
  1037. {
  1038. tmp = realloc(r->argv, (r->argc + 1) * sizeof(*r->argv));
  1039. if (!tmp)
  1040. break;
  1041. r->argv = tmp;
  1042. r->argv[r->argc++] = fw3_strdup(p);
  1043. }
  1044. free(s);
  1045. }
  1046. #ifndef DISABLE_IPV6
  1047. static void
  1048. rule_print6(struct ip6t_entry *e)
  1049. {
  1050. char buf1[INET6_ADDRSTRLEN], buf2[INET6_ADDRSTRLEN];
  1051. char *pname;
  1052. if (e->ipv6.flags & IP6T_F_PROTO)
  1053. {
  1054. if (e->ipv6.invflags & XT_INV_PROTO)
  1055. printf(" !");
  1056. pname = get_protoname(container_of(e, struct fw3_ipt_rule, e6));
  1057. if (pname)
  1058. printf(" -p %s", pname);
  1059. else
  1060. printf(" -p %u", e->ipv6.proto);
  1061. }
  1062. if (e->ipv6.iniface[0])
  1063. {
  1064. if (e->ipv6.invflags & IP6T_INV_VIA_IN)
  1065. printf(" !");
  1066. printf(" -i %s", e->ipv6.iniface);
  1067. }
  1068. if (e->ipv6.outiface[0])
  1069. {
  1070. if (e->ipv6.invflags & IP6T_INV_VIA_OUT)
  1071. printf(" !");
  1072. printf(" -o %s", e->ipv6.outiface);
  1073. }
  1074. if (memcmp(&e->ipv6.src, &in6addr_any, sizeof(struct in6_addr)))
  1075. {
  1076. if (e->ipv6.invflags & IP6T_INV_SRCIP)
  1077. printf(" !");
  1078. printf(" -s %s/%s",
  1079. inet_ntop(AF_INET6, &e->ipv6.src, buf1, sizeof(buf1)),
  1080. inet_ntop(AF_INET6, &e->ipv6.smsk, buf2, sizeof(buf2)));
  1081. }
  1082. if (memcmp(&e->ipv6.dst, &in6addr_any, sizeof(struct in6_addr)))
  1083. {
  1084. if (e->ipv6.invflags & IP6T_INV_DSTIP)
  1085. printf(" !");
  1086. printf(" -d %s/%s",
  1087. inet_ntop(AF_INET6, &e->ipv6.dst, buf1, sizeof(buf1)),
  1088. inet_ntop(AF_INET6, &e->ipv6.dmsk, buf2, sizeof(buf2)));
  1089. }
  1090. }
  1091. #endif
  1092. static void
  1093. rule_print4(struct ipt_entry *e)
  1094. {
  1095. struct in_addr in_zero = { 0 };
  1096. char buf1[sizeof("255.255.255.255")], buf2[sizeof("255.255.255.255")];
  1097. char *pname;
  1098. if (e->ip.proto)
  1099. {
  1100. if (e->ip.invflags & XT_INV_PROTO)
  1101. printf(" !");
  1102. pname = get_protoname(container_of(e, struct fw3_ipt_rule, e));
  1103. if (pname)
  1104. printf(" -p %s", pname);
  1105. else
  1106. printf(" -p %u", e->ip.proto);
  1107. }
  1108. if (e->ip.iniface[0])
  1109. {
  1110. if (e->ip.invflags & IPT_INV_VIA_IN)
  1111. printf(" !");
  1112. printf(" -i %s", e->ip.iniface);
  1113. }
  1114. if (e->ip.outiface[0])
  1115. {
  1116. if (e->ip.invflags & IPT_INV_VIA_OUT)
  1117. printf(" !");
  1118. printf(" -o %s", e->ip.outiface);
  1119. }
  1120. if (memcmp(&e->ip.src, &in_zero, sizeof(struct in_addr)))
  1121. {
  1122. if (e->ip.invflags & IPT_INV_SRCIP)
  1123. printf(" !");
  1124. printf(" -s %s/%s",
  1125. inet_ntop(AF_INET, &e->ip.src, buf1, sizeof(buf1)),
  1126. inet_ntop(AF_INET, &e->ip.smsk, buf2, sizeof(buf2)));
  1127. }
  1128. if (memcmp(&e->ip.dst, &in_zero, sizeof(struct in_addr)))
  1129. {
  1130. if (e->ip.invflags & IPT_INV_DSTIP)
  1131. printf(" !");
  1132. printf(" -d %s/%s",
  1133. inet_ntop(AF_INET, &e->ip.dst, buf1, sizeof(buf1)),
  1134. inet_ntop(AF_INET, &e->ip.dmsk, buf2, sizeof(buf2)));
  1135. }
  1136. }
  1137. static void
  1138. rule_print(struct fw3_ipt_rule *r, const char *prefix, const char *chain)
  1139. {
  1140. debug(r->h, "%s %s", prefix, chain);
  1141. #ifndef DISABLE_IPV6
  1142. if (r->h->family == FW3_FAMILY_V6)
  1143. rule_print6(&r->e6);
  1144. else
  1145. #endif
  1146. rule_print4(&r->e);
  1147. fw3_xt_print_matches(&r->e.ip, r->matches);
  1148. fw3_xt_print_target(&r->e.ip, r->target);
  1149. printf("\n");
  1150. }
  1151. static bool
  1152. parse_option(struct fw3_ipt_rule *r, int optc, bool inv)
  1153. {
  1154. struct xtables_rule_match *m;
  1155. struct xtables_match *em;
  1156. /* is a target option */
  1157. if (r->target && fw3_xt_has_target_parse(r->target) &&
  1158. optc >= r->target->option_offset &&
  1159. optc < (r->target->option_offset + 256))
  1160. {
  1161. xtables_option_tpcall(optc, r->argv, inv, r->target, &r->e);
  1162. return false;
  1163. }
  1164. /* try to dispatch argument to one of the match parsers */
  1165. for (m = r->matches; m; m = m->next)
  1166. {
  1167. em = m->match;
  1168. if (m->completed || !fw3_xt_has_match_parse(em))
  1169. continue;
  1170. if (optc < em->option_offset ||
  1171. optc >= (em->option_offset + 256))
  1172. continue;
  1173. xtables_option_mpcall(optc, r->argv, inv, em, &r->e);
  1174. return false;
  1175. }
  1176. /* unhandled option, might belong to a protocol match */
  1177. if ((em = load_protomatch(r)) != NULL)
  1178. {
  1179. init_match(r, em, false);
  1180. r->protocol_loaded = true;
  1181. optind--;
  1182. return true;
  1183. }
  1184. if (optc == ':')
  1185. warn("parse_option(): option '%s' needs argument", r->argv[optind-1]);
  1186. if (optc == '?')
  1187. warn("parse_option(): unknown option '%s'", r->argv[optind-1]);
  1188. return false;
  1189. }
  1190. void
  1191. fw3_ipt_rule_addarg(struct fw3_ipt_rule *r, bool inv,
  1192. const char *k, const char *v)
  1193. {
  1194. int n;
  1195. char **tmp;
  1196. if (!k)
  1197. return;
  1198. n = inv + !!k + !!v;
  1199. tmp = realloc(r->argv, (r->argc + n) * sizeof(*tmp));
  1200. if (!tmp)
  1201. return;
  1202. r->argv = tmp;
  1203. if (inv)
  1204. r->argv[r->argc++] = fw3_strdup("!");
  1205. r->argv[r->argc++] = fw3_strdup(k);
  1206. if (v)
  1207. r->argv[r->argc++] = fw3_strdup(v);
  1208. }
  1209. static unsigned char *
  1210. rule_mask(struct fw3_ipt_rule *r)
  1211. {
  1212. size_t s;
  1213. unsigned char *p, *mask = NULL;
  1214. struct xtables_rule_match *m;
  1215. #define SZ(x) XT_ALIGN(sizeof(struct x))
  1216. #ifndef DISABLE_IPV6
  1217. if (r->h->family == FW3_FAMILY_V6)
  1218. {
  1219. s = SZ(ip6t_entry);
  1220. for (m = r->matches; m; m = m->next)
  1221. s += SZ(ip6t_entry_match) + m->match->size;
  1222. s += SZ(ip6t_entry_target);
  1223. if (r->target)
  1224. s += r->target->size;
  1225. mask = fw3_alloc(s);
  1226. memset(mask, 0xFF, SZ(ip6t_entry));
  1227. p = mask + SZ(ip6t_entry);
  1228. for (m = r->matches; m; m = m->next)
  1229. {
  1230. memset(p, 0xFF, SZ(ip6t_entry_match) + m->match->userspacesize);
  1231. p += SZ(ip6t_entry_match) + m->match->size;
  1232. }
  1233. memset(p, 0xFF, SZ(ip6t_entry_target) + (r->target ? r->target->userspacesize : 0));
  1234. }
  1235. else
  1236. #endif
  1237. {
  1238. s = SZ(ipt_entry);
  1239. for (m = r->matches; m; m = m->next)
  1240. s += SZ(ipt_entry_match) + m->match->size;
  1241. s += SZ(ipt_entry_target);
  1242. if (r->target)
  1243. s += r->target->size;
  1244. mask = fw3_alloc(s);
  1245. memset(mask, 0xFF, SZ(ipt_entry));
  1246. p = mask + SZ(ipt_entry);
  1247. for (m = r->matches; m; m = m->next)
  1248. {
  1249. memset(p, 0xFF, SZ(ipt_entry_match) + m->match->userspacesize);
  1250. p += SZ(ipt_entry_match) + m->match->size;
  1251. }
  1252. memset(p, 0xFF, SZ(ipt_entry_target) + (r->target ? r->target->userspacesize : 0));
  1253. }
  1254. return mask;
  1255. }
  1256. static void *
  1257. rule_build(struct fw3_ipt_rule *r)
  1258. {
  1259. size_t s, target_size = (r->target) ? r->target->t->u.target_size : 0;
  1260. struct xtables_rule_match *m;
  1261. #ifndef DISABLE_IPV6
  1262. if (r->h->family == FW3_FAMILY_V6)
  1263. {
  1264. struct ip6t_entry *e6;
  1265. s = XT_ALIGN(sizeof(struct ip6t_entry));
  1266. for (m = r->matches; m; m = m->next)
  1267. s += m->match->m->u.match_size;
  1268. e6 = fw3_alloc(s + target_size);
  1269. memcpy(e6, &r->e6, sizeof(struct ip6t_entry));
  1270. e6->target_offset = s;
  1271. e6->next_offset = s + target_size;
  1272. s = 0;
  1273. for (m = r->matches; m; m = m->next)
  1274. {
  1275. memcpy(e6->elems + s, m->match->m, m->match->m->u.match_size);
  1276. s += m->match->m->u.match_size;
  1277. }
  1278. if (target_size)
  1279. memcpy(e6->elems + s, r->target->t, target_size);
  1280. return e6;
  1281. }
  1282. else
  1283. #endif
  1284. {
  1285. struct ipt_entry *e;
  1286. s = XT_ALIGN(sizeof(struct ipt_entry));
  1287. for (m = r->matches; m; m = m->next)
  1288. s += m->match->m->u.match_size;
  1289. e = fw3_alloc(s + target_size);
  1290. memcpy(e, &r->e, sizeof(struct ipt_entry));
  1291. e->target_offset = s;
  1292. e->next_offset = s + target_size;
  1293. s = 0;
  1294. for (m = r->matches; m; m = m->next)
  1295. {
  1296. memcpy(e->elems + s, m->match->m, m->match->m->u.match_size);
  1297. s += m->match->m->u.match_size;
  1298. }
  1299. if (target_size)
  1300. memcpy(e->elems + s, r->target->t, target_size);
  1301. return e;
  1302. }
  1303. }
  1304. static void
  1305. set_rule_tag(struct fw3_ipt_rule *r)
  1306. {
  1307. int i;
  1308. char *p, **tmp;
  1309. const char *tag = "!fw3";
  1310. for (i = 0; i < r->argc; i++)
  1311. if (!strcmp(r->argv[i], "--comment") && (i + 1) < r->argc)
  1312. if (asprintf(&p, "%s: %s", tag, r->argv[i + 1]) > 0)
  1313. {
  1314. free(r->argv[i + 1]);
  1315. r->argv[i + 1] = p;
  1316. return;
  1317. }
  1318. tmp = realloc(r->argv, (r->argc + 4) * sizeof(*r->argv));
  1319. if (tmp)
  1320. {
  1321. r->argv = tmp;
  1322. r->argv[r->argc++] = fw3_strdup("-m");
  1323. r->argv[r->argc++] = fw3_strdup("comment");
  1324. r->argv[r->argc++] = fw3_strdup("--comment");
  1325. r->argv[r->argc++] = fw3_strdup(tag);
  1326. }
  1327. }
  1328. void
  1329. __fw3_ipt_rule_append(struct fw3_ipt_rule *r, bool repl, const char *fmt, ...)
  1330. {
  1331. void *rule;
  1332. unsigned char *mask;
  1333. struct xtables_rule_match *m;
  1334. struct xtables_match *em;
  1335. struct xtables_target *et;
  1336. struct xtables_globals *g;
  1337. struct fw3_device dev;
  1338. struct fw3_address addr;
  1339. enum xtables_exittype status;
  1340. int i, optc;
  1341. bool inv = false;
  1342. char buf[32];
  1343. va_list ap;
  1344. va_start(ap, fmt);
  1345. vsnprintf(buf, sizeof(buf) - 1, fmt, ap);
  1346. va_end(ap);
  1347. g = (r->h->family == FW3_FAMILY_V6) ? &xtg6 : &xtg;
  1348. g->opts = g->orig_opts;
  1349. optind = 0;
  1350. opterr = 0;
  1351. status = setjmp(fw3_ipt_error_jmp);
  1352. if (status > 0)
  1353. {
  1354. info(" ! Skipping due to previous exception (code %u)", status);
  1355. goto free;
  1356. }
  1357. set_rule_tag(r);
  1358. while ((optc = getopt_long(r->argc, r->argv, "-:m:j:i:o:s:d:", g->opts,
  1359. NULL)) != -1)
  1360. {
  1361. switch (optc)
  1362. {
  1363. case 'm':
  1364. em = find_match(r, optarg);
  1365. if (!em)
  1366. {
  1367. warn("fw3_ipt_rule_append(): Can't find match '%s'", optarg);
  1368. goto free;
  1369. }
  1370. init_match(r, em, true);
  1371. break;
  1372. case 'j':
  1373. et = get_target(r, optarg);
  1374. if (!et)
  1375. {
  1376. warn("fw3_ipt_rule_append(): Can't find target '%s'", optarg);
  1377. goto free;
  1378. }
  1379. break;
  1380. case 'i':
  1381. case 'o':
  1382. if (!fw3_parse_device(&dev, optarg, false) ||
  1383. dev.any || dev.invert || *dev.network)
  1384. {
  1385. warn("fw3_ipt_rule_append(): Bad argument '%s'", optarg);
  1386. goto free;
  1387. }
  1388. dev.invert = inv;
  1389. fw3_ipt_rule_in_out(r, (optc == 'i') ? &dev : NULL,
  1390. (optc == 'o') ? &dev : NULL);
  1391. break;
  1392. case 's':
  1393. case 'd':
  1394. if (!fw3_parse_address(&addr, optarg, false) ||
  1395. addr.range || addr.invert)
  1396. {
  1397. warn("fw3_ipt_rule_append(): Bad argument '%s'", optarg);
  1398. goto free;
  1399. }
  1400. addr.invert = inv;
  1401. fw3_ipt_rule_src_dest(r, (optc == 's') ? &addr : NULL,
  1402. (optc == 'd') ? &addr : NULL);
  1403. break;
  1404. case 1:
  1405. if ((optarg[0] == '!') && (optarg[1] == '\0'))
  1406. {
  1407. optarg[0] = '\0';
  1408. inv = true;
  1409. continue;
  1410. }
  1411. warn("fw3_ipt_rule_append(): Bad argument '%s'", optarg);
  1412. goto free;
  1413. default:
  1414. if (parse_option(r, optc, inv))
  1415. continue;
  1416. break;
  1417. }
  1418. inv = false;
  1419. }
  1420. for (m = r->matches; m; m = m->next)
  1421. xtables_option_mfcall(m->match);
  1422. if (r->target)
  1423. xtables_option_tfcall(r->target);
  1424. rule = rule_build(r);
  1425. #ifndef DISABLE_IPV6
  1426. if (r->h->family == FW3_FAMILY_V6)
  1427. {
  1428. if (repl)
  1429. {
  1430. mask = rule_mask(r);
  1431. while (ip6tc_delete_entry(buf, rule, mask, r->h->handle))
  1432. if (fw3_pr_debug)
  1433. rule_print(r, "-D", buf);
  1434. free(mask);
  1435. }
  1436. if (fw3_pr_debug)
  1437. rule_print(r, "-A", buf);
  1438. if (!ip6tc_append_entry(buf, rule, r->h->handle))
  1439. warn("ip6tc_append_entry(): %s", ip6tc_strerror(errno));
  1440. }
  1441. else
  1442. #endif
  1443. {
  1444. if (repl)
  1445. {
  1446. mask = rule_mask(r);
  1447. while (iptc_delete_entry(buf, rule, mask, r->h->handle))
  1448. if (fw3_pr_debug)
  1449. rule_print(r, "-D", buf);
  1450. free(mask);
  1451. }
  1452. if (fw3_pr_debug)
  1453. rule_print(r, "-A", buf);
  1454. if (!iptc_append_entry(buf, rule, r->h->handle))
  1455. warn("iptc_append_entry(): %s\n", iptc_strerror(errno));
  1456. }
  1457. free(rule);
  1458. free:
  1459. for (i = 1; i < r->argc; i++)
  1460. free(r->argv[i]);
  1461. free(r->argv);
  1462. xtables_rule_matches_free(&r->matches);
  1463. if (r->target)
  1464. free(r->target->t);
  1465. free(r);
  1466. /* reset all targets and matches */
  1467. for (em = xtables_matches; em; em = em->next)
  1468. em->mflags = 0;
  1469. for (et = xtables_targets; et; et = et->next)
  1470. {
  1471. et->tflags = 0;
  1472. et->used = 0;
  1473. }
  1474. xtables_free_opts(1);
  1475. }
  1476. struct fw3_ipt_rule *
  1477. fw3_ipt_rule_create(struct fw3_ipt_handle *handle, struct fw3_protocol *proto,
  1478. struct fw3_device *in, struct fw3_device *out,
  1479. struct fw3_address *src, struct fw3_address *dest)
  1480. {
  1481. struct fw3_ipt_rule *r;
  1482. r = fw3_ipt_rule_new(handle);
  1483. fw3_ipt_rule_proto(r, proto);
  1484. fw3_ipt_rule_in_out(r, in, out);
  1485. fw3_ipt_rule_src_dest(r, src, dest);
  1486. return r;
  1487. }
  1488. void
  1489. xtables_register_match(struct xtables_match *me)
  1490. {
  1491. int i;
  1492. static struct xtables_match **tmp;
  1493. if (!xext.register_match)
  1494. xext.register_match = dlsym(RTLD_NEXT, "xtables_register_match");
  1495. if (!xext.register_match)
  1496. return;
  1497. xext.register_match(me);
  1498. if (xext.retain)
  1499. {
  1500. for (i = 0; i < xext.mcount; i++)
  1501. if (xext.matches[i] == me)
  1502. return;
  1503. tmp = realloc(xext.matches, sizeof(me) * (xext.mcount + 1));
  1504. if (!tmp)
  1505. return;
  1506. xext.matches = tmp;
  1507. xext.matches[xext.mcount++] = me;
  1508. }
  1509. }
  1510. void
  1511. xtables_register_target(struct xtables_target *me)
  1512. {
  1513. int i;
  1514. static struct xtables_target **tmp;
  1515. if (!xext.register_target)
  1516. xext.register_target = dlsym(RTLD_NEXT, "xtables_register_target");
  1517. if (!xext.register_target)
  1518. return;
  1519. xext.register_target(me);
  1520. if (xext.retain)
  1521. {
  1522. for (i = 0; i < xext.tcount; i++)
  1523. if (xext.targets[i] == me)
  1524. return;
  1525. tmp = realloc(xext.targets, sizeof(me) * (xext.tcount + 1));
  1526. if (!tmp)
  1527. return;
  1528. xext.targets = tmp;
  1529. xext.targets[xext.tcount++] = me;
  1530. }
  1531. }