Loading include/linux/netfilter/nfnetlink.h +1 −1 Original line number Original line Diff line number Diff line Loading @@ -146,7 +146,7 @@ extern void nfnl_unlock(void); extern int nfnetlink_subsys_register(struct nfnetlink_subsystem *n); extern int nfnetlink_subsys_register(struct nfnetlink_subsystem *n); extern int nfnetlink_subsys_unregister(struct nfnetlink_subsystem *n); extern int nfnetlink_subsys_unregister(struct nfnetlink_subsystem *n); extern int nfattr_parse(struct nfattr *tb[], int maxattr, extern void nfattr_parse(struct nfattr *tb[], int maxattr, struct nfattr *nfa, int len); struct nfattr *nfa, int len); #define nfattr_parse_nested(tb, max, nfa) \ #define nfattr_parse_nested(tb, max, nfa) \ Loading net/ipv4/netfilter/ip_conntrack_netlink.c +37 −46 Original line number Original line Diff line number Diff line Loading @@ -28,11 +28,8 @@ #include <linux/netlink.h> #include <linux/netlink.h> #include <linux/spinlock.h> #include <linux/spinlock.h> #include <linux/notifier.h> #include <linux/notifier.h> #include <linux/rtnetlink.h> #include <linux/netfilter.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> #include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ip_conntrack.h> #include <linux/netfilter_ipv4/ip_conntrack.h> #include <linux/netfilter_ipv4/ip_conntrack_core.h> #include <linux/netfilter_ipv4/ip_conntrack_core.h> #include <linux/netfilter_ipv4/ip_conntrack_helper.h> #include <linux/netfilter_ipv4/ip_conntrack_helper.h> Loading @@ -58,14 +55,17 @@ ctnetlink_dump_tuples_proto(struct sk_buff *skb, const struct ip_conntrack_tuple *tuple) const struct ip_conntrack_tuple *tuple) { { struct ip_conntrack_protocol *proto; struct ip_conntrack_protocol *proto; int ret = 0; NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum); NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum); proto = ip_conntrack_proto_find_get(tuple->dst.protonum); proto = ip_conntrack_proto_find_get(tuple->dst.protonum); if (proto && proto->tuple_to_nfattr) if (likely(proto && proto->tuple_to_nfattr)) { return proto->tuple_to_nfattr(skb, tuple); ret = proto->tuple_to_nfattr(skb, tuple); ip_conntrack_proto_put(proto); } return 0; return ret; nfattr_failure: nfattr_failure: return -1; return -1; Loading Loading @@ -175,7 +175,7 @@ ctnetlink_dump_counters(struct sk_buff *skb, const struct ip_conntrack *ct, { { enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG; enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG; struct nfattr *nest_count = NFA_NEST(skb, type); struct nfattr *nest_count = NFA_NEST(skb, type); u_int64_t tmp; u_int32_t tmp; tmp = htonl(ct->counters[dir].packets); tmp = htonl(ct->counters[dir].packets); NFA_PUT(skb, CTA_COUNTERS32_PACKETS, sizeof(u_int32_t), &tmp); NFA_PUT(skb, CTA_COUNTERS32_PACKETS, sizeof(u_int32_t), &tmp); Loading Loading @@ -479,9 +479,7 @@ ctnetlink_parse_tuple_ip(struct nfattr *attr, struct ip_conntrack_tuple *tuple) DEBUGP("entered %s\n", __FUNCTION__); DEBUGP("entered %s\n", __FUNCTION__); nfattr_parse_nested(tb, CTA_IP_MAX, attr); if (nfattr_parse_nested(tb, CTA_IP_MAX, attr) < 0) goto nfattr_failure; if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip)) if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip)) return -EINVAL; return -EINVAL; Loading @@ -497,9 +495,6 @@ ctnetlink_parse_tuple_ip(struct nfattr *attr, struct ip_conntrack_tuple *tuple) DEBUGP("leaving\n"); DEBUGP("leaving\n"); return 0; return 0; nfattr_failure: return -1; } } static const int cta_min_proto[CTA_PROTO_MAX] = { static const int cta_min_proto[CTA_PROTO_MAX] = { Loading @@ -521,8 +516,7 @@ ctnetlink_parse_tuple_proto(struct nfattr *attr, DEBUGP("entered %s\n", __FUNCTION__); DEBUGP("entered %s\n", __FUNCTION__); if (nfattr_parse_nested(tb, CTA_PROTO_MAX, attr) < 0) nfattr_parse_nested(tb, CTA_PROTO_MAX, attr); goto nfattr_failure; if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto)) if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto)) return -EINVAL; return -EINVAL; Loading @@ -539,9 +533,6 @@ ctnetlink_parse_tuple_proto(struct nfattr *attr, } } return ret; return ret; nfattr_failure: return -1; } } static inline int static inline int Loading @@ -555,8 +546,7 @@ ctnetlink_parse_tuple(struct nfattr *cda[], struct ip_conntrack_tuple *tuple, memset(tuple, 0, sizeof(*tuple)); memset(tuple, 0, sizeof(*tuple)); if (nfattr_parse_nested(tb, CTA_TUPLE_MAX, cda[type-1]) < 0) nfattr_parse_nested(tb, CTA_TUPLE_MAX, cda[type-1]); goto nfattr_failure; if (!tb[CTA_TUPLE_IP-1]) if (!tb[CTA_TUPLE_IP-1]) return -EINVAL; return -EINVAL; Loading @@ -583,9 +573,6 @@ ctnetlink_parse_tuple(struct nfattr *cda[], struct ip_conntrack_tuple *tuple, DEBUGP("leaving\n"); DEBUGP("leaving\n"); return 0; return 0; nfattr_failure: return -1; } } #ifdef CONFIG_IP_NF_NAT_NEEDED #ifdef CONFIG_IP_NF_NAT_NEEDED Loading @@ -603,11 +590,10 @@ static int ctnetlink_parse_nat_proto(struct nfattr *attr, DEBUGP("entered %s\n", __FUNCTION__); DEBUGP("entered %s\n", __FUNCTION__); if (nfattr_parse_nested(tb, CTA_PROTONAT_MAX, attr) < 0) nfattr_parse_nested(tb, CTA_PROTONAT_MAX, attr); goto nfattr_failure; if (nfattr_bad_size(tb, CTA_PROTONAT_MAX, cta_min_protonat)) if (nfattr_bad_size(tb, CTA_PROTONAT_MAX, cta_min_protonat)) goto nfattr_failure; return -EINVAL; npt = ip_nat_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum); npt = ip_nat_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum); if (!npt) if (!npt) Loading @@ -626,9 +612,6 @@ static int ctnetlink_parse_nat_proto(struct nfattr *attr, DEBUGP("leaving\n"); DEBUGP("leaving\n"); return 0; return 0; nfattr_failure: return -1; } } static inline int static inline int Loading @@ -642,8 +625,7 @@ ctnetlink_parse_nat(struct nfattr *cda[], memset(range, 0, sizeof(*range)); memset(range, 0, sizeof(*range)); if (nfattr_parse_nested(tb, CTA_NAT_MAX, cda[CTA_NAT-1]) < 0) nfattr_parse_nested(tb, CTA_NAT_MAX, cda[CTA_NAT-1]); goto nfattr_failure; if (tb[CTA_NAT_MINIP-1]) if (tb[CTA_NAT_MINIP-1]) range->min_ip = *(u_int32_t *)NFA_DATA(tb[CTA_NAT_MINIP-1]); range->min_ip = *(u_int32_t *)NFA_DATA(tb[CTA_NAT_MINIP-1]); Loading @@ -665,9 +647,6 @@ ctnetlink_parse_nat(struct nfattr *cda[], DEBUGP("leaving\n"); DEBUGP("leaving\n"); return 0; return 0; nfattr_failure: return -1; } } #endif #endif Loading @@ -678,8 +657,7 @@ ctnetlink_parse_help(struct nfattr *attr, char **helper_name) DEBUGP("entered %s\n", __FUNCTION__); DEBUGP("entered %s\n", __FUNCTION__); if (nfattr_parse_nested(tb, CTA_HELP_MAX, attr) < 0) nfattr_parse_nested(tb, CTA_HELP_MAX, attr); goto nfattr_failure; if (!tb[CTA_HELP_NAME-1]) if (!tb[CTA_HELP_NAME-1]) return -EINVAL; return -EINVAL; Loading @@ -687,9 +665,6 @@ ctnetlink_parse_help(struct nfattr *attr, char **helper_name) *helper_name = NFA_DATA(tb[CTA_HELP_NAME-1]); *helper_name = NFA_DATA(tb[CTA_HELP_NAME-1]); return 0; return 0; nfattr_failure: return -1; } } static int static int Loading Loading @@ -804,7 +779,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, ct = tuplehash_to_ctrack(h); ct = tuplehash_to_ctrack(h); err = -ENOMEM; err = -ENOMEM; skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); if (!skb2) { if (!skb2) { ip_conntrack_put(ct); ip_conntrack_put(ct); return -ENOMEM; return -ENOMEM; Loading @@ -827,7 +802,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, free: free: kfree_skb(skb2); kfree_skb(skb2); out: out: return -1; return err; } } static inline int static inline int Loading Loading @@ -957,8 +932,7 @@ ctnetlink_change_protoinfo(struct ip_conntrack *ct, struct nfattr *cda[]) u_int16_t npt = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum; u_int16_t npt = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum; int err = 0; int err = 0; if (nfattr_parse_nested(tb, CTA_PROTOINFO_MAX, attr) < 0) nfattr_parse_nested(tb, CTA_PROTOINFO_MAX, attr); goto nfattr_failure; proto = ip_conntrack_proto_find_get(npt); proto = ip_conntrack_proto_find_get(npt); if (!proto) if (!proto) Loading @@ -969,9 +943,6 @@ ctnetlink_change_protoinfo(struct ip_conntrack *ct, struct nfattr *cda[]) ip_conntrack_proto_put(proto); ip_conntrack_proto_put(proto); return err; return err; nfattr_failure: return -ENOMEM; } } static int static int Loading Loading @@ -1005,6 +976,11 @@ ctnetlink_change_conntrack(struct ip_conntrack *ct, struct nfattr *cda[]) return err; return err; } } #if defined(CONFIG_IP_NF_CONNTRACK_MARK) if (cda[CTA_MARK-1]) ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1])); #endif DEBUGP("all done\n"); DEBUGP("all done\n"); return 0; return 0; } } Loading Loading @@ -1048,6 +1024,11 @@ ctnetlink_create_conntrack(struct nfattr *cda[], if (ct->helper) if (ct->helper) ip_conntrack_helper_put(ct->helper); ip_conntrack_helper_put(ct->helper); #if defined(CONFIG_IP_NF_CONNTRACK_MARK) if (cda[CTA_MARK-1]) ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1])); #endif DEBUGP("conntrack with id %u inserted\n", ct->id); DEBUGP("conntrack with id %u inserted\n", ct->id); return 0; return 0; Loading Loading @@ -1312,6 +1293,14 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, if (!exp) if (!exp) return -ENOENT; return -ENOENT; if (cda[CTA_EXPECT_ID-1]) { u_int32_t id = *(u_int32_t *)NFA_DATA(cda[CTA_EXPECT_ID-1]); if (exp->id != ntohl(id)) { ip_conntrack_expect_put(exp); return -ENOENT; } } err = -ENOMEM; err = -ENOMEM; skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); if (!skb2) if (!skb2) Loading Loading @@ -1554,6 +1543,8 @@ static struct nfnetlink_subsystem ctnl_exp_subsys = { .cb = ctnl_exp_cb, .cb = ctnl_exp_cb, }; }; MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK); static int __init ctnetlink_init(void) static int __init ctnetlink_init(void) { { int ret; int ret; Loading net/ipv4/netfilter/ip_conntrack_proto_icmp.c +8 −7 Original line number Original line Diff line number Diff line Loading @@ -151,13 +151,13 @@ icmp_error_message(struct sk_buff *skb, /* Not enough header? */ /* Not enough header? */ inside = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_in), &_in); inside = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_in), &_in); if (inside == NULL) if (inside == NULL) return NF_ACCEPT; return -NF_ACCEPT; /* Ignore ICMP's containing fragments (shouldn't happen) */ /* Ignore ICMP's containing fragments (shouldn't happen) */ if (inside->ip.frag_off & htons(IP_OFFSET)) { if (inside->ip.frag_off & htons(IP_OFFSET)) { DEBUGP("icmp_error_track: fragment of proto %u\n", DEBUGP("icmp_error_track: fragment of proto %u\n", inside->ip.protocol); inside->ip.protocol); return NF_ACCEPT; return -NF_ACCEPT; } } innerproto = ip_conntrack_proto_find_get(inside->ip.protocol); innerproto = ip_conntrack_proto_find_get(inside->ip.protocol); Loading @@ -166,7 +166,7 @@ icmp_error_message(struct sk_buff *skb, if (!ip_ct_get_tuple(&inside->ip, skb, dataoff, &origtuple, innerproto)) { if (!ip_ct_get_tuple(&inside->ip, skb, dataoff, &origtuple, innerproto)) { DEBUGP("icmp_error: ! get_tuple p=%u", inside->ip.protocol); DEBUGP("icmp_error: ! get_tuple p=%u", inside->ip.protocol); ip_conntrack_proto_put(innerproto); ip_conntrack_proto_put(innerproto); return NF_ACCEPT; return -NF_ACCEPT; } } /* Ordinarily, we'd expect the inverted tupleproto, but it's /* Ordinarily, we'd expect the inverted tupleproto, but it's Loading @@ -174,7 +174,7 @@ icmp_error_message(struct sk_buff *skb, if (!ip_ct_invert_tuple(&innertuple, &origtuple, innerproto)) { if (!ip_ct_invert_tuple(&innertuple, &origtuple, innerproto)) { DEBUGP("icmp_error_track: Can't invert tuple\n"); DEBUGP("icmp_error_track: Can't invert tuple\n"); ip_conntrack_proto_put(innerproto); ip_conntrack_proto_put(innerproto); return NF_ACCEPT; return -NF_ACCEPT; } } ip_conntrack_proto_put(innerproto); ip_conntrack_proto_put(innerproto); Loading @@ -190,7 +190,7 @@ icmp_error_message(struct sk_buff *skb, if (!h) { if (!h) { DEBUGP("icmp_error_track: no match\n"); DEBUGP("icmp_error_track: no match\n"); return NF_ACCEPT; return -NF_ACCEPT; } } /* Reverse direction from that found */ /* Reverse direction from that found */ if (DIRECTION(h) != IP_CT_DIR_REPLY) if (DIRECTION(h) != IP_CT_DIR_REPLY) Loading Loading @@ -296,7 +296,8 @@ static int icmp_nfattr_to_tuple(struct nfattr *tb[], struct ip_conntrack_tuple *tuple) struct ip_conntrack_tuple *tuple) { { if (!tb[CTA_PROTO_ICMP_TYPE-1] if (!tb[CTA_PROTO_ICMP_TYPE-1] || !tb[CTA_PROTO_ICMP_CODE-1]) || !tb[CTA_PROTO_ICMP_CODE-1] || !tb[CTA_PROTO_ICMP_ID-1]) return -1; return -1; tuple->dst.u.icmp.type = tuple->dst.u.icmp.type = Loading @@ -304,7 +305,7 @@ static int icmp_nfattr_to_tuple(struct nfattr *tb[], tuple->dst.u.icmp.code = tuple->dst.u.icmp.code = *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_CODE-1]); *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_CODE-1]); tuple->src.u.icmp.id = tuple->src.u.icmp.id = *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]); *(u_int16_t *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]); return 0; return 0; } } Loading net/ipv4/netfilter/ip_conntrack_proto_tcp.c +6 −5 Original line number Original line Diff line number Diff line Loading @@ -362,8 +362,12 @@ static int nfattr_to_tcp(struct nfattr *cda[], struct ip_conntrack *ct) struct nfattr *attr = cda[CTA_PROTOINFO_TCP-1]; struct nfattr *attr = cda[CTA_PROTOINFO_TCP-1]; struct nfattr *tb[CTA_PROTOINFO_TCP_MAX]; struct nfattr *tb[CTA_PROTOINFO_TCP_MAX]; if (nfattr_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr) < 0) /* updates could not contain anything about the private goto nfattr_failure; * protocol info, in that case skip the parsing */ if (!attr) return 0; nfattr_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr); if (!tb[CTA_PROTOINFO_TCP_STATE-1]) if (!tb[CTA_PROTOINFO_TCP_STATE-1]) return -EINVAL; return -EINVAL; Loading @@ -374,9 +378,6 @@ static int nfattr_to_tcp(struct nfattr *cda[], struct ip_conntrack *ct) write_unlock_bh(&tcp_lock); write_unlock_bh(&tcp_lock); return 0; return 0; nfattr_failure: return -1; } } #endif #endif Loading net/ipv4/netfilter/ip_nat_helper_pptp.c +26 −2 Original line number Original line Diff line number Diff line Loading @@ -73,6 +73,7 @@ static void pptp_nat_expected(struct ip_conntrack *ct, struct ip_conntrack_tuple t; struct ip_conntrack_tuple t; struct ip_ct_pptp_master *ct_pptp_info; struct ip_ct_pptp_master *ct_pptp_info; struct ip_nat_pptp *nat_pptp_info; struct ip_nat_pptp *nat_pptp_info; struct ip_nat_range range; ct_pptp_info = &master->help.ct_pptp_info; ct_pptp_info = &master->help.ct_pptp_info; nat_pptp_info = &master->nat.help.nat_pptp_info; nat_pptp_info = &master->nat.help.nat_pptp_info; Loading Loading @@ -110,7 +111,30 @@ static void pptp_nat_expected(struct ip_conntrack *ct, DEBUGP("not found!\n"); DEBUGP("not found!\n"); } } ip_nat_follow_master(ct, exp); /* This must be a fresh one. */ BUG_ON(ct->status & IPS_NAT_DONE_MASK); /* Change src to where master sends to */ range.flags = IP_NAT_RANGE_MAP_IPS; range.min_ip = range.max_ip = ct->master->tuplehash[!exp->dir].tuple.dst.ip; if (exp->dir == IP_CT_DIR_ORIGINAL) { range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED; range.min = range.max = exp->saved_proto; } /* hook doesn't matter, but it has to do source manip */ ip_nat_setup_info(ct, &range, NF_IP_POST_ROUTING); /* For DST manip, map port here to where it's expected. */ range.flags = IP_NAT_RANGE_MAP_IPS; range.min_ip = range.max_ip = ct->master->tuplehash[!exp->dir].tuple.src.ip; if (exp->dir == IP_CT_DIR_REPLY) { range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED; range.min = range.max = exp->saved_proto; } /* hook doesn't matter, but it has to do destination manip */ ip_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING); } } /* outbound packets == from PNS to PAC */ /* outbound packets == from PNS to PAC */ Loading Loading @@ -213,7 +237,7 @@ pptp_exp_gre(struct ip_conntrack_expect *expect_orig, /* alter expectation for PNS->PAC direction */ /* alter expectation for PNS->PAC direction */ invert_tuplepr(&inv_t, &expect_orig->tuple); invert_tuplepr(&inv_t, &expect_orig->tuple); expect_orig->saved_proto.gre.key = htons(nat_pptp_info->pac_call_id); expect_orig->saved_proto.gre.key = htons(ct_pptp_info->pns_call_id); expect_orig->tuple.src.u.gre.key = htons(nat_pptp_info->pns_call_id); expect_orig->tuple.src.u.gre.key = htons(nat_pptp_info->pns_call_id); expect_orig->tuple.dst.u.gre.key = htons(ct_pptp_info->pac_call_id); expect_orig->tuple.dst.u.gre.key = htons(ct_pptp_info->pac_call_id); expect_orig->dir = IP_CT_DIR_ORIGINAL; expect_orig->dir = IP_CT_DIR_ORIGINAL; Loading Loading
include/linux/netfilter/nfnetlink.h +1 −1 Original line number Original line Diff line number Diff line Loading @@ -146,7 +146,7 @@ extern void nfnl_unlock(void); extern int nfnetlink_subsys_register(struct nfnetlink_subsystem *n); extern int nfnetlink_subsys_register(struct nfnetlink_subsystem *n); extern int nfnetlink_subsys_unregister(struct nfnetlink_subsystem *n); extern int nfnetlink_subsys_unregister(struct nfnetlink_subsystem *n); extern int nfattr_parse(struct nfattr *tb[], int maxattr, extern void nfattr_parse(struct nfattr *tb[], int maxattr, struct nfattr *nfa, int len); struct nfattr *nfa, int len); #define nfattr_parse_nested(tb, max, nfa) \ #define nfattr_parse_nested(tb, max, nfa) \ Loading
net/ipv4/netfilter/ip_conntrack_netlink.c +37 −46 Original line number Original line Diff line number Diff line Loading @@ -28,11 +28,8 @@ #include <linux/netlink.h> #include <linux/netlink.h> #include <linux/spinlock.h> #include <linux/spinlock.h> #include <linux/notifier.h> #include <linux/notifier.h> #include <linux/rtnetlink.h> #include <linux/netfilter.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> #include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ip_conntrack.h> #include <linux/netfilter_ipv4/ip_conntrack.h> #include <linux/netfilter_ipv4/ip_conntrack_core.h> #include <linux/netfilter_ipv4/ip_conntrack_core.h> #include <linux/netfilter_ipv4/ip_conntrack_helper.h> #include <linux/netfilter_ipv4/ip_conntrack_helper.h> Loading @@ -58,14 +55,17 @@ ctnetlink_dump_tuples_proto(struct sk_buff *skb, const struct ip_conntrack_tuple *tuple) const struct ip_conntrack_tuple *tuple) { { struct ip_conntrack_protocol *proto; struct ip_conntrack_protocol *proto; int ret = 0; NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum); NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum); proto = ip_conntrack_proto_find_get(tuple->dst.protonum); proto = ip_conntrack_proto_find_get(tuple->dst.protonum); if (proto && proto->tuple_to_nfattr) if (likely(proto && proto->tuple_to_nfattr)) { return proto->tuple_to_nfattr(skb, tuple); ret = proto->tuple_to_nfattr(skb, tuple); ip_conntrack_proto_put(proto); } return 0; return ret; nfattr_failure: nfattr_failure: return -1; return -1; Loading Loading @@ -175,7 +175,7 @@ ctnetlink_dump_counters(struct sk_buff *skb, const struct ip_conntrack *ct, { { enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG; enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG; struct nfattr *nest_count = NFA_NEST(skb, type); struct nfattr *nest_count = NFA_NEST(skb, type); u_int64_t tmp; u_int32_t tmp; tmp = htonl(ct->counters[dir].packets); tmp = htonl(ct->counters[dir].packets); NFA_PUT(skb, CTA_COUNTERS32_PACKETS, sizeof(u_int32_t), &tmp); NFA_PUT(skb, CTA_COUNTERS32_PACKETS, sizeof(u_int32_t), &tmp); Loading Loading @@ -479,9 +479,7 @@ ctnetlink_parse_tuple_ip(struct nfattr *attr, struct ip_conntrack_tuple *tuple) DEBUGP("entered %s\n", __FUNCTION__); DEBUGP("entered %s\n", __FUNCTION__); nfattr_parse_nested(tb, CTA_IP_MAX, attr); if (nfattr_parse_nested(tb, CTA_IP_MAX, attr) < 0) goto nfattr_failure; if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip)) if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip)) return -EINVAL; return -EINVAL; Loading @@ -497,9 +495,6 @@ ctnetlink_parse_tuple_ip(struct nfattr *attr, struct ip_conntrack_tuple *tuple) DEBUGP("leaving\n"); DEBUGP("leaving\n"); return 0; return 0; nfattr_failure: return -1; } } static const int cta_min_proto[CTA_PROTO_MAX] = { static const int cta_min_proto[CTA_PROTO_MAX] = { Loading @@ -521,8 +516,7 @@ ctnetlink_parse_tuple_proto(struct nfattr *attr, DEBUGP("entered %s\n", __FUNCTION__); DEBUGP("entered %s\n", __FUNCTION__); if (nfattr_parse_nested(tb, CTA_PROTO_MAX, attr) < 0) nfattr_parse_nested(tb, CTA_PROTO_MAX, attr); goto nfattr_failure; if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto)) if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto)) return -EINVAL; return -EINVAL; Loading @@ -539,9 +533,6 @@ ctnetlink_parse_tuple_proto(struct nfattr *attr, } } return ret; return ret; nfattr_failure: return -1; } } static inline int static inline int Loading @@ -555,8 +546,7 @@ ctnetlink_parse_tuple(struct nfattr *cda[], struct ip_conntrack_tuple *tuple, memset(tuple, 0, sizeof(*tuple)); memset(tuple, 0, sizeof(*tuple)); if (nfattr_parse_nested(tb, CTA_TUPLE_MAX, cda[type-1]) < 0) nfattr_parse_nested(tb, CTA_TUPLE_MAX, cda[type-1]); goto nfattr_failure; if (!tb[CTA_TUPLE_IP-1]) if (!tb[CTA_TUPLE_IP-1]) return -EINVAL; return -EINVAL; Loading @@ -583,9 +573,6 @@ ctnetlink_parse_tuple(struct nfattr *cda[], struct ip_conntrack_tuple *tuple, DEBUGP("leaving\n"); DEBUGP("leaving\n"); return 0; return 0; nfattr_failure: return -1; } } #ifdef CONFIG_IP_NF_NAT_NEEDED #ifdef CONFIG_IP_NF_NAT_NEEDED Loading @@ -603,11 +590,10 @@ static int ctnetlink_parse_nat_proto(struct nfattr *attr, DEBUGP("entered %s\n", __FUNCTION__); DEBUGP("entered %s\n", __FUNCTION__); if (nfattr_parse_nested(tb, CTA_PROTONAT_MAX, attr) < 0) nfattr_parse_nested(tb, CTA_PROTONAT_MAX, attr); goto nfattr_failure; if (nfattr_bad_size(tb, CTA_PROTONAT_MAX, cta_min_protonat)) if (nfattr_bad_size(tb, CTA_PROTONAT_MAX, cta_min_protonat)) goto nfattr_failure; return -EINVAL; npt = ip_nat_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum); npt = ip_nat_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum); if (!npt) if (!npt) Loading @@ -626,9 +612,6 @@ static int ctnetlink_parse_nat_proto(struct nfattr *attr, DEBUGP("leaving\n"); DEBUGP("leaving\n"); return 0; return 0; nfattr_failure: return -1; } } static inline int static inline int Loading @@ -642,8 +625,7 @@ ctnetlink_parse_nat(struct nfattr *cda[], memset(range, 0, sizeof(*range)); memset(range, 0, sizeof(*range)); if (nfattr_parse_nested(tb, CTA_NAT_MAX, cda[CTA_NAT-1]) < 0) nfattr_parse_nested(tb, CTA_NAT_MAX, cda[CTA_NAT-1]); goto nfattr_failure; if (tb[CTA_NAT_MINIP-1]) if (tb[CTA_NAT_MINIP-1]) range->min_ip = *(u_int32_t *)NFA_DATA(tb[CTA_NAT_MINIP-1]); range->min_ip = *(u_int32_t *)NFA_DATA(tb[CTA_NAT_MINIP-1]); Loading @@ -665,9 +647,6 @@ ctnetlink_parse_nat(struct nfattr *cda[], DEBUGP("leaving\n"); DEBUGP("leaving\n"); return 0; return 0; nfattr_failure: return -1; } } #endif #endif Loading @@ -678,8 +657,7 @@ ctnetlink_parse_help(struct nfattr *attr, char **helper_name) DEBUGP("entered %s\n", __FUNCTION__); DEBUGP("entered %s\n", __FUNCTION__); if (nfattr_parse_nested(tb, CTA_HELP_MAX, attr) < 0) nfattr_parse_nested(tb, CTA_HELP_MAX, attr); goto nfattr_failure; if (!tb[CTA_HELP_NAME-1]) if (!tb[CTA_HELP_NAME-1]) return -EINVAL; return -EINVAL; Loading @@ -687,9 +665,6 @@ ctnetlink_parse_help(struct nfattr *attr, char **helper_name) *helper_name = NFA_DATA(tb[CTA_HELP_NAME-1]); *helper_name = NFA_DATA(tb[CTA_HELP_NAME-1]); return 0; return 0; nfattr_failure: return -1; } } static int static int Loading Loading @@ -804,7 +779,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, ct = tuplehash_to_ctrack(h); ct = tuplehash_to_ctrack(h); err = -ENOMEM; err = -ENOMEM; skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); if (!skb2) { if (!skb2) { ip_conntrack_put(ct); ip_conntrack_put(ct); return -ENOMEM; return -ENOMEM; Loading @@ -827,7 +802,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, free: free: kfree_skb(skb2); kfree_skb(skb2); out: out: return -1; return err; } } static inline int static inline int Loading Loading @@ -957,8 +932,7 @@ ctnetlink_change_protoinfo(struct ip_conntrack *ct, struct nfattr *cda[]) u_int16_t npt = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum; u_int16_t npt = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum; int err = 0; int err = 0; if (nfattr_parse_nested(tb, CTA_PROTOINFO_MAX, attr) < 0) nfattr_parse_nested(tb, CTA_PROTOINFO_MAX, attr); goto nfattr_failure; proto = ip_conntrack_proto_find_get(npt); proto = ip_conntrack_proto_find_get(npt); if (!proto) if (!proto) Loading @@ -969,9 +943,6 @@ ctnetlink_change_protoinfo(struct ip_conntrack *ct, struct nfattr *cda[]) ip_conntrack_proto_put(proto); ip_conntrack_proto_put(proto); return err; return err; nfattr_failure: return -ENOMEM; } } static int static int Loading Loading @@ -1005,6 +976,11 @@ ctnetlink_change_conntrack(struct ip_conntrack *ct, struct nfattr *cda[]) return err; return err; } } #if defined(CONFIG_IP_NF_CONNTRACK_MARK) if (cda[CTA_MARK-1]) ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1])); #endif DEBUGP("all done\n"); DEBUGP("all done\n"); return 0; return 0; } } Loading Loading @@ -1048,6 +1024,11 @@ ctnetlink_create_conntrack(struct nfattr *cda[], if (ct->helper) if (ct->helper) ip_conntrack_helper_put(ct->helper); ip_conntrack_helper_put(ct->helper); #if defined(CONFIG_IP_NF_CONNTRACK_MARK) if (cda[CTA_MARK-1]) ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1])); #endif DEBUGP("conntrack with id %u inserted\n", ct->id); DEBUGP("conntrack with id %u inserted\n", ct->id); return 0; return 0; Loading Loading @@ -1312,6 +1293,14 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, if (!exp) if (!exp) return -ENOENT; return -ENOENT; if (cda[CTA_EXPECT_ID-1]) { u_int32_t id = *(u_int32_t *)NFA_DATA(cda[CTA_EXPECT_ID-1]); if (exp->id != ntohl(id)) { ip_conntrack_expect_put(exp); return -ENOENT; } } err = -ENOMEM; err = -ENOMEM; skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); if (!skb2) if (!skb2) Loading Loading @@ -1554,6 +1543,8 @@ static struct nfnetlink_subsystem ctnl_exp_subsys = { .cb = ctnl_exp_cb, .cb = ctnl_exp_cb, }; }; MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK); static int __init ctnetlink_init(void) static int __init ctnetlink_init(void) { { int ret; int ret; Loading
net/ipv4/netfilter/ip_conntrack_proto_icmp.c +8 −7 Original line number Original line Diff line number Diff line Loading @@ -151,13 +151,13 @@ icmp_error_message(struct sk_buff *skb, /* Not enough header? */ /* Not enough header? */ inside = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_in), &_in); inside = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_in), &_in); if (inside == NULL) if (inside == NULL) return NF_ACCEPT; return -NF_ACCEPT; /* Ignore ICMP's containing fragments (shouldn't happen) */ /* Ignore ICMP's containing fragments (shouldn't happen) */ if (inside->ip.frag_off & htons(IP_OFFSET)) { if (inside->ip.frag_off & htons(IP_OFFSET)) { DEBUGP("icmp_error_track: fragment of proto %u\n", DEBUGP("icmp_error_track: fragment of proto %u\n", inside->ip.protocol); inside->ip.protocol); return NF_ACCEPT; return -NF_ACCEPT; } } innerproto = ip_conntrack_proto_find_get(inside->ip.protocol); innerproto = ip_conntrack_proto_find_get(inside->ip.protocol); Loading @@ -166,7 +166,7 @@ icmp_error_message(struct sk_buff *skb, if (!ip_ct_get_tuple(&inside->ip, skb, dataoff, &origtuple, innerproto)) { if (!ip_ct_get_tuple(&inside->ip, skb, dataoff, &origtuple, innerproto)) { DEBUGP("icmp_error: ! get_tuple p=%u", inside->ip.protocol); DEBUGP("icmp_error: ! get_tuple p=%u", inside->ip.protocol); ip_conntrack_proto_put(innerproto); ip_conntrack_proto_put(innerproto); return NF_ACCEPT; return -NF_ACCEPT; } } /* Ordinarily, we'd expect the inverted tupleproto, but it's /* Ordinarily, we'd expect the inverted tupleproto, but it's Loading @@ -174,7 +174,7 @@ icmp_error_message(struct sk_buff *skb, if (!ip_ct_invert_tuple(&innertuple, &origtuple, innerproto)) { if (!ip_ct_invert_tuple(&innertuple, &origtuple, innerproto)) { DEBUGP("icmp_error_track: Can't invert tuple\n"); DEBUGP("icmp_error_track: Can't invert tuple\n"); ip_conntrack_proto_put(innerproto); ip_conntrack_proto_put(innerproto); return NF_ACCEPT; return -NF_ACCEPT; } } ip_conntrack_proto_put(innerproto); ip_conntrack_proto_put(innerproto); Loading @@ -190,7 +190,7 @@ icmp_error_message(struct sk_buff *skb, if (!h) { if (!h) { DEBUGP("icmp_error_track: no match\n"); DEBUGP("icmp_error_track: no match\n"); return NF_ACCEPT; return -NF_ACCEPT; } } /* Reverse direction from that found */ /* Reverse direction from that found */ if (DIRECTION(h) != IP_CT_DIR_REPLY) if (DIRECTION(h) != IP_CT_DIR_REPLY) Loading Loading @@ -296,7 +296,8 @@ static int icmp_nfattr_to_tuple(struct nfattr *tb[], struct ip_conntrack_tuple *tuple) struct ip_conntrack_tuple *tuple) { { if (!tb[CTA_PROTO_ICMP_TYPE-1] if (!tb[CTA_PROTO_ICMP_TYPE-1] || !tb[CTA_PROTO_ICMP_CODE-1]) || !tb[CTA_PROTO_ICMP_CODE-1] || !tb[CTA_PROTO_ICMP_ID-1]) return -1; return -1; tuple->dst.u.icmp.type = tuple->dst.u.icmp.type = Loading @@ -304,7 +305,7 @@ static int icmp_nfattr_to_tuple(struct nfattr *tb[], tuple->dst.u.icmp.code = tuple->dst.u.icmp.code = *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_CODE-1]); *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_CODE-1]); tuple->src.u.icmp.id = tuple->src.u.icmp.id = *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]); *(u_int16_t *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]); return 0; return 0; } } Loading
net/ipv4/netfilter/ip_conntrack_proto_tcp.c +6 −5 Original line number Original line Diff line number Diff line Loading @@ -362,8 +362,12 @@ static int nfattr_to_tcp(struct nfattr *cda[], struct ip_conntrack *ct) struct nfattr *attr = cda[CTA_PROTOINFO_TCP-1]; struct nfattr *attr = cda[CTA_PROTOINFO_TCP-1]; struct nfattr *tb[CTA_PROTOINFO_TCP_MAX]; struct nfattr *tb[CTA_PROTOINFO_TCP_MAX]; if (nfattr_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr) < 0) /* updates could not contain anything about the private goto nfattr_failure; * protocol info, in that case skip the parsing */ if (!attr) return 0; nfattr_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr); if (!tb[CTA_PROTOINFO_TCP_STATE-1]) if (!tb[CTA_PROTOINFO_TCP_STATE-1]) return -EINVAL; return -EINVAL; Loading @@ -374,9 +378,6 @@ static int nfattr_to_tcp(struct nfattr *cda[], struct ip_conntrack *ct) write_unlock_bh(&tcp_lock); write_unlock_bh(&tcp_lock); return 0; return 0; nfattr_failure: return -1; } } #endif #endif Loading
net/ipv4/netfilter/ip_nat_helper_pptp.c +26 −2 Original line number Original line Diff line number Diff line Loading @@ -73,6 +73,7 @@ static void pptp_nat_expected(struct ip_conntrack *ct, struct ip_conntrack_tuple t; struct ip_conntrack_tuple t; struct ip_ct_pptp_master *ct_pptp_info; struct ip_ct_pptp_master *ct_pptp_info; struct ip_nat_pptp *nat_pptp_info; struct ip_nat_pptp *nat_pptp_info; struct ip_nat_range range; ct_pptp_info = &master->help.ct_pptp_info; ct_pptp_info = &master->help.ct_pptp_info; nat_pptp_info = &master->nat.help.nat_pptp_info; nat_pptp_info = &master->nat.help.nat_pptp_info; Loading Loading @@ -110,7 +111,30 @@ static void pptp_nat_expected(struct ip_conntrack *ct, DEBUGP("not found!\n"); DEBUGP("not found!\n"); } } ip_nat_follow_master(ct, exp); /* This must be a fresh one. */ BUG_ON(ct->status & IPS_NAT_DONE_MASK); /* Change src to where master sends to */ range.flags = IP_NAT_RANGE_MAP_IPS; range.min_ip = range.max_ip = ct->master->tuplehash[!exp->dir].tuple.dst.ip; if (exp->dir == IP_CT_DIR_ORIGINAL) { range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED; range.min = range.max = exp->saved_proto; } /* hook doesn't matter, but it has to do source manip */ ip_nat_setup_info(ct, &range, NF_IP_POST_ROUTING); /* For DST manip, map port here to where it's expected. */ range.flags = IP_NAT_RANGE_MAP_IPS; range.min_ip = range.max_ip = ct->master->tuplehash[!exp->dir].tuple.src.ip; if (exp->dir == IP_CT_DIR_REPLY) { range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED; range.min = range.max = exp->saved_proto; } /* hook doesn't matter, but it has to do destination manip */ ip_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING); } } /* outbound packets == from PNS to PAC */ /* outbound packets == from PNS to PAC */ Loading Loading @@ -213,7 +237,7 @@ pptp_exp_gre(struct ip_conntrack_expect *expect_orig, /* alter expectation for PNS->PAC direction */ /* alter expectation for PNS->PAC direction */ invert_tuplepr(&inv_t, &expect_orig->tuple); invert_tuplepr(&inv_t, &expect_orig->tuple); expect_orig->saved_proto.gre.key = htons(nat_pptp_info->pac_call_id); expect_orig->saved_proto.gre.key = htons(ct_pptp_info->pns_call_id); expect_orig->tuple.src.u.gre.key = htons(nat_pptp_info->pns_call_id); expect_orig->tuple.src.u.gre.key = htons(nat_pptp_info->pns_call_id); expect_orig->tuple.dst.u.gre.key = htons(ct_pptp_info->pac_call_id); expect_orig->tuple.dst.u.gre.key = htons(ct_pptp_info->pac_call_id); expect_orig->dir = IP_CT_DIR_ORIGINAL; expect_orig->dir = IP_CT_DIR_ORIGINAL; Loading