ip_conntrack_standalone.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:9k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* This file contains all the functions required for the standalone
  2.    ip_conntrack module.
  3.    These are not required by the compatibility layer.
  4. */
  5. /* (c) 1999 Paul `Rusty' Russell.  Licenced under the GNU General
  6.    Public Licence. */
  7. #include <linux/types.h>
  8. #include <linux/ip.h>
  9. #include <linux/netfilter.h>
  10. #include <linux/netfilter_ipv4.h>
  11. #include <linux/module.h>
  12. #include <linux/skbuff.h>
  13. #include <linux/proc_fs.h>
  14. #include <linux/version.h>
  15. #include <net/checksum.h>
  16. #define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock)
  17. #define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_conntrack_lock)
  18. #include <linux/netfilter_ipv4/ip_conntrack.h>
  19. #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
  20. #include <linux/netfilter_ipv4/ip_conntrack_core.h>
  21. #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
  22. #include <linux/netfilter_ipv4/listhelp.h>
  23. #if 0
  24. #define DEBUGP printk
  25. #else
  26. #define DEBUGP(format, args...)
  27. #endif
  28. struct module *ip_conntrack_module = THIS_MODULE;
  29. MODULE_LICENSE("GPL");
  30. static unsigned int
  31. print_tuple(char *buffer, const struct ip_conntrack_tuple *tuple,
  32.     struct ip_conntrack_protocol *proto)
  33. {
  34. int len;
  35. len = sprintf(buffer, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ",
  36.       NIPQUAD(tuple->src.ip), NIPQUAD(tuple->dst.ip));
  37. len += proto->print_tuple(buffer + len, tuple);
  38. return len;
  39. }
  40. /* FIXME: Don't print source proto part. --RR */
  41. static unsigned int
  42. print_expect(char *buffer, const struct ip_conntrack_expect *expect)
  43. {
  44. unsigned int len;
  45. len = sprintf(buffer, "EXPECTING: proto=%u ",
  46.       expect->tuple.dst.protonum);
  47. len += print_tuple(buffer + len, &expect->tuple,
  48.    __find_proto(expect->tuple.dst.protonum));
  49. len += sprintf(buffer + len, "n");
  50. return len;
  51. }
  52. static unsigned int
  53. print_conntrack(char *buffer, const struct ip_conntrack *conntrack)
  54. {
  55. unsigned int len;
  56. struct ip_conntrack_protocol *proto
  57. = __find_proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
  58.        .tuple.dst.protonum);
  59. len = sprintf(buffer, "%-8s %u %lu ",
  60.       proto->name,
  61.       conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
  62.       .tuple.dst.protonum,
  63.       timer_pending(&conntrack->timeout)
  64.       ? (conntrack->timeout.expires - jiffies)/HZ : 0);
  65. len += proto->print_conntrack(buffer + len, conntrack);
  66. len += print_tuple(buffer + len,
  67.    &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
  68.    proto);
  69. if (!(conntrack->status & IPS_SEEN_REPLY))
  70. len += sprintf(buffer + len, "[UNREPLIED] ");
  71. len += print_tuple(buffer + len,
  72.    &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,
  73.    proto);
  74. if (conntrack->status & IPS_ASSURED)
  75. len += sprintf(buffer + len, "[ASSURED] ");
  76. len += sprintf(buffer + len, "use=%u ",
  77.        atomic_read(&conntrack->ct_general.use));
  78. len += sprintf(buffer + len, "n");
  79. return len;
  80. }
  81. /* Returns true when finished. */
  82. static inline int
  83. conntrack_iterate(const struct ip_conntrack_tuple_hash *hash,
  84.   char *buffer, off_t offset, off_t *upto,
  85.   unsigned int *len, unsigned int maxlen)
  86. {
  87. unsigned int newlen;
  88. IP_NF_ASSERT(hash->ctrack);
  89. MUST_BE_READ_LOCKED(&ip_conntrack_lock);
  90. /* Only count originals */
  91. if (DIRECTION(hash))
  92. return 0;
  93. if ((*upto)++ < offset)
  94. return 0;
  95. newlen = print_conntrack(buffer + *len, hash->ctrack);
  96. if (*len + newlen > maxlen)
  97. return 1;
  98. else *len += newlen;
  99. return 0;
  100. }
  101. static int
  102. list_conntracks(char *buffer, char **start, off_t offset, int length)
  103. {
  104. unsigned int i;
  105. unsigned int len = 0;
  106. off_t upto = 0;
  107. struct list_head *e;
  108. READ_LOCK(&ip_conntrack_lock);
  109. /* Traverse hash; print originals then reply. */
  110. for (i = 0; i < ip_conntrack_htable_size; i++) {
  111. if (LIST_FIND(&ip_conntrack_hash[i], conntrack_iterate,
  112.       struct ip_conntrack_tuple_hash *,
  113.       buffer, offset, &upto, &len, length))
  114. goto finished;
  115. }
  116. /* Now iterate through expecteds. */
  117. for (e = expect_list.next; e != &expect_list; e = e->next) {
  118. unsigned int last_len;
  119. struct ip_conntrack_expect *expect
  120. = (struct ip_conntrack_expect *)e;
  121. if (upto++ < offset) continue;
  122. last_len = len;
  123. len += print_expect(buffer + len, expect);
  124. if (len > length) {
  125. len = last_len;
  126. goto finished;
  127. }
  128. }
  129.  finished:
  130. READ_UNLOCK(&ip_conntrack_lock);
  131. /* `start' hack - see fs/proc/generic.c line ~165 */
  132. *start = (char *)((unsigned int)upto - offset);
  133. return len;
  134. }
  135. static unsigned int ip_confirm(unsigned int hooknum,
  136.        struct sk_buff **pskb,
  137.        const struct net_device *in,
  138.        const struct net_device *out,
  139.        int (*okfn)(struct sk_buff *))
  140. {
  141. /* We've seen it coming out the other side: confirm it */
  142. return ip_conntrack_confirm(*pskb);
  143. }
  144. static unsigned int ip_refrag(unsigned int hooknum,
  145.       struct sk_buff **pskb,
  146.       const struct net_device *in,
  147.       const struct net_device *out,
  148.       int (*okfn)(struct sk_buff *))
  149. {
  150. struct rtable *rt = (struct rtable *)(*pskb)->dst;
  151. /* We've seen it coming out the other side: confirm */
  152. if (ip_confirm(hooknum, pskb, in, out, okfn) != NF_ACCEPT)
  153. return NF_DROP;
  154. /* Local packets are never produced too large for their
  155.    interface.  We degfragment them at LOCAL_OUT, however,
  156.    so we have to refragment them here. */
  157. if ((*pskb)->len > rt->u.dst.pmtu) {
  158. /* No hook can be after us, so this should be OK. */
  159. ip_fragment(*pskb, okfn);
  160. return NF_STOLEN;
  161. }
  162. return NF_ACCEPT;
  163. }
  164. static unsigned int ip_conntrack_local(unsigned int hooknum,
  165.        struct sk_buff **pskb,
  166.        const struct net_device *in,
  167.        const struct net_device *out,
  168.        int (*okfn)(struct sk_buff *))
  169. {
  170. /* root is playing with raw sockets. */
  171. if ((*pskb)->len < sizeof(struct iphdr)
  172.     || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) {
  173. if (net_ratelimit())
  174. printk("ipt_hook: happy cracking.n");
  175. return NF_ACCEPT;
  176. }
  177. return ip_conntrack_in(hooknum, pskb, in, out, okfn);
  178. }
  179. /* Connection tracking may drop packets, but never alters them, so
  180.    make it the first hook. */
  181. static struct nf_hook_ops ip_conntrack_in_ops
  182. = { { NULL, NULL }, ip_conntrack_in, PF_INET, NF_IP_PRE_ROUTING,
  183. NF_IP_PRI_CONNTRACK };
  184. static struct nf_hook_ops ip_conntrack_local_out_ops
  185. = { { NULL, NULL }, ip_conntrack_local, PF_INET, NF_IP_LOCAL_OUT,
  186. NF_IP_PRI_CONNTRACK };
  187. /* Refragmenter; last chance. */
  188. static struct nf_hook_ops ip_conntrack_out_ops
  189. = { { NULL, NULL }, ip_refrag, PF_INET, NF_IP_POST_ROUTING, NF_IP_PRI_LAST };
  190. static struct nf_hook_ops ip_conntrack_local_in_ops
  191. = { { NULL, NULL }, ip_confirm, PF_INET, NF_IP_LOCAL_IN, NF_IP_PRI_LAST-1 };
  192. static int init_or_cleanup(int init)
  193. {
  194. struct proc_dir_entry *proc;
  195. int ret = 0;
  196. if (!init) goto cleanup;
  197. ret = ip_conntrack_init();
  198. if (ret < 0)
  199. goto cleanup_nothing;
  200. proc = proc_net_create("ip_conntrack",0,list_conntracks);
  201. if (!proc) goto cleanup_init;
  202. proc->owner = THIS_MODULE;
  203. ret = nf_register_hook(&ip_conntrack_in_ops);
  204. if (ret < 0) {
  205. printk("ip_conntrack: can't register pre-routing hook.n");
  206. goto cleanup_proc;
  207. }
  208. ret = nf_register_hook(&ip_conntrack_local_out_ops);
  209. if (ret < 0) {
  210. printk("ip_conntrack: can't register local out hook.n");
  211. goto cleanup_inops;
  212. }
  213. ret = nf_register_hook(&ip_conntrack_out_ops);
  214. if (ret < 0) {
  215. printk("ip_conntrack: can't register post-routing hook.n");
  216. goto cleanup_inandlocalops;
  217. }
  218. ret = nf_register_hook(&ip_conntrack_local_in_ops);
  219. if (ret < 0) {
  220. printk("ip_conntrack: can't register local in hook.n");
  221. goto cleanup_inoutandlocalops;
  222. }
  223. return ret;
  224.  cleanup:
  225. nf_unregister_hook(&ip_conntrack_local_in_ops);
  226.  cleanup_inoutandlocalops:
  227. nf_unregister_hook(&ip_conntrack_out_ops);
  228.  cleanup_inandlocalops:
  229. nf_unregister_hook(&ip_conntrack_local_out_ops);
  230.  cleanup_inops:
  231. nf_unregister_hook(&ip_conntrack_in_ops);
  232.  cleanup_proc:
  233. proc_net_remove("ip_conntrack");
  234.  cleanup_init:
  235. ip_conntrack_cleanup();
  236.  cleanup_nothing:
  237. return ret;
  238. }
  239. /* FIXME: Allow NULL functions and sub in pointers to generic for
  240.    them. --RR */
  241. int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
  242. {
  243. int ret = 0;
  244. struct list_head *i;
  245. WRITE_LOCK(&ip_conntrack_lock);
  246. for (i = protocol_list.next; i != &protocol_list; i = i->next) {
  247. if (((struct ip_conntrack_protocol *)i)->proto
  248.     == proto->proto) {
  249. ret = -EBUSY;
  250. goto out;
  251. }
  252. }
  253. list_prepend(&protocol_list, proto);
  254. MOD_INC_USE_COUNT;
  255.  out:
  256. WRITE_UNLOCK(&ip_conntrack_lock);
  257. return ret;
  258. }
  259. /* FIXME: Implement this --RR */
  260. #if 0
  261. void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
  262. {
  263. }
  264. #endif
  265. static int __init init(void)
  266. {
  267. return init_or_cleanup(1);
  268. }
  269. static void __exit fini(void)
  270. {
  271. init_or_cleanup(0);
  272. }
  273. module_init(init);
  274. module_exit(fini);
  275. EXPORT_SYMBOL(ip_conntrack_protocol_register);
  276. EXPORT_SYMBOL(invert_tuplepr);
  277. EXPORT_SYMBOL(ip_conntrack_alter_reply);
  278. EXPORT_SYMBOL(ip_conntrack_destroyed);
  279. EXPORT_SYMBOL(ip_conntrack_get);
  280. EXPORT_SYMBOL(ip_conntrack_module);
  281. EXPORT_SYMBOL(ip_conntrack_helper_register);
  282. EXPORT_SYMBOL(ip_conntrack_helper_unregister);
  283. EXPORT_SYMBOL(ip_ct_selective_cleanup);
  284. EXPORT_SYMBOL(ip_ct_refresh);
  285. EXPORT_SYMBOL(ip_conntrack_expect_related);
  286. EXPORT_SYMBOL(ip_conntrack_tuple_taken);
  287. EXPORT_SYMBOL(ip_ct_gather_frags);
  288. EXPORT_SYMBOL(ip_conntrack_htable_size);