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

mark.c 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  1. /**************************************
  2. * AUTHOR: Federico Tomassini *
  3. * Copyright (C) Federico Tomassini *
  4. * Contact effetom@gmail.com *
  5. ***********************************************
  6. ******* BEGIN 3/2006 ********
  7. *************************************************************************
  8. * *
  9. * This program is free software; you can redistribute it and/or modify *
  10. * it under the terms of the GNU General Public License as published by *
  11. * the Free Software Foundation; either version 2 of the License, or *
  12. * (at your option) any later version. *
  13. * *
  14. * This program is distributed in the hope that it will be useful, *
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  17. * GNU General Public License for more details. *
  18. * *
  19. ************************************************************************/
  20. /*
  21. * This code is written with my blood.
  22. * My hand was hurt. The keyboard was red.
  23. * In this code you can find my sacrifice.
  24. *
  25. * This code is a netfilter iptc library.
  26. * iptc is very bad documented: wisdom and
  27. * debuggers was my friends to understand
  28. * netfilter behavior.
  29. * I hope you'll never need to code netfilter
  30. * apps.
  31. * Memory dumpers are with you.
  32. */
  33. #include "includes.h"
  34. #include "config.h"
  35. // to delete
  36. #include <fcntl.h>
  37. #include "iptunnel.h"
  38. #include "mark.h"
  39. #include "err_errno.h"
  40. #include "log.h"
  41. static int death_loop_rule;
  42. static int clean_on_exit;
  43. static rule_store rr, fr, dr;
  44. static int dumped;
  45. /* Table init: is too easy for comments.
  46. * Returns:
  47. * 0
  48. * -1
  49. */
  50. int
  51. table_init(const char *table, iptc_handle_t * t)
  52. {
  53. *t = iptc_init(table);
  54. error("In table_int, t: %s and errno %d", table, errno);
  55. if (!(*t)) {
  56. error("In table_init, table %s: -> %s", table,
  57. iptc_strerror(errno));
  58. err_ret(ERR_NETFIL, -1);
  59. }
  60. return 0;
  61. }
  62. /*
  63. * insert the rule -rule- on chain -chain-
  64. * at the position pos.
  65. * Returns:
  66. * 0
  67. * -1
  68. */
  69. int
  70. insert_rule(const char *rule, iptc_handle_t * t, const char *chain,
  71. int pos)
  72. {
  73. int res;
  74. res = iptc_insert_entry(chain, (struct ipt_entry *) rule, 0, t);
  75. error
  76. ("res is: %d rule is: %p chain is: %s pos is: %d t is: %p",
  77. res, *rule, chain, pos, t);
  78. if (!res) {
  79. error("In insert_rule: %s.", iptc_strerror(errno));
  80. err_ret(ERR_NETRUL, -1);
  81. }
  82. return 0;
  83. }
  84. /*
  85. * append the rule -rule- on chain -chain-.
  86. * Returns:
  87. * 0
  88. * -1
  89. */
  90. int
  91. append_rule(const char *rule, iptc_handle_t * t, const char *chain)
  92. {
  93. int res;
  94. res = iptc_append_entry(chain, (struct ipt_entry *) rule, t);
  95. error("res is: %d, chain: %s, rule: %s, t: %s, Errno is: %d", res,
  96. chain, rule, t, errno);
  97. if (!res) {
  98. error("In append_rule: %s.", iptc_strerror(errno));
  99. err_ret(ERR_NETRUL, -1);
  100. }
  101. return 0;
  102. }
  103. /*
  104. * commit modified rules and chains.
  105. * Returns:
  106. * 0
  107. * -1
  108. */
  109. int
  110. commit_rules(iptc_handle_t * t)
  111. {
  112. int res;
  113. res = iptc_commit(t);
  114. error
  115. ("This is the value of res: %i This is the value of t is: %p errno is: %d",
  116. res, t, errno);
  117. if (!res) {
  118. error("In commit_rules: %s.", iptc_strerror(errno));
  119. err_ret(ERR_NETCOM, -1);
  120. }
  121. return 0;
  122. }
  123. /*
  124. * Put in -rule- the netfilter rule:
  125. *
  126. * -A OUTPUT -o ntk_tunl+ -m conntrack \
  127. * --ctstate RELATED,ESTABLISHED -j CONNMARK \
  128. * --restore-mark
  129. *
  130. * -rule- has to be RESTORE_OUTPUT_RULE_SZ-sized
  131. */
  132. void
  133. restore_output_rule_init(char *rule)
  134. {
  135. struct ipt_entry *ee;
  136. struct ipt_entry_match *em;
  137. struct ipt_entry_target *et;
  138. struct ipt_conntrack_info *ici;
  139. struct ipt_connmark_target_info *icmi;
  140. memset(rule, 0, RESTORE_OUTPUT_RULE_SZ);
  141. ee = (struct ipt_entry *) (rule);
  142. em = (struct ipt_entry_match *) (rule + OFFSET_MATCH);
  143. ici = (struct ipt_conntrack_info *) (rule + OFFSET_MATCH_INFO);
  144. et = (struct ipt_entry_target *) (rule + OFFSET_TARGET);
  145. icmi = (struct ipt_connmark_target_info *) (rule + OFFSET_TARGET_INFO);
  146. ee->next_offset = RESTORE_OUTPUT_RULE_SZ;
  147. ee->target_offset = OFFSET_TARGET;
  148. snprintf(ee->ip.outiface, IFNAMSIZ, "%s+", NTK_TUNL_PREFIX);
  149. memset(ee->ip.outiface_mask, 0xFF, strlen(ee->ip.outiface) - 1);
  150. strcpy(em->u.user.name, MOD_CONNTRACK);
  151. em->u.match_size = MATCH_SZ;;
  152. em->u.user.match_size = em->u.match_size;
  153. et->u.target_size = TARGET_SZ;
  154. et->u.user.target_size = et->u.target_size;
  155. strcpy(et->u.user.name, MOD_CONNMARK);
  156. ici->flags = 1;
  157. ici->statemask |= IPT_CONNTRACK_STATE_BIT(IP_CT_RELATED);
  158. ici->statemask |= IPT_CONNTRACK_STATE_BIT(IP_CT_ESTABLISHED);
  159. icmi->mode = IPT_CONNMARK_RESTORE;
  160. icmi->mask = 0xffffffffUL;
  161. }
  162. /*
  163. * Put in -rule- the netfilter rule:
  164. *
  165. * -A POSTROUTING -o ntk_tunl+ -m conntrack
  166. * --ctstate NEW -j ntk_mark_chain
  167. *
  168. * -rule- has to be NTK_FORWARD_RULE_SZ-sized
  169. */
  170. void
  171. ntk_forward_rule_init(char *rule)
  172. {
  173. struct ipt_entry *ee;
  174. struct ipt_entry_match *em;
  175. struct ipt_entry_target *et;
  176. struct ipt_conntrack_info *ici;
  177. memset(rule, 0, NTK_FORWARD_RULE_SZ);
  178. ee = (struct ipt_entry *) (rule);
  179. em = (struct ipt_entry_match *) (rule + IPT_ENTRY_SZ);
  180. ici = (struct ipt_conntrack_info *) (rule + OFFSET_MATCH_INFO);
  181. et = (struct ipt_entry_target *) (rule + OFFSET_TARGET);
  182. ee->next_offset = NTK_FORWARD_RULE_SZ;
  183. ee->target_offset = OFFSET_TARGET;
  184. snprintf(ee->ip.outiface, IFNAMSIZ, "%s+", NTK_TUNL_PREFIX);
  185. memset(ee->ip.outiface_mask, 0xFF, strlen(ee->ip.outiface) - 1);
  186. strcpy(em->u.user.name, MOD_CONNTRACK);
  187. em->u.match_size = MATCH_SZ;
  188. em->u.user.match_size = em->u.match_size;
  189. ici->flags = 1;
  190. ici->statemask |= IPT_CONNTRACK_STATE_BIT(IP_CT_NEW);
  191. et->u.target_size = IPT_ENTRY_TARGET_SZ + 4;
  192. et->u.user.target_size = et->u.target_size;
  193. strcpy(et->u.user.name, NTK_MARK_CHAIN);
  194. }
  195. /*
  196. * Put in -rule- the netfilter rule:
  197. *
  198. *
  199. * -A ntk_mark_chain -o ntk_tunl<outiface_num>
  200. * -j CONNMARK --set-mark <outiface_num>
  201. *
  202. * -rule- has to be MARK_RULE_SZ-sized
  203. */
  204. void
  205. mark_rule_init(char *rule, char *outiface, int outiface_num)
  206. {
  207. struct ipt_entry *ee;
  208. struct ipt_entry_target *et;
  209. struct ipt_connmark_target_info *icmi;
  210. memset(rule, 0, MARK_RULE_SZ);
  211. ee = (struct ipt_entry *) (rule);
  212. et = (struct ipt_entry_target *) (rule + IPT_ENTRY_SZ);
  213. icmi =
  214. (struct ipt_connmark_target_info *) (rule + IPT_ENTRY_SZ +
  215. IPT_ENTRY_TARGET_SZ);
  216. ee->next_offset = MARK_RULE_SZ;
  217. ee->target_offset = IPT_ENTRY_SZ;
  218. et->u.target_size = TARGET_SZ;
  219. et->u.user.target_size = et->u.target_size;
  220. strcpy(et->u.user.name, MOD_CONNMARK);
  221. icmi->mode = IPT_CONNMARK_SET;
  222. icmi->mask = 0xffffffffUL;
  223. snprintf(ee->ip.outiface, IFNAMSIZ, "%s%d", outiface, outiface_num);
  224. memset(ee->ip.outiface_mask, 0xFF, strlen(ee->ip.outiface));
  225. icmi->mark = outiface_num + 1;
  226. }
  227. /*
  228. * Put in -rule- the netfilter rule:
  229. *
  230. *
  231. * -A PREROUTING -o ntk_tunl+ \
  232. * -j CONNMARK --set-mark 25
  233. *
  234. * -rule- has to be IGW_FILTER_RULE_SZ-sized
  235. */
  236. void
  237. igw_mark_rule_init(char *rule)
  238. {
  239. int res;
  240. struct ipt_entry *e;
  241. struct ipt_entry_target *et;
  242. memset(rule, 0, IGW_FILTER_RULE_SZ);
  243. e = (struct ipt_entry *) rule;
  244. et = (struct ipt_entry_target *) (rule + IPT_ENTRY_SZ);
  245. e->next_offset = IGW_FILTER_RULE_SZ;
  246. e->target_offset = IPT_ENTRY_SZ;
  247. snprintf(e->ip.iniface, IFNAMSIZ, "%s+", NTK_TUNL_PREFIX);
  248. memset(e->ip.iniface_mask, 0xFF, strlen(e->ip.iniface) - 1);
  249. et->u.target_size = IPT_ENTRY_TARGET_SZ + 4;
  250. et->u.user.target_size = et->u.target_size;
  251. strcpy(et->u.user.name, MARK_TARGET);
  252. res = INET_MARK;
  253. memcpy(et->data, &res, 4);
  254. }
  255. /*
  256. * Build the chain ntk_mark_chain on
  257. * mangle table.
  258. */
  259. int
  260. ntk_mark_chain_init(iptc_handle_t * t)
  261. {
  262. int res;
  263. res = iptc_is_chain(NTK_MARK_CHAIN, *t);
  264. if (res) {
  265. debug(DBG_NORMAL, "In mark_init: bizarre, ntk mangle"
  266. "chain is present yet. it will be flushed.");
  267. res = iptc_flush_entries(NTK_MARK_CHAIN, t);
  268. if (!res)
  269. goto dontwork;
  270. } else {
  271. res = iptc_create_chain(NTK_MARK_CHAIN, t);
  272. if (!res)
  273. goto dontwork;
  274. }
  275. return 0;
  276. dontwork:
  277. error("In ntk_mark_chain_init: -> %s", iptc_strerror(errno));
  278. err_ret(ERR_NETCHA, -1)
  279. }
  280. /*
  281. * Takes committed rules and copies them
  282. * to structs. This is usefule to delete
  283. * the rules on exit, even if netfilter
  284. * was modified before the deletion/
  285. * Returns:
  286. * 0
  287. * -1
  288. */
  289. int
  290. store_rules()
  291. {
  292. int res;
  293. iptc_handle_t t;
  294. struct ipt_entry *r, *f, *d;
  295. res = table_init(MANGLE_TABLE, &t);
  296. if (res) {
  297. error(err_str);
  298. err_ret(ERR_NETSTO, -1);
  299. }
  300. r = (struct ipt_entry *) iptc_first_rule(CHAIN_OUTPUT, &t);
  301. f = (struct ipt_entry *) iptc_first_rule(CHAIN_POSTROUTING, &t);
  302. /* Not elegant style, but faster */
  303. if (death_loop_rule) {
  304. d = (struct ipt_entry *) iptc_first_rule(CHAIN_PREROUTING, &t);
  305. if (r && f && d) {
  306. rr.sz = RESTORE_OUTPUT_RULE_SZ;
  307. memcpy(rr.e, r, rr.sz);
  308. rr.chain = CHAIN_OUTPUT;
  309. fr.sz = NTK_FORWARD_RULE_SZ;
  310. memcpy(fr.e, f, fr.sz);
  311. fr.chain = CHAIN_POSTROUTING;
  312. dr.sz = IGW_FILTER_RULE_SZ;
  313. memcpy(dr.e, d, dr.sz);
  314. dr.chain = CHAIN_PREROUTING;
  315. error("This is store_rules, And the value of t is: %p", t);
  316. commit_rules(&t);
  317. return 0;
  318. } else {
  319. error("This is store_rules else, And the value of t is: %p",
  320. t);
  321. commit_rules(&t);
  322. error("In store_rules: %s.", iptc_strerror(errno));
  323. err_ret(ERR_NETSTO, -1);
  324. }
  325. }
  326. if (r && f) {
  327. rr.sz = RESTORE_OUTPUT_RULE_SZ;
  328. memcpy(rr.e, r, rr.sz);
  329. rr.chain = CHAIN_OUTPUT;
  330. fr.sz = NTK_FORWARD_RULE_SZ;
  331. memcpy(fr.e, f, fr.sz);
  332. fr.chain = CHAIN_POSTROUTING;
  333. commit_rules(&t);
  334. return 0;
  335. }
  336. commit_rules(&t);
  337. err_ret(ERR_NETSTO, -1);
  338. }
  339. /* Two debugging functions: to delete */
  340. int
  341. dump_rules()
  342. {
  343. int fd;
  344. fd = open(DATA_DIR "/mark_rules", O_CREAT | O_WRONLY | O_TRUNC, 0540);
  345. if (fd == -1) {
  346. dumped = 0;
  347. error("Storing rules to fs: %s.", strerror(errno));
  348. return -1;
  349. }
  350. write(fd, &rr, sizeof(rule_store));
  351. write(fd, &fr, sizeof(rule_store));
  352. write(fd, &dr, sizeof(rule_store));
  353. close(fd);
  354. dumped = 1;
  355. return 0;
  356. }
  357. int
  358. load_dump_rules()
  359. {
  360. int fd;
  361. rule_store d_rr, d_fr, d_dr;
  362. if (!dumped)
  363. return 0;
  364. fd = open("/usr/share/netsukuku/mark_rules", O_RDONLY);
  365. if (fd == -1)
  366. return -1;
  367. read(fd, &d_rr, sizeof(rule_store));
  368. read(fd, &d_fr, sizeof(rule_store));
  369. read(fd, &d_dr, sizeof(rule_store));
  370. close(fd);
  371. if (memcmp(&rr, &d_rr, sizeof(rule_store)))
  372. error("Stored rule rr differs from original.");
  373. if (memcmp(&fr, &d_fr, sizeof(rule_store)))
  374. error("Stored rule fr differs from original.");
  375. if (memcmp(&dr, &d_dr, sizeof(rule_store)))
  376. error("Stored rule dr differs from original.");
  377. return 0;
  378. }
  379. /*
  380. * This function builds:
  381. * - OUTPUT rule
  382. * - POSTROUTING rule
  383. * - PREROUTING rule
  384. * - ntk_mark_chain
  385. * and store rules for future deletion.
  386. *
  387. * Returns:
  388. * 0
  389. * -1
  390. *
  391. * If -1, any rule will be committed.
  392. */
  393. int
  394. mark_init(int igw)
  395. {
  396. int res;
  397. iptc_handle_t t;
  398. char rule[MAX_RULE_SZ];
  399. /*res=inet_aton(NTK_NET_STR,&inet_dst);
  400. if (!res) {
  401. error("Can not convert str to addr.");
  402. goto cannot_init;
  403. }
  404. res=inet_aton(NTK_NET_MASK_STR,&inet_dst_mask);
  405. if (!res) {
  406. error("Can not convert str to addr.");
  407. goto cannot_init;
  408. } */
  409. res = table_init(MANGLE_TABLE, &t);
  410. if (res) {
  411. error(err_str);
  412. goto cannot_init;
  413. }
  414. res = ntk_mark_chain_init(&t);
  415. if (res) {
  416. error(err_str);
  417. error("Unable to create netfilter ntk_mark_chain.");
  418. goto cannot_init;
  419. }
  420. restore_output_rule_init(rule);
  421. error("Rule in mark_init: %s", *rule);
  422. res = insert_rule(rule, &t, CHAIN_OUTPUT, 0);
  423. if (res) {
  424. error(err_str);
  425. error("Unable to create netfilter restore-marking rule.");
  426. goto cannot_init;
  427. }
  428. ntk_forward_rule_init(rule);
  429. res = insert_rule(rule, &t, CHAIN_POSTROUTING, 0);
  430. if (res) {
  431. error(err_str);
  432. error("Unable to create netfilter forwarding rule.");
  433. goto cannot_init;
  434. }
  435. if (igw) {
  436. death_loop_rule = 1;
  437. igw_mark_rule_init(rule);
  438. res = insert_rule(rule, &t, CHAIN_PREROUTING, 0);
  439. if (res) {
  440. error(err_str);
  441. error("Unable to create netfilter igw death loop rule.");
  442. death_loop_rule = 0;
  443. goto cannot_init;
  444. }
  445. } else
  446. death_loop_rule = 0;
  447. res = commit_rules(&t);
  448. if (res) {
  449. error(err_str);
  450. error("Netfilter mangle table was not altered!");
  451. goto cannot_init;
  452. }
  453. res = store_rules();
  454. if (res) {
  455. error(err_str);
  456. error
  457. ("Rules storing failed: autocleaning netfilter on exit disable.");
  458. clean_on_exit = 0;
  459. } else
  460. clean_on_exit = 1;
  461. dump_rules();
  462. debug(DBG_NORMAL, "Netfilter chain ntk_mark_chain created (mangle).");
  463. debug(DBG_NORMAL,
  464. "Netfilter restoring rule created (mangle->output).");
  465. debug(DBG_NORMAL,
  466. "Netfilter forwarding rule created (mangle->postrouting).");
  467. if (igw)
  468. debug(DBG_NORMAL, "Netfilter death loop igw rule created.");
  469. debug(DBG_NORMAL, "mark_init(), netfilter mangle table initialized.");
  470. loginfo("Netfilter mangle table modified.");
  471. return 0;
  472. cannot_init:
  473. err_ret(ERR_MRKINI, -1);
  474. }
  475. /*
  476. * Count the number of rules in ntk_mangle_chain.
  477. *
  478. * Returns the number of rules present in
  479. * this chain.
  480. */
  481. int
  482. count_ntk_mark_chain(iptc_handle_t * t)
  483. {
  484. int nchain = 0;
  485. const struct ipt_entry *e;
  486. e = iptc_first_rule(NTK_MARK_CHAIN, t);
  487. while (e) {
  488. nchain++;
  489. e = iptc_next_rule(e, t);
  490. }
  491. return nchain;
  492. }
  493. /*
  494. * This function build the rules:
  495. *
  496. * -A ntk_mark_chain -o ntk_tunl<m>
  497. * -j CONNMARK --set-mark m
  498. *
  499. * If:
  500. *
  501. * s= n-number_of_rules_present
  502. * then:
  503. * if s>0, will be created s rules,
  504. * else:
  505. * nothing.
  506. *
  507. * Returns:
  508. * 0
  509. * -1
  510. */
  511. int
  512. create_mark_rules(int n)
  513. {
  514. int nchain;
  515. int res, i;
  516. char rule[MARK_RULE_SZ];
  517. iptc_handle_t t;
  518. res = table_init(MANGLE_TABLE, &t);
  519. if (res) {
  520. error(err_str);
  521. err_ret(ERR_NETRUL, -1);
  522. }
  523. nchain = count_ntk_mark_chain(&t);
  524. if (nchain == -1) {
  525. error("In create_mark_rules: can not read ntk_mark_chain.");
  526. err_ret(ERR_NETRUL, -1);
  527. }
  528. if (nchain >= n) {
  529. debug(DBG_NORMAL, "In create_mark_rules: rules present yet.");
  530. return 0;
  531. }
  532. for (i = nchain; i < n; i++) {
  533. mark_rule_init(rule, NTK_TUNL_PREFIX, i);
  534. res = append_rule(rule, &t, NTK_MARK_CHAIN);
  535. if (res) {
  536. error(err_str);
  537. err_ret(ERR_NETRUL, -1);
  538. }
  539. }
  540. res = commit_rules(&t);
  541. if (res) {
  542. error(err_str);
  543. err_ret(ERR_NETRUL, -1);
  544. }
  545. debug(DBG_NORMAL, "Created %d marking rules.", n - nchain);
  546. return 0;
  547. }
  548. /*
  549. * Deltion function:
  550. * this delete the chain ntk_mark_chain
  551. * Returns:
  552. * 0
  553. * -1
  554. */
  555. int
  556. delete_ntk_forward_chain(iptc_handle_t * t)
  557. {
  558. int res;
  559. res = iptc_is_chain(NTK_MARK_CHAIN, *t);
  560. if (!res)
  561. return 0;
  562. res = iptc_flush_entries(NTK_MARK_CHAIN, t);
  563. if (!res)
  564. goto cannot_delete;
  565. res = iptc_delete_chain(NTK_MARK_CHAIN, t);
  566. if (!res)
  567. goto cannot_delete;
  568. return 0;
  569. cannot_delete:
  570. error("In delete_ntk_forward_chain: -> %s", iptc_strerror(errno));
  571. err_ret(ERR_NETDEL, -1);
  572. }
  573. /* delete the first rule of a chain.
  574. * Unused.
  575. */
  576. int
  577. delete_first_rule(iptc_handle_t * t, const char *chain)
  578. {
  579. int res;
  580. const struct ipt_entry *e;
  581. e = iptc_first_rule(chain, t);
  582. if (!e)
  583. return 0;
  584. res = iptc_delete_num_entry(chain, 0, t);
  585. if (!res)
  586. goto cannot_delete;
  587. return 0;
  588. cannot_delete:
  589. error("In delete_first_rule: -> %s", iptc_strerror(errno));
  590. err_ret(ERR_NETDEL, -1);
  591. }
  592. /*
  593. * Search for the position of rule -rule.rule-
  594. * on the chain rule.chain
  595. * Returns:
  596. * pos if rule was found
  597. * -1 if rule wasn't found
  598. */
  599. int
  600. rule_position(rule_store * rule, iptc_handle_t * t)
  601. {
  602. const struct ipt_entry *e;
  603. int res, count = -1, found = 0;
  604. e = iptc_first_rule(rule->chain, t);
  605. while (e) {
  606. count++;
  607. res = memcmp(e, rule->e, rule->sz);
  608. if (!res) {
  609. found = 1;
  610. break;
  611. }
  612. e = iptc_next_rule(e, t);
  613. }
  614. return found ? count : -1;
  615. }
  616. /*
  617. * Delete rule -rule.rule- on chain rule.chain.
  618. * Returns
  619. * 0 if deletion is Ok or if nothing
  620. * has to be deleted
  621. * -1 error
  622. */
  623. int
  624. delete_rule(rule_store * rule, iptc_handle_t * t)
  625. {
  626. int pos, res;
  627. pos = rule_position(rule, t);
  628. if (pos == -1) {
  629. debug(DBG_NORMAL, "No rule in %s to be deleted.", rule->chain);
  630. return 0;
  631. }
  632. res = iptc_delete_num_entry(rule->chain, pos, t);
  633. if (!res) {
  634. debug(DBG_NORMAL, "Unable to delete rule in chain %s.",
  635. rule->chain);
  636. err_ret(ERR_NETDEL, -1);
  637. }
  638. return 0;
  639. }
  640. /*
  641. * clean the rules committed by:
  642. * - mark_init
  643. * - create_mark_rules()
  644. * Returns:
  645. * 0
  646. * -1
  647. */
  648. int
  649. mark_close()
  650. {
  651. iptc_handle_t t;
  652. int res;
  653. if (!clean_on_exit) {
  654. debug(DBG_NORMAL, "mark_close: cleaning is not my task.");
  655. return 0;
  656. }
  657. load_dump_rules();
  658. res = table_init(MANGLE_TABLE, &t);
  659. if (res)
  660. goto reset_error;
  661. res = 0;
  662. res += delete_rule(&rr, &t);
  663. res += delete_rule(&fr, &t);
  664. if (death_loop_rule) {
  665. debug(DBG_INSANE,
  666. "In mark_close: I'm an IGW: deleting death loop rule.");
  667. res += delete_rule(&dr, &t);
  668. }
  669. if (res)
  670. goto reset_error;
  671. res = delete_ntk_forward_chain(&t);
  672. if (res)
  673. goto reset_error;
  674. res = commit_rules(&t);
  675. if (res)
  676. goto reset_error;
  677. debug(DBG_NORMAL, "Netfilter completely restored.");
  678. return 0;
  679. reset_error:
  680. error(err_str);
  681. loginfo("Netfilter was not restored. To clean, run:\n"
  682. "\tiptables -t mangle -F\n"
  683. "\tiptables -t mangle -X %s", NTK_MARK_CHAIN);
  684. err_ret(ERR_NETRST, -1);
  685. }