📄 nf_conntrack_l3proto_ipv4.c
字号:
static ctl_table nf_ct_netfilter_table[] = { { .ctl_name = NET_NETFILTER, .procname = "netfilter", .mode = 0555, .child = nf_ct_sysctl_table, }, { .ctl_name = 0 }};static ctl_table nf_ct_net_table[] = { { .ctl_name = CTL_NET, .procname = "net", .mode = 0555, .child = nf_ct_netfilter_table, }, { .ctl_name = 0 }};#endif/* Fast function for those who don't want to parse /proc (and I don't blame them). *//* Reversing the socket's dst/src point of view gives us the reply mapping. */static intgetorigdst(struct sock *sk, int optval, void __user *user, int *len){ struct inet_sock *inet = inet_sk(sk); struct nf_conntrack_tuple_hash *h; struct nf_conntrack_tuple tuple; NF_CT_TUPLE_U_BLANK(&tuple); tuple.src.u3.ip = inet->rcv_saddr; tuple.src.u.tcp.port = inet->sport; tuple.dst.u3.ip = inet->daddr; tuple.dst.u.tcp.port = inet->dport; tuple.src.l3num = PF_INET; tuple.dst.protonum = IPPROTO_TCP; /* We only do TCP at the moment: is there a better way? */ if (strcmp(sk->sk_prot->name, "TCP")) { DEBUGP("SO_ORIGINAL_DST: Not a TCP socket\n"); return -ENOPROTOOPT; } if ((unsigned int) *len < sizeof(struct sockaddr_in)) { DEBUGP("SO_ORIGINAL_DST: len %u not %u\n", *len, sizeof(struct sockaddr_in)); return -EINVAL; } h = nf_conntrack_find_get(&tuple, NULL); if (h) { struct sockaddr_in sin; struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h); sin.sin_family = AF_INET; sin.sin_port = ct->tuplehash[IP_CT_DIR_ORIGINAL] .tuple.dst.u.tcp.port; sin.sin_addr.s_addr = ct->tuplehash[IP_CT_DIR_ORIGINAL] .tuple.dst.u3.ip; DEBUGP("SO_ORIGINAL_DST: %u.%u.%u.%u %u\n", NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port)); nf_ct_put(ct); if (copy_to_user(user, &sin, sizeof(sin)) != 0) return -EFAULT; else return 0; } DEBUGP("SO_ORIGINAL_DST: Can't find %u.%u.%u.%u/%u-%u.%u.%u.%u/%u.\n", NIPQUAD(tuple.src.u3.ip), ntohs(tuple.src.u.tcp.port), NIPQUAD(tuple.dst.u3.ip), ntohs(tuple.dst.u.tcp.port)); return -ENOENT;}#if defined(CONFIG_NF_CT_NETLINK) || \ defined(CONFIG_NF_CT_NETLINK_MODULE)#include <linux/netfilter/nfnetlink.h>#include <linux/netfilter/nfnetlink_conntrack.h>static int ipv4_tuple_to_nfattr(struct sk_buff *skb, const struct nf_conntrack_tuple *tuple){ NFA_PUT(skb, CTA_IP_V4_SRC, sizeof(u_int32_t), &tuple->src.u3.ip); NFA_PUT(skb, CTA_IP_V4_DST, sizeof(u_int32_t), &tuple->dst.u3.ip); return 0;nfattr_failure: return -1;}static const size_t cta_min_ip[CTA_IP_MAX] = { [CTA_IP_V4_SRC-1] = sizeof(u_int32_t), [CTA_IP_V4_DST-1] = sizeof(u_int32_t),};static int ipv4_nfattr_to_tuple(struct nfattr *tb[], struct nf_conntrack_tuple *t){ if (!tb[CTA_IP_V4_SRC-1] || !tb[CTA_IP_V4_DST-1]) return -EINVAL; if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip)) return -EINVAL; t->src.u3.ip = *(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_SRC-1]); t->dst.u3.ip = *(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_DST-1]); return 0;}#endifstatic struct nf_sockopt_ops so_getorigdst = { .pf = PF_INET, .get_optmin = SO_ORIGINAL_DST, .get_optmax = SO_ORIGINAL_DST+1, .get = &getorigdst,};struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 = { .l3proto = PF_INET, .name = "ipv4", .pkt_to_tuple = ipv4_pkt_to_tuple, .invert_tuple = ipv4_invert_tuple, .print_tuple = ipv4_print_tuple, .print_conntrack = ipv4_print_conntrack, .prepare = ipv4_prepare, .get_features = ipv4_get_features,#if defined(CONFIG_NF_CT_NETLINK) || \ defined(CONFIG_NF_CT_NETLINK_MODULE) .tuple_to_nfattr = ipv4_tuple_to_nfattr, .nfattr_to_tuple = ipv4_nfattr_to_tuple,#endif .me = THIS_MODULE,};extern struct nf_conntrack_protocol nf_conntrack_protocol_tcp4;extern struct nf_conntrack_protocol nf_conntrack_protocol_udp4;extern struct nf_conntrack_protocol nf_conntrack_protocol_icmp;static int init_or_cleanup(int init){ int ret = 0; if (!init) goto cleanup; ret = nf_register_sockopt(&so_getorigdst); if (ret < 0) { printk(KERN_ERR "Unable to register netfilter socket option\n"); goto cleanup_nothing; } ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp4); if (ret < 0) { printk("nf_conntrack_ipv4: can't register tcp.\n"); goto cleanup_sockopt; } ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_udp4); if (ret < 0) { printk("nf_conntrack_ipv4: can't register udp.\n"); goto cleanup_tcp; } ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_icmp); if (ret < 0) { printk("nf_conntrack_ipv4: can't register icmp.\n"); goto cleanup_udp; } ret = nf_conntrack_l3proto_register(&nf_conntrack_l3proto_ipv4); if (ret < 0) { printk("nf_conntrack_ipv4: can't register ipv4\n"); goto cleanup_icmp; } ret = nf_register_hook(&ipv4_conntrack_defrag_ops); if (ret < 0) { printk("nf_conntrack_ipv4: can't register pre-routing defrag hook.\n"); goto cleanup_ipv4; } ret = nf_register_hook(&ipv4_conntrack_defrag_local_out_ops); if (ret < 0) { printk("nf_conntrack_ipv4: can't register local_out defrag hook.\n"); goto cleanup_defragops; } ret = nf_register_hook(&ipv4_conntrack_in_ops); if (ret < 0) { printk("nf_conntrack_ipv4: can't register pre-routing hook.\n"); goto cleanup_defraglocalops; } ret = nf_register_hook(&ipv4_conntrack_local_out_ops); if (ret < 0) { printk("nf_conntrack_ipv4: can't register local out hook.\n"); goto cleanup_inops; } ret = nf_register_hook(&ipv4_conntrack_helper_in_ops); if (ret < 0) { printk("nf_conntrack_ipv4: can't register local helper hook.\n"); goto cleanup_inandlocalops; } ret = nf_register_hook(&ipv4_conntrack_helper_out_ops); if (ret < 0) { printk("nf_conntrack_ipv4: can't register postrouting helper hook.\n"); goto cleanup_helperinops; } ret = nf_register_hook(&ipv4_conntrack_out_ops); if (ret < 0) { printk("nf_conntrack_ipv4: can't register post-routing hook.\n"); goto cleanup_helperoutops; } ret = nf_register_hook(&ipv4_conntrack_local_in_ops); if (ret < 0) { printk("nf_conntrack_ipv4: can't register local in hook.\n"); goto cleanup_inoutandlocalops; }#ifdef CONFIG_SYSCTL nf_ct_ipv4_sysctl_header = register_sysctl_table(nf_ct_net_table, 0); if (nf_ct_ipv4_sysctl_header == NULL) { printk("nf_conntrack: can't register to sysctl.\n"); ret = -ENOMEM; goto cleanup_localinops; }#endif return ret; cleanup: synchronize_net();#ifdef CONFIG_SYSCTL unregister_sysctl_table(nf_ct_ipv4_sysctl_header); cleanup_localinops:#endif nf_unregister_hook(&ipv4_conntrack_local_in_ops); cleanup_inoutandlocalops: nf_unregister_hook(&ipv4_conntrack_out_ops); cleanup_helperoutops: nf_unregister_hook(&ipv4_conntrack_helper_out_ops); cleanup_helperinops: nf_unregister_hook(&ipv4_conntrack_helper_in_ops); cleanup_inandlocalops: nf_unregister_hook(&ipv4_conntrack_local_out_ops); cleanup_inops: nf_unregister_hook(&ipv4_conntrack_in_ops); cleanup_defraglocalops: nf_unregister_hook(&ipv4_conntrack_defrag_local_out_ops); cleanup_defragops: nf_unregister_hook(&ipv4_conntrack_defrag_ops); cleanup_ipv4: nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv4); cleanup_icmp: nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmp); cleanup_udp: nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp4); cleanup_tcp: nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp4); cleanup_sockopt: nf_unregister_sockopt(&so_getorigdst); cleanup_nothing: return ret;}MODULE_LICENSE("GPL");static int __init init(void){ need_conntrack(); return init_or_cleanup(1);}static void __exit fini(void){ init_or_cleanup(0);}module_init(init);module_exit(fini);EXPORT_SYMBOL(nf_ct_ipv4_gather_frags);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -