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

Linux/Unix编程

开发平台:

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