ip_tables.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:43k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * Packet matching code.
  3.  *
  4.  * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
  5.  * Copyright (C) 2009-2002 Netfilter core team <coreteam@netfilter.org>
  6.  *
  7.  * 19 Jan 2002 Harald Welte <laforge@gnumonks.org>
  8.  *  - increase module usage count as soon as we have rules inside
  9.  *    a table
  10.  */
  11. #include <linux/config.h>
  12. #include <linux/cache.h>
  13. #include <linux/skbuff.h>
  14. #include <linux/kmod.h>
  15. #include <linux/vmalloc.h>
  16. #include <linux/netdevice.h>
  17. #include <linux/module.h>
  18. #include <linux/tcp.h>
  19. #include <linux/udp.h>
  20. #include <linux/icmp.h>
  21. #include <net/ip.h>
  22. #include <asm/uaccess.h>
  23. #include <asm/semaphore.h>
  24. #include <linux/proc_fs.h>
  25. #include <linux/netfilter_ipv4/ip_tables.h>
  26. /*#define DEBUG_IP_FIREWALL*/
  27. /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
  28. /*#define DEBUG_IP_FIREWALL_USER*/
  29. #ifdef DEBUG_IP_FIREWALL
  30. #define dprintf(format, args...)  printk(format , ## args)
  31. #else
  32. #define dprintf(format, args...)
  33. #endif
  34. #ifdef DEBUG_IP_FIREWALL_USER
  35. #define duprintf(format, args...) printk(format , ## args)
  36. #else
  37. #define duprintf(format, args...)
  38. #endif
  39. #ifdef CONFIG_NETFILTER_DEBUG
  40. #define IP_NF_ASSERT(x)
  41. do {
  42. if (!(x))
  43. printk("IP_NF_ASSERT: %s:%s:%un",
  44.        __FUNCTION__, __FILE__, __LINE__);
  45. } while(0)
  46. #else
  47. #define IP_NF_ASSERT(x)
  48. #endif
  49. #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
  50. /* Mutex protects lists (only traversed in user context). */
  51. static DECLARE_MUTEX(ipt_mutex);
  52. /* Must have mutex */
  53. #define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0)
  54. #define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0)
  55. #include <linux/netfilter_ipv4/lockhelp.h>
  56. #include <linux/netfilter_ipv4/listhelp.h>
  57. #if 0
  58. /* All the better to debug you with... */
  59. #define static
  60. #define inline
  61. #endif
  62. /* Locking is simple: we assume at worst case there will be one packet
  63.    in user context and one from bottom halves (or soft irq if Alexey's
  64.    softnet patch was applied).
  65.    We keep a set of rules for each CPU, so we can avoid write-locking
  66.    them; doing a readlock_bh() stops packets coming through if we're
  67.    in user context.
  68.    To be cache friendly on SMP, we arrange them like so:
  69.    [ n-entries ]
  70.    ... cache-align padding ...
  71.    [ n-entries ]
  72.    Hence the start of any table is given by get_table() below.  */
  73. /* The table itself */
  74. struct ipt_table_info
  75. {
  76. /* Size per table */
  77. unsigned int size;
  78. /* Number of entries: FIXME. --RR */
  79. unsigned int number;
  80. /* Initial number of entries. Needed for module usage count */
  81. unsigned int initial_entries;
  82. /* Entry points and underflows */
  83. unsigned int hook_entry[NF_IP_NUMHOOKS];
  84. unsigned int underflow[NF_IP_NUMHOOKS];
  85. /* ipt_entry tables: one per CPU */
  86. char entries[0] ____cacheline_aligned;
  87. };
  88. static LIST_HEAD(ipt_target);
  89. static LIST_HEAD(ipt_match);
  90. static LIST_HEAD(ipt_tables);
  91. #define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0)
  92. #ifdef CONFIG_SMP
  93. #define TABLE_OFFSET(t,p) (SMP_ALIGN((t)->size)*(p))
  94. #else
  95. #define TABLE_OFFSET(t,p) 0
  96. #endif
  97. #if 0
  98. #define down(x) do { printk("DOWN:%u:" #x "n", __LINE__); down(x); } while(0)
  99. #define down_interruptible(x) ({ int __r; printk("DOWNi:%u:" #x "n", __LINE__); __r = down_interruptible(x); if (__r != 0) printk("ABORT-DOWNi:%un", __LINE__); __r; })
  100. #define up(x) do { printk("UP:%u:" #x "n", __LINE__); up(x); } while(0)
  101. #endif
  102. /* Returns whether matches rule or not. */
  103. static inline int
  104. ip_packet_match(const struct iphdr *ip,
  105. const char *indev,
  106. const char *outdev,
  107. const struct ipt_ip *ipinfo,
  108. int isfrag)
  109. {
  110. size_t i;
  111. unsigned long ret;
  112. #define FWINV(bool,invflg) ((bool) ^ !!(ipinfo->invflags & invflg))
  113. if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr,
  114.   IPT_INV_SRCIP)
  115.     || FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
  116.      IPT_INV_DSTIP)) {
  117. dprintf("Source or dest mismatch.n");
  118. dprintf("SRC: %u.%u.%u.%u. Mask: %u.%u.%u.%u. Target: %u.%u.%u.%u.%sn",
  119. NIPQUAD(ip->saddr),
  120. NIPQUAD(ipinfo->smsk.s_addr),
  121. NIPQUAD(ipinfo->src.s_addr),
  122. ipinfo->invflags & IPT_INV_SRCIP ? " (INV)" : "");
  123. dprintf("DST: %u.%u.%u.%u Mask: %u.%u.%u.%u Target: %u.%u.%u.%u.%sn",
  124. NIPQUAD(ip->daddr),
  125. NIPQUAD(ipinfo->dmsk.s_addr),
  126. NIPQUAD(ipinfo->dst.s_addr),
  127. ipinfo->invflags & IPT_INV_DSTIP ? " (INV)" : "");
  128. return 0;
  129. }
  130. /* Look for ifname matches; this should unroll nicely. */
  131. for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
  132. ret |= (((const unsigned long *)indev)[i]
  133. ^ ((const unsigned long *)ipinfo->iniface)[i])
  134. & ((const unsigned long *)ipinfo->iniface_mask)[i];
  135. }
  136. if (FWINV(ret != 0, IPT_INV_VIA_IN)) {
  137. dprintf("VIA in mismatch (%s vs %s).%sn",
  138. indev, ipinfo->iniface,
  139. ipinfo->invflags&IPT_INV_VIA_IN ?" (INV)":"");
  140. return 0;
  141. }
  142. for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
  143. ret |= (((const unsigned long *)outdev)[i]
  144. ^ ((const unsigned long *)ipinfo->outiface)[i])
  145. & ((const unsigned long *)ipinfo->outiface_mask)[i];
  146. }
  147. if (FWINV(ret != 0, IPT_INV_VIA_OUT)) {
  148. dprintf("VIA out mismatch (%s vs %s).%sn",
  149. outdev, ipinfo->outiface,
  150. ipinfo->invflags&IPT_INV_VIA_OUT ?" (INV)":"");
  151. return 0;
  152. }
  153. /* Check specific protocol */
  154. if (ipinfo->proto
  155.     && FWINV(ip->protocol != ipinfo->proto, IPT_INV_PROTO)) {
  156. dprintf("Packet protocol %hi does not match %hi.%sn",
  157. ip->protocol, ipinfo->proto,
  158. ipinfo->invflags&IPT_INV_PROTO ? " (INV)":"");
  159. return 0;
  160. }
  161. /* If we have a fragment rule but the packet is not a fragment
  162.  * then we return zero */
  163. if (FWINV((ipinfo->flags&IPT_F_FRAG) && !isfrag, IPT_INV_FRAG)) {
  164. dprintf("Fragment rule but not fragment.%sn",
  165. ipinfo->invflags & IPT_INV_FRAG ? " (INV)" : "");
  166. return 0;
  167. }
  168. return 1;
  169. }
  170. static inline int
  171. ip_checkentry(const struct ipt_ip *ip)
  172. {
  173. if (ip->flags & ~IPT_F_MASK) {
  174. duprintf("Unknown flag bits set: %08Xn",
  175.  ip->flags & ~IPT_F_MASK);
  176. return 0;
  177. }
  178. if (ip->invflags & ~IPT_INV_MASK) {
  179. duprintf("Unknown invflag bits set: %08Xn",
  180.  ip->invflags & ~IPT_INV_MASK);
  181. return 0;
  182. }
  183. return 1;
  184. }
  185. static unsigned int
  186. ipt_error(struct sk_buff **pskb,
  187.   unsigned int hooknum,
  188.   const struct net_device *in,
  189.   const struct net_device *out,
  190.   const void *targinfo,
  191.   void *userinfo)
  192. {
  193. if (net_ratelimit())
  194. printk("ip_tables: error: `%s'n", (char *)targinfo);
  195. return NF_DROP;
  196. }
  197. static inline
  198. int do_match(struct ipt_entry_match *m,
  199.      const struct sk_buff *skb,
  200.      const struct net_device *in,
  201.      const struct net_device *out,
  202.      int offset,
  203.      const void *hdr,
  204.      u_int16_t datalen,
  205.      int *hotdrop)
  206. {
  207. /* Stop iteration if it doesn't match */
  208. if (!m->u.kernel.match->match(skb, in, out, m->data,
  209.       offset, hdr, datalen, hotdrop))
  210. return 1;
  211. else
  212. return 0;
  213. }
  214. static inline struct ipt_entry *
  215. get_entry(void *base, unsigned int offset)
  216. {
  217. return (struct ipt_entry *)(base + offset);
  218. }
  219. /* Returns one of the generic firewall policies, like NF_ACCEPT. */
  220. unsigned int
  221. ipt_do_table(struct sk_buff **pskb,
  222.      unsigned int hook,
  223.      const struct net_device *in,
  224.      const struct net_device *out,
  225.      struct ipt_table *table,
  226.      void *userdata)
  227. {
  228. static const char nulldevname[IFNAMSIZ] = { 0 };
  229. u_int16_t offset;
  230. struct iphdr *ip;
  231. void *protohdr;
  232. u_int16_t datalen;
  233. int hotdrop = 0;
  234. /* Initializing verdict to NF_DROP keeps gcc happy. */
  235. unsigned int verdict = NF_DROP;
  236. const char *indev, *outdev;
  237. void *table_base;
  238. struct ipt_entry *e, *back;
  239. /* Initialization */
  240. ip = (*pskb)->nh.iph;
  241. protohdr = (u_int32_t *)ip + ip->ihl;
  242. datalen = (*pskb)->len - ip->ihl * 4;
  243. indev = in ? in->name : nulldevname;
  244. outdev = out ? out->name : nulldevname;
  245. /* We handle fragments by dealing with the first fragment as
  246.  * if it was a normal packet.  All other fragments are treated
  247.  * normally, except that they will NEVER match rules that ask
  248.  * things we don't know, ie. tcp syn flag or ports).  If the
  249.  * rule is also a fragment-specific rule, non-fragments won't
  250.  * match it. */
  251. offset = ntohs(ip->frag_off) & IP_OFFSET;
  252. read_lock_bh(&table->lock);
  253. IP_NF_ASSERT(table->valid_hooks & (1 << hook));
  254. table_base = (void *)table->private->entries
  255. + TABLE_OFFSET(table->private,
  256.        cpu_number_map(smp_processor_id()));
  257. e = get_entry(table_base, table->private->hook_entry[hook]);
  258. #ifdef CONFIG_NETFILTER_DEBUG
  259. /* Check noone else using our table */
  260. if (((struct ipt_entry *)table_base)->comefrom != 0xdead57ac
  261.     && ((struct ipt_entry *)table_base)->comefrom != 0xeeeeeeec) {
  262. printk("ASSERT: CPU #%u, %s comefrom(%p) = %Xn",
  263.        smp_processor_id(),
  264.        table->name,
  265.        &((struct ipt_entry *)table_base)->comefrom,
  266.        ((struct ipt_entry *)table_base)->comefrom);
  267. }
  268. ((struct ipt_entry *)table_base)->comefrom = 0x57acc001;
  269. #endif
  270. /* For return from builtin chain */
  271. back = get_entry(table_base, table->private->underflow[hook]);
  272. do {
  273. IP_NF_ASSERT(e);
  274. IP_NF_ASSERT(back);
  275. (*pskb)->nfcache |= e->nfcache;
  276. if (ip_packet_match(ip, indev, outdev, &e->ip, offset)) {
  277. struct ipt_entry_target *t;
  278. if (IPT_MATCH_ITERATE(e, do_match,
  279.       *pskb, in, out,
  280.       offset, protohdr,
  281.       datalen, &hotdrop) != 0)
  282. goto no_match;
  283. ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
  284. t = ipt_get_target(e);
  285. IP_NF_ASSERT(t->u.kernel.target);
  286. /* Standard target? */
  287. if (!t->u.kernel.target->target) {
  288. int v;
  289. v = ((struct ipt_standard_target *)t)->verdict;
  290. if (v < 0) {
  291. /* Pop from stack? */
  292. if (v != IPT_RETURN) {
  293. verdict = (unsigned)(-v) - 1;
  294. break;
  295. }
  296. e = back;
  297. back = get_entry(table_base,
  298.  back->comefrom);
  299. continue;
  300. }
  301. if (table_base + v
  302.     != (void *)e + e->next_offset) {
  303. /* Save old back ptr in next entry */
  304. struct ipt_entry *next
  305. = (void *)e + e->next_offset;
  306. next->comefrom
  307. = (void *)back - table_base;
  308. /* set back pointer to next entry */
  309. back = next;
  310. }
  311. e = get_entry(table_base, v);
  312. } else {
  313. /* Targets which reenter must return
  314.                                    abs. verdicts */
  315. #ifdef CONFIG_NETFILTER_DEBUG
  316. ((struct ipt_entry *)table_base)->comefrom
  317. = 0xeeeeeeec;
  318. #endif
  319. verdict = t->u.kernel.target->target(pskb,
  320.      hook,
  321.      in, out,
  322.      t->data,
  323.      userdata);
  324. #ifdef CONFIG_NETFILTER_DEBUG
  325. if (((struct ipt_entry *)table_base)->comefrom
  326.     != 0xeeeeeeec
  327.     && verdict == IPT_CONTINUE) {
  328. printk("Target %s reentered!n",
  329.        t->u.kernel.target->name);
  330. verdict = NF_DROP;
  331. }
  332. ((struct ipt_entry *)table_base)->comefrom
  333. = 0x57acc001;
  334. #endif
  335. /* Target might have changed stuff. */
  336. ip = (*pskb)->nh.iph;
  337. protohdr = (u_int32_t *)ip + ip->ihl;
  338. datalen = (*pskb)->len - ip->ihl * 4;
  339. if (verdict == IPT_CONTINUE)
  340. e = (void *)e + e->next_offset;
  341. else
  342. /* Verdict */
  343. break;
  344. }
  345. } else {
  346. no_match:
  347. e = (void *)e + e->next_offset;
  348. }
  349. } while (!hotdrop);
  350. #ifdef CONFIG_NETFILTER_DEBUG
  351. ((struct ipt_entry *)table_base)->comefrom = 0xdead57ac;
  352. #endif
  353. read_unlock_bh(&table->lock);
  354. #ifdef DEBUG_ALLOW_ALL
  355. return NF_ACCEPT;
  356. #else
  357. if (hotdrop)
  358. return NF_DROP;
  359. else return verdict;
  360. #endif
  361. }
  362. /* If it succeeds, returns element and locks mutex */
  363. static inline void *
  364. find_inlist_lock_noload(struct list_head *head,
  365. const char *name,
  366. int *error,
  367. struct semaphore *mutex)
  368. {
  369. void *ret;
  370. #if 0
  371. duprintf("find_inlist: searching for `%s' in %s.n",
  372.  name, head == &ipt_target ? "ipt_target"
  373.  : head == &ipt_match ? "ipt_match"
  374.  : head == &ipt_tables ? "ipt_tables" : "UNKNOWN");
  375. #endif
  376. *error = down_interruptible(mutex);
  377. if (*error != 0)
  378. return NULL;
  379. ret = list_named_find(head, name);
  380. if (!ret) {
  381. *error = -ENOENT;
  382. up(mutex);
  383. }
  384. return ret;
  385. }
  386. #ifndef CONFIG_KMOD
  387. #define find_inlist_lock(h,n,p,e,m) find_inlist_lock_noload((h),(n),(e),(m))
  388. #else
  389. static void *
  390. find_inlist_lock(struct list_head *head,
  391.  const char *name,
  392.  const char *prefix,
  393.  int *error,
  394.  struct semaphore *mutex)
  395. {
  396. void *ret;
  397. ret = find_inlist_lock_noload(head, name, error, mutex);
  398. if (!ret) {
  399. char modulename[IPT_FUNCTION_MAXNAMELEN + strlen(prefix) + 1];
  400. strcpy(modulename, prefix);
  401. strcat(modulename, name);
  402. duprintf("find_inlist: loading `%s'.n", modulename);
  403. request_module(modulename);
  404. ret = find_inlist_lock_noload(head, name, error, mutex);
  405. }
  406. return ret;
  407. }
  408. #endif
  409. static inline struct ipt_table *
  410. find_table_lock(const char *name, int *error, struct semaphore *mutex)
  411. {
  412. return find_inlist_lock(&ipt_tables, name, "iptable_", error, mutex);
  413. }
  414. static inline struct ipt_match *
  415. find_match_lock(const char *name, int *error, struct semaphore *mutex)
  416. {
  417. return find_inlist_lock(&ipt_match, name, "ipt_", error, mutex);
  418. }
  419. static inline struct ipt_target *
  420. find_target_lock(const char *name, int *error, struct semaphore *mutex)
  421. {
  422. return find_inlist_lock(&ipt_target, name, "ipt_", error, mutex);
  423. }
  424. /* All zeroes == unconditional rule. */
  425. static inline int
  426. unconditional(const struct ipt_ip *ip)
  427. {
  428. unsigned int i;
  429. for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++)
  430. if (((__u32 *)ip)[i])
  431. return 0;
  432. return 1;
  433. }
  434. /* Figures out from what hook each rule can be called: returns 0 if
  435.    there are loops.  Puts hook bitmask in comefrom. */
  436. static int
  437. mark_source_chains(struct ipt_table_info *newinfo, unsigned int valid_hooks)
  438. {
  439. unsigned int hook;
  440. /* No recursion; use packet counter to save back ptrs (reset
  441.    to 0 as we leave), and comefrom to save source hook bitmask */
  442. for (hook = 0; hook < NF_IP_NUMHOOKS; hook++) {
  443. unsigned int pos = newinfo->hook_entry[hook];
  444. struct ipt_entry *e
  445. = (struct ipt_entry *)(newinfo->entries + pos);
  446. if (!(valid_hooks & (1 << hook)))
  447. continue;
  448. /* Set initial back pointer. */
  449. e->counters.pcnt = pos;
  450. for (;;) {
  451. struct ipt_standard_target *t
  452. = (void *)ipt_get_target(e);
  453. if (e->comefrom & (1 << NF_IP_NUMHOOKS)) {
  454. printk("iptables: loop hook %u pos %u %08X.n",
  455.        hook, pos, e->comefrom);
  456. return 0;
  457. }
  458. e->comefrom
  459. |= ((1 << hook) | (1 << NF_IP_NUMHOOKS));
  460. /* Unconditional return/END. */
  461. if (e->target_offset == sizeof(struct ipt_entry)
  462.     && (strcmp(t->target.u.user.name,
  463.        IPT_STANDARD_TARGET) == 0)
  464.     && t->verdict < 0
  465.     && unconditional(&e->ip)) {
  466. unsigned int oldpos, size;
  467. /* Return: backtrack through the last
  468.    big jump. */
  469. do {
  470. e->comefrom ^= (1<<NF_IP_NUMHOOKS);
  471. #ifdef DEBUG_IP_FIREWALL_USER
  472. if (e->comefrom
  473.     & (1 << NF_IP_NUMHOOKS)) {
  474. duprintf("Back unset "
  475.  "on hook %u "
  476.  "rule %un",
  477.  hook, pos);
  478. }
  479. #endif
  480. oldpos = pos;
  481. pos = e->counters.pcnt;
  482. e->counters.pcnt = 0;
  483. /* We're at the start. */
  484. if (pos == oldpos)
  485. goto next;
  486. e = (struct ipt_entry *)
  487. (newinfo->entries + pos);
  488. } while (oldpos == pos + e->next_offset);
  489. /* Move along one */
  490. size = e->next_offset;
  491. e = (struct ipt_entry *)
  492. (newinfo->entries + pos + size);
  493. e->counters.pcnt = pos;
  494. pos += size;
  495. } else {
  496. int newpos = t->verdict;
  497. if (strcmp(t->target.u.user.name,
  498.    IPT_STANDARD_TARGET) == 0
  499.     && newpos >= 0) {
  500. /* This a jump; chase it. */
  501. duprintf("Jump rule %u -> %un",
  502.  pos, newpos);
  503. } else {
  504. /* ... this is a fallthru */
  505. newpos = pos + e->next_offset;
  506. }
  507. e = (struct ipt_entry *)
  508. (newinfo->entries + newpos);
  509. e->counters.pcnt = pos;
  510. pos = newpos;
  511. }
  512. }
  513. next:
  514. duprintf("Finished chain %un", hook);
  515. }
  516. return 1;
  517. }
  518. static inline int
  519. cleanup_match(struct ipt_entry_match *m, unsigned int *i)
  520. {
  521. if (i && (*i)-- == 0)
  522. return 1;
  523. if (m->u.kernel.match->destroy)
  524. m->u.kernel.match->destroy(m->data,
  525.    m->u.match_size - sizeof(*m));
  526. if (m->u.kernel.match->me)
  527. __MOD_DEC_USE_COUNT(m->u.kernel.match->me);
  528. return 0;
  529. }
  530. static inline int
  531. standard_check(const struct ipt_entry_target *t,
  532.        unsigned int max_offset)
  533. {
  534. struct ipt_standard_target *targ = (void *)t;
  535. /* Check standard info. */
  536. if (t->u.target_size
  537.     != IPT_ALIGN(sizeof(struct ipt_standard_target))) {
  538. duprintf("standard_check: target size %u != %un",
  539.  t->u.target_size,
  540.  IPT_ALIGN(sizeof(struct ipt_standard_target)));
  541. return 0;
  542. }
  543. if (targ->verdict >= 0
  544.     && targ->verdict > max_offset - sizeof(struct ipt_entry)) {
  545. duprintf("ipt_standard_check: bad verdict (%i)n",
  546.  targ->verdict);
  547. return 0;
  548. }
  549. if (targ->verdict < -NF_MAX_VERDICT - 1) {
  550. duprintf("ipt_standard_check: bad negative verdict (%i)n",
  551.  targ->verdict);
  552. return 0;
  553. }
  554. return 1;
  555. }
  556. static inline int
  557. check_match(struct ipt_entry_match *m,
  558.     const char *name,
  559.     const struct ipt_ip *ip,
  560.     unsigned int hookmask,
  561.     unsigned int *i)
  562. {
  563. int ret;
  564. struct ipt_match *match;
  565. match = find_match_lock(m->u.user.name, &ret, &ipt_mutex);
  566. if (!match) {
  567. duprintf("check_match: `%s' not foundn", m->u.user.name);
  568. return ret;
  569. }
  570. if (match->me)
  571. __MOD_INC_USE_COUNT(match->me);
  572. m->u.kernel.match = match;
  573. up(&ipt_mutex);
  574. if (m->u.kernel.match->checkentry
  575.     && !m->u.kernel.match->checkentry(name, ip, m->data,
  576.       m->u.match_size - sizeof(*m),
  577.       hookmask)) {
  578. if (m->u.kernel.match->me)
  579. __MOD_DEC_USE_COUNT(m->u.kernel.match->me);
  580. duprintf("ip_tables: check failed for `%s'.n",
  581.  m->u.kernel.match->name);
  582. return -EINVAL;
  583. }
  584. (*i)++;
  585. return 0;
  586. }
  587. static struct ipt_target ipt_standard_target;
  588. static inline int
  589. check_entry(struct ipt_entry *e, const char *name, unsigned int size,
  590.     unsigned int *i)
  591. {
  592. struct ipt_entry_target *t;
  593. struct ipt_target *target;
  594. int ret;
  595. unsigned int j;
  596. if (!ip_checkentry(&e->ip)) {
  597. duprintf("ip_tables: ip check failed %p %s.n", e, name);
  598. return -EINVAL;
  599. }
  600. j = 0;
  601. ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom, &j);
  602. if (ret != 0)
  603. goto cleanup_matches;
  604. t = ipt_get_target(e);
  605. target = find_target_lock(t->u.user.name, &ret, &ipt_mutex);
  606. if (!target) {
  607. duprintf("check_entry: `%s' not foundn", t->u.user.name);
  608. goto cleanup_matches;
  609. }
  610. if (target->me)
  611. __MOD_INC_USE_COUNT(target->me);
  612. t->u.kernel.target = target;
  613. up(&ipt_mutex);
  614. if (t->u.kernel.target == &ipt_standard_target) {
  615. if (!standard_check(t, size)) {
  616. ret = -EINVAL;
  617. goto cleanup_matches;
  618. }
  619. } else if (t->u.kernel.target->checkentry
  620.    && !t->u.kernel.target->checkentry(name, e, t->data,
  621.       t->u.target_size
  622.       - sizeof(*t),
  623.       e->comefrom)) {
  624. if (t->u.kernel.target->me)
  625. __MOD_DEC_USE_COUNT(t->u.kernel.target->me);
  626. duprintf("ip_tables: check failed for `%s'.n",
  627.  t->u.kernel.target->name);
  628. ret = -EINVAL;
  629. goto cleanup_matches;
  630. }
  631. (*i)++;
  632. return 0;
  633.  cleanup_matches:
  634. IPT_MATCH_ITERATE(e, cleanup_match, &j);
  635. return ret;
  636. }
  637. static inline int
  638. check_entry_size_and_hooks(struct ipt_entry *e,
  639.    struct ipt_table_info *newinfo,
  640.    unsigned char *base,
  641.    unsigned char *limit,
  642.    const unsigned int *hook_entries,
  643.    const unsigned int *underflows,
  644.    unsigned int *i)
  645. {
  646. unsigned int h;
  647. if ((unsigned long)e % __alignof__(struct ipt_entry) != 0
  648.     || (unsigned char *)e + sizeof(struct ipt_entry) >= limit) {
  649. duprintf("Bad offset %pn", e);
  650. return -EINVAL;
  651. }
  652. if (e->next_offset
  653.     < sizeof(struct ipt_entry) + sizeof(struct ipt_entry_target)) {
  654. duprintf("checking: element %p size %un",
  655.  e, e->next_offset);
  656. return -EINVAL;
  657. }
  658. /* Check hooks & underflows */
  659. for (h = 0; h < NF_IP_NUMHOOKS; h++) {
  660. if ((unsigned char *)e - base == hook_entries[h])
  661. newinfo->hook_entry[h] = hook_entries[h];
  662. if ((unsigned char *)e - base == underflows[h])
  663. newinfo->underflow[h] = underflows[h];
  664. }
  665. /* FIXME: underflows must be unconditional, standard verdicts
  666.            < 0 (not IPT_RETURN). --RR */
  667. /* Clear counters and comefrom */
  668. e->counters = ((struct ipt_counters) { 0, 0 });
  669. e->comefrom = 0;
  670. (*i)++;
  671. return 0;
  672. }
  673. static inline int
  674. cleanup_entry(struct ipt_entry *e, unsigned int *i)
  675. {
  676. struct ipt_entry_target *t;
  677. if (i && (*i)-- == 0)
  678. return 1;
  679. /* Cleanup all matches */
  680. IPT_MATCH_ITERATE(e, cleanup_match, NULL);
  681. t = ipt_get_target(e);
  682. if (t->u.kernel.target->destroy)
  683. t->u.kernel.target->destroy(t->data,
  684.     t->u.target_size - sizeof(*t));
  685. if (t->u.kernel.target->me)
  686. __MOD_DEC_USE_COUNT(t->u.kernel.target->me);
  687. return 0;
  688. }
  689. /* Checks and translates the user-supplied table segment (held in
  690.    newinfo) */
  691. static int
  692. translate_table(const char *name,
  693. unsigned int valid_hooks,
  694. struct ipt_table_info *newinfo,
  695. unsigned int size,
  696. unsigned int number,
  697. const unsigned int *hook_entries,
  698. const unsigned int *underflows)
  699. {
  700. unsigned int i;
  701. int ret;
  702. newinfo->size = size;
  703. newinfo->number = number;
  704. /* Init all hooks to impossible value. */
  705. for (i = 0; i < NF_IP_NUMHOOKS; i++) {
  706. newinfo->hook_entry[i] = 0xFFFFFFFF;
  707. newinfo->underflow[i] = 0xFFFFFFFF;
  708. }
  709. duprintf("translate_table: size %un", newinfo->size);
  710. i = 0;
  711. /* Walk through entries, checking offsets. */
  712. ret = IPT_ENTRY_ITERATE(newinfo->entries, newinfo->size,
  713. check_entry_size_and_hooks,
  714. newinfo,
  715. newinfo->entries,
  716. newinfo->entries + size,
  717. hook_entries, underflows, &i);
  718. if (ret != 0)
  719. return ret;
  720. if (i != number) {
  721. duprintf("translate_table: %u not %u entriesn",
  722.  i, number);
  723. return -EINVAL;
  724. }
  725. /* Check hooks all assigned */
  726. for (i = 0; i < NF_IP_NUMHOOKS; i++) {
  727. /* Only hooks which are valid */
  728. if (!(valid_hooks & (1 << i)))
  729. continue;
  730. if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
  731. duprintf("Invalid hook entry %u %un",
  732.  i, hook_entries[i]);
  733. return -EINVAL;
  734. }
  735. if (newinfo->underflow[i] == 0xFFFFFFFF) {
  736. duprintf("Invalid underflow %u %un",
  737.  i, underflows[i]);
  738. return -EINVAL;
  739. }
  740. }
  741. if (!mark_source_chains(newinfo, valid_hooks))
  742. return -ELOOP;
  743. /* Finally, each sanity check must pass */
  744. i = 0;
  745. ret = IPT_ENTRY_ITERATE(newinfo->entries, newinfo->size,
  746. check_entry, name, size, &i);
  747. if (ret != 0) {
  748. IPT_ENTRY_ITERATE(newinfo->entries, newinfo->size,
  749.   cleanup_entry, &i);
  750. return ret;
  751. }
  752. /* And one copy for every other CPU */
  753. for (i = 1; i < smp_num_cpus; i++) {
  754. memcpy(newinfo->entries + SMP_ALIGN(newinfo->size)*i,
  755.        newinfo->entries,
  756.        SMP_ALIGN(newinfo->size));
  757. }
  758. return ret;
  759. }
  760. static struct ipt_table_info *
  761. replace_table(struct ipt_table *table,
  762.       unsigned int num_counters,
  763.       struct ipt_table_info *newinfo,
  764.       int *error)
  765. {
  766. struct ipt_table_info *oldinfo;
  767. #ifdef CONFIG_NETFILTER_DEBUG
  768. {
  769. struct ipt_entry *table_base;
  770. unsigned int i;
  771. for (i = 0; i < smp_num_cpus; i++) {
  772. table_base =
  773. (void *)newinfo->entries
  774. + TABLE_OFFSET(newinfo, i);
  775. table_base->comefrom = 0xdead57ac;
  776. }
  777. }
  778. #endif
  779. /* Do the substitution. */
  780. write_lock_bh(&table->lock);
  781. /* Check inside lock: is the old number correct? */
  782. if (num_counters != table->private->number) {
  783. duprintf("num_counters != table->private->number (%u/%u)n",
  784.  num_counters, table->private->number);
  785. write_unlock_bh(&table->lock);
  786. *error = -EAGAIN;
  787. return NULL;
  788. }
  789. oldinfo = table->private;
  790. table->private = newinfo;
  791. newinfo->initial_entries = oldinfo->initial_entries;
  792. write_unlock_bh(&table->lock);
  793. return oldinfo;
  794. }
  795. /* Gets counters. */
  796. static inline int
  797. add_entry_to_counter(const struct ipt_entry *e,
  798.      struct ipt_counters total[],
  799.      unsigned int *i)
  800. {
  801. ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
  802. (*i)++;
  803. return 0;
  804. }
  805. static void
  806. get_counters(const struct ipt_table_info *t,
  807.      struct ipt_counters counters[])
  808. {
  809. unsigned int cpu;
  810. unsigned int i;
  811. for (cpu = 0; cpu < smp_num_cpus; cpu++) {
  812. i = 0;
  813. IPT_ENTRY_ITERATE(t->entries + TABLE_OFFSET(t, cpu),
  814.   t->size,
  815.   add_entry_to_counter,
  816.   counters,
  817.   &i);
  818. }
  819. }
  820. static int
  821. copy_entries_to_user(unsigned int total_size,
  822.      struct ipt_table *table,
  823.      void *userptr)
  824. {
  825. unsigned int off, num, countersize;
  826. struct ipt_entry *e;
  827. struct ipt_counters *counters;
  828. int ret = 0;
  829. /* We need atomic snapshot of counters: rest doesn't change
  830.    (other than comefrom, which userspace doesn't care
  831.    about). */
  832. countersize = sizeof(struct ipt_counters) * table->private->number;
  833. counters = vmalloc(countersize);
  834. if (counters == NULL)
  835. return -ENOMEM;
  836. /* First, sum counters... */
  837. memset(counters, 0, countersize);
  838. write_lock_bh(&table->lock);
  839. get_counters(table->private, counters);
  840. write_unlock_bh(&table->lock);
  841. /* ... then copy entire thing from CPU 0... */
  842. if (copy_to_user(userptr, table->private->entries, total_size) != 0) {
  843. ret = -EFAULT;
  844. goto free_counters;
  845. }
  846. /* FIXME: use iterator macros --RR */
  847. /* ... then go back and fix counters and names */
  848. for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
  849. unsigned int i;
  850. struct ipt_entry_match *m;
  851. struct ipt_entry_target *t;
  852. e = (struct ipt_entry *)(table->private->entries + off);
  853. if (copy_to_user(userptr + off
  854.  + offsetof(struct ipt_entry, counters),
  855.  &counters[num],
  856.  sizeof(counters[num])) != 0) {
  857. ret = -EFAULT;
  858. goto free_counters;
  859. }
  860. for (i = sizeof(struct ipt_entry);
  861.      i < e->target_offset;
  862.      i += m->u.match_size) {
  863. m = (void *)e + i;
  864. if (copy_to_user(userptr + off + i
  865.  + offsetof(struct ipt_entry_match,
  866.     u.user.name),
  867.  m->u.kernel.match->name,
  868.  strlen(m->u.kernel.match->name)+1)
  869.     != 0) {
  870. ret = -EFAULT;
  871. goto free_counters;
  872. }
  873. }
  874. t = ipt_get_target(e);
  875. if (copy_to_user(userptr + off + e->target_offset
  876.  + offsetof(struct ipt_entry_target,
  877.     u.user.name),
  878.  t->u.kernel.target->name,
  879.  strlen(t->u.kernel.target->name)+1) != 0) {
  880. ret = -EFAULT;
  881. goto free_counters;
  882. }
  883. }
  884.  free_counters:
  885. vfree(counters);
  886. return ret;
  887. }
  888. static int
  889. get_entries(const struct ipt_get_entries *entries,
  890.     struct ipt_get_entries *uptr)
  891. {
  892. int ret;
  893. struct ipt_table *t;
  894. t = find_table_lock(entries->name, &ret, &ipt_mutex);
  895. if (t) {
  896. duprintf("t->private->number = %un",
  897.  t->private->number);
  898. if (entries->size == t->private->size)
  899. ret = copy_entries_to_user(t->private->size,
  900.    t, uptr->entrytable);
  901. else {
  902. duprintf("get_entries: I've got %u not %u!n",
  903.  t->private->size,
  904.  entries->size);
  905. ret = -EINVAL;
  906. }
  907. up(&ipt_mutex);
  908. } else
  909. duprintf("get_entries: Can't find %s!n",
  910.  entries->name);
  911. return ret;
  912. }
  913. static int
  914. do_replace(void *user, unsigned int len)
  915. {
  916. int ret;
  917. struct ipt_replace tmp;
  918. struct ipt_table *t;
  919. struct ipt_table_info *newinfo, *oldinfo;
  920. struct ipt_counters *counters;
  921. if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
  922. return -EFAULT;
  923. /* Hack: Causes ipchains to give correct error msg --RR */
  924. if (len != sizeof(tmp) + tmp.size)
  925. return -ENOPROTOOPT;
  926. /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */
  927. if ((SMP_ALIGN(tmp.size) >> PAGE_SHIFT) + 2 > num_physpages)
  928. return -ENOMEM;
  929. newinfo = vmalloc(sizeof(struct ipt_table_info)
  930.   + SMP_ALIGN(tmp.size) * smp_num_cpus);
  931. if (!newinfo)
  932. return -ENOMEM;
  933. if (copy_from_user(newinfo->entries, user + sizeof(tmp),
  934.    tmp.size) != 0) {
  935. ret = -EFAULT;
  936. goto free_newinfo;
  937. }
  938. counters = vmalloc(tmp.num_counters * sizeof(struct ipt_counters));
  939. if (!counters) {
  940. ret = -ENOMEM;
  941. goto free_newinfo;
  942. }
  943. memset(counters, 0, tmp.num_counters * sizeof(struct ipt_counters));
  944. ret = translate_table(tmp.name, tmp.valid_hooks,
  945.       newinfo, tmp.size, tmp.num_entries,
  946.       tmp.hook_entry, tmp.underflow);
  947. if (ret != 0)
  948. goto free_newinfo_counters;
  949. duprintf("ip_tables: Translated tablen");
  950. t = find_table_lock(tmp.name, &ret, &ipt_mutex);
  951. if (!t)
  952. goto free_newinfo_counters_untrans;
  953. /* You lied! */
  954. if (tmp.valid_hooks != t->valid_hooks) {
  955. duprintf("Valid hook crap: %08X vs %08Xn",
  956.  tmp.valid_hooks, t->valid_hooks);
  957. ret = -EINVAL;
  958. goto free_newinfo_counters_untrans_unlock;
  959. }
  960. oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret);
  961. if (!oldinfo)
  962. goto free_newinfo_counters_untrans_unlock;
  963. /* Update module usage count based on number of rules */
  964. duprintf("do_replace: oldnum=%u, initnum=%u, newnum=%un",
  965. oldinfo->number, oldinfo->initial_entries, newinfo->number);
  966. if (t->me && (oldinfo->number <= oldinfo->initial_entries) &&
  967.       (newinfo->number > oldinfo->initial_entries))
  968. __MOD_INC_USE_COUNT(t->me);
  969. else if (t->me && (oldinfo->number > oldinfo->initial_entries) &&
  970.    (newinfo->number <= oldinfo->initial_entries))
  971. __MOD_DEC_USE_COUNT(t->me);
  972. /* Get the old counters. */
  973. get_counters(oldinfo, counters);
  974. /* Decrease module usage counts and free resource */
  975. IPT_ENTRY_ITERATE(oldinfo->entries, oldinfo->size, cleanup_entry,NULL);
  976. vfree(oldinfo);
  977. /* Silent error: too late now. */
  978. copy_to_user(tmp.counters, counters,
  979.      sizeof(struct ipt_counters) * tmp.num_counters);
  980. vfree(counters);
  981. up(&ipt_mutex);
  982. return 0;
  983.  free_newinfo_counters_untrans_unlock:
  984. up(&ipt_mutex);
  985.  free_newinfo_counters_untrans:
  986. IPT_ENTRY_ITERATE(newinfo->entries, newinfo->size, cleanup_entry,NULL);
  987.  free_newinfo_counters:
  988. vfree(counters);
  989.  free_newinfo:
  990. vfree(newinfo);
  991. return ret;
  992. }
  993. /* We're lazy, and add to the first CPU; overflow works its fey magic
  994.  * and everything is OK. */
  995. static inline int
  996. add_counter_to_entry(struct ipt_entry *e,
  997.      const struct ipt_counters addme[],
  998.      unsigned int *i)
  999. {
  1000. #if 0
  1001. duprintf("add_counter: Entry %u %lu/%lu + %lu/%lun",
  1002.  *i,
  1003.  (long unsigned int)e->counters.pcnt,
  1004.  (long unsigned int)e->counters.bcnt,
  1005.  (long unsigned int)addme[*i].pcnt,
  1006.  (long unsigned int)addme[*i].bcnt);
  1007. #endif
  1008. ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
  1009. (*i)++;
  1010. return 0;
  1011. }
  1012. static int
  1013. do_add_counters(void *user, unsigned int len)
  1014. {
  1015. unsigned int i;
  1016. struct ipt_counters_info tmp, *paddc;
  1017. struct ipt_table *t;
  1018. int ret;
  1019. if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
  1020. return -EFAULT;
  1021. if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct ipt_counters))
  1022. return -EINVAL;
  1023. paddc = vmalloc(len);
  1024. if (!paddc)
  1025. return -ENOMEM;
  1026. if (copy_from_user(paddc, user, len) != 0) {
  1027. ret = -EFAULT;
  1028. goto free;
  1029. }
  1030. t = find_table_lock(tmp.name, &ret, &ipt_mutex);
  1031. if (!t)
  1032. goto free;
  1033. write_lock_bh(&t->lock);
  1034. if (t->private->number != paddc->num_counters) {
  1035. ret = -EINVAL;
  1036. goto unlock_up_free;
  1037. }
  1038. i = 0;
  1039. IPT_ENTRY_ITERATE(t->private->entries,
  1040.   t->private->size,
  1041.   add_counter_to_entry,
  1042.   paddc->counters,
  1043.   &i);
  1044.  unlock_up_free:
  1045. write_unlock_bh(&t->lock);
  1046. up(&ipt_mutex);
  1047.  free:
  1048. vfree(paddc);
  1049. return ret;
  1050. }
  1051. static int
  1052. do_ipt_set_ctl(struct sock *sk, int cmd, void *user, unsigned int len)
  1053. {
  1054. int ret;
  1055. if (!capable(CAP_NET_ADMIN))
  1056. return -EPERM;
  1057. switch (cmd) {
  1058. case IPT_SO_SET_REPLACE:
  1059. ret = do_replace(user, len);
  1060. break;
  1061. case IPT_SO_SET_ADD_COUNTERS:
  1062. ret = do_add_counters(user, len);
  1063. break;
  1064. default:
  1065. duprintf("do_ipt_set_ctl:  unknown request %in", cmd);
  1066. ret = -EINVAL;
  1067. }
  1068. return ret;
  1069. }
  1070. static int
  1071. do_ipt_get_ctl(struct sock *sk, int cmd, void *user, int *len)
  1072. {
  1073. int ret;
  1074. if (!capable(CAP_NET_ADMIN))
  1075. return -EPERM;
  1076. switch (cmd) {
  1077. case IPT_SO_GET_INFO: {
  1078. char name[IPT_TABLE_MAXNAMELEN];
  1079. struct ipt_table *t;
  1080. if (*len != sizeof(struct ipt_getinfo)) {
  1081. duprintf("length %u != %un", *len,
  1082.  sizeof(struct ipt_getinfo));
  1083. ret = -EINVAL;
  1084. break;
  1085. }
  1086. if (copy_from_user(name, user, sizeof(name)) != 0) {
  1087. ret = -EFAULT;
  1088. break;
  1089. }
  1090. name[IPT_TABLE_MAXNAMELEN-1] = '';
  1091. t = find_table_lock(name, &ret, &ipt_mutex);
  1092. if (t) {
  1093. struct ipt_getinfo info;
  1094. info.valid_hooks = t->valid_hooks;
  1095. memcpy(info.hook_entry, t->private->hook_entry,
  1096.        sizeof(info.hook_entry));
  1097. memcpy(info.underflow, t->private->underflow,
  1098.        sizeof(info.underflow));
  1099. info.num_entries = t->private->number;
  1100. info.size = t->private->size;
  1101. strcpy(info.name, name);
  1102. if (copy_to_user(user, &info, *len) != 0)
  1103. ret = -EFAULT;
  1104. else
  1105. ret = 0;
  1106. up(&ipt_mutex);
  1107. }
  1108. }
  1109. break;
  1110. case IPT_SO_GET_ENTRIES: {
  1111. struct ipt_get_entries get;
  1112. if (*len < sizeof(get)) {
  1113. duprintf("get_entries: %u < %un", *len, sizeof(get));
  1114. ret = -EINVAL;
  1115. } else if (copy_from_user(&get, user, sizeof(get)) != 0) {
  1116. ret = -EFAULT;
  1117. } else if (*len != sizeof(struct ipt_get_entries) + get.size) {
  1118. duprintf("get_entries: %u != %un", *len,
  1119.  sizeof(struct ipt_get_entries) + get.size);
  1120. ret = -EINVAL;
  1121. } else
  1122. ret = get_entries(&get, user);
  1123. break;
  1124. }
  1125. default:
  1126. duprintf("do_ipt_get_ctl: unknown request %in", cmd);
  1127. ret = -EINVAL;
  1128. }
  1129. return ret;
  1130. }
  1131. /* Registration hooks for targets. */
  1132. int
  1133. ipt_register_target(struct ipt_target *target)
  1134. {
  1135. int ret;
  1136. MOD_INC_USE_COUNT;
  1137. ret = down_interruptible(&ipt_mutex);
  1138. if (ret != 0) {
  1139. MOD_DEC_USE_COUNT;
  1140. return ret;
  1141. }
  1142. if (!list_named_insert(&ipt_target, target)) {
  1143. duprintf("ipt_register_target: `%s' already in list!n",
  1144.  target->name);
  1145. ret = -EINVAL;
  1146. MOD_DEC_USE_COUNT;
  1147. }
  1148. up(&ipt_mutex);
  1149. return ret;
  1150. }
  1151. void
  1152. ipt_unregister_target(struct ipt_target *target)
  1153. {
  1154. down(&ipt_mutex);
  1155. LIST_DELETE(&ipt_target, target);
  1156. up(&ipt_mutex);
  1157. MOD_DEC_USE_COUNT;
  1158. }
  1159. int
  1160. ipt_register_match(struct ipt_match *match)
  1161. {
  1162. int ret;
  1163. MOD_INC_USE_COUNT;
  1164. ret = down_interruptible(&ipt_mutex);
  1165. if (ret != 0) {
  1166. MOD_DEC_USE_COUNT;
  1167. return ret;
  1168. }
  1169. if (!list_named_insert(&ipt_match, match)) {
  1170. duprintf("ipt_register_match: `%s' already in list!n",
  1171.  match->name);
  1172. MOD_DEC_USE_COUNT;
  1173. ret = -EINVAL;
  1174. }
  1175. up(&ipt_mutex);
  1176. return ret;
  1177. }
  1178. void
  1179. ipt_unregister_match(struct ipt_match *match)
  1180. {
  1181. down(&ipt_mutex);
  1182. LIST_DELETE(&ipt_match, match);
  1183. up(&ipt_mutex);
  1184. MOD_DEC_USE_COUNT;
  1185. }
  1186. int ipt_register_table(struct ipt_table *table)
  1187. {
  1188. int ret;
  1189. struct ipt_table_info *newinfo;
  1190. static struct ipt_table_info bootstrap
  1191. = { 0, 0, 0, { 0 }, { 0 }, { } };
  1192. MOD_INC_USE_COUNT;
  1193. newinfo = vmalloc(sizeof(struct ipt_table_info)
  1194.   + SMP_ALIGN(table->table->size) * smp_num_cpus);
  1195. if (!newinfo) {
  1196. ret = -ENOMEM;
  1197. MOD_DEC_USE_COUNT;
  1198. return ret;
  1199. }
  1200. memcpy(newinfo->entries, table->table->entries, table->table->size);
  1201. ret = translate_table(table->name, table->valid_hooks,
  1202.       newinfo, table->table->size,
  1203.       table->table->num_entries,
  1204.       table->table->hook_entry,
  1205.       table->table->underflow);
  1206. if (ret != 0) {
  1207. vfree(newinfo);
  1208. MOD_DEC_USE_COUNT;
  1209. return ret;
  1210. }
  1211. ret = down_interruptible(&ipt_mutex);
  1212. if (ret != 0) {
  1213. vfree(newinfo);
  1214. MOD_DEC_USE_COUNT;
  1215. return ret;
  1216. }
  1217. /* Don't autoload: we'd eat our tail... */
  1218. if (list_named_find(&ipt_tables, table->name)) {
  1219. ret = -EEXIST;
  1220. goto free_unlock;
  1221. }
  1222. /* Simplifies replace_table code. */
  1223. table->private = &bootstrap;
  1224. if (!replace_table(table, 0, newinfo, &ret))
  1225. goto free_unlock;
  1226. duprintf("table->private->number = %un",
  1227.  table->private->number);
  1228. /* save number of initial entries */
  1229. table->private->initial_entries = table->private->number;
  1230. table->lock = RW_LOCK_UNLOCKED;
  1231. list_prepend(&ipt_tables, table);
  1232.  unlock:
  1233. up(&ipt_mutex);
  1234. return ret;
  1235.  free_unlock:
  1236. vfree(newinfo);
  1237. MOD_DEC_USE_COUNT;
  1238. goto unlock;
  1239. }
  1240. void ipt_unregister_table(struct ipt_table *table)
  1241. {
  1242. down(&ipt_mutex);
  1243. LIST_DELETE(&ipt_tables, table);
  1244. up(&ipt_mutex);
  1245. /* Decrease module usage counts and free resources */
  1246. IPT_ENTRY_ITERATE(table->private->entries, table->private->size,
  1247.   cleanup_entry, NULL);
  1248. vfree(table->private);
  1249. MOD_DEC_USE_COUNT;
  1250. }
  1251. /* Returns 1 if the port is matched by the range, 0 otherwise */
  1252. static inline int
  1253. port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert)
  1254. {
  1255. int ret;
  1256. ret = (port >= min && port <= max) ^ invert;
  1257. return ret;
  1258. }
  1259. static int
  1260. tcp_find_option(u_int8_t option,
  1261. const struct tcphdr *tcp,
  1262. u_int16_t datalen,
  1263. int invert,
  1264. int *hotdrop)
  1265. {
  1266. unsigned int i = sizeof(struct tcphdr);
  1267. const u_int8_t *opt = (u_int8_t *)tcp;
  1268. duprintf("tcp_match: finding optionn");
  1269. /* If we don't have the whole header, drop packet. */
  1270. if (tcp->doff * 4 > datalen) {
  1271. *hotdrop = 1;
  1272. return 0;
  1273. }
  1274. while (i < tcp->doff * 4) {
  1275. if (opt[i] == option) return !invert;
  1276. if (opt[i] < 2) i++;
  1277. else i += opt[i+1]?:1;
  1278. }
  1279. return invert;
  1280. }
  1281. static int
  1282. tcp_match(const struct sk_buff *skb,
  1283.   const struct net_device *in,
  1284.   const struct net_device *out,
  1285.   const void *matchinfo,
  1286.   int offset,
  1287.   const void *hdr,
  1288.   u_int16_t datalen,
  1289.   int *hotdrop)
  1290. {
  1291. const struct tcphdr *tcp = hdr;
  1292. const struct ipt_tcp *tcpinfo = matchinfo;
  1293. /* To quote Alan:
  1294.    Don't allow a fragment of TCP 8 bytes in. Nobody normal
  1295.    causes this. Its a cracker trying to break in by doing a
  1296.    flag overwrite to pass the direction checks.
  1297. */
  1298. if (offset == 1) {
  1299. duprintf("Dropping evil TCP offset=1 frag.n");
  1300. *hotdrop = 1;
  1301. return 0;
  1302. } else if (offset == 0 && datalen < sizeof(struct tcphdr)) {
  1303. /* We've been asked to examine this packet, and we
  1304.    can't.  Hence, no choice but to drop. */
  1305. duprintf("Dropping evil TCP offset=0 tinygram.n");
  1306. *hotdrop = 1;
  1307. return 0;
  1308. }
  1309. /* FIXME: Try tcp doff >> packet len against various stacks --RR */
  1310. #define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
  1311. /* Must not be a fragment. */
  1312. return !offset
  1313. && port_match(tcpinfo->spts[0], tcpinfo->spts[1],
  1314.       ntohs(tcp->source),
  1315.       !!(tcpinfo->invflags & IPT_TCP_INV_SRCPT))
  1316. && port_match(tcpinfo->dpts[0], tcpinfo->dpts[1],
  1317.       ntohs(tcp->dest),
  1318.       !!(tcpinfo->invflags & IPT_TCP_INV_DSTPT))
  1319. && FWINVTCP((((unsigned char *)tcp)[13]
  1320.      & tcpinfo->flg_mask)
  1321.     == tcpinfo->flg_cmp,
  1322.     IPT_TCP_INV_FLAGS)
  1323. && (!tcpinfo->option
  1324.     || tcp_find_option(tcpinfo->option, tcp, datalen,
  1325.        tcpinfo->invflags
  1326.        & IPT_TCP_INV_OPTION,
  1327.        hotdrop));
  1328. }
  1329. /* Called when user tries to insert an entry of this type. */
  1330. static int
  1331. tcp_checkentry(const char *tablename,
  1332.        const struct ipt_ip *ip,
  1333.        void *matchinfo,
  1334.        unsigned int matchsize,
  1335.        unsigned int hook_mask)
  1336. {
  1337. const struct ipt_tcp *tcpinfo = matchinfo;
  1338. /* Must specify proto == TCP, and no unknown invflags */
  1339. return ip->proto == IPPROTO_TCP
  1340. && !(ip->invflags & IPT_INV_PROTO)
  1341. && matchsize == IPT_ALIGN(sizeof(struct ipt_tcp))
  1342. && !(tcpinfo->invflags & ~IPT_TCP_INV_MASK);
  1343. }
  1344. static int
  1345. udp_match(const struct sk_buff *skb,
  1346.   const struct net_device *in,
  1347.   const struct net_device *out,
  1348.   const void *matchinfo,
  1349.   int offset,
  1350.   const void *hdr,
  1351.   u_int16_t datalen,
  1352.   int *hotdrop)
  1353. {
  1354. const struct udphdr *udp = hdr;
  1355. const struct ipt_udp *udpinfo = matchinfo;
  1356. if (offset == 0 && datalen < sizeof(struct udphdr)) {
  1357. /* We've been asked to examine this packet, and we
  1358.    can't.  Hence, no choice but to drop. */
  1359. duprintf("Dropping evil UDP tinygram.n");
  1360. *hotdrop = 1;
  1361. return 0;
  1362. }
  1363. /* Must not be a fragment. */
  1364. return !offset
  1365. && port_match(udpinfo->spts[0], udpinfo->spts[1],
  1366.       ntohs(udp->source),
  1367.       !!(udpinfo->invflags & IPT_UDP_INV_SRCPT))
  1368. && port_match(udpinfo->dpts[0], udpinfo->dpts[1],
  1369.       ntohs(udp->dest),
  1370.       !!(udpinfo->invflags & IPT_UDP_INV_DSTPT));
  1371. }
  1372. /* Called when user tries to insert an entry of this type. */
  1373. static int
  1374. udp_checkentry(const char *tablename,
  1375.        const struct ipt_ip *ip,
  1376.        void *matchinfo,
  1377.        unsigned int matchinfosize,
  1378.        unsigned int hook_mask)
  1379. {
  1380. const struct ipt_udp *udpinfo = matchinfo;
  1381. /* Must specify proto == UDP, and no unknown invflags */
  1382. if (ip->proto != IPPROTO_UDP || (ip->invflags & IPT_INV_PROTO)) {
  1383. duprintf("ipt_udp: Protocol %u != %un", ip->proto,
  1384.  IPPROTO_UDP);
  1385. return 0;
  1386. }
  1387. if (matchinfosize != IPT_ALIGN(sizeof(struct ipt_udp))) {
  1388. duprintf("ipt_udp: matchsize %u != %un",
  1389.  matchinfosize, IPT_ALIGN(sizeof(struct ipt_udp)));
  1390. return 0;
  1391. }
  1392. if (udpinfo->invflags & ~IPT_UDP_INV_MASK) {
  1393. duprintf("ipt_udp: unknown flags %Xn",
  1394.  udpinfo->invflags);
  1395. return 0;
  1396. }
  1397. return 1;
  1398. }
  1399. /* Returns 1 if the type and code is matched by the range, 0 otherwise */
  1400. static inline int
  1401. icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
  1402.      u_int8_t type, u_int8_t code,
  1403.      int invert)
  1404. {
  1405. return (type == test_type && code >= min_code && code <= max_code)
  1406. ^ invert;
  1407. }
  1408. static int
  1409. icmp_match(const struct sk_buff *skb,
  1410.    const struct net_device *in,
  1411.    const struct net_device *out,
  1412.    const void *matchinfo,
  1413.    int offset,
  1414.    const void *hdr,
  1415.    u_int16_t datalen,
  1416.    int *hotdrop)
  1417. {
  1418. const struct icmphdr *icmp = hdr;
  1419. const struct ipt_icmp *icmpinfo = matchinfo;
  1420. if (offset == 0 && datalen < 2) {
  1421. /* We've been asked to examine this packet, and we
  1422.    can't.  Hence, no choice but to drop. */
  1423. duprintf("Dropping evil ICMP tinygram.n");
  1424. *hotdrop = 1;
  1425. return 0;
  1426. }
  1427. /* Must not be a fragment. */
  1428. return !offset
  1429. && icmp_type_code_match(icmpinfo->type,
  1430. icmpinfo->code[0],
  1431. icmpinfo->code[1],
  1432. icmp->type, icmp->code,
  1433. !!(icmpinfo->invflags&IPT_ICMP_INV));
  1434. }
  1435. /* Called when user tries to insert an entry of this type. */
  1436. static int
  1437. icmp_checkentry(const char *tablename,
  1438.    const struct ipt_ip *ip,
  1439.    void *matchinfo,
  1440.    unsigned int matchsize,
  1441.    unsigned int hook_mask)
  1442. {
  1443. const struct ipt_icmp *icmpinfo = matchinfo;
  1444. /* Must specify proto == ICMP, and no unknown invflags */
  1445. return ip->proto == IPPROTO_ICMP
  1446. && !(ip->invflags & IPT_INV_PROTO)
  1447. && matchsize == IPT_ALIGN(sizeof(struct ipt_icmp))
  1448. && !(icmpinfo->invflags & ~IPT_ICMP_INV);
  1449. }
  1450. /* The built-in targets: standard (NULL) and error. */
  1451. static struct ipt_target ipt_standard_target
  1452. = { { NULL, NULL }, IPT_STANDARD_TARGET, NULL, NULL, NULL };
  1453. static struct ipt_target ipt_error_target
  1454. = { { NULL, NULL }, IPT_ERROR_TARGET, ipt_error, NULL, NULL };
  1455. static struct nf_sockopt_ops ipt_sockopts
  1456. = { { NULL, NULL }, PF_INET, IPT_BASE_CTL, IPT_SO_SET_MAX+1, do_ipt_set_ctl,
  1457.     IPT_BASE_CTL, IPT_SO_GET_MAX+1, do_ipt_get_ctl, 0, NULL  };
  1458. static struct ipt_match tcp_matchstruct
  1459. = { { NULL, NULL }, "tcp", &tcp_match, &tcp_checkentry, NULL };
  1460. static struct ipt_match udp_matchstruct
  1461. = { { NULL, NULL }, "udp", &udp_match, &udp_checkentry, NULL };
  1462. static struct ipt_match icmp_matchstruct
  1463. = { { NULL, NULL }, "icmp", &icmp_match, &icmp_checkentry, NULL };
  1464. #ifdef CONFIG_PROC_FS
  1465. static inline int print_name(const struct ipt_table *t,
  1466.      off_t start_offset, char *buffer, int length,
  1467.      off_t *pos, unsigned int *count)
  1468. {
  1469. if ((*count)++ >= start_offset) {
  1470. unsigned int namelen;
  1471. namelen = sprintf(buffer + *pos, "%sn", t->name);
  1472. if (*pos + namelen > length) {
  1473. /* Stop iterating */
  1474. return 1;
  1475. }
  1476. *pos += namelen;
  1477. }
  1478. return 0;
  1479. }
  1480. static int ipt_get_tables(char *buffer, char **start, off_t offset, int length)
  1481. {
  1482. off_t pos = 0;
  1483. unsigned int count = 0;
  1484. if (down_interruptible(&ipt_mutex) != 0)
  1485. return 0;
  1486. LIST_FIND(&ipt_tables, print_name, struct ipt_table *,
  1487.   offset, buffer, length, &pos, &count);
  1488. up(&ipt_mutex);
  1489. /* `start' hack - see fs/proc/generic.c line ~105 */
  1490. *start=(char *)((unsigned long)count-offset);
  1491. return pos;
  1492. }
  1493. #endif /*CONFIG_PROC_FS*/
  1494. static int __init init(void)
  1495. {
  1496. int ret;
  1497. /* Noone else will be downing sem now, so we won't sleep */
  1498. down(&ipt_mutex);
  1499. list_append(&ipt_target, &ipt_standard_target);
  1500. list_append(&ipt_target, &ipt_error_target);
  1501. list_append(&ipt_match, &tcp_matchstruct);
  1502. list_append(&ipt_match, &udp_matchstruct);
  1503. list_append(&ipt_match, &icmp_matchstruct);
  1504. up(&ipt_mutex);
  1505. /* Register setsockopt */
  1506. ret = nf_register_sockopt(&ipt_sockopts);
  1507. if (ret < 0) {
  1508. duprintf("Unable to register sockopts.n");
  1509. return ret;
  1510. }
  1511. #ifdef CONFIG_PROC_FS
  1512. {
  1513. struct proc_dir_entry *proc;
  1514. proc = proc_net_create("ip_tables_names", 0, ipt_get_tables);
  1515. if (!proc) {
  1516. nf_unregister_sockopt(&ipt_sockopts);
  1517. return -ENOMEM;
  1518. }
  1519. proc->owner = THIS_MODULE;
  1520. }
  1521. #endif
  1522. printk("ip_tables: (C) 2000-2002 Netfilter core teamn");
  1523. return 0;
  1524. }
  1525. static void __exit fini(void)
  1526. {
  1527. nf_unregister_sockopt(&ipt_sockopts);
  1528. #ifdef CONFIG_PROC_FS
  1529. proc_net_remove("ip_tables_names");
  1530. #endif
  1531. }
  1532. EXPORT_SYMBOL(ipt_register_table);
  1533. EXPORT_SYMBOL(ipt_unregister_table);
  1534. EXPORT_SYMBOL(ipt_register_match);
  1535. EXPORT_SYMBOL(ipt_unregister_match);
  1536. EXPORT_SYMBOL(ipt_do_table);
  1537. EXPORT_SYMBOL(ipt_register_target);
  1538. EXPORT_SYMBOL(ipt_unregister_target);
  1539. module_init(init);
  1540. module_exit(fini);
  1541. MODULE_LICENSE("GPL");