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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* netfilter.c: look after the filters for various protocols. 
  2.  * Heavily influenced by the old firewall.c by David Bonn and Alan Cox.
  3.  *
  4.  * Thanks to Rob `CmdrTaco' Malda for not influencing this code in any
  5.  * way.
  6.  *
  7.  * Rusty Russell (C)2000 -- This code is GPL.
  8.  *
  9.  * February 2000: Modified by James Morris to have 1 queue per protocol.
  10.  * 15-Mar-2000:   Added NF_REPEAT --RR.
  11.  */
  12. #include <linux/config.h>
  13. #include <linux/netfilter.h>
  14. #include <net/protocol.h>
  15. #include <linux/init.h>
  16. #include <linux/skbuff.h>
  17. #include <linux/wait.h>
  18. #include <linux/module.h>
  19. #include <linux/interrupt.h>
  20. #include <linux/if.h>
  21. #include <linux/netdevice.h>
  22. #include <linux/brlock.h>
  23. #include <linux/inetdevice.h>
  24. #include <net/sock.h>
  25. #include <net/route.h>
  26. #include <linux/ip.h>
  27. #define __KERNEL_SYSCALLS__
  28. #include <linux/unistd.h>
  29. /* In this code, we can be waiting indefinitely for userspace to
  30.  * service a packet if a hook returns NF_QUEUE.  We could keep a count
  31.  * of skbuffs queued for userspace, and not deregister a hook unless
  32.  * this is zero, but that sucks.  Now, we simply check when the
  33.  * packets come back: if the hook is gone, the packet is discarded. */
  34. #ifdef CONFIG_NETFILTER_DEBUG
  35. #define NFDEBUG(format, args...)  printk(format , ## args)
  36. #else
  37. #define NFDEBUG(format, args...)
  38. #endif
  39. /* Sockopts only registered and called from user context, so
  40.    BR_NETPROTO_LOCK would be overkill.  Also, [gs]etsockopt calls may
  41.    sleep. */
  42. static DECLARE_MUTEX(nf_sockopt_mutex);
  43. struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS];
  44. static LIST_HEAD(nf_sockopts);
  45. /* 
  46.  * A queue handler may be registered for each protocol.  Each is protected by
  47.  * long term mutex.  The handler must provide an an outfn() to accept packets
  48.  * for queueing and must reinject all packets it receives, no matter what.
  49.  */
  50. static struct nf_queue_handler_t {
  51. nf_queue_outfn_t outfn;
  52. void *data;
  53. } queue_handler[NPROTO];
  54. int nf_register_hook(struct nf_hook_ops *reg)
  55. {
  56. struct list_head *i;
  57. br_write_lock_bh(BR_NETPROTO_LOCK);
  58. for (i = nf_hooks[reg->pf][reg->hooknum].next; 
  59.      i != &nf_hooks[reg->pf][reg->hooknum]; 
  60.      i = i->next) {
  61. if (reg->priority < ((struct nf_hook_ops *)i)->priority)
  62. break;
  63. }
  64. list_add(&reg->list, i->prev);
  65. br_write_unlock_bh(BR_NETPROTO_LOCK);
  66. return 0;
  67. }
  68. void nf_unregister_hook(struct nf_hook_ops *reg)
  69. {
  70. br_write_lock_bh(BR_NETPROTO_LOCK);
  71. list_del(&reg->list);
  72. br_write_unlock_bh(BR_NETPROTO_LOCK);
  73. }
  74. /* Do exclusive ranges overlap? */
  75. static inline int overlap(int min1, int max1, int min2, int max2)
  76. {
  77. return max1 > min2 && min1 < max2;
  78. }
  79. /* Functions to register sockopt ranges (exclusive). */
  80. int nf_register_sockopt(struct nf_sockopt_ops *reg)
  81. {
  82. struct list_head *i;
  83. int ret = 0;
  84. if (down_interruptible(&nf_sockopt_mutex) != 0)
  85. return -EINTR;
  86. for (i = nf_sockopts.next; i != &nf_sockopts; i = i->next) {
  87. struct nf_sockopt_ops *ops = (struct nf_sockopt_ops *)i;
  88. if (ops->pf == reg->pf
  89.     && (overlap(ops->set_optmin, ops->set_optmax, 
  90. reg->set_optmin, reg->set_optmax)
  91. || overlap(ops->get_optmin, ops->get_optmax, 
  92.    reg->get_optmin, reg->get_optmax))) {
  93. NFDEBUG("nf_sock overlap: %u-%u/%u-%u v %u-%u/%u-%un",
  94. ops->set_optmin, ops->set_optmax, 
  95. ops->get_optmin, ops->get_optmax, 
  96. reg->set_optmin, reg->set_optmax,
  97. reg->get_optmin, reg->get_optmax);
  98. ret = -EBUSY;
  99. goto out;
  100. }
  101. }
  102. list_add(&reg->list, &nf_sockopts);
  103. out:
  104. up(&nf_sockopt_mutex);
  105. return ret;
  106. }
  107. void nf_unregister_sockopt(struct nf_sockopt_ops *reg)
  108. {
  109. /* No point being interruptible: we're probably in cleanup_module() */
  110.  restart:
  111. down(&nf_sockopt_mutex);
  112. if (reg->use != 0) {
  113. /* To be woken by nf_sockopt call... */
  114. /* FIXME: Stuart Young's name appears gratuitously. */
  115. set_current_state(TASK_UNINTERRUPTIBLE);
  116. reg->cleanup_task = current;
  117. up(&nf_sockopt_mutex);
  118. schedule();
  119. goto restart;
  120. }
  121. list_del(&reg->list);
  122. up(&nf_sockopt_mutex);
  123. }
  124. #ifdef CONFIG_NETFILTER_DEBUG
  125. #include <net/ip.h>
  126. #include <net/route.h>
  127. #include <net/tcp.h>
  128. #include <linux/netfilter_ipv4.h>
  129. static void debug_print_hooks_ip(unsigned int nf_debug)
  130. {
  131. if (nf_debug & (1 << NF_IP_PRE_ROUTING)) {
  132. printk("PRE_ROUTING ");
  133. nf_debug ^= (1 << NF_IP_PRE_ROUTING);
  134. }
  135. if (nf_debug & (1 << NF_IP_LOCAL_IN)) {
  136. printk("LOCAL_IN ");
  137. nf_debug ^= (1 << NF_IP_LOCAL_IN);
  138. }
  139. if (nf_debug & (1 << NF_IP_FORWARD)) {
  140. printk("FORWARD ");
  141. nf_debug ^= (1 << NF_IP_FORWARD);
  142. }
  143. if (nf_debug & (1 << NF_IP_LOCAL_OUT)) {
  144. printk("LOCAL_OUT ");
  145. nf_debug ^= (1 << NF_IP_LOCAL_OUT);
  146. }
  147. if (nf_debug & (1 << NF_IP_POST_ROUTING)) {
  148. printk("POST_ROUTING ");
  149. nf_debug ^= (1 << NF_IP_POST_ROUTING);
  150. }
  151. if (nf_debug)
  152. printk("Crap bits: 0x%04X", nf_debug);
  153. printk("n");
  154. }
  155. void nf_dump_skb(int pf, struct sk_buff *skb)
  156. {
  157. printk("skb: pf=%i %s dev=%s len=%un", 
  158.        pf,
  159.        skb->sk ? "(owned)" : "(unowned)",
  160.        skb->dev ? skb->dev->name : "(no dev)",
  161.        skb->len);
  162. switch (pf) {
  163. case PF_INET: {
  164. const struct iphdr *ip = skb->nh.iph;
  165. __u32 *opt = (__u32 *) (ip + 1);
  166. int opti;
  167. __u16 src_port = 0, dst_port = 0;
  168. if (ip->protocol == IPPROTO_TCP
  169.     || ip->protocol == IPPROTO_UDP) {
  170. struct tcphdr *tcp=(struct tcphdr *)((__u32 *)ip+ip->ihl);
  171. src_port = ntohs(tcp->source);
  172. dst_port = ntohs(tcp->dest);
  173. }
  174. printk("PROTO=%d %u.%u.%u.%u:%hu %u.%u.%u.%u:%hu"
  175.        " L=%hu S=0x%2.2hX I=%hu F=0x%4.4hX T=%hu",
  176.        ip->protocol, NIPQUAD(ip->saddr),
  177.        src_port, NIPQUAD(ip->daddr),
  178.        dst_port,
  179.        ntohs(ip->tot_len), ip->tos, ntohs(ip->id),
  180.        ntohs(ip->frag_off), ip->ttl);
  181. for (opti = 0; opti < (ip->ihl - sizeof(struct iphdr) / 4); opti++)
  182. printk(" O=0x%8.8X", *opt++);
  183. printk("n");
  184. }
  185. }
  186. }
  187. void nf_debug_ip_local_deliver(struct sk_buff *skb)
  188. {
  189. /* If it's a loopback packet, it must have come through
  190.  * NF_IP_LOCAL_OUT, NF_IP_RAW_INPUT, NF_IP_PRE_ROUTING and
  191.  * NF_IP_LOCAL_IN.  Otherwise, must have gone through
  192.  * NF_IP_RAW_INPUT and NF_IP_PRE_ROUTING.  */
  193. if (!skb->dev) {
  194. printk("ip_local_deliver: skb->dev is NULL.n");
  195. }
  196. else if (strcmp(skb->dev->name, "lo") == 0) {
  197. if (skb->nf_debug != ((1 << NF_IP_LOCAL_OUT)
  198.       | (1 << NF_IP_POST_ROUTING)
  199.       | (1 << NF_IP_PRE_ROUTING)
  200.       | (1 << NF_IP_LOCAL_IN))) {
  201. printk("ip_local_deliver: bad loopback skb: ");
  202. debug_print_hooks_ip(skb->nf_debug);
  203. nf_dump_skb(PF_INET, skb);
  204. }
  205. }
  206. else {
  207. if (skb->nf_debug != ((1<<NF_IP_PRE_ROUTING)
  208.       | (1<<NF_IP_LOCAL_IN))) {
  209. printk("ip_local_deliver: bad non-lo skb: ");
  210. debug_print_hooks_ip(skb->nf_debug);
  211. nf_dump_skb(PF_INET, skb);
  212. }
  213. }
  214. }
  215. void nf_debug_ip_loopback_xmit(struct sk_buff *newskb)
  216. {
  217. if (newskb->nf_debug != ((1 << NF_IP_LOCAL_OUT)
  218.  | (1 << NF_IP_POST_ROUTING))) {
  219. printk("ip_dev_loopback_xmit: bad owned skb = %p: ", 
  220.        newskb);
  221. debug_print_hooks_ip(newskb->nf_debug);
  222. nf_dump_skb(PF_INET, newskb);
  223. }
  224. /* Clear to avoid confusing input check */
  225. newskb->nf_debug = 0;
  226. }
  227. void nf_debug_ip_finish_output2(struct sk_buff *skb)
  228. {
  229. /* If it's owned, it must have gone through the
  230.  * NF_IP_LOCAL_OUT and NF_IP_POST_ROUTING.
  231.  * Otherwise, must have gone through
  232.  * NF_IP_PRE_ROUTING, NF_IP_FORWARD and NF_IP_POST_ROUTING.
  233.  */
  234. if (skb->sk) {
  235. if (skb->nf_debug != ((1 << NF_IP_LOCAL_OUT)
  236.       | (1 << NF_IP_POST_ROUTING))) {
  237. printk("ip_finish_output: bad owned skb = %p: ", skb);
  238. debug_print_hooks_ip(skb->nf_debug);
  239. nf_dump_skb(PF_INET, skb);
  240. }
  241. } else {
  242. if (skb->nf_debug != ((1 << NF_IP_PRE_ROUTING)
  243.       | (1 << NF_IP_FORWARD)
  244.       | (1 << NF_IP_POST_ROUTING))) {
  245. /* Fragments, entunnelled packets, TCP RSTs
  246.                            generated by ipt_REJECT will have no
  247.                            owners, but still may be local */
  248. if (skb->nf_debug != ((1 << NF_IP_LOCAL_OUT)
  249.       | (1 << NF_IP_POST_ROUTING))){
  250. printk("ip_finish_output:"
  251.        " bad unowned skb = %p: ",skb);
  252. debug_print_hooks_ip(skb->nf_debug);
  253. nf_dump_skb(PF_INET, skb);
  254. }
  255. }
  256. }
  257. }
  258. #endif /*CONFIG_NETFILTER_DEBUG*/
  259. /* Call get/setsockopt() */
  260. static int nf_sockopt(struct sock *sk, int pf, int val, 
  261.       char *opt, int *len, int get)
  262. {
  263. struct list_head *i;
  264. struct nf_sockopt_ops *ops;
  265. int ret;
  266. if (down_interruptible(&nf_sockopt_mutex) != 0)
  267. return -EINTR;
  268. for (i = nf_sockopts.next; i != &nf_sockopts; i = i->next) {
  269. ops = (struct nf_sockopt_ops *)i;
  270. if (ops->pf == pf) {
  271. if (get) {
  272. if (val >= ops->get_optmin
  273.     && val < ops->get_optmax) {
  274. ops->use++;
  275. up(&nf_sockopt_mutex);
  276. ret = ops->get(sk, val, opt, len);
  277. goto out;
  278. }
  279. } else {
  280. if (val >= ops->set_optmin
  281.     && val < ops->set_optmax) {
  282. ops->use++;
  283. up(&nf_sockopt_mutex);
  284. ret = ops->set(sk, val, opt, *len);
  285. goto out;
  286. }
  287. }
  288. }
  289. }
  290. up(&nf_sockopt_mutex);
  291. return -ENOPROTOOPT;
  292.  out:
  293. down(&nf_sockopt_mutex);
  294. ops->use--;
  295. if (ops->cleanup_task)
  296. wake_up_process(ops->cleanup_task);
  297. up(&nf_sockopt_mutex);
  298. return ret;
  299. }
  300. int nf_setsockopt(struct sock *sk, int pf, int val, char *opt,
  301.   int len)
  302. {
  303. return nf_sockopt(sk, pf, val, opt, &len, 0);
  304. }
  305. int nf_getsockopt(struct sock *sk, int pf, int val, char *opt, int *len)
  306. {
  307. return nf_sockopt(sk, pf, val, opt, len, 1);
  308. }
  309. static unsigned int nf_iterate(struct list_head *head,
  310.        struct sk_buff **skb,
  311.        int hook,
  312.        const struct net_device *indev,
  313.        const struct net_device *outdev,
  314.        struct list_head **i,
  315.        int (*okfn)(struct sk_buff *))
  316. {
  317. for (*i = (*i)->next; *i != head; *i = (*i)->next) {
  318. struct nf_hook_ops *elem = (struct nf_hook_ops *)*i;
  319. switch (elem->hook(hook, skb, indev, outdev, okfn)) {
  320. case NF_QUEUE:
  321. return NF_QUEUE;
  322. case NF_STOLEN:
  323. return NF_STOLEN;
  324. case NF_DROP:
  325. return NF_DROP;
  326. case NF_REPEAT:
  327. *i = (*i)->prev;
  328. break;
  329. #ifdef CONFIG_NETFILTER_DEBUG
  330. case NF_ACCEPT:
  331. break;
  332. default:
  333. NFDEBUG("Evil return from %p(%u).n", 
  334. elem->hook, hook);
  335. #endif
  336. }
  337. }
  338. return NF_ACCEPT;
  339. }
  340. int nf_register_queue_handler(int pf, nf_queue_outfn_t outfn, void *data)
  341. {      
  342. int ret;
  343. br_write_lock_bh(BR_NETPROTO_LOCK);
  344. if (queue_handler[pf].outfn)
  345. ret = -EBUSY;
  346. else {
  347. queue_handler[pf].outfn = outfn;
  348. queue_handler[pf].data = data;
  349. ret = 0;
  350. }
  351. br_write_unlock_bh(BR_NETPROTO_LOCK);
  352. return ret;
  353. }
  354. /* The caller must flush their queue before this */
  355. int nf_unregister_queue_handler(int pf)
  356. {
  357. br_write_lock_bh(BR_NETPROTO_LOCK);
  358. queue_handler[pf].outfn = NULL;
  359. queue_handler[pf].data = NULL;
  360. br_write_unlock_bh(BR_NETPROTO_LOCK);
  361. return 0;
  362. }
  363. /* 
  364.  * Any packet that leaves via this function must come back 
  365.  * through nf_reinject().
  366.  */
  367. static void nf_queue(struct sk_buff *skb, 
  368.      struct list_head *elem, 
  369.      int pf, unsigned int hook,
  370.      struct net_device *indev,
  371.      struct net_device *outdev,
  372.      int (*okfn)(struct sk_buff *))
  373. {
  374. int status;
  375. struct nf_info *info;
  376. if (!queue_handler[pf].outfn) {
  377. kfree_skb(skb);
  378. return;
  379. }
  380. info = kmalloc(sizeof(*info), GFP_ATOMIC);
  381. if (!info) {
  382. if (net_ratelimit())
  383. printk(KERN_ERR "OOM queueing packet %pn",
  384.        skb);
  385. kfree_skb(skb);
  386. return;
  387. }
  388. *info = (struct nf_info) { 
  389. (struct nf_hook_ops *)elem, pf, hook, indev, outdev, okfn };
  390. /* Bump dev refs so they don't vanish while packet is out */
  391. if (indev) dev_hold(indev);
  392. if (outdev) dev_hold(outdev);
  393. status = queue_handler[pf].outfn(skb, info, queue_handler[pf].data);
  394. if (status < 0) {
  395. /* James M doesn't say fuck enough. */
  396. if (indev) dev_put(indev);
  397. if (outdev) dev_put(outdev);
  398. kfree(info);
  399. kfree_skb(skb);
  400. return;
  401. }
  402. }
  403. int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
  404.  struct net_device *indev,
  405.  struct net_device *outdev,
  406.  int (*okfn)(struct sk_buff *))
  407. {
  408. struct list_head *elem;
  409. unsigned int verdict;
  410. int ret = 0;
  411. /* This stopgap cannot be removed until all the hooks are audited. */
  412. if (skb_is_nonlinear(skb) && skb_linearize(skb, GFP_ATOMIC) != 0) {
  413. kfree_skb(skb);
  414. return -ENOMEM;
  415. }
  416. if (skb->ip_summed == CHECKSUM_HW) {
  417. if (outdev == NULL) {
  418. skb->ip_summed = CHECKSUM_NONE;
  419. } else {
  420. skb_checksum_help(skb);
  421. }
  422. }
  423. /* We may already have this, but read-locks nest anyway */
  424. br_read_lock_bh(BR_NETPROTO_LOCK);
  425. #ifdef CONFIG_NETFILTER_DEBUG
  426. if (skb->nf_debug & (1 << hook)) {
  427. printk("nf_hook: hook %i already set.n", hook);
  428. nf_dump_skb(pf, skb);
  429. }
  430. skb->nf_debug |= (1 << hook);
  431. #endif
  432. elem = &nf_hooks[pf][hook];
  433. verdict = nf_iterate(&nf_hooks[pf][hook], &skb, hook, indev,
  434.      outdev, &elem, okfn);
  435. if (verdict == NF_QUEUE) {
  436. NFDEBUG("nf_hook: Verdict = QUEUE.n");
  437. nf_queue(skb, elem, pf, hook, indev, outdev, okfn);
  438. }
  439. switch (verdict) {
  440. case NF_ACCEPT:
  441. ret = okfn(skb);
  442. break;
  443. case NF_DROP:
  444. kfree_skb(skb);
  445. ret = -EPERM;
  446. break;
  447. }
  448. br_read_unlock_bh(BR_NETPROTO_LOCK);
  449. return ret;
  450. }
  451. void nf_reinject(struct sk_buff *skb, struct nf_info *info,
  452.  unsigned int verdict)
  453. {
  454. struct list_head *elem = &info->elem->list;
  455. struct list_head *i;
  456. /* We don't have BR_NETPROTO_LOCK here */
  457. br_read_lock_bh(BR_NETPROTO_LOCK);
  458. for (i = nf_hooks[info->pf][info->hook].next; i != elem; i = i->next) {
  459. if (i == &nf_hooks[info->pf][info->hook]) {
  460. /* The module which sent it to userspace is gone. */
  461. NFDEBUG("%s: module disappeared, dropping packet.n",
  462.          __FUNCTION__);
  463. verdict = NF_DROP;
  464. break;
  465. }
  466. }
  467. /* Continue traversal iff userspace said ok... */
  468. if (verdict == NF_REPEAT) {
  469. elem = elem->prev;
  470. verdict = NF_ACCEPT;
  471. }
  472. if (verdict == NF_ACCEPT) {
  473. verdict = nf_iterate(&nf_hooks[info->pf][info->hook],
  474.      &skb, info->hook, 
  475.      info->indev, info->outdev, &elem,
  476.      info->okfn);
  477. }
  478. switch (verdict) {
  479. case NF_ACCEPT:
  480. info->okfn(skb);
  481. break;
  482. case NF_QUEUE:
  483. nf_queue(skb, elem, info->pf, info->hook, 
  484.  info->indev, info->outdev, info->okfn);
  485. break;
  486. case NF_DROP:
  487. kfree_skb(skb);
  488. break;
  489. }
  490. br_read_unlock_bh(BR_NETPROTO_LOCK);
  491. /* Release those devices we held, or Alexey will kill me. */
  492. if (info->indev) dev_put(info->indev);
  493. if (info->outdev) dev_put(info->outdev);
  494. kfree(info);
  495. return;
  496. }
  497. #ifdef CONFIG_INET
  498. /* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */
  499. int ip_route_me_harder(struct sk_buff **pskb)
  500. {
  501. struct iphdr *iph = (*pskb)->nh.iph;
  502. struct rtable *rt;
  503. struct rt_key key = { dst:iph->daddr,
  504.       src:iph->saddr,
  505.       oif:(*pskb)->sk ? (*pskb)->sk->bound_dev_if : 0,
  506.       tos:RT_TOS(iph->tos)|RTO_CONN,
  507. #ifdef CONFIG_IP_ROUTE_FWMARK
  508.       fwmark:(*pskb)->nfmark
  509. #endif
  510.     };
  511. struct net_device *dev_src = NULL;
  512. int err;
  513. /* accomodate ip_route_output_slow(), which expects the key src to be
  514.    0 or a local address; however some non-standard hacks like
  515.    ipt_REJECT.c:send_reset() can cause packets with foreign
  516.            saddr to be appear on the NF_IP_LOCAL_OUT hook -MB */
  517. if(key.src && !(dev_src = ip_dev_find(key.src)))
  518. key.src = 0;
  519. if ((err=ip_route_output_key(&rt, &key)) != 0) {
  520. printk("route_me_harder: ip_route_output_key(dst=%u.%u.%u.%u, src=%u.%u.%u.%u, oif=%d, tos=0x%x, fwmark=0x%lx) error %dn",
  521. NIPQUAD(iph->daddr), NIPQUAD(iph->saddr),
  522. (*pskb)->sk ? (*pskb)->sk->bound_dev_if : 0,
  523. RT_TOS(iph->tos)|RTO_CONN,
  524. #ifdef CONFIG_IP_ROUTE_FWMARK
  525. (*pskb)->nfmark,
  526. #else
  527. 0UL,
  528. #endif
  529. err);
  530. goto out;
  531. }
  532. /* Drop old route. */
  533. dst_release((*pskb)->dst);
  534. (*pskb)->dst = &rt->u.dst;
  535. /* Change in oif may mean change in hh_len. */
  536. if (skb_headroom(*pskb) < (*pskb)->dst->dev->hard_header_len) {
  537. struct sk_buff *nskb;
  538. nskb = skb_realloc_headroom(*pskb,
  539.     (*pskb)->dst->dev->hard_header_len);
  540. if (!nskb) {
  541. err = -ENOMEM;
  542. goto out;
  543. }
  544. if ((*pskb)->sk)
  545. skb_set_owner_w(nskb, (*pskb)->sk);
  546. kfree_skb(*pskb);
  547. *pskb = nskb;
  548. }
  549. out:
  550. if (dev_src)
  551. dev_put(dev_src);
  552. return err;
  553. }
  554. #endif /*CONFIG_INET*/
  555. /* This does not belong here, but ipt_REJECT needs it if connection
  556.    tracking in use: without this, connection may not be in hash table,
  557.    and hence manufactured ICMP or RST packets will not be associated
  558.    with it. */
  559. void (*ip_ct_attach)(struct sk_buff *, struct nf_ct_info *);
  560. void __init netfilter_init(void)
  561. {
  562. int i, h;
  563. for (i = 0; i < NPROTO; i++) {
  564. for (h = 0; h < NF_MAX_HOOKS; h++)
  565. INIT_LIST_HEAD(&nf_hooks[i][h]);
  566. }
  567. }