iptables.c 36 KB

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