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.

libiptc.c 53KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293
  1. /* Library which manipulates firewall rules. Version $Revision: 1.1 $ */
  2. /* Architecture of firewall rules is as follows:
  3. *
  4. * Chains go INPUT, FORWARD, OUTPUT then user chains.
  5. * Each user chain starts with an ERROR node.
  6. * Every chain ends with an unconditional jump: a RETURN for user chains,
  7. * and a POLICY for built-ins.
  8. */
  9. /* (C) 1999 Paul ``Rusty'' Russell - Placed under the GNU GPL (See
  10. * COPYING for details).
  11. * (C) 2000-2004 by the Netfilter Core Team <coreteam@netfilter.org>
  12. *
  13. * 2003-Jun-20: Harald Welte <laforge@netfilter.org>:
  14. * - Reimplementation of chain cache to use offsets instead of entries
  15. * 2003-Jun-23: Harald Welte <laforge@netfilter.org>:
  16. * - performance optimization, sponsored by Astaro AG (http://www.astaro.com/)
  17. * don't rebuild the chain cache after every operation, instead fix it
  18. * up after a ruleset change.
  19. * 2004-Aug-18: Harald Welte <laforge@netfilter.org>:
  20. * - futher performance work: total reimplementation of libiptc.
  21. * - libiptc now has a real internal (linked-list) represntation of the
  22. * ruleset and a parser/compiler from/to this internal representation
  23. * - again sponsored by Astaro AG (http://www.astaro.com/)
  24. */
  25. #include <sys/types.h>
  26. #include <sys/socket.h>
  27. #include <linux/version.h>
  28. #include "linux_list.h"
  29. //#define IPTC_DEBUG2 1
  30. #ifdef IPTC_DEBUG2
  31. #include <fcntl.h>
  32. #define DEBUGP(x, args...) fprintf(stderr, "%s: " x, __FUNCTION__, ## args)
  33. #define DEBUGP_C(x, args...) fprintf(stderr, x, ## args)
  34. #else
  35. #define DEBUGP(x, args...)
  36. #define DEBUGP_C(x, args...)
  37. #endif
  38. #ifndef IPT_LIB_DIR
  39. #define IPT_LIB_DIR "/usr/local/lib/iptables"
  40. #endif
  41. static int sockfd = -1;
  42. static int sockfd_use = 0;
  43. static void *iptc_fn = NULL;
  44. static const char *hooknames[]
  45. = {[HOOK_PRE_ROUTING] "PREROUTING",
  46. [HOOK_LOCAL_IN] "INPUT",
  47. [HOOK_FORWARD] "FORWARD",
  48. [HOOK_LOCAL_OUT] "OUTPUT",
  49. [HOOK_POST_ROUTING] "POSTROUTING",
  50. #ifdef HOOK_DROPPING
  51. [HOOK_DROPPING] "DROPPING"
  52. #endif
  53. };
  54. #if 0
  55. /* Convenience structures */
  56. struct ipt_error_target {
  57. STRUCT_ENTRY_TARGET t;
  58. char error[TABLE_MAXNAMELEN];
  59. };
  60. #endif
  61. struct chain_head;
  62. struct rule_head;
  63. struct counter_map {
  64. enum {
  65. COUNTER_MAP_NOMAP,
  66. COUNTER_MAP_NORMAL_MAP,
  67. COUNTER_MAP_ZEROED,
  68. COUNTER_MAP_SET
  69. } maptype;
  70. unsigned int mappos;
  71. };
  72. enum iptcc_rule_type {
  73. IPTCC_R_STANDARD, /* standard target (ACCEPT, ...) */
  74. IPTCC_R_MODULE, /* extension module (SNAT, ...) */
  75. IPTCC_R_FALLTHROUGH, /* fallthrough rule */
  76. IPTCC_R_JUMP, /* jump to other chain */
  77. };
  78. struct rule_head {
  79. struct list_head list;
  80. struct chain_head *chain;
  81. struct counter_map counter_map;
  82. unsigned int index; /* index (needed for counter_map) */
  83. unsigned int offset; /* offset in rule blob */
  84. enum iptcc_rule_type type;
  85. struct chain_head *jump; /* jump target, if IPTCC_R_JUMP */
  86. unsigned int size; /* size of entry data */
  87. STRUCT_ENTRY entry[0];
  88. };
  89. struct chain_head {
  90. struct list_head list;
  91. char name[TABLE_MAXNAMELEN];
  92. unsigned int hooknum; /* hook number+1 if builtin */
  93. unsigned int references; /* how many jumps reference us */
  94. int verdict; /* verdict if builtin */
  95. STRUCT_COUNTERS counters; /* per-chain counters */
  96. struct counter_map counter_map;
  97. unsigned int num_rules; /* number of rules in list */
  98. struct list_head rules; /* list of rules */
  99. unsigned int index; /* index (needed for jump resolval) */
  100. unsigned int head_offset; /* offset in rule blob */
  101. unsigned int foot_index; /* index (needed for counter_map) */
  102. unsigned int foot_offset; /* offset in rule blob */
  103. };
  104. STRUCT_TC_HANDLE {
  105. int changed; /* Have changes been made? */
  106. struct list_head chains;
  107. struct chain_head *chain_iterator_cur;
  108. struct rule_head *rule_iterator_cur;
  109. STRUCT_GETINFO info;
  110. STRUCT_GET_ENTRIES *entries;
  111. };
  112. /* allocate a new chain head for the cache */
  113. static struct chain_head *
  114. iptcc_alloc_chain_head(const char *name, int hooknum)
  115. {
  116. struct chain_head *c = malloc(sizeof(*c));
  117. if (!c)
  118. return NULL;
  119. memset(c, 0, sizeof(*c));
  120. strncpy(c->name, name, TABLE_MAXNAMELEN);
  121. c->hooknum = hooknum;
  122. INIT_LIST_HEAD(&c->rules);
  123. return c;
  124. }
  125. /* allocate and initialize a new rule for the cache */
  126. static struct rule_head *
  127. iptcc_alloc_rule(struct chain_head *c, unsigned int size)
  128. {
  129. struct rule_head *r = malloc(sizeof(*r) + size);
  130. if (!r)
  131. return NULL;
  132. memset(r, 0, sizeof(*r));
  133. r->chain = c;
  134. r->size = size;
  135. return r;
  136. }
  137. /* notify us that the ruleset has been modified by the user */
  138. static void
  139. set_changed(TC_HANDLE_T h)
  140. {
  141. h->changed = 1;
  142. }
  143. #ifdef IPTC_DEBUG
  144. static void do_check(TC_HANDLE_T h, unsigned int line);
  145. #define CHECK(h) do { if (!getenv("IPTC_NO_CHECK")) do_check((h), __LINE__); } while(0)
  146. #else
  147. #define CHECK(h)
  148. #endif
  149. /**********************************************************************
  150. * iptc blob utility functions (iptcb_*)
  151. **********************************************************************/
  152. static inline int
  153. iptcb_get_number(const STRUCT_ENTRY * i,
  154. const STRUCT_ENTRY * seek, unsigned int *pos)
  155. {
  156. if (i == seek)
  157. return 1;
  158. (*pos)++;
  159. return 0;
  160. }
  161. static inline int
  162. iptcb_get_entry_n(STRUCT_ENTRY * i,
  163. unsigned int number,
  164. unsigned int *pos, STRUCT_ENTRY ** pe)
  165. {
  166. if (*pos == number) {
  167. *pe = i;
  168. return 1;
  169. }
  170. (*pos)++;
  171. return 0;
  172. }
  173. static inline STRUCT_ENTRY *
  174. iptcb_get_entry(TC_HANDLE_T h, unsigned int offset)
  175. {
  176. return (STRUCT_ENTRY *) ((char *) h->entries->entrytable + offset);
  177. }
  178. static unsigned int
  179. iptcb_entry2index(const TC_HANDLE_T h, const STRUCT_ENTRY * seek)
  180. {
  181. unsigned int pos = 0;
  182. if (ENTRY_ITERATE(h->entries->entrytable, h->entries->size,
  183. iptcb_get_number, seek, &pos) == 0) {
  184. fprintf(stderr, "ERROR: offset %u not an entry!\n",
  185. (unsigned int) ((char *) seek -
  186. (char *) h->entries->entrytable));
  187. abort();
  188. }
  189. return pos;
  190. }
  191. static inline STRUCT_ENTRY *
  192. iptcb_offset2entry(TC_HANDLE_T h, unsigned int offset)
  193. {
  194. return (STRUCT_ENTRY *) ((void *) h->entries->entrytable + offset);
  195. }
  196. static inline unsigned long
  197. iptcb_entry2offset(const TC_HANDLE_T h, const STRUCT_ENTRY * e)
  198. {
  199. return (void *) e - (void *) h->entries->entrytable;
  200. }
  201. static inline unsigned int
  202. iptcb_offset2index(const TC_HANDLE_T h, unsigned int offset)
  203. {
  204. return iptcb_entry2index(h, iptcb_offset2entry(h, offset));
  205. }
  206. /* Returns 0 if not hook entry, else hooknumber + 1 */
  207. static inline unsigned int
  208. iptcb_ent_is_hook_entry(STRUCT_ENTRY * e, TC_HANDLE_T h)
  209. {
  210. unsigned int i;
  211. for (i = 0; i < NUMHOOKS; i++) {
  212. if ((h->info.valid_hooks & (1 << i))
  213. && iptcb_get_entry(h, h->info.hook_entry[i]) == e)
  214. return i + 1;
  215. }
  216. return 0;
  217. }
  218. /**********************************************************************
  219. * iptc cache utility functions (iptcc_*)
  220. **********************************************************************/
  221. /* Is the given chain builtin (1) or user-defined (0) */
  222. static unsigned int
  223. iptcc_is_builtin(struct chain_head *c)
  224. {
  225. return (c->hooknum ? 1 : 0);
  226. }
  227. /* Get a specific rule within a chain */
  228. static struct rule_head *
  229. iptcc_get_rule_num(struct chain_head *c, unsigned int rulenum)
  230. {
  231. struct rule_head *r;
  232. unsigned int num = 0;
  233. list_for_each_entry(r, &c->rules, list) {
  234. num++;
  235. if (num == rulenum)
  236. return r;
  237. }
  238. return NULL;
  239. }
  240. /* Get a specific rule within a chain backwards */
  241. static struct rule_head *
  242. iptcc_get_rule_num_reverse(struct chain_head *c, unsigned int rulenum)
  243. {
  244. struct rule_head *r;
  245. unsigned int num = 0;
  246. list_for_each_entry_reverse(r, &c->rules, list) {
  247. num++;
  248. if (num == rulenum)
  249. return r;
  250. }
  251. return NULL;
  252. }
  253. /* Returns chain head if found, otherwise NULL. */
  254. static struct chain_head *
  255. iptcc_find_chain_by_offset(TC_HANDLE_T handle, unsigned int offset)
  256. {
  257. struct list_head *pos;
  258. if (list_empty(&handle->chains))
  259. return NULL;
  260. list_for_each(pos, &handle->chains) {
  261. struct chain_head *c = list_entry(pos, struct chain_head, list);
  262. if (offset >= c->head_offset && offset <= c->foot_offset)
  263. return c;
  264. }
  265. return NULL;
  266. }
  267. /* Returns chain head if found, otherwise NULL. */
  268. static struct chain_head *
  269. iptcc_find_label(const char *name, TC_HANDLE_T handle)
  270. {
  271. struct list_head *pos;
  272. if (list_empty(&handle->chains))
  273. return NULL;
  274. list_for_each(pos, &handle->chains) {
  275. struct chain_head *c = list_entry(pos, struct chain_head, list);
  276. if (!strcmp(c->name, name))
  277. return c;
  278. }
  279. return NULL;
  280. }
  281. /* called when rule is to be removed from cache */
  282. static void
  283. iptcc_delete_rule(struct rule_head *r)
  284. {
  285. DEBUGP("deleting rule %p (offset %u)\n", r, r->offset);
  286. /* clean up reference count of called chain */
  287. if (r->type == IPTCC_R_JUMP && r->jump)
  288. r->jump->references--;
  289. list_del(&r->list);
  290. free(r);
  291. }
  292. /**********************************************************************
  293. * RULESET PARSER (blob -> cache)
  294. **********************************************************************/
  295. /* Delete policy rule of previous chain, since cache doesn't contain
  296. * chain policy rules.
  297. * WARNING: This function has ugly design and relies on a lot of context, only
  298. * to be called from specific places within the parser */
  299. static int
  300. __iptcc_p_del_policy(TC_HANDLE_T h, unsigned int num)
  301. {
  302. if (h->chain_iterator_cur) {
  303. /* policy rule is last rule */
  304. struct rule_head *pr = (struct rule_head *)
  305. h->chain_iterator_cur->rules.prev;
  306. /* save verdict */
  307. h->chain_iterator_cur->verdict =
  308. *(int *) GET_TARGET(pr->entry)->data;
  309. /* save counter and counter_map information */
  310. h->chain_iterator_cur->counter_map.maptype =
  311. COUNTER_MAP_NORMAL_MAP;
  312. h->chain_iterator_cur->counter_map.mappos = num - 1;
  313. memcpy(&h->chain_iterator_cur->counters, &pr->entry->counters,
  314. sizeof(h->chain_iterator_cur->counters));
  315. /* foot_offset points to verdict rule */
  316. h->chain_iterator_cur->foot_index = num;
  317. h->chain_iterator_cur->foot_offset = pr->offset;
  318. /* delete rule from cache */
  319. iptcc_delete_rule(pr);
  320. h->chain_iterator_cur->num_rules--;
  321. return 1;
  322. }
  323. return 0;
  324. }
  325. /* alphabetically insert a chain into the list */
  326. static inline void
  327. iptc_insert_chain(TC_HANDLE_T h, struct chain_head *c)
  328. {
  329. struct chain_head *tmp;
  330. /* sort only user defined chains */
  331. if (!c->hooknum) {
  332. list_for_each_entry(tmp, &h->chains, list) {
  333. if (!tmp->hooknum && strcmp(c->name, tmp->name) <= 0) {
  334. list_add(&c->list, tmp->list.prev);
  335. return;
  336. }
  337. }
  338. }
  339. /* survived till end of list: add at tail */
  340. list_add_tail(&c->list, &h->chains);
  341. }
  342. /* Another ugly helper function split out of cache_add_entry to make it less
  343. * spaghetti code */
  344. static void
  345. __iptcc_p_add_chain(TC_HANDLE_T h, struct chain_head *c,
  346. unsigned int offset, unsigned int *num)
  347. {
  348. __iptcc_p_del_policy(h, *num);
  349. c->head_offset = offset;
  350. c->index = *num;
  351. iptc_insert_chain(h, c);
  352. h->chain_iterator_cur = c;
  353. }
  354. /* main parser function: add an entry from the blob to the cache */
  355. static int
  356. cache_add_entry(STRUCT_ENTRY * e,
  357. TC_HANDLE_T h, STRUCT_ENTRY ** prev, unsigned int *num)
  358. {
  359. unsigned int builtin;
  360. unsigned int offset = (char *) e - (char *) h->entries->entrytable;
  361. DEBUGP("entering...");
  362. /* Last entry ("policy rule"). End it. */
  363. if (iptcb_entry2offset(h, e) + e->next_offset == h->entries->size) {
  364. /* This is the ERROR node at the end of the chain */
  365. DEBUGP_C("%u:%u: end of table:\n", *num, offset);
  366. __iptcc_p_del_policy(h, *num);
  367. h->chain_iterator_cur = NULL;
  368. goto out_inc;
  369. }
  370. /* We know this is the start of a new chain if it's an ERROR
  371. * target, or a hook entry point */
  372. if (strcmp(GET_TARGET(e)->u.user.name, ERROR_TARGET) == 0) {
  373. struct chain_head *c =
  374. iptcc_alloc_chain_head((const char *) GET_TARGET(e)->data, 0);
  375. DEBUGP_C("%u:%u:new userdefined chain %s: %p\n", *num, offset,
  376. (char *) c->name, c);
  377. if (!c) {
  378. errno = -ENOMEM;
  379. return -1;
  380. }
  381. __iptcc_p_add_chain(h, c, offset, num);
  382. } else if ((builtin = iptcb_ent_is_hook_entry(e, h)) != 0) {
  383. struct chain_head *c =
  384. iptcc_alloc_chain_head((char *) hooknames[builtin - 1],
  385. builtin);
  386. DEBUGP_C("%u:%u new builtin chain: %p (rules=%p)\n",
  387. *num, offset, c, &c->rules);
  388. if (!c) {
  389. errno = -ENOMEM;
  390. return -1;
  391. }
  392. c->hooknum = builtin;
  393. __iptcc_p_add_chain(h, c, offset, num);
  394. /* FIXME: this is ugly. */
  395. goto new_rule;
  396. } else {
  397. /* has to be normal rule */
  398. struct rule_head *r;
  399. new_rule:
  400. if (!(r = iptcc_alloc_rule(h->chain_iterator_cur, e->next_offset))) {
  401. errno = ENOMEM;
  402. return -1;
  403. }
  404. DEBUGP_C("%u:%u normal rule: %p: ", *num, offset, r);
  405. r->index = *num;
  406. r->offset = offset;
  407. memcpy(r->entry, e, e->next_offset);
  408. r->counter_map.maptype = COUNTER_MAP_NORMAL_MAP;
  409. r->counter_map.mappos = r->index;
  410. /* handling of jumps, etc. */
  411. if (!strcmp(GET_TARGET(e)->u.user.name, STANDARD_TARGET)) {
  412. STRUCT_STANDARD_TARGET *t;
  413. t = (STRUCT_STANDARD_TARGET *) GET_TARGET(e);
  414. if (t->target.u.target_size
  415. != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) {
  416. free(r);
  417. errno = EINVAL;
  418. return -1;
  419. }
  420. if (t->verdict < 0) {
  421. DEBUGP_C("standard, verdict=%d\n", t->verdict);
  422. r->type = IPTCC_R_STANDARD;
  423. } else if (t->verdict == r->offset + e->next_offset) {
  424. DEBUGP_C("fallthrough\n");
  425. r->type = IPTCC_R_FALLTHROUGH;
  426. } else {
  427. DEBUGP_C("jump, target=%u\n", t->verdict);
  428. r->type = IPTCC_R_JUMP;
  429. /* Jump target fixup has to be deferred
  430. * until second pass, since we migh not
  431. * yet have parsed the target */
  432. }
  433. } else {
  434. DEBUGP_C("module, target=%s\n", GET_TARGET(e)->u.user.name);
  435. r->type = IPTCC_R_MODULE;
  436. }
  437. list_add_tail(&r->list, &h->chain_iterator_cur->rules);
  438. h->chain_iterator_cur->num_rules++;
  439. }
  440. out_inc:
  441. (*num)++;
  442. return 0;
  443. }
  444. /* parse an iptables blob into it's pieces */
  445. static int
  446. parse_table(TC_HANDLE_T h)
  447. {
  448. STRUCT_ENTRY *prev;
  449. unsigned int num = 0;
  450. struct chain_head *c;
  451. /* First pass: over ruleset blob */
  452. ENTRY_ITERATE(h->entries->entrytable, h->entries->size,
  453. cache_add_entry, h, &prev, &num);
  454. /* Second pass: fixup parsed data from first pass */
  455. list_for_each_entry(c, &h->chains, list) {
  456. struct rule_head *r;
  457. list_for_each_entry(r, &c->rules, list) {
  458. struct chain_head *c;
  459. STRUCT_STANDARD_TARGET *t;
  460. if (r->type != IPTCC_R_JUMP)
  461. continue;
  462. t = (STRUCT_STANDARD_TARGET *) GET_TARGET(r->entry);
  463. c = iptcc_find_chain_by_offset(h, t->verdict);
  464. if (!c)
  465. return -1;
  466. r->jump = c;
  467. c->references++;
  468. }
  469. }
  470. /* FIXME: sort chains */
  471. return 1;
  472. }
  473. /**********************************************************************
  474. * RULESET COMPILATION (cache -> blob)
  475. **********************************************************************/
  476. /* Convenience structures */
  477. struct iptcb_chain_start {
  478. STRUCT_ENTRY e;
  479. struct ipt_error_target name;
  480. };
  481. #define IPTCB_CHAIN_START_SIZE (sizeof(STRUCT_ENTRY) + \
  482. ALIGN(sizeof(struct ipt_error_target)))
  483. struct iptcb_chain_foot {
  484. STRUCT_ENTRY e;
  485. STRUCT_STANDARD_TARGET target;
  486. };
  487. #define IPTCB_CHAIN_FOOT_SIZE (sizeof(STRUCT_ENTRY) + \
  488. ALIGN(sizeof(STRUCT_STANDARD_TARGET)))
  489. struct iptcb_chain_error {
  490. STRUCT_ENTRY entry;
  491. struct ipt_error_target target;
  492. };
  493. #define IPTCB_CHAIN_ERROR_SIZE (sizeof(STRUCT_ENTRY) + \
  494. ALIGN(sizeof(struct ipt_error_target)))
  495. /* compile rule from cache into blob */
  496. static inline int
  497. iptcc_compile_rule(TC_HANDLE_T h, STRUCT_REPLACE * repl,
  498. struct rule_head *r)
  499. {
  500. /* handle jumps */
  501. if (r->type == IPTCC_R_JUMP) {
  502. STRUCT_STANDARD_TARGET *t;
  503. t = (STRUCT_STANDARD_TARGET *) GET_TARGET(r->entry);
  504. /* memset for memcmp convenience on delete/replace */
  505. memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN);
  506. strcpy(t->target.u.user.name, STANDARD_TARGET);
  507. /* Jumps can only happen to builtin chains, so we
  508. * can safely assume that they always have a header */
  509. t->verdict = r->jump->head_offset + IPTCB_CHAIN_START_SIZE;
  510. } else if (r->type == IPTCC_R_FALLTHROUGH) {
  511. STRUCT_STANDARD_TARGET *t;
  512. t = (STRUCT_STANDARD_TARGET *) GET_TARGET(r->entry);
  513. t->verdict = r->offset + r->size;
  514. }
  515. /* copy entry from cache to blob */
  516. memcpy((char *) repl->entries + r->offset, r->entry, r->size);
  517. return 1;
  518. }
  519. /* compile chain from cache into blob */
  520. static int
  521. iptcc_compile_chain(TC_HANDLE_T h, STRUCT_REPLACE * repl,
  522. struct chain_head *c)
  523. {
  524. int ret;
  525. struct rule_head *r;
  526. struct iptcb_chain_start *head;
  527. struct iptcb_chain_foot *foot;
  528. #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 7, 0)
  529. /* only user-defined chains have heaer */
  530. if (!iptcc_is_builtin(c)) {
  531. /* put chain header in place */
  532. head = (void *) repl->entries + c->head_offset;
  533. head->e.target_offset = sizeof(STRUCT_ENTRY);
  534. head->e.next_offset = IPTCB_CHAIN_START_SIZE;
  535. strcpy(head->name.t.u.user.name, ERROR_TARGET);
  536. head->name.t.u.target_size =
  537. ALIGN(sizeof(struct ipt_error_target));
  538. strcpy(head->name.error, c->name);
  539. } else {
  540. repl->hook_entry[c->hooknum - 1] = c->head_offset;
  541. repl->underflow[c->hooknum - 1] = c->foot_offset;
  542. }
  543. #endif
  544. #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
  545. /* only user-defined chains have heaer */
  546. if (!iptcc_is_builtin(c)) {
  547. /* put chain header in place */
  548. head = (void *) repl->entries + c->head_offset;
  549. head->e.target_offset = sizeof(STRUCT_ENTRY);
  550. head->e.next_offset = IPTCB_CHAIN_START_SIZE;
  551. strcpy(head->name.target.u.user.name, ERROR_TARGET);
  552. head->name.target.u.target_size =
  553. ALIGN(sizeof(struct ipt_error_target));
  554. strcpy(head->name.errorname, c->name);
  555. } else {
  556. repl->hook_entry[c->hooknum - 1] = c->head_offset;
  557. repl->underflow[c->hooknum - 1] = c->foot_offset;
  558. }
  559. #endif
  560. /* iterate over rules */
  561. list_for_each_entry(r, &c->rules, list) {
  562. ret = iptcc_compile_rule(h, repl, r);
  563. if (ret < 0)
  564. return ret;
  565. }
  566. /* put chain footer in place */
  567. foot = (void *) repl->entries + c->foot_offset;
  568. foot->e.target_offset = sizeof(STRUCT_ENTRY);
  569. foot->e.next_offset = IPTCB_CHAIN_FOOT_SIZE;
  570. strcpy(foot->target.target.u.user.name, STANDARD_TARGET);
  571. foot->target.target.u.target_size =
  572. ALIGN(sizeof(STRUCT_STANDARD_TARGET));
  573. /* builtin targets have verdict, others return */
  574. if (iptcc_is_builtin(c))
  575. foot->target.verdict = c->verdict;
  576. else
  577. foot->target.verdict = RETURN;
  578. /* set policy-counters */
  579. memcpy(&foot->e.counters, &c->counters, sizeof(STRUCT_COUNTERS));
  580. return 0;
  581. }
  582. /* calculate offset and number for every rule in the cache */
  583. static int
  584. iptcc_compile_chain_offsets(TC_HANDLE_T h, struct chain_head *c,
  585. unsigned int *offset, unsigned int *num)
  586. {
  587. struct rule_head *r;
  588. c->head_offset = *offset;
  589. DEBUGP("%s: chain_head %u, offset=%u\n", c->name, *num, *offset);
  590. if (!iptcc_is_builtin(c)) {
  591. /* Chain has header */
  592. *offset += sizeof(STRUCT_ENTRY)
  593. + ALIGN(sizeof(struct ipt_error_target));
  594. (*num)++;
  595. }
  596. list_for_each_entry(r, &c->rules, list) {
  597. DEBUGP("rule %u, offset=%u, index=%u\n", *num, *offset, *num);
  598. r->offset = *offset;
  599. r->index = *num;
  600. *offset += r->size;
  601. (*num)++;
  602. }
  603. DEBUGP("%s; chain_foot %u, offset=%u, index=%u\n", c->name, *num,
  604. *offset, *num);
  605. c->foot_offset = *offset;
  606. c->foot_index = *num;
  607. *offset += sizeof(STRUCT_ENTRY)
  608. + ALIGN(sizeof(STRUCT_STANDARD_TARGET));
  609. (*num)++;
  610. return 1;
  611. }
  612. /* put the pieces back together again */
  613. static int
  614. iptcc_compile_table_prep(TC_HANDLE_T h, unsigned int *size)
  615. {
  616. struct chain_head *c;
  617. unsigned int offset = 0, num = 0;
  618. int ret = 0;
  619. /* First pass: calculate offset for every rule */
  620. list_for_each_entry(c, &h->chains, list) {
  621. ret = iptcc_compile_chain_offsets(h, c, &offset, &num);
  622. if (ret < 0)
  623. return ret;
  624. }
  625. /* Append one error rule at end of chain */
  626. num++;
  627. offset += sizeof(STRUCT_ENTRY)
  628. + ALIGN(sizeof(struct ipt_error_target));
  629. /* ruleset size is now in offset */
  630. *size = offset;
  631. return num;
  632. }
  633. static int
  634. iptcc_compile_table(TC_HANDLE_T h, STRUCT_REPLACE * repl)
  635. {
  636. struct chain_head *c;
  637. struct iptcb_chain_error *error;
  638. /* Second pass: copy from cache to offsets, fill in jumps */
  639. list_for_each_entry(c, &h->chains, list) {
  640. int ret = iptcc_compile_chain(h, repl, c);
  641. if (ret < 0)
  642. return ret;
  643. }
  644. #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 7, 0)
  645. /* Append error rule at end of chain */
  646. error = (void *) repl->entries + repl->size - IPTCB_CHAIN_ERROR_SIZE;
  647. error->entry.target_offset = sizeof(STRUCT_ENTRY);
  648. error->entry.next_offset = IPTCB_CHAIN_ERROR_SIZE;
  649. error->target.t.u.user.target_size =
  650. ALIGN(sizeof(struct ipt_error_target));
  651. strcpy((char *) &error->target.t.u.user.name, ERROR_TARGET);
  652. strcpy((char *) &error->target.error, "ERROR");
  653. #endif
  654. #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
  655. /* Append error rule at end of chain */
  656. error = (void *) repl->entries + repl->size - IPTCB_CHAIN_ERROR_SIZE;
  657. error->entry.target_offset = sizeof(STRUCT_ENTRY);
  658. error->entry.next_offset = IPTCB_CHAIN_ERROR_SIZE;
  659. error->target.target.u.user.target_size =
  660. ALIGN(sizeof(struct ipt_error_target));
  661. strcpy((char *) &error->target.target.u.user.name, ERROR_TARGET);
  662. strcpy((char *) &error->target.errorname, "ERROR");
  663. #endif
  664. return 1;
  665. }
  666. /**********************************************************************
  667. * EXTERNAL API (operates on cache only)
  668. **********************************************************************/
  669. /* Allocate handle of given size */
  670. static TC_HANDLE_T
  671. alloc_handle(const char *tablename, unsigned int size,
  672. unsigned int num_rules)
  673. {
  674. TC_HANDLE_T h;
  675. h = malloc(sizeof(STRUCT_TC_HANDLE));
  676. if (!h) {
  677. errno = ENOMEM;
  678. return NULL;
  679. }
  680. memset(h, 0, sizeof(*h));
  681. INIT_LIST_HEAD(&h->chains);
  682. strcpy(h->info.name, tablename);
  683. h->entries = malloc(sizeof(STRUCT_GET_ENTRIES) + size);
  684. if (!h->entries)
  685. goto out_free_handle;
  686. strcpy(h->entries->name, tablename);
  687. h->entries->size = size;
  688. return h;
  689. out_free_handle:
  690. free(h);
  691. return NULL;
  692. }
  693. TC_HANDLE_T
  694. TC_INIT(const char *tablename)
  695. {
  696. TC_HANDLE_T h;
  697. STRUCT_GETINFO info;
  698. unsigned int tmp;
  699. socklen_t s;
  700. iptc_fn = TC_INIT;
  701. if (strlen(tablename) >= TABLE_MAXNAMELEN) {
  702. errno = EINVAL;
  703. return NULL;
  704. }
  705. if (sockfd_use == 0) {
  706. sockfd = socket(TC_AF, SOCK_RAW, IPPROTO_RAW);
  707. if (sockfd < 0)
  708. return NULL;
  709. }
  710. sockfd_use++;
  711. s = sizeof(info);
  712. strcpy(info.name, tablename);
  713. if (getsockopt(sockfd, TC_IPPROTO, SO_GET_INFO, &info, &s) < 0) {
  714. if (--sockfd_use == 0) {
  715. close(sockfd);
  716. sockfd = -1;
  717. }
  718. return NULL;
  719. }
  720. DEBUGP("valid_hooks=0x%08x, num_entries=%u, size=%u\n",
  721. info.valid_hooks, info.num_entries, info.size);
  722. if ((h = alloc_handle(info.name, info.size, info.num_entries))
  723. == NULL) {
  724. if (--sockfd_use == 0) {
  725. close(sockfd);
  726. sockfd = -1;
  727. }
  728. return NULL;
  729. }
  730. /* Initialize current state */
  731. h->info = info;
  732. h->entries->size = h->info.size;
  733. tmp = sizeof(STRUCT_GET_ENTRIES) + h->info.size;
  734. if (getsockopt(sockfd, TC_IPPROTO, SO_GET_ENTRIES, h->entries,
  735. &tmp) < 0)
  736. goto error;
  737. #ifdef IPTC_DEBUG2
  738. {
  739. int fd = open("/tmp/libiptc-so_get_entries.blob",
  740. O_CREAT | O_WRONLY);
  741. if (fd >= 0) {
  742. write(fd, h->entries, tmp);
  743. close(fd);
  744. }
  745. }
  746. #endif
  747. if (parse_table(h) < 0)
  748. goto error;
  749. CHECK(h);
  750. return h;
  751. error:
  752. if (--sockfd_use == 0) {
  753. close(sockfd);
  754. sockfd = -1;
  755. }
  756. TC_FREE(&h);
  757. return NULL;
  758. }
  759. void
  760. TC_FREE(TC_HANDLE_T * h)
  761. {
  762. struct chain_head *c, *tmp;
  763. iptc_fn = TC_FREE;
  764. if (--sockfd_use == 0) {
  765. close(sockfd);
  766. sockfd = -1;
  767. }
  768. list_for_each_entry_safe(c, tmp, &(*h)->chains, list) {
  769. struct rule_head *r, *rtmp;
  770. list_for_each_entry_safe(r, rtmp, &c->rules, list) {
  771. free(r);
  772. }
  773. free(c);
  774. }
  775. free((*h)->entries);
  776. free(*h);
  777. *h = NULL;
  778. }
  779. static inline int
  780. print_match(const STRUCT_ENTRY_MATCH * m)
  781. {
  782. printf("Match name: `%s'\n", m->u.user.name);
  783. return 0;
  784. }
  785. /*static int dump_entry(STRUCT_ENTRY *e, const TC_HANDLE_T handle);*/
  786. void
  787. TC_DUMP_ENTRIES(const TC_HANDLE_T handle)
  788. {
  789. iptc_fn = TC_DUMP_ENTRIES;
  790. CHECK(handle);
  791. #if 0
  792. printf("libiptc v%s. %u bytes.\n",
  793. IPTABLES_VERSION, handle->entries->size);
  794. printf("Table `%s'\n", handle->info.name);
  795. printf("Hooks: pre/in/fwd/out/post = %u/%u/%u/%u/%u\n",
  796. handle->info.hook_entry[HOOK_PRE_ROUTING],
  797. handle->info.hook_entry[HOOK_LOCAL_IN],
  798. handle->info.hook_entry[HOOK_FORWARD],
  799. handle->info.hook_entry[HOOK_LOCAL_OUT],
  800. handle->info.hook_entry[HOOK_POST_ROUTING]);
  801. printf("Underflows: pre/in/fwd/out/post = %u/%u/%u/%u/%u\n",
  802. handle->info.underflow[HOOK_PRE_ROUTING],
  803. handle->info.underflow[HOOK_LOCAL_IN],
  804. handle->info.underflow[HOOK_FORWARD],
  805. handle->info.underflow[HOOK_LOCAL_OUT],
  806. handle->info.underflow[HOOK_POST_ROUTING]);
  807. ENTRY_ITERATE(handle->entries->entrytable, handle->entries->size,
  808. dump_entry, handle);
  809. #endif
  810. }
  811. /* Does this chain exist? */
  812. int
  813. TC_IS_CHAIN(const char *chain, const TC_HANDLE_T handle)
  814. {
  815. iptc_fn = TC_IS_CHAIN;
  816. return iptcc_find_label(chain, handle) != NULL;
  817. }
  818. static void
  819. iptcc_chain_iterator_advance(TC_HANDLE_T handle)
  820. {
  821. struct chain_head *c = handle->chain_iterator_cur;
  822. if (c->list.next == &handle->chains)
  823. handle->chain_iterator_cur = NULL;
  824. else
  825. handle->chain_iterator_cur =
  826. list_entry(c->list.next, struct chain_head, list);
  827. }
  828. /* Iterator functions to run through the chains. */
  829. const char *
  830. TC_FIRST_CHAIN(TC_HANDLE_T * handle)
  831. {
  832. struct chain_head *c = list_entry((*handle)->chains.next,
  833. struct chain_head, list);
  834. iptc_fn = TC_FIRST_CHAIN;
  835. if (list_empty(&(*handle)->chains)) {
  836. DEBUGP(": no chains\n");
  837. return NULL;
  838. }
  839. (*handle)->chain_iterator_cur = c;
  840. iptcc_chain_iterator_advance(*handle);
  841. DEBUGP(": returning `%s'\n", c->name);
  842. return c->name;
  843. }
  844. /* Iterator functions to run through the chains. Returns NULL at end. */
  845. const char *
  846. TC_NEXT_CHAIN(TC_HANDLE_T * handle)
  847. {
  848. struct chain_head *c = (*handle)->chain_iterator_cur;
  849. iptc_fn = TC_NEXT_CHAIN;
  850. if (!c) {
  851. DEBUGP(": no more chains\n");
  852. return NULL;
  853. }
  854. iptcc_chain_iterator_advance(*handle);
  855. DEBUGP(": returning `%s'\n", c->name);
  856. return c->name;
  857. }
  858. /* Get first rule in the given chain: NULL for empty chain. */
  859. const STRUCT_ENTRY *
  860. TC_FIRST_RULE(const char *chain, TC_HANDLE_T * handle)
  861. {
  862. struct chain_head *c;
  863. struct rule_head *r;
  864. iptc_fn = TC_FIRST_RULE;
  865. DEBUGP("first rule(%s): ", chain);
  866. c = iptcc_find_label(chain, *handle);
  867. if (!c) {
  868. errno = ENOENT;
  869. return NULL;
  870. }
  871. /* Empty chain: single return/policy rule */
  872. if (list_empty(&c->rules)) {
  873. DEBUGP_C("no rules, returning NULL\n");
  874. return NULL;
  875. }
  876. r = list_entry(c->rules.next, struct rule_head, list);
  877. (*handle)->rule_iterator_cur = r;
  878. DEBUGP_C("%p\n", r);
  879. return r->entry;
  880. }
  881. /* Returns NULL when rules run out. */
  882. const STRUCT_ENTRY *
  883. TC_NEXT_RULE(const STRUCT_ENTRY * prev, TC_HANDLE_T * handle)
  884. {
  885. struct rule_head *r;
  886. iptc_fn = TC_NEXT_RULE;
  887. DEBUGP("rule_iterator_cur=%p...", (*handle)->rule_iterator_cur);
  888. if (!(*handle)->rule_iterator_cur) {
  889. DEBUGP_C("returning NULL\n");
  890. return NULL;
  891. }
  892. r = list_entry((*handle)->rule_iterator_cur->list.next,
  893. struct rule_head, list);
  894. iptc_fn = TC_NEXT_RULE;
  895. DEBUGP_C("next=%p, head=%p...", &r->list,
  896. &(*handle)->rule_iterator_cur->chain->rules);
  897. if (&r->list == &(*handle)->rule_iterator_cur->chain->rules) {
  898. (*handle)->rule_iterator_cur = NULL;
  899. DEBUGP_C("finished, returning NULL\n");
  900. return NULL;
  901. }
  902. (*handle)->rule_iterator_cur = r;
  903. /* NOTE: prev is without any influence ! */
  904. DEBUGP_C("returning rule %p\n", r);
  905. return r->entry;
  906. }
  907. /* How many rules in this chain? */
  908. unsigned int
  909. TC_NUM_RULES(const char *chain, TC_HANDLE_T * handle)
  910. {
  911. struct chain_head *c;
  912. iptc_fn = TC_NUM_RULES;
  913. CHECK(*handle);
  914. c = iptcc_find_label(chain, *handle);
  915. if (!c) {
  916. errno = ENOENT;
  917. return (unsigned int) -1;
  918. }
  919. return c->num_rules;
  920. }
  921. const STRUCT_ENTRY *
  922. TC_GET_RULE(const char *chain, unsigned int n, TC_HANDLE_T * handle)
  923. {
  924. struct chain_head *c;
  925. struct rule_head *r;
  926. iptc_fn = TC_GET_RULE;
  927. CHECK(*handle);
  928. c = iptcc_find_label(chain, *handle);
  929. if (!c) {
  930. errno = ENOENT;
  931. return NULL;
  932. }
  933. r = iptcc_get_rule_num(c, n);
  934. if (!r)
  935. return NULL;
  936. return r->entry;
  937. }
  938. /* Returns a pointer to the target name of this position. */
  939. const char *
  940. standard_target_map(int verdict)
  941. {
  942. switch (verdict) {
  943. case RETURN:
  944. return LABEL_RETURN;
  945. break;
  946. case -NF_ACCEPT - 1:
  947. return LABEL_ACCEPT;
  948. break;
  949. case -NF_DROP - 1:
  950. return LABEL_DROP;
  951. break;
  952. case -NF_QUEUE - 1:
  953. return LABEL_QUEUE;
  954. break;
  955. default:
  956. fprintf(stderr, "ERROR: %d not a valid target)\n", verdict);
  957. abort();
  958. break;
  959. }
  960. /* not reached */
  961. return NULL;
  962. }
  963. /* Returns a pointer to the target name of this position. */
  964. const char *
  965. TC_GET_TARGET(const STRUCT_ENTRY * ce, TC_HANDLE_T * handle)
  966. {
  967. STRUCT_ENTRY *e = (STRUCT_ENTRY *) ce;
  968. struct rule_head *r = container_of(e, struct rule_head, entry[0]);
  969. iptc_fn = TC_GET_TARGET;
  970. switch (r->type) {
  971. int spos;
  972. case IPTCC_R_FALLTHROUGH:
  973. return "";
  974. break;
  975. case IPTCC_R_JUMP:
  976. DEBUGP("r=%p, jump=%p, name=`%s'\n", r, r->jump, r->jump->name);
  977. return r->jump->name;
  978. break;
  979. case IPTCC_R_STANDARD:
  980. spos = *(int *) GET_TARGET(e)->data;
  981. DEBUGP("r=%p, spos=%d'\n", r, spos);
  982. return standard_target_map(spos);
  983. break;
  984. case IPTCC_R_MODULE:
  985. return GET_TARGET(e)->u.user.name;
  986. break;
  987. }
  988. return NULL;
  989. }
  990. /* Is this a built-in chain? Actually returns hook + 1. */
  991. int
  992. TC_BUILTIN(const char *chain, const TC_HANDLE_T handle)
  993. {
  994. struct chain_head *c;
  995. iptc_fn = TC_BUILTIN;
  996. c = iptcc_find_label(chain, handle);
  997. if (!c) {
  998. errno = ENOENT;
  999. return 0;
  1000. }
  1001. return iptcc_is_builtin(c);
  1002. }
  1003. /* Get the policy of a given built-in chain */
  1004. const char *
  1005. TC_GET_POLICY(const char *chain,
  1006. STRUCT_COUNTERS * counters, TC_HANDLE_T * handle)
  1007. {
  1008. struct chain_head *c;
  1009. iptc_fn = TC_GET_POLICY;
  1010. DEBUGP("called for chain %s\n", chain);
  1011. c = iptcc_find_label(chain, *handle);
  1012. if (!c) {
  1013. errno = ENOENT;
  1014. return NULL;
  1015. }
  1016. if (!iptcc_is_builtin(c))
  1017. return NULL;
  1018. *counters = c->counters;
  1019. return standard_target_map(c->verdict);
  1020. }
  1021. static int
  1022. iptcc_standard_map(struct rule_head *r, int verdict)
  1023. {
  1024. STRUCT_ENTRY *e = r->entry;
  1025. STRUCT_STANDARD_TARGET *t;
  1026. t = (STRUCT_STANDARD_TARGET *) GET_TARGET(e);
  1027. if (t->target.u.target_size != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) {
  1028. errno = EINVAL;
  1029. return 0;
  1030. }
  1031. /* memset for memcmp convenience on delete/replace */
  1032. memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN);
  1033. strcpy(t->target.u.user.name, STANDARD_TARGET);
  1034. t->verdict = verdict;
  1035. r->type = IPTCC_R_STANDARD;
  1036. return 1;
  1037. }
  1038. static int
  1039. iptcc_map_target(const TC_HANDLE_T handle, struct rule_head *r)
  1040. {
  1041. STRUCT_ENTRY *e = r->entry;
  1042. STRUCT_ENTRY_TARGET *t = GET_TARGET(e);
  1043. /* Maybe it's empty (=> fall through) */
  1044. if (strcmp(t->u.user.name, "") == 0) {
  1045. r->type = IPTCC_R_FALLTHROUGH;
  1046. return 1;
  1047. }
  1048. /* Maybe it's a standard target name... */
  1049. else if (strcmp(t->u.user.name, LABEL_ACCEPT) == 0)
  1050. return iptcc_standard_map(r, -NF_ACCEPT - 1);
  1051. else if (strcmp(t->u.user.name, LABEL_DROP) == 0)
  1052. return iptcc_standard_map(r, -NF_DROP - 1);
  1053. else if (strcmp(t->u.user.name, LABEL_QUEUE) == 0)
  1054. return iptcc_standard_map(r, -NF_QUEUE - 1);
  1055. else if (strcmp(t->u.user.name, LABEL_RETURN) == 0)
  1056. return iptcc_standard_map(r, RETURN);
  1057. else if (TC_BUILTIN(t->u.user.name, handle)) {
  1058. /* Can't jump to builtins. */
  1059. errno = EINVAL;
  1060. return 0;
  1061. } else {
  1062. /* Maybe it's an existing chain name. */
  1063. struct chain_head *c;
  1064. DEBUGP("trying to find chain `%s': ", t->u.user.name);
  1065. c = iptcc_find_label(t->u.user.name, handle);
  1066. if (c) {
  1067. DEBUGP_C("found!\n");
  1068. r->type = IPTCC_R_JUMP;
  1069. r->jump = c;
  1070. c->references++;
  1071. return 1;
  1072. }
  1073. DEBUGP_C("not found :(\n");
  1074. }
  1075. /* Must be a module? If not, kernel will reject... */
  1076. /* memset to all 0 for your memcmp convenience: don't clear version */
  1077. memset(t->u.user.name + strlen(t->u.user.name),
  1078. 0, FUNCTION_MAXNAMELEN - 1 - strlen(t->u.user.name));
  1079. r->type = IPTCC_R_MODULE;
  1080. set_changed(handle);
  1081. return 1;
  1082. }
  1083. /* Insert the entry `fw' in chain `chain' into position `rulenum'. */
  1084. int
  1085. TC_INSERT_ENTRY(const IPT_CHAINLABEL chain,
  1086. const STRUCT_ENTRY * e,
  1087. unsigned int rulenum, TC_HANDLE_T * handle)
  1088. {
  1089. struct chain_head *c;
  1090. struct rule_head *r;
  1091. struct list_head *prev;
  1092. iptc_fn = TC_INSERT_ENTRY;
  1093. if (!(c = iptcc_find_label(chain, *handle))) {
  1094. errno = ENOENT;
  1095. return 0;
  1096. }
  1097. /* first rulenum index = 0
  1098. first c->num_rules index = 1 */
  1099. if (rulenum > c->num_rules) {
  1100. errno = E2BIG;
  1101. return 0;
  1102. }
  1103. /* If we are inserting at the end just take advantage of the
  1104. double linked list, insert will happen before the entry
  1105. prev points to. */
  1106. if (rulenum == c->num_rules) {
  1107. prev = &c->rules;
  1108. } else if (rulenum + 1 <= c->num_rules / 2) {
  1109. r = iptcc_get_rule_num(c, rulenum + 1);
  1110. prev = &r->list;
  1111. } else {
  1112. r = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum);
  1113. prev = &r->list;
  1114. }
  1115. if (!(r = iptcc_alloc_rule(c, e->next_offset))) {
  1116. errno = ENOMEM;
  1117. return 0;
  1118. }
  1119. memcpy(r->entry, e, e->next_offset);
  1120. r->counter_map.maptype = COUNTER_MAP_SET;
  1121. if (!iptcc_map_target(*handle, r)) {
  1122. free(r);
  1123. return 0;
  1124. }
  1125. list_add_tail(&r->list, prev);
  1126. c->num_rules++;
  1127. set_changed(*handle);
  1128. return 1;
  1129. }
  1130. /* Atomically replace rule `rulenum' in `chain' with `fw'. */
  1131. int
  1132. TC_REPLACE_ENTRY(const IPT_CHAINLABEL chain,
  1133. const STRUCT_ENTRY * e,
  1134. unsigned int rulenum, TC_HANDLE_T * handle)
  1135. {
  1136. struct chain_head *c;
  1137. struct rule_head *r, *old;
  1138. iptc_fn = TC_REPLACE_ENTRY;
  1139. if (!(c = iptcc_find_label(chain, *handle))) {
  1140. errno = ENOENT;
  1141. return 0;
  1142. }
  1143. if (rulenum >= c->num_rules) {
  1144. errno = E2BIG;
  1145. return 0;
  1146. }
  1147. /* Take advantage of the double linked list if possible. */
  1148. if (rulenum + 1 <= c->num_rules / 2) {
  1149. old = iptcc_get_rule_num(c, rulenum + 1);
  1150. } else {
  1151. old = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum);
  1152. }
  1153. if (!(r = iptcc_alloc_rule(c, e->next_offset))) {
  1154. errno = ENOMEM;
  1155. return 0;
  1156. }
  1157. memcpy(r->entry, e, e->next_offset);
  1158. r->counter_map.maptype = COUNTER_MAP_SET;
  1159. if (!iptcc_map_target(*handle, r)) {
  1160. free(r);
  1161. return 0;
  1162. }
  1163. list_add(&r->list, &old->list);
  1164. iptcc_delete_rule(old);
  1165. set_changed(*handle);
  1166. return 1;
  1167. }
  1168. /* Append entry `fw' to chain `chain'. Equivalent to insert with
  1169. rulenum = length of chain. */
  1170. int
  1171. TC_APPEND_ENTRY(const IPT_CHAINLABEL chain,
  1172. const STRUCT_ENTRY * e, TC_HANDLE_T * handle)
  1173. {
  1174. struct chain_head *c;
  1175. struct rule_head *r;
  1176. iptc_fn = TC_APPEND_ENTRY;
  1177. if (!(c = iptcc_find_label(chain, *handle))) {
  1178. DEBUGP("unable to find chain `%s'\n", chain);
  1179. errno = ENOENT;
  1180. return 0;
  1181. }
  1182. if (!(r = iptcc_alloc_rule(c, e->next_offset))) {
  1183. DEBUGP("unable to allocate rule for chain `%s'\n", chain);
  1184. errno = ENOMEM;
  1185. return 0;
  1186. }
  1187. memcpy(r->entry, e, e->next_offset);
  1188. r->counter_map.maptype = COUNTER_MAP_SET;
  1189. if (!iptcc_map_target(*handle, r)) {
  1190. DEBUGP("unable to map target of rule for chain `%s'\n", chain);
  1191. free(r);
  1192. return 0;
  1193. }
  1194. list_add_tail(&r->list, &c->rules);
  1195. c->num_rules++;
  1196. set_changed(*handle);
  1197. return 1;
  1198. }
  1199. static inline int
  1200. match_different(const STRUCT_ENTRY_MATCH * a,
  1201. const unsigned char *a_elems,
  1202. const unsigned char *b_elems, unsigned char **maskptr)
  1203. {
  1204. const STRUCT_ENTRY_MATCH *b;
  1205. unsigned int i;
  1206. /* Offset of b is the same as a. */
  1207. b = (void *) b_elems + ((unsigned char *) a - a_elems);
  1208. if (a->u.match_size != b->u.match_size)
  1209. return 1;
  1210. if (strcmp(a->u.user.name, b->u.user.name) != 0)
  1211. return 1;
  1212. *maskptr += ALIGN(sizeof(*a));
  1213. for (i = 0; i < a->u.match_size - ALIGN(sizeof(*a)); i++)
  1214. if (((a->data[i] ^ b->data[i]) & (*maskptr)[i]) != 0)
  1215. return 1;
  1216. *maskptr += i;
  1217. return 0;
  1218. }
  1219. static inline int
  1220. target_same(struct rule_head *a, struct rule_head *b,
  1221. const unsigned char *mask)
  1222. {
  1223. unsigned int i;
  1224. STRUCT_ENTRY_TARGET *ta, *tb;
  1225. if (a->type != b->type)
  1226. return 0;
  1227. ta = GET_TARGET(a->entry);
  1228. tb = GET_TARGET(b->entry);
  1229. switch (a->type) {
  1230. case IPTCC_R_FALLTHROUGH:
  1231. return 1;
  1232. case IPTCC_R_JUMP:
  1233. return a->jump == b->jump;
  1234. case IPTCC_R_STANDARD:
  1235. return ((STRUCT_STANDARD_TARGET *) ta)->verdict
  1236. == ((STRUCT_STANDARD_TARGET *) tb)->verdict;
  1237. case IPTCC_R_MODULE:
  1238. if (ta->u.target_size != tb->u.target_size)
  1239. return 0;
  1240. if (strcmp(ta->u.user.name, tb->u.user.name) != 0)
  1241. return 0;
  1242. for (i = 0; i < ta->u.target_size - sizeof(*ta); i++)
  1243. if (((ta->data[i] ^ tb->data[i]) & mask[i]) != 0)
  1244. return 0;
  1245. return 1;
  1246. default:
  1247. fprintf(stderr, "ERROR: bad type %i\n", a->type);
  1248. abort();
  1249. }
  1250. }
  1251. static unsigned char *is_same(const STRUCT_ENTRY * a,
  1252. const STRUCT_ENTRY * b,
  1253. unsigned char *matchmask);
  1254. /* Delete the first rule in `chain' which matches `fw'. */
  1255. int
  1256. TC_DELETE_ENTRY(const IPT_CHAINLABEL chain,
  1257. const STRUCT_ENTRY * origfw,
  1258. unsigned char *matchmask, TC_HANDLE_T * handle)
  1259. {
  1260. struct chain_head *c;
  1261. struct rule_head *r, *i;
  1262. iptc_fn = TC_DELETE_ENTRY;
  1263. if (!(c = iptcc_find_label(chain, *handle))) {
  1264. errno = ENOENT;
  1265. return 0;
  1266. }
  1267. /* Create a rule_head from origfw. */
  1268. r = iptcc_alloc_rule(c, origfw->next_offset);
  1269. if (!r) {
  1270. errno = ENOMEM;
  1271. return 0;
  1272. }
  1273. memcpy(r->entry, origfw, origfw->next_offset);
  1274. r->counter_map.maptype = COUNTER_MAP_NOMAP;
  1275. if (!iptcc_map_target(*handle, r)) {
  1276. DEBUGP("unable to map target of rule for chain `%s'\n", chain);
  1277. free(r);
  1278. return 0;
  1279. }
  1280. list_for_each_entry(i, &c->rules, list) {
  1281. unsigned char *mask;
  1282. mask = is_same(r->entry, i->entry, matchmask);
  1283. if (!mask)
  1284. continue;
  1285. if (!target_same(r, i, mask))
  1286. continue;
  1287. /* If we are about to delete the rule that is the
  1288. * current iterator, move rule iterator back. next
  1289. * pointer will then point to real next node */
  1290. if (i == (*handle)->rule_iterator_cur) {
  1291. (*handle)->rule_iterator_cur =
  1292. list_entry((*handle)->rule_iterator_cur->list.prev,
  1293. struct rule_head, list);
  1294. }
  1295. c->num_rules--;
  1296. iptcc_delete_rule(i);
  1297. set_changed(*handle);
  1298. free(r);
  1299. return 1;
  1300. }
  1301. free(r);
  1302. errno = ENOENT;
  1303. return 0;
  1304. }
  1305. /* Delete the rule in position `rulenum' in `chain'. */
  1306. int
  1307. TC_DELETE_NUM_ENTRY(const IPT_CHAINLABEL chain,
  1308. unsigned int rulenum, TC_HANDLE_T * handle)
  1309. {
  1310. struct chain_head *c;
  1311. struct rule_head *r;
  1312. iptc_fn = TC_DELETE_NUM_ENTRY;
  1313. if (!(c = iptcc_find_label(chain, *handle))) {
  1314. errno = ENOENT;
  1315. return 0;
  1316. }
  1317. if (rulenum >= c->num_rules) {
  1318. errno = E2BIG;
  1319. return 0;
  1320. }
  1321. /* Take advantage of the double linked list if possible. */
  1322. if (rulenum + 1 <= c->num_rules / 2) {
  1323. r = iptcc_get_rule_num(c, rulenum + 1);
  1324. } else {
  1325. r = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum);
  1326. }
  1327. /* If we are about to delete the rule that is the current
  1328. * iterator, move rule iterator back. next pointer will then
  1329. * point to real next node */
  1330. if (r == (*handle)->rule_iterator_cur) {
  1331. (*handle)->rule_iterator_cur =
  1332. list_entry((*handle)->rule_iterator_cur->list.prev,
  1333. struct rule_head, list);
  1334. }
  1335. c->num_rules--;
  1336. iptcc_delete_rule(r);
  1337. set_changed(*handle);
  1338. return 1;
  1339. }
  1340. /* Check the packet `fw' on chain `chain'. Returns the verdict, or
  1341. NULL and sets errno. */
  1342. const char *
  1343. TC_CHECK_PACKET(const IPT_CHAINLABEL chain,
  1344. STRUCT_ENTRY * entry, TC_HANDLE_T * handle)
  1345. {
  1346. iptc_fn = TC_CHECK_PACKET;
  1347. errno = ENOSYS;
  1348. return NULL;
  1349. }
  1350. /* Flushes the entries in the given chain (ie. empties chain). */
  1351. int
  1352. TC_FLUSH_ENTRIES(const IPT_CHAINLABEL chain, TC_HANDLE_T * handle)
  1353. {
  1354. struct chain_head *c;
  1355. struct rule_head *r, *tmp;
  1356. iptc_fn = TC_FLUSH_ENTRIES;
  1357. if (!(c = iptcc_find_label(chain, *handle))) {
  1358. errno = ENOENT;
  1359. return 0;
  1360. }
  1361. list_for_each_entry_safe(r, tmp, &c->rules, list) {
  1362. iptcc_delete_rule(r);
  1363. }
  1364. c->num_rules = 0;
  1365. set_changed(*handle);
  1366. return 1;
  1367. }
  1368. /* Zeroes the counters in a chain. */
  1369. int
  1370. TC_ZERO_ENTRIES(const IPT_CHAINLABEL chain, TC_HANDLE_T * handle)
  1371. {
  1372. struct chain_head *c;
  1373. struct rule_head *r;
  1374. iptc_fn = TC_ZERO_ENTRIES;
  1375. if (!(c = iptcc_find_label(chain, *handle))) {
  1376. errno = ENOENT;
  1377. return 0;
  1378. }
  1379. list_for_each_entry(r, &c->rules, list) {
  1380. if (r->counter_map.maptype == COUNTER_MAP_NORMAL_MAP)
  1381. r->counter_map.maptype = COUNTER_MAP_ZEROED;
  1382. }
  1383. set_changed(*handle);
  1384. return 1;
  1385. }
  1386. STRUCT_COUNTERS *
  1387. TC_READ_COUNTER(const IPT_CHAINLABEL chain,
  1388. unsigned int rulenum, TC_HANDLE_T * handle)
  1389. {
  1390. struct chain_head *c;
  1391. struct rule_head *r;
  1392. iptc_fn = TC_READ_COUNTER;
  1393. CHECK(*handle);
  1394. if (!(c = iptcc_find_label(chain, *handle))) {
  1395. errno = ENOENT;
  1396. return NULL;
  1397. }
  1398. if (!(r = iptcc_get_rule_num(c, rulenum))) {
  1399. errno = E2BIG;
  1400. return NULL;
  1401. }
  1402. return &r->entry[0].counters;
  1403. }
  1404. int
  1405. TC_ZERO_COUNTER(const IPT_CHAINLABEL chain,
  1406. unsigned int rulenum, TC_HANDLE_T * handle)
  1407. {
  1408. struct chain_head *c;
  1409. struct rule_head *r;
  1410. iptc_fn = TC_ZERO_COUNTER;
  1411. CHECK(*handle);
  1412. if (!(c = iptcc_find_label(chain, *handle))) {
  1413. errno = ENOENT;
  1414. return 0;
  1415. }
  1416. if (!(r = iptcc_get_rule_num(c, rulenum))) {
  1417. errno = E2BIG;
  1418. return 0;
  1419. }
  1420. if (r->counter_map.maptype == COUNTER_MAP_NORMAL_MAP)
  1421. r->counter_map.maptype = COUNTER_MAP_ZEROED;
  1422. set_changed(*handle);
  1423. return 1;
  1424. }
  1425. int
  1426. TC_SET_COUNTER(const IPT_CHAINLABEL chain,
  1427. unsigned int rulenum,
  1428. STRUCT_COUNTERS * counters, TC_HANDLE_T * handle)
  1429. {
  1430. struct chain_head *c;
  1431. struct rule_head *r;
  1432. STRUCT_ENTRY *e;
  1433. iptc_fn = TC_SET_COUNTER;
  1434. CHECK(*handle);
  1435. if (!(c = iptcc_find_label(chain, *handle))) {
  1436. errno = ENOENT;
  1437. return 0;
  1438. }
  1439. if (!(r = iptcc_get_rule_num(c, rulenum))) {
  1440. errno = E2BIG;
  1441. return 0;
  1442. }
  1443. e = r->entry;
  1444. r->counter_map.maptype = COUNTER_MAP_SET;
  1445. memcpy(&e->counters, counters, sizeof(STRUCT_COUNTERS));
  1446. set_changed(*handle);
  1447. return 1;
  1448. }
  1449. /* Creates a new chain. */
  1450. /* To create a chain, create two rules: error node and unconditional
  1451. * return. */
  1452. int
  1453. TC_CREATE_CHAIN(const IPT_CHAINLABEL chain, TC_HANDLE_T * handle)
  1454. {
  1455. static struct chain_head *c;
  1456. iptc_fn = TC_CREATE_CHAIN;
  1457. /* find_label doesn't cover built-in targets: DROP, ACCEPT,
  1458. QUEUE, RETURN. */
  1459. if (iptcc_find_label(chain, *handle)
  1460. || strcmp(chain, LABEL_DROP) == 0
  1461. || strcmp(chain, LABEL_ACCEPT) == 0
  1462. || strcmp(chain, LABEL_QUEUE) == 0
  1463. || strcmp(chain, LABEL_RETURN) == 0) {
  1464. DEBUGP("Chain `%s' already exists\n", chain);
  1465. errno = EEXIST;
  1466. return 0;
  1467. }
  1468. if (strlen(chain) + 1 > sizeof(IPT_CHAINLABEL)) {
  1469. DEBUGP("Chain name `%s' too long\n", chain);
  1470. errno = EINVAL;
  1471. return 0;
  1472. }
  1473. c = iptcc_alloc_chain_head(chain, 0);
  1474. if (!c) {
  1475. DEBUGP("Cannot allocate memory for chain `%s'\n", chain);
  1476. errno = ENOMEM;
  1477. return 0;
  1478. }
  1479. DEBUGP("Creating chain `%s'\n", chain);
  1480. list_add_tail(&c->list, &(*handle)->chains);
  1481. set_changed(*handle);
  1482. return 1;
  1483. }
  1484. /* Get the number of references to this chain. */
  1485. int
  1486. TC_GET_REFERENCES(unsigned int *ref, const IPT_CHAINLABEL chain,
  1487. TC_HANDLE_T * handle)
  1488. {
  1489. struct chain_head *c;
  1490. iptc_fn = TC_GET_REFERENCES;
  1491. if (!(c = iptcc_find_label(chain, *handle))) {
  1492. errno = ENOENT;
  1493. return 0;
  1494. }
  1495. *ref = c->references;
  1496. return 1;
  1497. }
  1498. /* Deletes a chain. */
  1499. int
  1500. TC_DELETE_CHAIN(const IPT_CHAINLABEL chain, TC_HANDLE_T * handle)
  1501. {
  1502. unsigned int references;
  1503. struct chain_head *c;
  1504. iptc_fn = TC_DELETE_CHAIN;
  1505. if (!(c = iptcc_find_label(chain, *handle))) {
  1506. DEBUGP("cannot find chain `%s'\n", chain);
  1507. errno = ENOENT;
  1508. return 0;
  1509. }
  1510. if (TC_BUILTIN(chain, *handle)) {
  1511. DEBUGP("cannot remove builtin chain `%s'\n", chain);
  1512. errno = EINVAL;
  1513. return 0;
  1514. }
  1515. if (!TC_GET_REFERENCES(&references, chain, handle)) {
  1516. DEBUGP("cannot get references on chain `%s'\n", chain);
  1517. return 0;
  1518. }
  1519. if (references > 0) {
  1520. DEBUGP("chain `%s' still has references\n", chain);
  1521. errno = EMLINK;
  1522. return 0;
  1523. }
  1524. if (c->num_rules) {
  1525. DEBUGP("chain `%s' is not empty\n", chain);
  1526. errno = ENOTEMPTY;
  1527. return 0;
  1528. }
  1529. /* If we are about to delete the chain that is the current
  1530. * iterator, move chain iterator firward. */
  1531. if (c == (*handle)->chain_iterator_cur)
  1532. iptcc_chain_iterator_advance(*handle);
  1533. list_del(&c->list);
  1534. free(c);
  1535. DEBUGP("chain `%s' deleted\n", chain);
  1536. set_changed(*handle);
  1537. return 1;
  1538. }
  1539. /* Renames a chain. */
  1540. int
  1541. TC_RENAME_CHAIN(const IPT_CHAINLABEL oldname,
  1542. const IPT_CHAINLABEL newname, TC_HANDLE_T * handle)
  1543. {
  1544. struct chain_head *c;
  1545. iptc_fn = TC_RENAME_CHAIN;
  1546. /* find_label doesn't cover built-in targets: DROP, ACCEPT,
  1547. QUEUE, RETURN. */
  1548. if (iptcc_find_label(newname, *handle)
  1549. || strcmp(newname, LABEL_DROP) == 0
  1550. || strcmp(newname, LABEL_ACCEPT) == 0
  1551. || strcmp(newname, LABEL_QUEUE) == 0
  1552. || strcmp(newname, LABEL_RETURN) == 0) {
  1553. errno = EEXIST;
  1554. return 0;
  1555. }
  1556. if (!(c = iptcc_find_label(oldname, *handle))
  1557. || TC_BUILTIN(oldname, *handle)) {
  1558. errno = ENOENT;
  1559. return 0;
  1560. }
  1561. if (strlen(newname) + 1 > sizeof(IPT_CHAINLABEL)) {
  1562. errno = EINVAL;
  1563. return 0;
  1564. }
  1565. strncpy(c->name, newname, sizeof(IPT_CHAINLABEL));
  1566. set_changed(*handle);
  1567. return 1;
  1568. }
  1569. /* Sets the policy on a built-in chain. */
  1570. int
  1571. TC_SET_POLICY(const IPT_CHAINLABEL chain,
  1572. const IPT_CHAINLABEL policy,
  1573. STRUCT_COUNTERS * counters, TC_HANDLE_T * handle)
  1574. {
  1575. struct chain_head *c;
  1576. iptc_fn = TC_SET_POLICY;
  1577. if (!(c = iptcc_find_label(chain, *handle))) {
  1578. DEBUGP("cannot find chain `%s'\n", chain);
  1579. errno = ENOENT;
  1580. return 0;
  1581. }
  1582. if (!iptcc_is_builtin(c)) {
  1583. DEBUGP("cannot set policy of userdefinedchain `%s'\n", chain);
  1584. errno = ENOENT;
  1585. return 0;
  1586. }
  1587. if (strcmp(policy, LABEL_ACCEPT) == 0)
  1588. c->verdict = -NF_ACCEPT - 1;
  1589. else if (strcmp(policy, LABEL_DROP) == 0)
  1590. c->verdict = -NF_DROP - 1;
  1591. else {
  1592. errno = EINVAL;
  1593. return 0;
  1594. }
  1595. if (counters) {
  1596. /* set byte and packet counters */
  1597. memcpy(&c->counters, counters, sizeof(STRUCT_COUNTERS));
  1598. c->counter_map.maptype = COUNTER_MAP_SET;
  1599. } else {
  1600. c->counter_map.maptype = COUNTER_MAP_NOMAP;
  1601. }
  1602. set_changed(*handle);
  1603. return 1;
  1604. }
  1605. /* Without this, on gcc 2.7.2.3, we get:
  1606. libiptc.c: In function `TC_COMMIT':
  1607. libiptc.c:833: fixed or forbidden register was spilled.
  1608. This may be due to a compiler bug or to impossible asm
  1609. statements or clauses.
  1610. */
  1611. static void
  1612. subtract_counters(STRUCT_COUNTERS * answer,
  1613. const STRUCT_COUNTERS * a, const STRUCT_COUNTERS * b)
  1614. {
  1615. answer->pcnt = a->pcnt - b->pcnt;
  1616. answer->bcnt = a->bcnt - b->bcnt;
  1617. }
  1618. static void
  1619. counters_nomap(STRUCT_COUNTERS_INFO * newcounters, unsigned int index)
  1620. {
  1621. newcounters->counters[index] = ((STRUCT_COUNTERS) {
  1622. 0, 0});
  1623. DEBUGP_C("NOMAP => zero\n");
  1624. }
  1625. static void
  1626. counters_normal_map(STRUCT_COUNTERS_INFO * newcounters,
  1627. STRUCT_REPLACE * repl,
  1628. unsigned int index, unsigned int mappos)
  1629. {
  1630. /* Original read: X.
  1631. * Atomic read on replacement: X + Y.
  1632. * Currently in kernel: Z.
  1633. * Want in kernel: X + Y + Z.
  1634. * => Add in X + Y
  1635. * => Add in replacement read.
  1636. */
  1637. newcounters->counters[index] = repl->counters[mappos];
  1638. DEBUGP_C("NORMAL_MAP => mappos %u \n", mappos);
  1639. }
  1640. static void
  1641. counters_map_zeroed(STRUCT_COUNTERS_INFO * newcounters,
  1642. STRUCT_REPLACE * repl,
  1643. unsigned int index,
  1644. unsigned int mappos, STRUCT_COUNTERS * counters)
  1645. {
  1646. /* Original read: X.
  1647. * Atomic read on replacement: X + Y.
  1648. * Currently in kernel: Z.
  1649. * Want in kernel: Y + Z.
  1650. * => Add in Y.
  1651. * => Add in (replacement read - original read).
  1652. */
  1653. subtract_counters(&newcounters->counters[index],
  1654. &repl->counters[mappos], counters);
  1655. DEBUGP_C("ZEROED => mappos %u\n", mappos);
  1656. }
  1657. static void
  1658. counters_map_set(STRUCT_COUNTERS_INFO * newcounters,
  1659. unsigned int index, STRUCT_COUNTERS * counters)
  1660. {
  1661. /* Want to set counter (iptables-restore) */
  1662. memcpy(&newcounters->counters[index], counters,
  1663. sizeof(STRUCT_COUNTERS));
  1664. DEBUGP_C("SET\n");
  1665. }
  1666. int
  1667. TC_COMMIT(TC_HANDLE_T * handle)
  1668. {
  1669. /* Replace, then map back the counters. */
  1670. STRUCT_REPLACE *repl;
  1671. STRUCT_COUNTERS_INFO *newcounters;
  1672. struct chain_head *c;
  1673. int ret;
  1674. size_t counterlen;
  1675. int new_number;
  1676. unsigned int new_size;
  1677. iptc_fn = TC_COMMIT;
  1678. CHECK(*handle);
  1679. /* Don't commit if nothing changed. */
  1680. if (!(*handle)->changed)
  1681. goto finished;
  1682. new_number = iptcc_compile_table_prep(*handle, &new_size);
  1683. if (new_number < 0) {
  1684. errno = ENOMEM;
  1685. return 0;
  1686. }
  1687. repl = malloc(sizeof(*repl) + new_size);
  1688. if (!repl) {
  1689. errno = ENOMEM;
  1690. return 0;
  1691. }
  1692. memset(repl, 0, sizeof(*repl) + new_size);
  1693. #if 0
  1694. TC_DUMP_ENTRIES(*handle);
  1695. #endif
  1696. counterlen = sizeof(STRUCT_COUNTERS_INFO)
  1697. + sizeof(STRUCT_COUNTERS) * new_number;
  1698. /* These are the old counters we will get from kernel */
  1699. repl->counters = malloc(sizeof(STRUCT_COUNTERS)
  1700. * (*handle)->info.num_entries);
  1701. if (!repl->counters) {
  1702. free(repl);
  1703. errno = ENOMEM;
  1704. return 0;
  1705. }
  1706. /* These are the counters we're going to put back, later. */
  1707. newcounters = malloc(counterlen);
  1708. if (!newcounters) {
  1709. free(repl->counters);
  1710. free(repl);
  1711. errno = ENOMEM;
  1712. return 0;
  1713. }
  1714. memset(newcounters, 0, counterlen);
  1715. strcpy(repl->name, (*handle)->info.name);
  1716. repl->num_entries = new_number;
  1717. repl->size = new_size;
  1718. repl->num_counters = (*handle)->info.num_entries;
  1719. repl->valid_hooks = (*handle)->info.valid_hooks;
  1720. DEBUGP("num_entries=%u, size=%u, num_counters=%u\n",
  1721. repl->num_entries, repl->size, repl->num_counters);
  1722. ret = iptcc_compile_table(*handle, repl);
  1723. if (ret < 0) {
  1724. errno = ret;
  1725. free(repl->counters);
  1726. free(repl);
  1727. free(newcounters);
  1728. return 0;
  1729. }
  1730. #ifdef IPTC_DEBUG2
  1731. {
  1732. int fd = open("/tmp/libiptc-so_set_replace.blob",
  1733. O_CREAT | O_WRONLY);
  1734. if (fd >= 0) {
  1735. write(fd, repl, sizeof(*repl) + repl->size);
  1736. close(fd);
  1737. }
  1738. }
  1739. #endif
  1740. if (setsockopt(sockfd, TC_IPPROTO, SO_SET_REPLACE, repl,
  1741. sizeof(*repl) + repl->size) < 0) {
  1742. free(repl->counters);
  1743. free(repl);
  1744. free(newcounters);
  1745. return 0;
  1746. }
  1747. /* Put counters back. */
  1748. strcpy(newcounters->name, (*handle)->info.name);
  1749. newcounters->num_counters = new_number;
  1750. list_for_each_entry(c, &(*handle)->chains, list) {
  1751. struct rule_head *r;
  1752. /* Builtin chains have their own counters */
  1753. if (iptcc_is_builtin(c)) {
  1754. DEBUGP("counter for chain-index %u: ", c->foot_index);
  1755. switch (c->counter_map.maptype) {
  1756. case COUNTER_MAP_NOMAP:
  1757. counters_nomap(newcounters, c->foot_index);
  1758. break;
  1759. case COUNTER_MAP_NORMAL_MAP:
  1760. counters_normal_map(newcounters, repl,
  1761. c->foot_index, c->counter_map.mappos);
  1762. break;
  1763. case COUNTER_MAP_ZEROED:
  1764. counters_map_zeroed(newcounters, repl,
  1765. c->foot_index,
  1766. c->counter_map.mappos, &c->counters);
  1767. break;
  1768. case COUNTER_MAP_SET:
  1769. counters_map_set(newcounters, c->foot_index, &c->counters);
  1770. break;
  1771. }
  1772. }
  1773. list_for_each_entry(r, &c->rules, list) {
  1774. DEBUGP("counter for index %u: ", r->index);
  1775. switch (r->counter_map.maptype) {
  1776. case COUNTER_MAP_NOMAP:
  1777. counters_nomap(newcounters, r->index);
  1778. break;
  1779. case COUNTER_MAP_NORMAL_MAP:
  1780. counters_normal_map(newcounters, repl,
  1781. r->index, r->counter_map.mappos);
  1782. break;
  1783. case COUNTER_MAP_ZEROED:
  1784. counters_map_zeroed(newcounters, repl,
  1785. r->index,
  1786. r->counter_map.mappos,
  1787. &r->entry->counters);
  1788. break;
  1789. case COUNTER_MAP_SET:
  1790. counters_map_set(newcounters, r->index,
  1791. &r->entry->counters);
  1792. break;
  1793. }
  1794. }
  1795. }
  1796. #ifdef KERNEL_64_USERSPACE_32
  1797. {
  1798. /* Kernel will think that pointer should be 64-bits, and get
  1799. padding. So we accomodate here (assumption: alignment of
  1800. `counters' is on 64-bit boundary). */
  1801. u_int64_t *kernptr = (u_int64_t *) & newcounters->counters;
  1802. if ((unsigned long) &newcounters->counters % 8 != 0) {
  1803. fprintf(stderr, "counters alignment incorrect! Mail rusty!\n");
  1804. abort();
  1805. }
  1806. *kernptr = newcounters->counters;
  1807. }
  1808. #endif /* KERNEL_64_USERSPACE_32 */
  1809. #ifdef IPTC_DEBUG2
  1810. {
  1811. int fd = open("/tmp/libiptc-so_set_add_counters.blob",
  1812. O_CREAT | O_WRONLY);
  1813. if (fd >= 0) {
  1814. write(fd, newcounters, counterlen);
  1815. close(fd);
  1816. }
  1817. }
  1818. #endif
  1819. if (setsockopt(sockfd, TC_IPPROTO, SO_SET_ADD_COUNTERS,
  1820. newcounters, counterlen) < 0) {
  1821. free(repl->counters);
  1822. free(repl);
  1823. free(newcounters);
  1824. return 0;
  1825. }
  1826. free(repl->counters);
  1827. free(repl);
  1828. free(newcounters);
  1829. finished:
  1830. TC_FREE(handle);
  1831. return 1;
  1832. }
  1833. /* Get raw socket. */
  1834. int
  1835. TC_GET_RAW_SOCKET()
  1836. {
  1837. return sockfd;
  1838. }
  1839. /* Translates errno numbers into more human-readable form than strerror. */
  1840. const char *
  1841. TC_STRERROR(int err)
  1842. {
  1843. unsigned int i;
  1844. struct table_struct {
  1845. void *fn;
  1846. int err;
  1847. const char *message;
  1848. } table[] = { {
  1849. TC_INIT, EPERM, "Permission denied (you must be root)"}, {
  1850. TC_INIT, EINVAL, "Module is wrong version"}, {
  1851. TC_INIT, ENOENT, "Table does not exist (do you need to insmod?)"}, {
  1852. TC_DELETE_CHAIN, ENOTEMPTY, "Chain is not empty"}, {
  1853. TC_DELETE_CHAIN, EINVAL, "Can't delete built-in chain"}, {
  1854. TC_DELETE_CHAIN, EMLINK, "Can't delete chain with references left"}, {
  1855. TC_CREATE_CHAIN, EEXIST, "Chain already exists"}, {
  1856. TC_INSERT_ENTRY, E2BIG, "Index of insertion too big"}, {
  1857. TC_REPLACE_ENTRY, E2BIG, "Index of replacement too big"}, {
  1858. TC_DELETE_NUM_ENTRY, E2BIG, "Index of deletion too big"}, {
  1859. TC_READ_COUNTER, E2BIG, "Index of counter too big"}, {
  1860. TC_ZERO_COUNTER, E2BIG, "Index of counter too big"}, {
  1861. TC_INSERT_ENTRY, ELOOP, "Loop found in table"}, {
  1862. TC_INSERT_ENTRY, EINVAL, "Target problem"},
  1863. /* EINVAL for CHECK probably means bad interface. */
  1864. {
  1865. TC_CHECK_PACKET, EINVAL,
  1866. "Bad arguments (does that interface exist?)"}, {
  1867. TC_CHECK_PACKET, ENOSYS,
  1868. "Checking will most likely never get implemented"},
  1869. /* ENOENT for DELETE probably means no matching rule */
  1870. {
  1871. TC_DELETE_ENTRY, ENOENT,
  1872. "Bad rule (does a matching rule exist in that chain?)"}, {
  1873. TC_SET_POLICY, ENOENT, "Bad built-in chain name"}, {
  1874. TC_SET_POLICY, EINVAL, "Bad policy name"}, {
  1875. NULL, 0, "Incompatible with this kernel"}, {
  1876. NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)"}, {
  1877. NULL, ENOSYS, "Will be implemented real soon. I promise ;)"}, {
  1878. NULL, ENOMEM, "Memory allocation problem"}, {
  1879. NULL, ENOENT, "No chain/target/match by that name"},};
  1880. for (i = 0; i < sizeof(table) / sizeof(struct table_struct); i++) {
  1881. if ((!table[i].fn || table[i].fn == iptc_fn)
  1882. && table[i].err == err)
  1883. return table[i].message;
  1884. }
  1885. return strerror(err);
  1886. }