From 3a2dfbe8acb154905fdc2fd03ec56df42e6c4cc4 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Tue, 28 Oct 2008 16:01:07 -0700 Subject: xfrm: Notify changes in UDP encapsulation via netlink Add new_mapping() implementation to the netlink xfrm_mgr to notify address/port changes detected in UDP encapsulated ESP packets. Signed-off-by: Martin Willi Signed-off-by: David S. Miller --- net/xfrm/xfrm_user.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) (limited to 'net/xfrm/xfrm_user.c') diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 4a8a1abb59e..76cf56d5d83 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -2503,6 +2503,57 @@ static int xfrm_send_report(u8 proto, struct xfrm_selector *sel, return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_REPORT, GFP_ATOMIC); } +static inline size_t xfrm_mapping_msgsize(void) +{ + return NLMSG_ALIGN(sizeof(struct xfrm_user_mapping)); +} + +static int build_mapping(struct sk_buff *skb, struct xfrm_state *x, + xfrm_address_t *new_saddr, __be16 new_sport) +{ + struct xfrm_user_mapping *um; + struct nlmsghdr *nlh; + + nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_MAPPING, sizeof(*um), 0); + if (nlh == NULL) + return -EMSGSIZE; + + um = nlmsg_data(nlh); + + memcpy(&um->id.daddr, &x->id.daddr, sizeof(um->id.daddr)); + um->id.spi = x->id.spi; + um->id.family = x->props.family; + um->id.proto = x->id.proto; + memcpy(&um->new_saddr, new_saddr, sizeof(um->new_saddr)); + memcpy(&um->old_saddr, &x->props.saddr, sizeof(um->old_saddr)); + um->new_sport = new_sport; + um->old_sport = x->encap->encap_sport; + um->reqid = x->props.reqid; + + return nlmsg_end(skb, nlh); +} + +static int xfrm_send_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, + __be16 sport) +{ + struct sk_buff *skb; + + if (x->id.proto != IPPROTO_ESP) + return -EINVAL; + + if (!x->encap) + return -EINVAL; + + skb = nlmsg_new(xfrm_mapping_msgsize(), GFP_ATOMIC); + if (skb == NULL) + return -ENOMEM; + + if (build_mapping(skb, x, ipaddr, sport) < 0) + BUG(); + + return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_MAPPING, GFP_ATOMIC); +} + static struct xfrm_mgr netlink_mgr = { .id = "netlink", .notify = xfrm_send_state_notify, @@ -2511,6 +2562,7 @@ static struct xfrm_mgr netlink_mgr = { .notify_policy = xfrm_send_policy_notify, .report = xfrm_send_report, .migrate = xfrm_send_migrate, + .new_mapping = xfrm_send_mapping, }; static int __init xfrm_user_init(void) -- cgit v1.2.3-70-g09d2 From 673c09be457bb23aa0eaaa79804cbb342210d195 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 25 Nov 2008 17:15:16 -0800 Subject: netns xfrm: add struct xfrm_state::xs_net To avoid unnecessary complications with passing netns around. * set once, very early after allocating * once set, never changes For a while create every xfrm_state in init_net. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- include/net/xfrm.h | 10 +++++++++- net/ipv4/ipcomp.c | 2 +- net/ipv6/ipcomp6.c | 2 +- net/key/af_key.c | 2 +- net/xfrm/xfrm_state.c | 9 +++++---- net/xfrm/xfrm_user.c | 4 ++-- 6 files changed, 19 insertions(+), 10 deletions(-) (limited to 'net/xfrm/xfrm_user.c') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 9107d6f5c29..9da89039832 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -130,6 +130,9 @@ struct xfrm_state_walk { /* Full description of state of transformer. */ struct xfrm_state { +#ifdef CONFIG_NET_NS + struct net *xs_net; +#endif union { struct hlist_node gclist; struct hlist_node bydst; @@ -223,6 +226,11 @@ struct xfrm_state void *data; }; +static inline struct net *xs_net(struct xfrm_state *x) +{ + return read_pnet(&x->xs_net); +} + /* xflags - make enum if more show up */ #define XFRM_TIME_DEFER 1 @@ -1296,7 +1304,7 @@ extern void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto); extern int xfrm_state_walk(struct xfrm_state_walk *walk, int (*func)(struct xfrm_state *, int, void*), void *); extern void xfrm_state_walk_done(struct xfrm_state_walk *walk); -extern struct xfrm_state *xfrm_state_alloc(void); +extern struct xfrm_state *xfrm_state_alloc(struct net *net); extern struct xfrm_state *xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, struct flowi *fl, struct xfrm_tmpl *tmpl, struct xfrm_policy *pol, int *err, diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index ec8264ae45c..0a35f1b6f22 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c @@ -49,7 +49,7 @@ static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x) { struct xfrm_state *t; - t = xfrm_state_alloc(); + t = xfrm_state_alloc(&init_net); if (t == NULL) goto out; diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index d4576a9c154..c369638e208 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -76,7 +76,7 @@ static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x) { struct xfrm_state *t = NULL; - t = xfrm_state_alloc(); + t = xfrm_state_alloc(&init_net); if (!t) goto out; diff --git a/net/key/af_key.c b/net/key/af_key.c index 5b22e011653..bde8aad4cc9 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1122,7 +1122,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, (key->sadb_key_bits+7) / 8 > key->sadb_key_len * sizeof(uint64_t))) return ERR_PTR(-EINVAL); - x = xfrm_state_alloc(); + x = xfrm_state_alloc(&init_net); if (x == NULL) return ERR_PTR(-ENOBUFS); diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 268fe3f9e49..81bde76d049 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -504,13 +504,14 @@ out: static void xfrm_replay_timer_handler(unsigned long data); -struct xfrm_state *xfrm_state_alloc(void) +struct xfrm_state *xfrm_state_alloc(struct net *net) { struct xfrm_state *x; x = kzalloc(sizeof(struct xfrm_state), GFP_ATOMIC); if (x) { + write_pnet(&x->xs_net, net); atomic_set(&x->refcnt, 1); atomic_set(&x->tunnel_users, 0); INIT_LIST_HEAD(&x->km.all); @@ -835,7 +836,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, error = -EEXIST; goto out; } - x = xfrm_state_alloc(); + x = xfrm_state_alloc(&init_net); if (x == NULL) { error = -ENOMEM; goto out; @@ -1017,7 +1018,7 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re if (!create) return NULL; - x = xfrm_state_alloc(); + x = xfrm_state_alloc(&init_net); if (likely(x)) { switch (family) { case AF_INET: @@ -1125,7 +1126,7 @@ EXPORT_SYMBOL(xfrm_state_add); static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp) { int err = -ENOMEM; - struct xfrm_state *x = xfrm_state_alloc(); + struct xfrm_state *x = xfrm_state_alloc(&init_net); if (!x) goto error; diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index ee15d5dd654..65cdaa5c228 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -320,7 +320,7 @@ static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p, struct nlattr **attrs, int *errp) { - struct xfrm_state *x = xfrm_state_alloc(); + struct xfrm_state *x = xfrm_state_alloc(&init_net); int err = -ENOMEM; if (!x) @@ -1663,7 +1663,7 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, struct nlattr *rt = attrs[XFRMA_TMPL]; struct xfrm_user_acquire *ua = nlmsg_data(nlh); - struct xfrm_state *x = xfrm_state_alloc(); + struct xfrm_state *x = xfrm_state_alloc(&init_net); int err = -ENOMEM; if (!x) -- cgit v1.2.3-70-g09d2 From 0331b1f383e1fa4049f8e75cafeea8f006171c64 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 25 Nov 2008 17:21:45 -0800 Subject: netns xfrm: add struct xfrm_policy::xp_net Again, to avoid complications with passing netns when not necessary. Again, ->xp_net is set-once field, once set it never changes. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- include/net/xfrm.h | 10 +++++++++- net/key/af_key.c | 4 ++-- net/xfrm/xfrm_policy.c | 5 +++-- net/xfrm/xfrm_user.c | 4 ++-- 4 files changed, 16 insertions(+), 7 deletions(-) (limited to 'net/xfrm/xfrm_user.c') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 0d4353c1109..1ab17565f01 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -475,6 +475,9 @@ struct xfrm_policy_walk { struct xfrm_policy { +#ifdef CONFIG_NET_NS + struct net *xp_net; +#endif struct hlist_node bydst; struct hlist_node byidx; @@ -499,6 +502,11 @@ struct xfrm_policy struct xfrm_tmpl xfrm_vec[XFRM_MAX_DEPTH]; }; +static inline struct net *xp_net(struct xfrm_policy *xp) +{ + return read_pnet(&xp->xp_net); +} + struct xfrm_kmaddress { xfrm_address_t local; xfrm_address_t remote; @@ -1425,7 +1433,7 @@ static inline int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb) } #endif -struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp); +struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp); extern void xfrm_policy_walk_init(struct xfrm_policy_walk *walk, u8 type); extern int xfrm_policy_walk(struct xfrm_policy_walk *walk, diff --git a/net/key/af_key.c b/net/key/af_key.c index f202ba6c8dc..036315d6b66 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -2174,7 +2174,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h if (!pol->sadb_x_policy_dir || pol->sadb_x_policy_dir >= IPSEC_DIR_MAX) return -EINVAL; - xp = xfrm_policy_alloc(GFP_KERNEL); + xp = xfrm_policy_alloc(&init_net, GFP_KERNEL); if (xp == NULL) return -ENOBUFS; @@ -3141,7 +3141,7 @@ static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt, (!pol->sadb_x_policy_dir || pol->sadb_x_policy_dir > IPSEC_DIR_OUTBOUND)) return NULL; - xp = xfrm_policy_alloc(GFP_ATOMIC); + xp = xfrm_policy_alloc(&init_net, GFP_ATOMIC); if (xp == NULL) { *dir = -ENOBUFS; return NULL; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index cf2bf3aa7ab..3eccefae2c8 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -228,13 +228,14 @@ expired: * SPD calls. */ -struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp) +struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp) { struct xfrm_policy *policy; policy = kzalloc(sizeof(struct xfrm_policy), gfp); if (policy) { + write_pnet(&policy->xp_net, net); INIT_LIST_HEAD(&policy->walk.all); INIT_HLIST_NODE(&policy->bydst); INIT_HLIST_NODE(&policy->byidx); @@ -1153,7 +1154,7 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol) static struct xfrm_policy *clone_policy(struct xfrm_policy *old, int dir) { - struct xfrm_policy *newp = xfrm_policy_alloc(GFP_ATOMIC); + struct xfrm_policy *newp = xfrm_policy_alloc(xp_net(old), GFP_ATOMIC); if (newp) { newp->selector = old->selector; diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 65cdaa5c228..765c01e784e 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1080,7 +1080,7 @@ static void copy_to_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_i static struct xfrm_policy *xfrm_policy_construct(struct xfrm_userpolicy_info *p, struct nlattr **attrs, int *errp) { - struct xfrm_policy *xp = xfrm_policy_alloc(GFP_KERNEL); + struct xfrm_policy *xp = xfrm_policy_alloc(&init_net, GFP_KERNEL); int err; if (!xp) { @@ -2291,7 +2291,7 @@ static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt, if (p->dir > XFRM_POLICY_OUT) return NULL; - xp = xfrm_policy_alloc(GFP_KERNEL); + xp = xfrm_policy_alloc(&init_net, GFP_KERNEL); if (xp == NULL) { *dir = -ENOBUFS; return NULL; -- cgit v1.2.3-70-g09d2 From 0e6024519b4da2d9413b97be1de8122d5709ccc1 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 25 Nov 2008 17:30:18 -0800 Subject: netns xfrm: state flush in netns Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- include/net/xfrm.h | 2 +- net/key/af_key.c | 2 +- net/xfrm/xfrm_state.c | 18 +++++++++--------- net/xfrm/xfrm_user.c | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) (limited to 'net/xfrm/xfrm_user.c') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 8699620f8c2..e4bb6722561 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1363,7 +1363,7 @@ struct xfrmk_spdinfo { extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq); extern int xfrm_state_delete(struct xfrm_state *x); -extern int xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info); +extern int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info); extern void xfrm_sad_getinfo(struct xfrmk_sadinfo *si); extern void xfrm_spd_getinfo(struct xfrmk_spdinfo *si); extern int xfrm_replay_check(struct xfrm_state *x, diff --git a/net/key/af_key.c b/net/key/af_key.c index 036315d6b66..e5d595a6092 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1732,7 +1732,7 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd audit_info.loginuid = audit_get_loginuid(current); audit_info.sessionid = audit_get_sessionid(current); audit_info.secid = 0; - err = xfrm_state_flush(proto, &audit_info); + err = xfrm_state_flush(&init_net, proto, &audit_info); if (err) return err; c.data.proto = proto; diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index f3f635d4ee6..5f4c5340ba3 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -576,15 +576,15 @@ EXPORT_SYMBOL(xfrm_state_delete); #ifdef CONFIG_SECURITY_NETWORK_XFRM static inline int -xfrm_state_flush_secctx_check(u8 proto, struct xfrm_audit *audit_info) +xfrm_state_flush_secctx_check(struct net *net, u8 proto, struct xfrm_audit *audit_info) { int i, err = 0; - for (i = 0; i <= init_net.xfrm.state_hmask; i++) { + for (i = 0; i <= net->xfrm.state_hmask; i++) { struct hlist_node *entry; struct xfrm_state *x; - hlist_for_each_entry(x, entry, init_net.xfrm.state_bydst+i, bydst) { + hlist_for_each_entry(x, entry, net->xfrm.state_bydst+i, bydst) { if (xfrm_id_proto_match(x->id.proto, proto) && (err = security_xfrm_state_delete(x)) != 0) { xfrm_audit_state_delete(x, 0, @@ -600,26 +600,26 @@ xfrm_state_flush_secctx_check(u8 proto, struct xfrm_audit *audit_info) } #else static inline int -xfrm_state_flush_secctx_check(u8 proto, struct xfrm_audit *audit_info) +xfrm_state_flush_secctx_check(struct net *net, u8 proto, struct xfrm_audit *audit_info) { return 0; } #endif -int xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info) +int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info) { int i, err = 0; spin_lock_bh(&xfrm_state_lock); - err = xfrm_state_flush_secctx_check(proto, audit_info); + err = xfrm_state_flush_secctx_check(net, proto, audit_info); if (err) goto out; - for (i = 0; i <= init_net.xfrm.state_hmask; i++) { + for (i = 0; i <= net->xfrm.state_hmask; i++) { struct hlist_node *entry; struct xfrm_state *x; restart: - hlist_for_each_entry(x, entry, init_net.xfrm.state_bydst+i, bydst) { + hlist_for_each_entry(x, entry, net->xfrm.state_bydst+i, bydst) { if (!xfrm_state_kern(x) && xfrm_id_proto_match(x->id.proto, proto)) { xfrm_state_hold(x); @@ -641,7 +641,7 @@ restart: out: spin_unlock_bh(&xfrm_state_lock); - wake_up(&init_net.xfrm.km_waitq); + wake_up(&net->xfrm.km_waitq); return err; } EXPORT_SYMBOL(xfrm_state_flush); diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 765c01e784e..49a7e897ba9 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1398,7 +1398,7 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, audit_info.loginuid = NETLINK_CB(skb).loginuid; audit_info.sessionid = NETLINK_CB(skb).sessionid; audit_info.secid = NETLINK_CB(skb).sid; - err = xfrm_state_flush(p->proto, &audit_info); + err = xfrm_state_flush(&init_net, p->proto, &audit_info); if (err) return err; c.data.proto = p->proto; -- cgit v1.2.3-70-g09d2 From 221df1ed33c9284fc7a6f6e47ca7f8d5f3665d43 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 25 Nov 2008 17:30:50 -0800 Subject: netns xfrm: state lookup in netns Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- include/net/xfrm.h | 4 ++-- net/ipv4/ah4.c | 2 +- net/ipv4/esp4.c | 2 +- net/ipv4/ipcomp.c | 4 ++-- net/ipv6/ah6.c | 2 +- net/ipv6/esp6.c | 2 +- net/ipv6/ipcomp6.c | 4 ++-- net/ipv6/xfrm6_input.c | 2 +- net/key/af_key.c | 2 +- net/xfrm/xfrm_input.c | 2 +- net/xfrm/xfrm_state.c | 34 +++++++++++++++++++--------------- net/xfrm/xfrm_user.c | 12 ++++++------ 12 files changed, 38 insertions(+), 34 deletions(-) (limited to 'net/xfrm/xfrm_user.c') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index e4bb6722561..15136c5e262 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1323,8 +1323,8 @@ extern int xfrm_state_check_expire(struct xfrm_state *x); extern void xfrm_state_insert(struct xfrm_state *x); extern int xfrm_state_add(struct xfrm_state *x); extern int xfrm_state_update(struct xfrm_state *x); -extern struct xfrm_state *xfrm_state_lookup(xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family); -extern struct xfrm_state *xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family); +extern struct xfrm_state *xfrm_state_lookup(struct net *net, xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family); +extern struct xfrm_state *xfrm_state_lookup_byaddr(struct net *net, xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family); #ifdef CONFIG_XFRM_SUB_POLICY extern int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n, unsigned short family); diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index 992ecd8662e..750426b0a27 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c @@ -209,7 +209,7 @@ static void ah4_err(struct sk_buff *skb, u32 info) icmp_hdr(skb)->code != ICMP_FRAG_NEEDED) return; - x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET); + x = xfrm_state_lookup(&init_net, (xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET); if (!x) return; printk(KERN_DEBUG "pmtu discovery on SA AH/%08x/%08x\n", diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 95a9c65003f..35950128aa9 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -421,7 +421,7 @@ static void esp4_err(struct sk_buff *skb, u32 info) icmp_hdr(skb)->code != ICMP_FRAG_NEEDED) return; - x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET); + x = xfrm_state_lookup(&init_net, (xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET); if (!x) return; NETDEBUG(KERN_DEBUG "pmtu discovery on SA ESP/%08x/%08x\n", diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index 0a35f1b6f22..3262ce06294 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c @@ -35,7 +35,7 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info) return; spi = htonl(ntohs(ipch->cpi)); - x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, + x = xfrm_state_lookup(&init_net, (xfrm_address_t *)&iph->daddr, spi, IPPROTO_COMP, AF_INET); if (!x) return; @@ -85,7 +85,7 @@ static int ipcomp_tunnel_attach(struct xfrm_state *x) int err = 0; struct xfrm_state *t; - t = xfrm_state_lookup((xfrm_address_t *)&x->id.daddr.a4, + t = xfrm_state_lookup(&init_net, (xfrm_address_t *)&x->id.daddr.a4, x->props.saddr.a4, IPPROTO_IPIP, AF_INET); if (!t) { t = ipcomp_tunnel_create(x); diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 13e330d8917..6ae014b86b6 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -415,7 +415,7 @@ static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, type != ICMPV6_PKT_TOOBIG) return; - x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET6); + x = xfrm_state_lookup(&init_net, (xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET6); if (!x) return; diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index c02a6308def..68f2af8c15c 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -364,7 +364,7 @@ static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, type != ICMPV6_PKT_TOOBIG) return; - x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET6); + x = xfrm_state_lookup(&init_net, (xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET6); if (!x) return; printk(KERN_DEBUG "pmtu discovery on SA ESP/%08x/%pI6\n", diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index c369638e208..3a0b3be7ece 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -63,7 +63,7 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, return; spi = htonl(ntohs(ipcomph->cpi)); - x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi, IPPROTO_COMP, AF_INET6); + x = xfrm_state_lookup(&init_net, (xfrm_address_t *)&iph->daddr, spi, IPPROTO_COMP, AF_INET6); if (!x) return; @@ -114,7 +114,7 @@ static int ipcomp6_tunnel_attach(struct xfrm_state *x) spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&x->props.saddr); if (spi) - t = xfrm_state_lookup((xfrm_address_t *)&x->id.daddr, + t = xfrm_state_lookup(&init_net, (xfrm_address_t *)&x->id.daddr, spi, IPPROTO_IPV6, AF_INET6); if (!t) { t = ipcomp6_tunnel_create(x); diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c index a71c7ddcb41..b69766a7774 100644 --- a/net/ipv6/xfrm6_input.c +++ b/net/ipv6/xfrm6_input.c @@ -100,7 +100,7 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, break; } - x = xfrm_state_lookup_byaddr(dst, src, proto, AF_INET6); + x = xfrm_state_lookup_byaddr(&init_net, dst, src, proto, AF_INET6); if (!x) continue; diff --git a/net/key/af_key.c b/net/key/af_key.c index e5d595a6092..449a5d03e28 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -683,7 +683,7 @@ static struct xfrm_state *pfkey_xfrm_state_lookup(struct sadb_msg *hdr, void ** if (!xaddr) return NULL; - return xfrm_state_lookup(xaddr, sa->sadb_sa_spi, proto, family); + return xfrm_state_lookup(&init_net, xaddr, sa->sadb_sa_spi, proto, family); } #define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1))) diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index 75279402ccf..c08a93e98a3 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c @@ -151,7 +151,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) goto drop; } - x = xfrm_state_lookup(daddr, spi, nexthdr, family); + x = xfrm_state_lookup(&init_net, daddr, spi, nexthdr, family); if (x == NULL) { XFRM_INC_STATS(LINUX_MIB_XFRMINNOSTATES); xfrm_audit_state_notfound(skb, family, spi, seq); diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 5f4c5340ba3..afde47498cd 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -670,13 +670,13 @@ xfrm_init_tempsel(struct xfrm_state *x, struct flowi *fl, return 0; } -static struct xfrm_state *__xfrm_state_lookup(xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family) +static struct xfrm_state *__xfrm_state_lookup(struct net *net, xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family) { - unsigned int h = xfrm_spi_hash(&init_net, daddr, spi, proto, family); + unsigned int h = xfrm_spi_hash(net, daddr, spi, proto, family); struct xfrm_state *x; struct hlist_node *entry; - hlist_for_each_entry(x, entry, init_net.xfrm.state_byspi+h, byspi) { + hlist_for_each_entry(x, entry, net->xfrm.state_byspi+h, byspi) { if (x->props.family != family || x->id.spi != spi || x->id.proto != proto) @@ -702,13 +702,13 @@ static struct xfrm_state *__xfrm_state_lookup(xfrm_address_t *daddr, __be32 spi, return NULL; } -static struct xfrm_state *__xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family) +static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family) { - unsigned int h = xfrm_src_hash(&init_net, daddr, saddr, family); + unsigned int h = xfrm_src_hash(net, daddr, saddr, family); struct xfrm_state *x; struct hlist_node *entry; - hlist_for_each_entry(x, entry, init_net.xfrm.state_bysrc+h, bysrc) { + hlist_for_each_entry(x, entry, net->xfrm.state_bysrc+h, bysrc) { if (x->props.family != family || x->id.proto != proto) continue; @@ -740,11 +740,13 @@ static struct xfrm_state *__xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm static inline struct xfrm_state * __xfrm_state_locate(struct xfrm_state *x, int use_spi, int family) { + struct net *net = xs_net(x); + if (use_spi) - return __xfrm_state_lookup(&x->id.daddr, x->id.spi, + return __xfrm_state_lookup(net, &x->id.daddr, x->id.spi, x->id.proto, family); else - return __xfrm_state_lookup_byaddr(&x->id.daddr, + return __xfrm_state_lookup_byaddr(net, &x->id.daddr, &x->props.saddr, x->id.proto, family); } @@ -818,7 +820,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, x = best; if (!x && !error && !acquire_in_progress) { if (tmpl->id.spi && - (x0 = __xfrm_state_lookup(daddr, tmpl->id.spi, + (x0 = __xfrm_state_lookup(&init_net, daddr, tmpl->id.spi, tmpl->id.proto, family)) != NULL) { to_put = x0; error = -EEXIST; @@ -1361,26 +1363,27 @@ int xfrm_state_check_expire(struct xfrm_state *x) EXPORT_SYMBOL(xfrm_state_check_expire); struct xfrm_state * -xfrm_state_lookup(xfrm_address_t *daddr, __be32 spi, u8 proto, +xfrm_state_lookup(struct net *net, xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family) { struct xfrm_state *x; spin_lock_bh(&xfrm_state_lock); - x = __xfrm_state_lookup(daddr, spi, proto, family); + x = __xfrm_state_lookup(net, daddr, spi, proto, family); spin_unlock_bh(&xfrm_state_lock); return x; } EXPORT_SYMBOL(xfrm_state_lookup); struct xfrm_state * -xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, +xfrm_state_lookup_byaddr(struct net *net, + xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family) { struct xfrm_state *x; spin_lock_bh(&xfrm_state_lock); - x = __xfrm_state_lookup_byaddr(daddr, saddr, proto, family); + x = __xfrm_state_lookup_byaddr(net, daddr, saddr, proto, family); spin_unlock_bh(&xfrm_state_lock); return x; } @@ -1486,6 +1489,7 @@ EXPORT_SYMBOL(xfrm_get_acqseq); int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high) { + struct net *net = xs_net(x); unsigned int h; struct xfrm_state *x0; int err = -ENOENT; @@ -1503,7 +1507,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high) err = -ENOENT; if (minspi == maxspi) { - x0 = xfrm_state_lookup(&x->id.daddr, minspi, x->id.proto, x->props.family); + x0 = xfrm_state_lookup(net, &x->id.daddr, minspi, x->id.proto, x->props.family); if (x0) { xfrm_state_put(x0); goto unlock; @@ -1513,7 +1517,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high) u32 spi = 0; for (h=0; hid.daddr, htonl(spi), x->id.proto, x->props.family); + x0 = xfrm_state_lookup(net, &x->id.daddr, htonl(spi), x->id.proto, x->props.family); if (x0 == NULL) { x->id.spi = htonl(spi); break; diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 49a7e897ba9..e02ef336119 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -440,7 +440,7 @@ static struct xfrm_state *xfrm_user_state_lookup(struct xfrm_usersa_id *p, if (xfrm_id_proto_match(p->proto, IPSEC_PROTO_ANY)) { err = -ESRCH; - x = xfrm_state_lookup(&p->daddr, p->spi, p->proto, p->family); + x = xfrm_state_lookup(&init_net, &p->daddr, p->spi, p->proto, p->family); } else { xfrm_address_t *saddr = NULL; @@ -451,8 +451,8 @@ static struct xfrm_state *xfrm_user_state_lookup(struct xfrm_usersa_id *p, } err = -ESRCH; - x = xfrm_state_lookup_byaddr(&p->daddr, saddr, p->proto, - p->family); + x = xfrm_state_lookup_byaddr(&init_net, &p->daddr, saddr, + p->proto, p->family); } out: @@ -1468,7 +1468,7 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, if (r_skb == NULL) return -ENOMEM; - x = xfrm_state_lookup(&id->daddr, id->spi, id->proto, id->family); + x = xfrm_state_lookup(&init_net, &id->daddr, id->spi, id->proto, id->family); if (x == NULL) { kfree_skb(r_skb); return -ESRCH; @@ -1509,7 +1509,7 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, if (!(nlh->nlmsg_flags&NLM_F_REPLACE)) return err; - x = xfrm_state_lookup(&p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family); + x = xfrm_state_lookup(&init_net, &p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family); if (x == NULL) return -ESRCH; @@ -1628,7 +1628,7 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, struct xfrm_user_expire *ue = nlmsg_data(nlh); struct xfrm_usersa_info *p = &ue->state; - x = xfrm_state_lookup(&p->id.daddr, p->id.spi, p->id.proto, p->family); + x = xfrm_state_lookup(&init_net, &p->id.daddr, p->id.spi, p->id.proto, p->family); err = -ENOENT; if (x == NULL) -- cgit v1.2.3-70-g09d2 From 5447c5e401c49aba0c36bb1066f2d25b152553b7 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 25 Nov 2008 17:31:51 -0800 Subject: netns xfrm: finding states in netns Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- include/net/xfrm.h | 7 ++--- net/core/pktgen.c | 3 ++- net/key/af_key.c | 6 ++--- net/xfrm/xfrm_state.c | 73 +++++++++++++++++++++++++++------------------------ net/xfrm/xfrm_user.c | 4 +-- 5 files changed, 49 insertions(+), 44 deletions(-) (limited to 'net/xfrm/xfrm_user.c') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 15136c5e262..4cbd0557c69 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1315,7 +1315,8 @@ extern struct xfrm_state *xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t struct flowi *fl, struct xfrm_tmpl *tmpl, struct xfrm_policy *pol, int *err, unsigned short family); -extern struct xfrm_state * xfrm_stateonly_find(xfrm_address_t *daddr, +extern struct xfrm_state * xfrm_stateonly_find(struct net *net, + xfrm_address_t *daddr, xfrm_address_t *saddr, unsigned short family, u8 mode, u8 proto, u32 reqid); @@ -1361,7 +1362,7 @@ struct xfrmk_spdinfo { u32 spdhmcnt; }; -extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq); +extern struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 seq); extern int xfrm_state_delete(struct xfrm_state *x); extern int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info); extern void xfrm_sad_getinfo(struct xfrmk_sadinfo *si); @@ -1446,7 +1447,7 @@ struct xfrm_policy *xfrm_policy_byid(u8, int dir, u32 id, int delete, int *err); int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info); u32 xfrm_get_acqseq(void); extern int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi); -struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto, +struct xfrm_state * xfrm_find_acq(struct net *net, u8 mode, u32 reqid, u8 proto, xfrm_address_t *daddr, xfrm_address_t *saddr, int create, unsigned short family); extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol); diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 15e0c2c7aac..65498483325 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -2165,7 +2165,8 @@ static void get_ipsec_sa(struct pktgen_dev *pkt_dev, int flow) struct xfrm_state *x = pkt_dev->flows[flow].x; if (!x) { /*slow path: we dont already have xfrm_state*/ - x = xfrm_stateonly_find((xfrm_address_t *)&pkt_dev->cur_daddr, + x = xfrm_stateonly_find(&init_net, + (xfrm_address_t *)&pkt_dev->cur_daddr, (xfrm_address_t *)&pkt_dev->cur_saddr, AF_INET, pkt_dev->ipsmode, diff --git a/net/key/af_key.c b/net/key/af_key.c index 449a5d03e28..4ef0827009e 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1348,7 +1348,7 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h } if (hdr->sadb_msg_seq) { - x = xfrm_find_acq_byseq(hdr->sadb_msg_seq); + x = xfrm_find_acq_byseq(&init_net, hdr->sadb_msg_seq); if (x && xfrm_addr_cmp(&x->id.daddr, xdaddr, family)) { xfrm_state_put(x); x = NULL; @@ -1356,7 +1356,7 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h } if (!x) - x = xfrm_find_acq(mode, reqid, proto, xdaddr, xsaddr, 1, family); + x = xfrm_find_acq(&init_net, mode, reqid, proto, xdaddr, xsaddr, 1, family); if (x == NULL) return -ENOENT; @@ -1404,7 +1404,7 @@ static int pfkey_acquire(struct sock *sk, struct sk_buff *skb, struct sadb_msg * if (hdr->sadb_msg_seq == 0 || hdr->sadb_msg_errno == 0) return 0; - x = xfrm_find_acq_byseq(hdr->sadb_msg_seq); + x = xfrm_find_acq_byseq(&init_net, hdr->sadb_msg_seq); if (x == NULL) return 0; diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index cd51e4e3d02..0d974fc9dd6 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -765,6 +765,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, struct xfrm_policy *pol, int *err, unsigned short family) { + struct net *net = xp_net(pol); unsigned int h; struct hlist_node *entry; struct xfrm_state *x, *x0, *to_put; @@ -775,8 +776,8 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, to_put = NULL; spin_lock_bh(&xfrm_state_lock); - h = xfrm_dst_hash(&init_net, daddr, saddr, tmpl->reqid, family); - hlist_for_each_entry(x, entry, init_net.xfrm.state_bydst+h, bydst) { + h = xfrm_dst_hash(net, daddr, saddr, tmpl->reqid, family); + hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { if (x->props.family == family && x->props.reqid == tmpl->reqid && !(x->props.flags & XFRM_STATE_WILDRECV) && @@ -820,13 +821,13 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, x = best; if (!x && !error && !acquire_in_progress) { if (tmpl->id.spi && - (x0 = __xfrm_state_lookup(&init_net, daddr, tmpl->id.spi, + (x0 = __xfrm_state_lookup(net, daddr, tmpl->id.spi, tmpl->id.proto, family)) != NULL) { to_put = x0; error = -EEXIST; goto out; } - x = xfrm_state_alloc(&init_net); + x = xfrm_state_alloc(net); if (x == NULL) { error = -ENOMEM; goto out; @@ -845,19 +846,19 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, if (km_query(x, tmpl, pol) == 0) { x->km.state = XFRM_STATE_ACQ; - list_add(&x->km.all, &init_net.xfrm.state_all); - hlist_add_head(&x->bydst, init_net.xfrm.state_bydst+h); - h = xfrm_src_hash(&init_net, daddr, saddr, family); - hlist_add_head(&x->bysrc, init_net.xfrm.state_bysrc+h); + list_add(&x->km.all, &net->xfrm.state_all); + hlist_add_head(&x->bydst, net->xfrm.state_bydst+h); + h = xfrm_src_hash(net, daddr, saddr, family); + hlist_add_head(&x->bysrc, net->xfrm.state_bysrc+h); if (x->id.spi) { - h = xfrm_spi_hash(&init_net, &x->id.daddr, x->id.spi, x->id.proto, family); - hlist_add_head(&x->byspi, init_net.xfrm.state_byspi+h); + h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, family); + hlist_add_head(&x->byspi, net->xfrm.state_byspi+h); } x->lft.hard_add_expires_seconds = sysctl_xfrm_acq_expires; x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ; add_timer(&x->timer); - init_net.xfrm.state_num++; - xfrm_hash_grow_check(&init_net, x->bydst.next != NULL); + net->xfrm.state_num++; + xfrm_hash_grow_check(net, x->bydst.next != NULL); } else { x->km.state = XFRM_STATE_DEAD; to_put = x; @@ -877,7 +878,8 @@ out: } struct xfrm_state * -xfrm_stateonly_find(xfrm_address_t *daddr, xfrm_address_t *saddr, +xfrm_stateonly_find(struct net *net, + xfrm_address_t *daddr, xfrm_address_t *saddr, unsigned short family, u8 mode, u8 proto, u32 reqid) { unsigned int h; @@ -885,8 +887,8 @@ xfrm_stateonly_find(xfrm_address_t *daddr, xfrm_address_t *saddr, struct hlist_node *entry; spin_lock(&xfrm_state_lock); - h = xfrm_dst_hash(&init_net, daddr, saddr, reqid, family); - hlist_for_each_entry(x, entry, init_net.xfrm.state_bydst+h, bydst) { + h = xfrm_dst_hash(net, daddr, saddr, reqid, family); + hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { if (x->props.family == family && x->props.reqid == reqid && !(x->props.flags & XFRM_STATE_WILDRECV) && @@ -972,13 +974,13 @@ void xfrm_state_insert(struct xfrm_state *x) EXPORT_SYMBOL(xfrm_state_insert); /* xfrm_state_lock is held */ -static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 reqid, u8 proto, xfrm_address_t *daddr, xfrm_address_t *saddr, int create) +static struct xfrm_state *__find_acq_core(struct net *net, unsigned short family, u8 mode, u32 reqid, u8 proto, xfrm_address_t *daddr, xfrm_address_t *saddr, int create) { - unsigned int h = xfrm_dst_hash(&init_net, daddr, saddr, reqid, family); + unsigned int h = xfrm_dst_hash(net, daddr, saddr, reqid, family); struct hlist_node *entry; struct xfrm_state *x; - hlist_for_each_entry(x, entry, init_net.xfrm.state_bydst+h, bydst) { + hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { if (x->props.reqid != reqid || x->props.mode != mode || x->props.family != family || @@ -1010,7 +1012,7 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re if (!create) return NULL; - x = xfrm_state_alloc(&init_net); + x = xfrm_state_alloc(net); if (likely(x)) { switch (family) { case AF_INET: @@ -1045,23 +1047,24 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re xfrm_state_hold(x); x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ; add_timer(&x->timer); - list_add(&x->km.all, &init_net.xfrm.state_all); - hlist_add_head(&x->bydst, init_net.xfrm.state_bydst+h); - h = xfrm_src_hash(&init_net, daddr, saddr, family); - hlist_add_head(&x->bysrc, init_net.xfrm.state_bysrc+h); + list_add(&x->km.all, &net->xfrm.state_all); + hlist_add_head(&x->bydst, net->xfrm.state_bydst+h); + h = xfrm_src_hash(net, daddr, saddr, family); + hlist_add_head(&x->bysrc, net->xfrm.state_bysrc+h); - init_net.xfrm.state_num++; + net->xfrm.state_num++; - xfrm_hash_grow_check(&init_net, x->bydst.next != NULL); + xfrm_hash_grow_check(net, x->bydst.next != NULL); } return x; } -static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq); +static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 seq); int xfrm_state_add(struct xfrm_state *x) { + struct net *net = xs_net(x); struct xfrm_state *x1, *to_put; int family; int err; @@ -1082,7 +1085,7 @@ int xfrm_state_add(struct xfrm_state *x) } if (use_spi && x->km.seq) { - x1 = __xfrm_find_acq_byseq(x->km.seq); + x1 = __xfrm_find_acq_byseq(net, x->km.seq); if (x1 && ((x1->id.proto != x->id.proto) || xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family))) { to_put = x1; @@ -1091,7 +1094,7 @@ int xfrm_state_add(struct xfrm_state *x) } if (use_spi && !x1) - x1 = __find_acq_core(family, x->props.mode, x->props.reqid, + x1 = __find_acq_core(net, family, x->props.mode, x->props.reqid, x->id.proto, &x->id.daddr, &x->props.saddr, 0); @@ -1390,14 +1393,14 @@ xfrm_state_lookup_byaddr(struct net *net, EXPORT_SYMBOL(xfrm_state_lookup_byaddr); struct xfrm_state * -xfrm_find_acq(u8 mode, u32 reqid, u8 proto, +xfrm_find_acq(struct net *net, u8 mode, u32 reqid, u8 proto, xfrm_address_t *daddr, xfrm_address_t *saddr, int create, unsigned short family) { struct xfrm_state *x; spin_lock_bh(&xfrm_state_lock); - x = __find_acq_core(family, mode, reqid, proto, daddr, saddr, create); + x = __find_acq_core(net, family, mode, reqid, proto, daddr, saddr, create); spin_unlock_bh(&xfrm_state_lock); return x; @@ -1444,15 +1447,15 @@ EXPORT_SYMBOL(xfrm_state_sort); /* Silly enough, but I'm lazy to build resolution list */ -static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq) +static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 seq) { int i; - for (i = 0; i <= init_net.xfrm.state_hmask; i++) { + for (i = 0; i <= net->xfrm.state_hmask; i++) { struct hlist_node *entry; struct xfrm_state *x; - hlist_for_each_entry(x, entry, init_net.xfrm.state_bydst+i, bydst) { + hlist_for_each_entry(x, entry, net->xfrm.state_bydst+i, bydst) { if (x->km.seq == seq && x->km.state == XFRM_STATE_ACQ) { xfrm_state_hold(x); @@ -1463,12 +1466,12 @@ static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq) return NULL; } -struct xfrm_state *xfrm_find_acq_byseq(u32 seq) +struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 seq) { struct xfrm_state *x; spin_lock_bh(&xfrm_state_lock); - x = __xfrm_find_acq_byseq(seq); + x = __xfrm_find_acq_byseq(net, seq); spin_unlock_bh(&xfrm_state_lock); return x; } diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index e02ef336119..3d577440b67 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -837,7 +837,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, x = NULL; if (p->info.seq) { - x = xfrm_find_acq_byseq(p->info.seq); + x = xfrm_find_acq_byseq(&init_net, p->info.seq); if (x && xfrm_addr_cmp(&x->id.daddr, daddr, family)) { xfrm_state_put(x); x = NULL; @@ -845,7 +845,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, } if (!x) - x = xfrm_find_acq(p->info.mode, p->info.reqid, + x = xfrm_find_acq(&init_net, p->info.mode, p->info.reqid, p->info.id.proto, daddr, &p->info.saddr, 1, family); -- cgit v1.2.3-70-g09d2 From 284fa7da300adcb700b44df2f64a536b434d4650 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 25 Nov 2008 17:32:14 -0800 Subject: netns xfrm: state walking in netns Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- include/net/xfrm.h | 2 +- net/key/af_key.c | 2 +- net/xfrm/xfrm_state.c | 6 +++--- net/xfrm/xfrm_user.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'net/xfrm/xfrm_user.c') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 4cbd0557c69..40ed4878bc1 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1307,7 +1307,7 @@ extern int xfrm_proc_init(void); #endif extern void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto); -extern int xfrm_state_walk(struct xfrm_state_walk *walk, +extern int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk, int (*func)(struct xfrm_state *, int, void*), void *); extern void xfrm_state_walk_done(struct xfrm_state_walk *walk); extern struct xfrm_state *xfrm_state_alloc(struct net *net); diff --git a/net/key/af_key.c b/net/key/af_key.c index 4ef0827009e..b74d939e2ee 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1776,7 +1776,7 @@ static int dump_sa(struct xfrm_state *x, int count, void *ptr) static int pfkey_dump_sa(struct pfkey_sock *pfk) { - return xfrm_state_walk(&pfk->dump.u.state, dump_sa, (void *) pfk); + return xfrm_state_walk(&init_net, &pfk->dump.u.state, dump_sa, (void *) pfk); } static void pfkey_dump_sa_done(struct pfkey_sock *pfk) diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 0d974fc9dd6..ea340bbbcc6 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -1544,7 +1544,7 @@ unlock: } EXPORT_SYMBOL(xfrm_alloc_spi); -int xfrm_state_walk(struct xfrm_state_walk *walk, +int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk, int (*func)(struct xfrm_state *, int, void*), void *data) { @@ -1557,10 +1557,10 @@ int xfrm_state_walk(struct xfrm_state_walk *walk, spin_lock_bh(&xfrm_state_lock); if (list_empty(&walk->all)) - x = list_first_entry(&init_net.xfrm.state_all, struct xfrm_state_walk, all); + x = list_first_entry(&net->xfrm.state_all, struct xfrm_state_walk, all); else x = list_entry(&walk->all, struct xfrm_state_walk, all); - list_for_each_entry_from(x, &init_net.xfrm.state_all, all) { + list_for_each_entry_from(x, &net->xfrm.state_all, all) { if (x->state == XFRM_STATE_DEAD) continue; state = container_of(x, struct xfrm_state, km); diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 3d577440b67..787b0ee6503 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -631,7 +631,7 @@ static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb) xfrm_state_walk_init(walk, 0); } - (void) xfrm_state_walk(walk, dump_one_state, &info); + (void) xfrm_state_walk(&init_net, walk, dump_one_state, &info); return skb->len; } -- cgit v1.2.3-70-g09d2 From 33ffbbd52c327225a3e28485c39dc5746d81be03 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 25 Nov 2008 17:33:32 -0800 Subject: netns xfrm: policy flushing in netns Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- include/net/xfrm.h | 2 +- net/key/af_key.c | 2 +- net/xfrm/xfrm_policy.c | 22 +++++++++++----------- net/xfrm/xfrm_user.c | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) (limited to 'net/xfrm/xfrm_user.c') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 40ed4878bc1..766cc71e96d 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1444,7 +1444,7 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, struct xfrm_sec_ctx *ctx, int delete, int *err); struct xfrm_policy *xfrm_policy_byid(u8, int dir, u32 id, int delete, int *err); -int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info); +int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info); u32 xfrm_get_acqseq(void); extern int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi); struct xfrm_state * xfrm_find_acq(struct net *net, u8 mode, u32 reqid, u8 proto, diff --git a/net/key/af_key.c b/net/key/af_key.c index b74d939e2ee..0f44856c1f1 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -2686,7 +2686,7 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg audit_info.loginuid = audit_get_loginuid(current); audit_info.sessionid = audit_get_sessionid(current); audit_info.secid = 0; - err = xfrm_policy_flush(XFRM_POLICY_TYPE_MAIN, &audit_info); + err = xfrm_policy_flush(&init_net, XFRM_POLICY_TYPE_MAIN, &audit_info); if (err) return err; c.data.type = XFRM_POLICY_TYPE_MAIN; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 11fee87a0cc..7c264a74edc 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -732,7 +732,7 @@ EXPORT_SYMBOL(xfrm_policy_byid); #ifdef CONFIG_SECURITY_NETWORK_XFRM static inline int -xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info) +xfrm_policy_flush_secctx_check(struct net *net, u8 type, struct xfrm_audit *audit_info) { int dir, err = 0; @@ -742,7 +742,7 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info) int i; hlist_for_each_entry(pol, entry, - &init_net.xfrm.policy_inexact[dir], bydst) { + &net->xfrm.policy_inexact[dir], bydst) { if (pol->type != type) continue; err = security_xfrm_policy_delete(pol->security); @@ -754,9 +754,9 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info) return err; } } - for (i = init_net.xfrm.policy_bydst[dir].hmask; i >= 0; i--) { + for (i = net->xfrm.policy_bydst[dir].hmask; i >= 0; i--) { hlist_for_each_entry(pol, entry, - init_net.xfrm.policy_bydst[dir].table + i, + net->xfrm.policy_bydst[dir].table + i, bydst) { if (pol->type != type) continue; @@ -776,19 +776,19 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info) } #else static inline int -xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info) +xfrm_policy_flush_secctx_check(struct net *net, u8 type, struct xfrm_audit *audit_info) { return 0; } #endif -int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info) +int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) { int dir, err = 0; write_lock_bh(&xfrm_policy_lock); - err = xfrm_policy_flush_secctx_check(type, audit_info); + err = xfrm_policy_flush_secctx_check(net, type, audit_info); if (err) goto out; @@ -800,7 +800,7 @@ int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info) killed = 0; again1: hlist_for_each_entry(pol, entry, - &init_net.xfrm.policy_inexact[dir], bydst) { + &net->xfrm.policy_inexact[dir], bydst) { if (pol->type != type) continue; hlist_del(&pol->bydst); @@ -818,10 +818,10 @@ int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info) goto again1; } - for (i = init_net.xfrm.policy_bydst[dir].hmask; i >= 0; i--) { + for (i = net->xfrm.policy_bydst[dir].hmask; i >= 0; i--) { again2: hlist_for_each_entry(pol, entry, - init_net.xfrm.policy_bydst[dir].table + i, + net->xfrm.policy_bydst[dir].table + i, bydst) { if (pol->type != type) continue; @@ -842,7 +842,7 @@ int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info) } } - init_net.xfrm.policy_count[dir] -= killed; + net->xfrm.policy_count[dir] -= killed; } atomic_inc(&flow_cache_genid); out: diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 787b0ee6503..d4983e831c3 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1546,7 +1546,7 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, audit_info.loginuid = NETLINK_CB(skb).loginuid; audit_info.sessionid = NETLINK_CB(skb).sessionid; audit_info.secid = NETLINK_CB(skb).sid; - err = xfrm_policy_flush(type, &audit_info); + err = xfrm_policy_flush(&init_net, type, &audit_info); if (err) return err; c.data.type = type; -- cgit v1.2.3-70-g09d2 From 8d1211a6aaea43ea36151c17b0193eb763ff2d7e Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 25 Nov 2008 17:34:20 -0800 Subject: netns xfrm: finding policy in netns Add netns parameter to xfrm_policy_bysel_ctx(), xfrm_policy_byidx(). Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- include/net/xfrm.h | 4 ++-- net/key/af_key.c | 6 +++--- net/xfrm/xfrm_policy.c | 14 +++++++------- net/xfrm/xfrm_user.c | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) (limited to 'net/xfrm/xfrm_user.c') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 766cc71e96d..ec2b7a9b3aa 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1439,11 +1439,11 @@ extern int xfrm_policy_walk(struct xfrm_policy_walk *walk, int (*func)(struct xfrm_policy *, int, int, void*), void *); extern void xfrm_policy_walk_done(struct xfrm_policy_walk *walk); int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl); -struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, +struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u8 type, int dir, struct xfrm_selector *sel, struct xfrm_sec_ctx *ctx, int delete, int *err); -struct xfrm_policy *xfrm_policy_byid(u8, int dir, u32 id, int delete, int *err); +struct xfrm_policy *xfrm_policy_byid(struct net *net, u8, int dir, u32 id, int delete, int *err); int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info); u32 xfrm_get_acqseq(void); extern int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi); diff --git a/net/key/af_key.c b/net/key/af_key.c index 0f44856c1f1..ca268116ac1 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -2324,7 +2324,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg return err; } - xp = xfrm_policy_bysel_ctx(XFRM_POLICY_TYPE_MAIN, + xp = xfrm_policy_bysel_ctx(&init_net, XFRM_POLICY_TYPE_MAIN, pol->sadb_x_policy_dir - 1, &sel, pol_ctx, 1, &err); security_xfrm_policy_free(pol_ctx); @@ -2571,8 +2571,8 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h return -EINVAL; delete = (hdr->sadb_msg_type == SADB_X_SPDDELETE2); - xp = xfrm_policy_byid(XFRM_POLICY_TYPE_MAIN, dir, pol->sadb_x_policy_id, - delete, &err); + xp = xfrm_policy_byid(&init_net, XFRM_POLICY_TYPE_MAIN, dir, + pol->sadb_x_policy_id, delete, &err); if (xp == NULL) return -ENOENT; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 7c264a74edc..96895ef6185 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -642,7 +642,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) } EXPORT_SYMBOL(xfrm_policy_insert); -struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, +struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u8 type, int dir, struct xfrm_selector *sel, struct xfrm_sec_ctx *ctx, int delete, int *err) @@ -653,7 +653,7 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, *err = 0; write_lock_bh(&xfrm_policy_lock); - chain = policy_hash_bysel(&init_net, sel, sel->family, dir); + chain = policy_hash_bysel(net, sel, sel->family, dir); ret = NULL; hlist_for_each_entry(pol, entry, chain, bydst) { if (pol->type == type && @@ -670,7 +670,7 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, hlist_del(&pol->bydst); hlist_del(&pol->byidx); list_del(&pol->walk.all); - init_net.xfrm.policy_count[dir]--; + net->xfrm.policy_count[dir]--; } ret = pol; break; @@ -686,8 +686,8 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, } EXPORT_SYMBOL(xfrm_policy_bysel_ctx); -struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete, - int *err) +struct xfrm_policy *xfrm_policy_byid(struct net *net, u8 type, int dir, u32 id, + int delete, int *err) { struct xfrm_policy *pol, *ret; struct hlist_head *chain; @@ -699,7 +699,7 @@ struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete, *err = 0; write_lock_bh(&xfrm_policy_lock); - chain = init_net.xfrm.policy_byidx + idx_hash(&init_net, id); + chain = net->xfrm.policy_byidx + idx_hash(net, id); ret = NULL; hlist_for_each_entry(pol, entry, chain, byidx) { if (pol->type == type && pol->index == id) { @@ -714,7 +714,7 @@ struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete, hlist_del(&pol->bydst); hlist_del(&pol->byidx); list_del(&pol->walk.all); - init_net.xfrm.policy_count[dir]--; + net->xfrm.policy_count[dir]--; } ret = pol; break; diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index d4983e831c3..efd6ab5c0ac 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1330,7 +1330,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, return err; if (p->index) - xp = xfrm_policy_byid(type, p->dir, p->index, delete, &err); + xp = xfrm_policy_byid(&init_net, type, p->dir, p->index, delete, &err); else { struct nlattr *rt = attrs[XFRMA_SEC_CTX]; struct xfrm_sec_ctx *ctx; @@ -1347,7 +1347,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, if (err) return err; } - xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, ctx, + xp = xfrm_policy_bysel_ctx(&init_net, type, p->dir, &p->sel, ctx, delete, &err); security_xfrm_policy_free(ctx); } @@ -1571,7 +1571,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, return err; if (p->index) - xp = xfrm_policy_byid(type, p->dir, p->index, 0, &err); + xp = xfrm_policy_byid(&init_net, type, p->dir, p->index, 0, &err); else { struct nlattr *rt = attrs[XFRMA_SEC_CTX]; struct xfrm_sec_ctx *ctx; @@ -1588,7 +1588,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, if (err) return err; } - xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, ctx, 0, &err); + xp = xfrm_policy_bysel_ctx(&init_net, type, p->dir, &p->sel, ctx, 0, &err); security_xfrm_policy_free(ctx); } if (xp == NULL) -- cgit v1.2.3-70-g09d2 From cdcbca7c1f1946758cfacb69bc1c7eeaccb11e2d Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 25 Nov 2008 17:34:49 -0800 Subject: netns xfrm: policy walking in netns Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- include/net/xfrm.h | 2 +- net/key/af_key.c | 4 ++-- net/xfrm/xfrm_policy.c | 6 +++--- net/xfrm/xfrm_user.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'net/xfrm/xfrm_user.c') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index ec2b7a9b3aa..1dc4ff0f485 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1435,7 +1435,7 @@ static inline int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb) struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp); extern void xfrm_policy_walk_init(struct xfrm_policy_walk *walk, u8 type); -extern int xfrm_policy_walk(struct xfrm_policy_walk *walk, +extern int xfrm_policy_walk(struct net *net, struct xfrm_policy_walk *walk, int (*func)(struct xfrm_policy *, int, int, void*), void *); extern void xfrm_policy_walk_done(struct xfrm_policy_walk *walk); int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl); diff --git a/net/key/af_key.c b/net/key/af_key.c index ca268116ac1..a0d849848dd 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1846,7 +1846,7 @@ static u32 gen_reqid(void) if (reqid == 0) reqid = IPSEC_MANUAL_REQID_MAX+1; xfrm_policy_walk_init(&walk, XFRM_POLICY_TYPE_MAIN); - rc = xfrm_policy_walk(&walk, check_reqid, (void*)&reqid); + rc = xfrm_policy_walk(&init_net, &walk, check_reqid, (void*)&reqid); xfrm_policy_walk_done(&walk); if (rc != -EEXIST) return reqid; @@ -2633,7 +2633,7 @@ static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr) static int pfkey_dump_sp(struct pfkey_sock *pfk) { - return xfrm_policy_walk(&pfk->dump.u.policy, dump_sp, (void *) pfk); + return xfrm_policy_walk(&init_net, &pfk->dump.u.policy, dump_sp, (void *) pfk); } static void pfkey_dump_sp_done(struct pfkey_sock *pfk) diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 96895ef6185..6165218fd7c 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -851,7 +851,7 @@ out: } EXPORT_SYMBOL(xfrm_policy_flush); -int xfrm_policy_walk(struct xfrm_policy_walk *walk, +int xfrm_policy_walk(struct net *net, struct xfrm_policy_walk *walk, int (*func)(struct xfrm_policy *, int, int, void*), void *data) { @@ -868,10 +868,10 @@ int xfrm_policy_walk(struct xfrm_policy_walk *walk, write_lock_bh(&xfrm_policy_lock); if (list_empty(&walk->walk.all)) - x = list_first_entry(&init_net.xfrm.policy_all, struct xfrm_policy_walk_entry, all); + x = list_first_entry(&net->xfrm.policy_all, struct xfrm_policy_walk_entry, all); else x = list_entry(&walk->walk.all, struct xfrm_policy_walk_entry, all); - list_for_each_entry_from(x, &init_net.xfrm.policy_all, all) { + list_for_each_entry_from(x, &net->xfrm.policy_all, all) { if (x->dead) continue; pol = container_of(x, struct xfrm_policy, walk); diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index efd6ab5c0ac..f6e02726cf1 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1279,7 +1279,7 @@ static int xfrm_dump_policy(struct sk_buff *skb, struct netlink_callback *cb) xfrm_policy_walk_init(walk, XFRM_POLICY_TYPE_ANY); } - (void) xfrm_policy_walk(walk, dump_one_policy, &info); + (void) xfrm_policy_walk(&init_net, walk, dump_one_policy, &info); return skb->len; } -- cgit v1.2.3-70-g09d2 From a6483b790f8efcd8db190c1c0ff93f9d9efe919a Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 25 Nov 2008 17:38:20 -0800 Subject: netns xfrm: per-netns NETLINK_XFRM socket Stub senders to init_net's one temporarily. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- include/net/netns/xfrm.h | 2 + include/net/xfrm.h | 7 +-- net/xfrm/xfrm_output.c | 3 +- net/xfrm/xfrm_state.c | 7 +-- net/xfrm/xfrm_user.c | 108 ++++++++++++++++++++++++++++++++--------------- 5 files changed, 83 insertions(+), 44 deletions(-) (limited to 'net/xfrm/xfrm_user.c') diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h index c53d17357a4..09f3060e9d1 100644 --- a/include/net/netns/xfrm.h +++ b/include/net/netns/xfrm.h @@ -39,6 +39,8 @@ struct netns_xfrm { struct xfrm_policy_hash policy_bydst[XFRM_POLICY_MAX * 2]; unsigned int policy_count[XFRM_POLICY_MAX * 2]; struct work_struct policy_hash_work; + + struct sock *nlsk; }; #endif diff --git a/include/net/xfrm.h b/include/net/xfrm.h index bd2515005ae..e027179e819 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -48,7 +48,6 @@ DECLARE_SNMP_STAT(struct linux_xfrm_mib, xfrm_statistics); #define XFRM_INC_STATS_USER(field) #endif -extern struct sock *xfrm_nl; extern u32 sysctl_xfrm_aevent_etime; extern u32 sysctl_xfrm_aevent_rseqth; extern int sysctl_xfrm_larval_drop; @@ -1516,18 +1515,20 @@ static inline int xfrm_policy_id2dir(u32 index) return index & 7; } -static inline int xfrm_aevent_is_on(void) +#ifdef CONFIG_XFRM +static inline int xfrm_aevent_is_on(struct net *net) { struct sock *nlsk; int ret = 0; rcu_read_lock(); - nlsk = rcu_dereference(xfrm_nl); + nlsk = rcu_dereference(net->xfrm.nlsk); if (nlsk) ret = netlink_has_listeners(nlsk, XFRMNLGRP_AEVENTS); rcu_read_unlock(); return ret; } +#endif static inline int xfrm_alg_len(struct xfrm_algo *alg) { diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index dc50f1e71f7..ba90e5e50ff 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c @@ -41,6 +41,7 @@ static int xfrm_output_one(struct sk_buff *skb, int err) { struct dst_entry *dst = skb->dst; struct xfrm_state *x = dst->xfrm; + struct net *net = xs_net(x); if (err <= 0) goto resume; @@ -74,7 +75,7 @@ static int xfrm_output_one(struct sk_buff *skb, int err) err = -EOVERFLOW; goto error; } - if (xfrm_aevent_is_on()) + if (xfrm_aevent_is_on(net)) xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); } diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index ea340bbbcc6..21db37ab0a2 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -24,9 +24,6 @@ #include "xfrm_hash.h" -struct sock *xfrm_nl; -EXPORT_SYMBOL(xfrm_nl); - u32 sysctl_xfrm_aevent_etime __read_mostly = XFRM_AE_ETIME; EXPORT_SYMBOL(sysctl_xfrm_aevent_etime); @@ -1659,7 +1656,7 @@ static void xfrm_replay_timer_handler(unsigned long data) spin_lock(&x->lock); if (x->km.state == XFRM_STATE_VALID) { - if (xfrm_aevent_is_on()) + if (xfrm_aevent_is_on(xs_net(x))) xfrm_replay_notify(x, XFRM_REPLAY_TIMEOUT); else x->xflags |= XFRM_TIME_DEFER; @@ -1715,7 +1712,7 @@ void xfrm_replay_advance(struct xfrm_state *x, __be32 net_seq) x->replay.bitmap |= (1U << diff); } - if (xfrm_aevent_is_on()) + if (xfrm_aevent_is_on(xs_net(x))) xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); } diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index f6e02726cf1..8b5b01dfb77 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -703,6 +703,7 @@ nla_put_failure: static int xfrm_get_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh, struct nlattr **attrs) { + struct net *net = sock_net(skb->sk); struct sk_buff *r_skb; u32 *flags = nlmsg_data(nlh); u32 spid = NETLINK_CB(skb).pid; @@ -715,7 +716,7 @@ static int xfrm_get_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh, if (build_spdinfo(r_skb, spid, seq, *flags) < 0) BUG(); - return nlmsg_unicast(xfrm_nl, r_skb, spid); + return nlmsg_unicast(net->xfrm.nlsk, r_skb, spid); } static inline size_t xfrm_sadinfo_msgsize(void) @@ -756,6 +757,7 @@ nla_put_failure: static int xfrm_get_sadinfo(struct sk_buff *skb, struct nlmsghdr *nlh, struct nlattr **attrs) { + struct net *net = sock_net(skb->sk); struct sk_buff *r_skb; u32 *flags = nlmsg_data(nlh); u32 spid = NETLINK_CB(skb).pid; @@ -768,12 +770,13 @@ static int xfrm_get_sadinfo(struct sk_buff *skb, struct nlmsghdr *nlh, if (build_sadinfo(r_skb, spid, seq, *flags) < 0) BUG(); - return nlmsg_unicast(xfrm_nl, r_skb, spid); + return nlmsg_unicast(net->xfrm.nlsk, r_skb, spid); } static int xfrm_get_sa(struct sk_buff *skb, struct nlmsghdr *nlh, struct nlattr **attrs) { + struct net *net = &init_net; struct xfrm_usersa_id *p = nlmsg_data(nlh); struct xfrm_state *x; struct sk_buff *resp_skb; @@ -787,7 +790,7 @@ static int xfrm_get_sa(struct sk_buff *skb, struct nlmsghdr *nlh, if (IS_ERR(resp_skb)) { err = PTR_ERR(resp_skb); } else { - err = nlmsg_unicast(xfrm_nl, resp_skb, NETLINK_CB(skb).pid); + err = nlmsg_unicast(net->xfrm.nlsk, resp_skb, NETLINK_CB(skb).pid); } xfrm_state_put(x); out_noput: @@ -820,6 +823,7 @@ static int verify_userspi_info(struct xfrm_userspi_info *p) static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, struct nlattr **attrs) { + struct net *net = &init_net; struct xfrm_state *x; struct xfrm_userspi_info *p; struct sk_buff *resp_skb; @@ -837,7 +841,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, x = NULL; if (p->info.seq) { - x = xfrm_find_acq_byseq(&init_net, p->info.seq); + x = xfrm_find_acq_byseq(net, p->info.seq); if (x && xfrm_addr_cmp(&x->id.daddr, daddr, family)) { xfrm_state_put(x); x = NULL; @@ -845,7 +849,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, } if (!x) - x = xfrm_find_acq(&init_net, p->info.mode, p->info.reqid, + x = xfrm_find_acq(net, p->info.mode, p->info.reqid, p->info.id.proto, daddr, &p->info.saddr, 1, family); @@ -863,7 +867,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, goto out; } - err = nlmsg_unicast(xfrm_nl, resp_skb, NETLINK_CB(skb).pid); + err = nlmsg_unicast(net->xfrm.nlsk, resp_skb, NETLINK_CB(skb).pid); out: xfrm_state_put(x); @@ -1311,6 +1315,7 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb, static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, struct nlattr **attrs) { + struct net *net = &init_net; struct xfrm_policy *xp; struct xfrm_userpolicy_id *p; u8 type = XFRM_POLICY_TYPE_MAIN; @@ -1330,7 +1335,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, return err; if (p->index) - xp = xfrm_policy_byid(&init_net, type, p->dir, p->index, delete, &err); + xp = xfrm_policy_byid(net, type, p->dir, p->index, delete, &err); else { struct nlattr *rt = attrs[XFRMA_SEC_CTX]; struct xfrm_sec_ctx *ctx; @@ -1347,7 +1352,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, if (err) return err; } - xp = xfrm_policy_bysel_ctx(&init_net, type, p->dir, &p->sel, ctx, + xp = xfrm_policy_bysel_ctx(net, type, p->dir, &p->sel, ctx, delete, &err); security_xfrm_policy_free(ctx); } @@ -1361,7 +1366,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, if (IS_ERR(resp_skb)) { err = PTR_ERR(resp_skb); } else { - err = nlmsg_unicast(xfrm_nl, resp_skb, + err = nlmsg_unicast(net->xfrm.nlsk, resp_skb, NETLINK_CB(skb).pid); } } else { @@ -1457,6 +1462,7 @@ nla_put_failure: static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, struct nlattr **attrs) { + struct net *net = &init_net; struct xfrm_state *x; struct sk_buff *r_skb; int err; @@ -1468,7 +1474,7 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, if (r_skb == NULL) return -ENOMEM; - x = xfrm_state_lookup(&init_net, &id->daddr, id->spi, id->proto, id->family); + x = xfrm_state_lookup(net, &id->daddr, id->spi, id->proto, id->family); if (x == NULL) { kfree_skb(r_skb); return -ESRCH; @@ -1486,7 +1492,7 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, if (build_aevent(r_skb, x, &c) < 0) BUG(); - err = nlmsg_unicast(xfrm_nl, r_skb, NETLINK_CB(skb).pid); + err = nlmsg_unicast(net->xfrm.nlsk, r_skb, NETLINK_CB(skb).pid); spin_unlock_bh(&x->lock); xfrm_state_put(x); return err; @@ -1869,6 +1875,7 @@ static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, struct xfrm_migrate *m, int num_migrate, struct xfrm_kmaddress *k) { + struct net *net = &init_net; struct sk_buff *skb; skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate, !!k), GFP_ATOMIC); @@ -1879,7 +1886,7 @@ static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, if (build_migrate(skb, m, num_migrate, k, sel, dir, type) < 0) BUG(); - return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_MIGRATE, GFP_ATOMIC); + return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_MIGRATE, GFP_ATOMIC); } #else static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, @@ -1968,6 +1975,7 @@ static struct xfrm_link { static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) { + struct net *net = sock_net(skb->sk); struct nlattr *attrs[XFRMA_MAX+1]; struct xfrm_link *link; int type, err; @@ -1989,7 +1997,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (link->dump == NULL) return -EINVAL; - return netlink_dump_start(xfrm_nl, skb, nlh, link->dump, link->done); + return netlink_dump_start(net->xfrm.nlsk, skb, nlh, link->dump, link->done); } err = nlmsg_parse(nlh, xfrm_msg_min[type], attrs, XFRMA_MAX, @@ -2033,6 +2041,7 @@ static int build_expire(struct sk_buff *skb, struct xfrm_state *x, struct km_eve static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c) { + struct net *net = &init_net; struct sk_buff *skb; skb = nlmsg_new(xfrm_expire_msgsize(), GFP_ATOMIC); @@ -2042,11 +2051,12 @@ static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c) if (build_expire(skb, x, c) < 0) BUG(); - return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); + return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); } static int xfrm_aevent_state_notify(struct xfrm_state *x, struct km_event *c) { + struct net *net = &init_net; struct sk_buff *skb; skb = nlmsg_new(xfrm_aevent_msgsize(), GFP_ATOMIC); @@ -2056,11 +2066,12 @@ static int xfrm_aevent_state_notify(struct xfrm_state *x, struct km_event *c) if (build_aevent(skb, x, c) < 0) BUG(); - return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_AEVENTS, GFP_ATOMIC); + return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_AEVENTS, GFP_ATOMIC); } static int xfrm_notify_sa_flush(struct km_event *c) { + struct net *net = &init_net; struct xfrm_usersa_flush *p; struct nlmsghdr *nlh; struct sk_buff *skb; @@ -2081,7 +2092,7 @@ static int xfrm_notify_sa_flush(struct km_event *c) nlmsg_end(skb, nlh); - return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC); + return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC); } static inline size_t xfrm_sa_len(struct xfrm_state *x) @@ -2111,6 +2122,7 @@ static inline size_t xfrm_sa_len(struct xfrm_state *x) static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c) { + struct net *net = &init_net; struct xfrm_usersa_info *p; struct xfrm_usersa_id *id; struct nlmsghdr *nlh; @@ -2155,7 +2167,7 @@ static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c) nlmsg_end(skb, nlh); - return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC); + return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC); nla_put_failure: /* Somebody screwed up with xfrm_sa_len! */ @@ -2235,6 +2247,7 @@ nlmsg_failure: static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt, struct xfrm_policy *xp, int dir) { + struct net *net = xs_net(x); struct sk_buff *skb; skb = nlmsg_new(xfrm_acquire_msgsize(x, xp), GFP_ATOMIC); @@ -2244,7 +2257,7 @@ static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt, if (build_acquire(skb, x, xt, xp, dir) < 0) BUG(); - return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_ACQUIRE, GFP_ATOMIC); + return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_ACQUIRE, GFP_ATOMIC); } /* User gives us xfrm_user_policy_info followed by an array of 0 @@ -2344,6 +2357,7 @@ nlmsg_failure: static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c) { + struct net *net = &init_net; struct sk_buff *skb; skb = nlmsg_new(xfrm_polexpire_msgsize(xp), GFP_ATOMIC); @@ -2353,11 +2367,12 @@ static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_eve if (build_polexpire(skb, xp, dir, c) < 0) BUG(); - return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); + return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); } static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c) { + struct net *net = &init_net; struct xfrm_userpolicy_info *p; struct xfrm_userpolicy_id *id; struct nlmsghdr *nlh; @@ -2408,7 +2423,7 @@ static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event * nlmsg_end(skb, nlh); - return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC); + return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC); nlmsg_failure: kfree_skb(skb); @@ -2417,6 +2432,7 @@ nlmsg_failure: static int xfrm_notify_policy_flush(struct km_event *c) { + struct net *net = &init_net; struct nlmsghdr *nlh; struct sk_buff *skb; @@ -2432,7 +2448,7 @@ static int xfrm_notify_policy_flush(struct km_event *c) nlmsg_end(skb, nlh); - return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC); + return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC); nlmsg_failure: kfree_skb(skb); @@ -2491,6 +2507,7 @@ nla_put_failure: static int xfrm_send_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr) { + struct net *net = &init_net; struct sk_buff *skb; skb = nlmsg_new(xfrm_report_msgsize(), GFP_ATOMIC); @@ -2500,7 +2517,7 @@ static int xfrm_send_report(u8 proto, struct xfrm_selector *sel, if (build_report(skb, proto, sel, addr) < 0) BUG(); - return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_REPORT, GFP_ATOMIC); + return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_REPORT, GFP_ATOMIC); } static inline size_t xfrm_mapping_msgsize(void) @@ -2536,6 +2553,7 @@ static int build_mapping(struct sk_buff *skb, struct xfrm_state *x, static int xfrm_send_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport) { + struct net *net = xs_net(x); struct sk_buff *skb; if (x->id.proto != IPPROTO_ESP) @@ -2551,7 +2569,7 @@ static int xfrm_send_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, if (build_mapping(skb, x, ipaddr, sport) < 0) BUG(); - return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_MAPPING, GFP_ATOMIC); + return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_MAPPING, GFP_ATOMIC); } static struct xfrm_mgr netlink_mgr = { @@ -2565,33 +2583,53 @@ static struct xfrm_mgr netlink_mgr = { .new_mapping = xfrm_send_mapping, }; -static int __init xfrm_user_init(void) +static int __net_init xfrm_user_net_init(struct net *net) { struct sock *nlsk; - printk(KERN_INFO "Initializing XFRM netlink socket\n"); - - nlsk = netlink_kernel_create(&init_net, NETLINK_XFRM, XFRMNLGRP_MAX, + nlsk = netlink_kernel_create(net, NETLINK_XFRM, XFRMNLGRP_MAX, xfrm_netlink_rcv, NULL, THIS_MODULE); if (nlsk == NULL) return -ENOMEM; - rcu_assign_pointer(xfrm_nl, nlsk); - - xfrm_register_km(&netlink_mgr); - + rcu_assign_pointer(net->xfrm.nlsk, nlsk); return 0; } -static void __exit xfrm_user_exit(void) +static void __net_exit xfrm_user_net_exit(struct net *net) { - struct sock *nlsk = xfrm_nl; + struct sock *nlsk = net->xfrm.nlsk; - xfrm_unregister_km(&netlink_mgr); - rcu_assign_pointer(xfrm_nl, NULL); + rcu_assign_pointer(net->xfrm.nlsk, NULL); synchronize_rcu(); netlink_kernel_release(nlsk); } +static struct pernet_operations xfrm_user_net_ops = { + .init = xfrm_user_net_init, + .exit = xfrm_user_net_exit, +}; + +static int __init xfrm_user_init(void) +{ + int rv; + + printk(KERN_INFO "Initializing XFRM netlink socket\n"); + + rv = register_pernet_subsys(&xfrm_user_net_ops); + if (rv < 0) + return rv; + rv = xfrm_register_km(&netlink_mgr); + if (rv < 0) + unregister_pernet_subsys(&xfrm_user_net_ops); + return rv; +} + +static void __exit xfrm_user_exit(void) +{ + xfrm_unregister_km(&netlink_mgr); + unregister_pernet_subsys(&xfrm_user_net_ops); +} + module_init(xfrm_user_init); module_exit(xfrm_user_exit); MODULE_LICENSE("GPL"); -- cgit v1.2.3-70-g09d2 From fc34acd36eecdec95171b98ef2516e3d4daa5c41 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 25 Nov 2008 17:50:08 -0800 Subject: netns xfrm: xfrm_user module in netns Grab netns either from netlink socket, state or policy. SA and SPD flush are in init_net for now, this requires little attention, see below. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- net/xfrm/xfrm_user.c | 76 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 31 deletions(-) (limited to 'net/xfrm/xfrm_user.c') diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 8b5b01dfb77..ab8b138e5e2 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -316,11 +316,12 @@ static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs) x->replay_maxdiff = nla_get_u32(rt); } -static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p, +static struct xfrm_state *xfrm_state_construct(struct net *net, + struct xfrm_usersa_info *p, struct nlattr **attrs, int *errp) { - struct xfrm_state *x = xfrm_state_alloc(&init_net); + struct xfrm_state *x = xfrm_state_alloc(net); int err = -ENOMEM; if (!x) @@ -391,6 +392,7 @@ error_no_put: static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, struct nlattr **attrs) { + struct net *net = sock_net(skb->sk); struct xfrm_usersa_info *p = nlmsg_data(nlh); struct xfrm_state *x; int err; @@ -403,7 +405,7 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, if (err) return err; - x = xfrm_state_construct(p, attrs, &err); + x = xfrm_state_construct(net, p, attrs, &err); if (!x) return err; @@ -431,7 +433,8 @@ out: return err; } -static struct xfrm_state *xfrm_user_state_lookup(struct xfrm_usersa_id *p, +static struct xfrm_state *xfrm_user_state_lookup(struct net *net, + struct xfrm_usersa_id *p, struct nlattr **attrs, int *errp) { @@ -440,7 +443,7 @@ static struct xfrm_state *xfrm_user_state_lookup(struct xfrm_usersa_id *p, if (xfrm_id_proto_match(p->proto, IPSEC_PROTO_ANY)) { err = -ESRCH; - x = xfrm_state_lookup(&init_net, &p->daddr, p->spi, p->proto, p->family); + x = xfrm_state_lookup(net, &p->daddr, p->spi, p->proto, p->family); } else { xfrm_address_t *saddr = NULL; @@ -451,7 +454,7 @@ static struct xfrm_state *xfrm_user_state_lookup(struct xfrm_usersa_id *p, } err = -ESRCH; - x = xfrm_state_lookup_byaddr(&init_net, &p->daddr, saddr, + x = xfrm_state_lookup_byaddr(net, &p->daddr, saddr, p->proto, p->family); } @@ -464,6 +467,7 @@ static struct xfrm_state *xfrm_user_state_lookup(struct xfrm_usersa_id *p, static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, struct nlattr **attrs) { + struct net *net = sock_net(skb->sk); struct xfrm_state *x; int err = -ESRCH; struct km_event c; @@ -472,7 +476,7 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, u32 sessionid = NETLINK_CB(skb).sessionid; u32 sid = NETLINK_CB(skb).sid; - x = xfrm_user_state_lookup(p, attrs, &err); + x = xfrm_user_state_lookup(net, p, attrs, &err); if (x == NULL) return err; @@ -615,6 +619,7 @@ static int xfrm_dump_sa_done(struct netlink_callback *cb) static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb) { + struct net *net = sock_net(skb->sk); struct xfrm_state_walk *walk = (struct xfrm_state_walk *) &cb->args[1]; struct xfrm_dump_info info; @@ -631,7 +636,7 @@ static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb) xfrm_state_walk_init(walk, 0); } - (void) xfrm_state_walk(&init_net, walk, dump_one_state, &info); + (void) xfrm_state_walk(net, walk, dump_one_state, &info); return skb->len; } @@ -776,13 +781,13 @@ static int xfrm_get_sadinfo(struct sk_buff *skb, struct nlmsghdr *nlh, static int xfrm_get_sa(struct sk_buff *skb, struct nlmsghdr *nlh, struct nlattr **attrs) { - struct net *net = &init_net; + struct net *net = sock_net(skb->sk); struct xfrm_usersa_id *p = nlmsg_data(nlh); struct xfrm_state *x; struct sk_buff *resp_skb; int err = -ESRCH; - x = xfrm_user_state_lookup(p, attrs, &err); + x = xfrm_user_state_lookup(net, p, attrs, &err); if (x == NULL) goto out_noput; @@ -823,7 +828,7 @@ static int verify_userspi_info(struct xfrm_userspi_info *p) static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, struct nlattr **attrs) { - struct net *net = &init_net; + struct net *net = sock_net(skb->sk); struct xfrm_state *x; struct xfrm_userspi_info *p; struct sk_buff *resp_skb; @@ -1082,9 +1087,9 @@ static void copy_to_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_i p->share = XFRM_SHARE_ANY; /* XXX xp->share */ } -static struct xfrm_policy *xfrm_policy_construct(struct xfrm_userpolicy_info *p, struct nlattr **attrs, int *errp) +static struct xfrm_policy *xfrm_policy_construct(struct net *net, struct xfrm_userpolicy_info *p, struct nlattr **attrs, int *errp) { - struct xfrm_policy *xp = xfrm_policy_alloc(&init_net, GFP_KERNEL); + struct xfrm_policy *xp = xfrm_policy_alloc(net, GFP_KERNEL); int err; if (!xp) { @@ -1114,6 +1119,7 @@ static struct xfrm_policy *xfrm_policy_construct(struct xfrm_userpolicy_info *p, static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, struct nlattr **attrs) { + struct net *net = sock_net(skb->sk); struct xfrm_userpolicy_info *p = nlmsg_data(nlh); struct xfrm_policy *xp; struct km_event c; @@ -1130,7 +1136,7 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, if (err) return err; - xp = xfrm_policy_construct(p, attrs, &err); + xp = xfrm_policy_construct(net, p, attrs, &err); if (!xp) return err; @@ -1267,6 +1273,7 @@ static int xfrm_dump_policy_done(struct netlink_callback *cb) static int xfrm_dump_policy(struct sk_buff *skb, struct netlink_callback *cb) { + struct net *net = sock_net(skb->sk); struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1]; struct xfrm_dump_info info; @@ -1283,7 +1290,7 @@ static int xfrm_dump_policy(struct sk_buff *skb, struct netlink_callback *cb) xfrm_policy_walk_init(walk, XFRM_POLICY_TYPE_ANY); } - (void) xfrm_policy_walk(&init_net, walk, dump_one_policy, &info); + (void) xfrm_policy_walk(net, walk, dump_one_policy, &info); return skb->len; } @@ -1315,7 +1322,7 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb, static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, struct nlattr **attrs) { - struct net *net = &init_net; + struct net *net = sock_net(skb->sk); struct xfrm_policy *xp; struct xfrm_userpolicy_id *p; u8 type = XFRM_POLICY_TYPE_MAIN; @@ -1395,6 +1402,7 @@ out: static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, struct nlattr **attrs) { + struct net *net = sock_net(skb->sk); struct km_event c; struct xfrm_usersa_flush *p = nlmsg_data(nlh); struct xfrm_audit audit_info; @@ -1403,7 +1411,7 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, audit_info.loginuid = NETLINK_CB(skb).loginuid; audit_info.sessionid = NETLINK_CB(skb).sessionid; audit_info.secid = NETLINK_CB(skb).sid; - err = xfrm_state_flush(&init_net, p->proto, &audit_info); + err = xfrm_state_flush(net, p->proto, &audit_info); if (err) return err; c.data.proto = p->proto; @@ -1462,7 +1470,7 @@ nla_put_failure: static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, struct nlattr **attrs) { - struct net *net = &init_net; + struct net *net = sock_net(skb->sk); struct xfrm_state *x; struct sk_buff *r_skb; int err; @@ -1501,6 +1509,7 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, struct nlattr **attrs) { + struct net *net = sock_net(skb->sk); struct xfrm_state *x; struct km_event c; int err = - EINVAL; @@ -1515,7 +1524,7 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, if (!(nlh->nlmsg_flags&NLM_F_REPLACE)) return err; - x = xfrm_state_lookup(&init_net, &p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family); + x = xfrm_state_lookup(net, &p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family); if (x == NULL) return -ESRCH; @@ -1540,6 +1549,7 @@ out: static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, struct nlattr **attrs) { + struct net *net = sock_net(skb->sk); struct km_event c; u8 type = XFRM_POLICY_TYPE_MAIN; int err; @@ -1552,7 +1562,7 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, audit_info.loginuid = NETLINK_CB(skb).loginuid; audit_info.sessionid = NETLINK_CB(skb).sessionid; audit_info.secid = NETLINK_CB(skb).sid; - err = xfrm_policy_flush(&init_net, type, &audit_info); + err = xfrm_policy_flush(net, type, &audit_info); if (err) return err; c.data.type = type; @@ -1566,6 +1576,7 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, struct nlattr **attrs) { + struct net *net = sock_net(skb->sk); struct xfrm_policy *xp; struct xfrm_user_polexpire *up = nlmsg_data(nlh); struct xfrm_userpolicy_info *p = &up->pol; @@ -1577,7 +1588,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, return err; if (p->index) - xp = xfrm_policy_byid(&init_net, type, p->dir, p->index, 0, &err); + xp = xfrm_policy_byid(net, type, p->dir, p->index, 0, &err); else { struct nlattr *rt = attrs[XFRMA_SEC_CTX]; struct xfrm_sec_ctx *ctx; @@ -1594,7 +1605,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, if (err) return err; } - xp = xfrm_policy_bysel_ctx(&init_net, type, p->dir, &p->sel, ctx, 0, &err); + xp = xfrm_policy_bysel_ctx(net, type, p->dir, &p->sel, ctx, 0, &err); security_xfrm_policy_free(ctx); } if (xp == NULL) @@ -1629,12 +1640,13 @@ out: static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, struct nlattr **attrs) { + struct net *net = sock_net(skb->sk); struct xfrm_state *x; int err; struct xfrm_user_expire *ue = nlmsg_data(nlh); struct xfrm_usersa_info *p = &ue->state; - x = xfrm_state_lookup(&init_net, &p->id.daddr, p->id.spi, p->id.proto, p->family); + x = xfrm_state_lookup(net, &p->id.daddr, p->id.spi, p->id.proto, p->family); err = -ENOENT; if (x == NULL) @@ -1663,13 +1675,14 @@ out: static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, struct nlattr **attrs) { + struct net *net = sock_net(skb->sk); struct xfrm_policy *xp; struct xfrm_user_tmpl *ut; int i; struct nlattr *rt = attrs[XFRMA_TMPL]; struct xfrm_user_acquire *ua = nlmsg_data(nlh); - struct xfrm_state *x = xfrm_state_alloc(&init_net); + struct xfrm_state *x = xfrm_state_alloc(net); int err = -ENOMEM; if (!x) @@ -1683,7 +1696,7 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, } /* build an XP */ - xp = xfrm_policy_construct(&ua->policy, attrs, &err); + xp = xfrm_policy_construct(net, &ua->policy, attrs, &err); if (!xp) { kfree(x); return err; @@ -2041,7 +2054,7 @@ static int build_expire(struct sk_buff *skb, struct xfrm_state *x, struct km_eve static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c) { - struct net *net = &init_net; + struct net *net = xs_net(x); struct sk_buff *skb; skb = nlmsg_new(xfrm_expire_msgsize(), GFP_ATOMIC); @@ -2056,7 +2069,7 @@ static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c) static int xfrm_aevent_state_notify(struct xfrm_state *x, struct km_event *c) { - struct net *net = &init_net; + struct net *net = xs_net(x); struct sk_buff *skb; skb = nlmsg_new(xfrm_aevent_msgsize(), GFP_ATOMIC); @@ -2122,7 +2135,7 @@ static inline size_t xfrm_sa_len(struct xfrm_state *x) static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c) { - struct net *net = &init_net; + struct net *net = xs_net(x); struct xfrm_usersa_info *p; struct xfrm_usersa_id *id; struct nlmsghdr *nlh; @@ -2266,6 +2279,7 @@ static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt, static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt, u8 *data, int len, int *dir) { + struct net *net = sock_net(sk); struct xfrm_userpolicy_info *p = (struct xfrm_userpolicy_info *)data; struct xfrm_user_tmpl *ut = (struct xfrm_user_tmpl *) (p + 1); struct xfrm_policy *xp; @@ -2304,7 +2318,7 @@ static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt, if (p->dir > XFRM_POLICY_OUT) return NULL; - xp = xfrm_policy_alloc(&init_net, GFP_KERNEL); + xp = xfrm_policy_alloc(net, GFP_KERNEL); if (xp == NULL) { *dir = -ENOBUFS; return NULL; @@ -2357,7 +2371,7 @@ nlmsg_failure: static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c) { - struct net *net = &init_net; + struct net *net = xp_net(xp); struct sk_buff *skb; skb = nlmsg_new(xfrm_polexpire_msgsize(xp), GFP_ATOMIC); @@ -2372,7 +2386,7 @@ static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_eve static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c) { - struct net *net = &init_net; + struct net *net = xp_net(xp); struct xfrm_userpolicy_info *p; struct xfrm_userpolicy_id *id; struct nlmsghdr *nlh; -- cgit v1.2.3-70-g09d2 From 7067802e262457a9737521e5669b622028b2283a Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 25 Nov 2008 17:50:36 -0800 Subject: netns xfrm: pass netns with KM notifications SA and SPD flush are executed with NULL SA and SPD respectively, for these cases pass netns explicitly from userspace socket. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- include/net/xfrm.h | 1 + net/key/af_key.c | 2 ++ net/xfrm/xfrm_user.c | 6 ++++-- 3 files changed, 7 insertions(+), 2 deletions(-) (limited to 'net/xfrm/xfrm_user.c') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index e027179e819..52e784fa2c5 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -256,6 +256,7 @@ struct km_event u32 seq; u32 pid; u32 event; + struct net *net; }; struct net_device; diff --git a/net/key/af_key.c b/net/key/af_key.c index a0d849848dd..ea7755ab7e6 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1739,6 +1739,7 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd c.seq = hdr->sadb_msg_seq; c.pid = hdr->sadb_msg_pid; c.event = XFRM_MSG_FLUSHSA; + c.net = &init_net; km_state_notify(NULL, &c); return 0; @@ -2693,6 +2694,7 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg c.event = XFRM_MSG_FLUSHPOLICY; c.pid = hdr->sadb_msg_pid; c.seq = hdr->sadb_msg_seq; + c.net = &init_net; km_policy_notify(NULL, 0, &c); return 0; diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index ab8b138e5e2..3e32ec2ea1a 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1418,6 +1418,7 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, c.event = nlh->nlmsg_type; c.seq = nlh->nlmsg_seq; c.pid = nlh->nlmsg_pid; + c.net = net; km_state_notify(NULL, &c); return 0; @@ -1569,6 +1570,7 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, c.event = nlh->nlmsg_type; c.seq = nlh->nlmsg_seq; c.pid = nlh->nlmsg_pid; + c.net = net; km_policy_notify(NULL, 0, &c); return 0; } @@ -2084,7 +2086,7 @@ static int xfrm_aevent_state_notify(struct xfrm_state *x, struct km_event *c) static int xfrm_notify_sa_flush(struct km_event *c) { - struct net *net = &init_net; + struct net *net = c->net; struct xfrm_usersa_flush *p; struct nlmsghdr *nlh; struct sk_buff *skb; @@ -2446,7 +2448,7 @@ nlmsg_failure: static int xfrm_notify_policy_flush(struct km_event *c) { - struct net *net = &init_net; + struct net *net = c->net; struct nlmsghdr *nlh; struct sk_buff *skb; -- cgit v1.2.3-70-g09d2 From db983c1144884cab10d6397532f4bf05eb0c01d2 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 25 Nov 2008 17:51:01 -0800 Subject: netns xfrm: KM reporting in netns Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- include/net/xfrm.h | 4 ++-- net/ipv6/mip6.c | 3 ++- net/xfrm/xfrm_state.c | 4 ++-- net/xfrm/xfrm_user.c | 5 ++--- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'net/xfrm/xfrm_user.c') diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 52e784fa2c5..f3ea1607c59 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -552,7 +552,7 @@ struct xfrm_mgr struct xfrm_policy *(*compile_policy)(struct sock *sk, int opt, u8 *data, int len, int *dir); int (*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport); int (*notify_policy)(struct xfrm_policy *x, int dir, struct km_event *c); - int (*report)(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr); + int (*report)(struct net *net, u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr); int (*migrate)(struct xfrm_selector *sel, u8 dir, u8 type, struct xfrm_migrate *m, int num_bundles, struct xfrm_kmaddress *k); }; @@ -1471,7 +1471,7 @@ extern int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type, extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport); extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid); -extern int km_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr); +extern int km_report(struct net *net, u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr); extern void xfrm_input_init(void); extern int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq); diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index 31295c8f619..f995e19c87a 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c @@ -205,6 +205,7 @@ static inline int mip6_report_rl_allow(struct timeval *stamp, static int mip6_destopt_reject(struct xfrm_state *x, struct sk_buff *skb, struct flowi *fl) { + struct net *net = xs_net(x); struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb; struct ipv6_destopt_hao *hao = NULL; struct xfrm_selector sel; @@ -247,7 +248,7 @@ static int mip6_destopt_reject(struct xfrm_state *x, struct sk_buff *skb, struct sel.sport_mask = htons(~0); sel.ifindex = fl->oif; - err = km_report(IPPROTO_DSTOPTS, &sel, + err = km_report(net, IPPROTO_DSTOPTS, &sel, (hao ? (xfrm_address_t *)&hao->addr : NULL)); out: diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 21db37ab0a2..d594b5af5f6 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -1833,7 +1833,7 @@ int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type, EXPORT_SYMBOL(km_migrate); #endif -int km_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr) +int km_report(struct net *net, u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr) { int err = -EINVAL; int ret; @@ -1842,7 +1842,7 @@ int km_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr) read_lock(&xfrm_km_lock); list_for_each_entry(km, &xfrm_km_list, list) { if (km->report) { - ret = km->report(proto, sel, addr); + ret = km->report(net, proto, sel, addr); if (!ret) err = ret; } diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 3e32ec2ea1a..b7240d5b77a 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -2520,10 +2520,9 @@ nla_put_failure: return -EMSGSIZE; } -static int xfrm_send_report(u8 proto, struct xfrm_selector *sel, - xfrm_address_t *addr) +static int xfrm_send_report(struct net *net, u8 proto, + struct xfrm_selector *sel, xfrm_address_t *addr) { - struct net *net = &init_net; struct sk_buff *skb; skb = nlmsg_new(xfrm_report_msgsize(), GFP_ATOMIC); -- cgit v1.2.3-70-g09d2 From b27aeadb5948d400df83db4d29590fb9862ba49d Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 25 Nov 2008 18:00:48 -0800 Subject: netns xfrm: per-netns sysctls Make net.core.xfrm_aevent_etime net.core.xfrm_acq_expires net.core.xfrm_aevent_rseqth net.core.xfrm_larval_drop sysctls per-netns. For that make net_core_path[] global, register it to prevent two /proc/net/core antries and change initcall position -- xfrm_init() is called from fs_initcall, so this one should be fs_initcall at least. Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- include/net/ip.h | 1 + include/net/netns/xfrm.h | 10 ++++++ include/net/xfrm.h | 14 +++++--- net/core/sysctl_net_core.c | 42 +++-------------------- net/xfrm/Makefile | 4 +-- net/xfrm/xfrm_policy.c | 10 ++++-- net/xfrm/xfrm_state.c | 16 +++------ net/xfrm/xfrm_sysctl.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++ net/xfrm/xfrm_user.c | 4 +-- 9 files changed, 125 insertions(+), 61 deletions(-) create mode 100644 net/xfrm/xfrm_sysctl.c (limited to 'net/xfrm/xfrm_user.c') diff --git a/include/net/ip.h b/include/net/ip.h index ddef10c22e3..10868139e65 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -187,6 +187,7 @@ extern void inet_get_local_port_range(int *low, int *high); extern int sysctl_ip_default_ttl; extern int sysctl_ip_nonlocal_bind; +extern struct ctl_path net_core_path[]; extern struct ctl_path net_ipv4_ctl_path[]; /* From inetpeer.c */ diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h index 09f3060e9d1..1ba912749ca 100644 --- a/include/net/netns/xfrm.h +++ b/include/net/netns/xfrm.h @@ -6,6 +6,8 @@ #include #include +struct ctl_table_header; + struct xfrm_policy_hash { struct hlist_head *table; unsigned int hmask; @@ -41,6 +43,14 @@ struct netns_xfrm { struct work_struct policy_hash_work; struct sock *nlsk; + + u32 sysctl_aevent_etime; + u32 sysctl_aevent_rseqth; + int sysctl_larval_drop; + u32 sysctl_acq_expires; +#ifdef CONFIG_SYSCTL + struct ctl_table_header *sysctl_hdr; +#endif }; #endif diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 1554ccd0c94..2e9f5c0018a 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -47,11 +47,6 @@ #define XFRM_INC_STATS_USER(net, field) ((void)(net)) #endif -extern u32 sysctl_xfrm_aevent_etime; -extern u32 sysctl_xfrm_aevent_rseqth; -extern int sysctl_xfrm_larval_drop; -extern u32 sysctl_xfrm_acq_expires; - extern struct mutex xfrm_cfg_mutex; /* Organization of SPD aka "XFRM rules" @@ -1310,6 +1305,15 @@ extern int xfrm_proc_init(struct net *net); extern void xfrm_proc_fini(struct net *net); #endif +extern int xfrm_sysctl_init(struct net *net); +#ifdef CONFIG_SYSCTL +extern void xfrm_sysctl_fini(struct net *net); +#else +static inline void xfrm_sysctl_fini(struct net *net) +{ +} +#endif + extern void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto); extern int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk, int (*func)(struct xfrm_state *, int, void*), void *); diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index 2bc0384b044..83d3398559e 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -12,7 +12,6 @@ #include #include #include -#include static struct ctl_table net_core_table[] = { #ifdef CONFIG_NET @@ -89,40 +88,6 @@ static struct ctl_table net_core_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, -#ifdef CONFIG_XFRM - { - .ctl_name = NET_CORE_AEVENT_ETIME, - .procname = "xfrm_aevent_etime", - .data = &sysctl_xfrm_aevent_etime, - .maxlen = sizeof(u32), - .mode = 0644, - .proc_handler = proc_dointvec - }, - { - .ctl_name = NET_CORE_AEVENT_RSEQTH, - .procname = "xfrm_aevent_rseqth", - .data = &sysctl_xfrm_aevent_rseqth, - .maxlen = sizeof(u32), - .mode = 0644, - .proc_handler = proc_dointvec - }, - { - .ctl_name = CTL_UNNUMBERED, - .procname = "xfrm_larval_drop", - .data = &sysctl_xfrm_larval_drop, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec - }, - { - .ctl_name = CTL_UNNUMBERED, - .procname = "xfrm_acq_expires", - .data = &sysctl_xfrm_acq_expires, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = proc_dointvec - }, -#endif /* CONFIG_XFRM */ #endif /* CONFIG_NET */ { .ctl_name = NET_CORE_BUDGET, @@ -155,7 +120,7 @@ static struct ctl_table netns_core_table[] = { { .ctl_name = 0 } }; -static __net_initdata struct ctl_path net_core_path[] = { +__net_initdata struct ctl_path net_core_path[] = { { .procname = "net", .ctl_name = CTL_NET, }, { .procname = "core", .ctl_name = NET_CORE, }, { }, @@ -207,8 +172,11 @@ static __net_initdata struct pernet_operations sysctl_core_ops = { static __init int sysctl_core_init(void) { + static struct ctl_table empty[1]; + + register_sysctl_paths(net_core_path, empty); register_net_sysctl_rotable(net_core_path, net_core_table); return register_pernet_subsys(&sysctl_core_ops); } -__initcall(sysctl_core_init); +fs_initcall(sysctl_core_init); diff --git a/net/xfrm/Makefile b/net/xfrm/Makefile index 0f439a72cca..c631047e1b2 100644 --- a/net/xfrm/Makefile +++ b/net/xfrm/Makefile @@ -3,8 +3,8 @@ # obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_hash.o \ - xfrm_input.o xfrm_output.o xfrm_algo.o + xfrm_input.o xfrm_output.o xfrm_algo.o \ + xfrm_sysctl.o obj-$(CONFIG_XFRM_STATISTICS) += xfrm_proc.o obj-$(CONFIG_XFRM_USER) += xfrm_user.o obj-$(CONFIG_XFRM_IPCOMP) += xfrm_ipcomp.o - diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 38822b34ba7..393cc65dbfa 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -34,8 +34,6 @@ #include "xfrm_hash.h" -int sysctl_xfrm_larval_drop __read_mostly = 1; - DEFINE_MUTEX(xfrm_cfg_mutex); EXPORT_SYMBOL(xfrm_cfg_mutex); @@ -1671,7 +1669,7 @@ restart: if (unlikely(nx<0)) { err = nx; - if (err == -EAGAIN && sysctl_xfrm_larval_drop) { + if (err == -EAGAIN && net->xfrm.sysctl_larval_drop) { /* EREMOTE tells the caller to generate * a one-shot blackhole route. */ @@ -2504,8 +2502,13 @@ static int __net_init xfrm_net_init(struct net *net) rv = xfrm_policy_init(net); if (rv < 0) goto out_policy; + rv = xfrm_sysctl_init(net); + if (rv < 0) + goto out_sysctl; return 0; +out_sysctl: + xfrm_policy_fini(net); out_policy: xfrm_state_fini(net); out_state: @@ -2516,6 +2519,7 @@ out_statistics: static void __net_exit xfrm_net_exit(struct net *net) { + xfrm_sysctl_fini(net); xfrm_policy_fini(net); xfrm_state_fini(net); xfrm_statistics_fini(net); diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 662e47b0bcc..2fd57f8f77c 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -24,14 +24,6 @@ #include "xfrm_hash.h" -u32 sysctl_xfrm_aevent_etime __read_mostly = XFRM_AE_ETIME; -EXPORT_SYMBOL(sysctl_xfrm_aevent_etime); - -u32 sysctl_xfrm_aevent_rseqth __read_mostly = XFRM_AE_SEQT_SIZE; -EXPORT_SYMBOL(sysctl_xfrm_aevent_rseqth); - -u32 sysctl_xfrm_acq_expires __read_mostly = 30; - /* Each xfrm_state may be linked to two tables: 1. Hash table by (spi,daddr,ah/esp) to find SA by SPI. (input,ctl) @@ -851,8 +843,8 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, family); hlist_add_head(&x->byspi, net->xfrm.state_byspi+h); } - x->lft.hard_add_expires_seconds = sysctl_xfrm_acq_expires; - x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ; + x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires; + x->timer.expires = jiffies + net->xfrm.sysctl_acq_expires*HZ; add_timer(&x->timer); net->xfrm.state_num++; xfrm_hash_grow_check(net, x->bydst.next != NULL); @@ -1040,9 +1032,9 @@ static struct xfrm_state *__find_acq_core(struct net *net, unsigned short family x->props.family = family; x->props.mode = mode; x->props.reqid = reqid; - x->lft.hard_add_expires_seconds = sysctl_xfrm_acq_expires; + x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires; xfrm_state_hold(x); - x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ; + x->timer.expires = jiffies + net->xfrm.sysctl_acq_expires*HZ; add_timer(&x->timer); list_add(&x->km.all, &net->xfrm.state_all); hlist_add_head(&x->bydst, net->xfrm.state_bydst+h); diff --git a/net/xfrm/xfrm_sysctl.c b/net/xfrm/xfrm_sysctl.c new file mode 100644 index 00000000000..2e6ffb66f06 --- /dev/null +++ b/net/xfrm/xfrm_sysctl.c @@ -0,0 +1,85 @@ +#include +#include +#include + +static void __xfrm_sysctl_init(struct net *net) +{ + net->xfrm.sysctl_aevent_etime = XFRM_AE_ETIME; + net->xfrm.sysctl_aevent_rseqth = XFRM_AE_SEQT_SIZE; + net->xfrm.sysctl_larval_drop = 1; + net->xfrm.sysctl_acq_expires = 30; +} + +#ifdef CONFIG_SYSCTL +static struct ctl_table xfrm_table[] = { + { + .ctl_name = NET_CORE_AEVENT_ETIME, + .procname = "xfrm_aevent_etime", + .maxlen = sizeof(u32), + .mode = 0644, + .proc_handler = proc_dointvec + }, + { + .ctl_name = NET_CORE_AEVENT_RSEQTH, + .procname = "xfrm_aevent_rseqth", + .maxlen = sizeof(u32), + .mode = 0644, + .proc_handler = proc_dointvec + }, + { + .ctl_name = CTL_UNNUMBERED, + .procname = "xfrm_larval_drop", + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec + }, + { + .ctl_name = CTL_UNNUMBERED, + .procname = "xfrm_acq_expires", + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec + }, + {} +}; + +int __net_init xfrm_sysctl_init(struct net *net) +{ + struct ctl_table *table; + + __xfrm_sysctl_init(net); + + table = kmemdup(xfrm_table, sizeof(xfrm_table), GFP_KERNEL); + if (!table) + goto out_kmemdup; + table[0].data = &net->xfrm.sysctl_aevent_etime; + table[1].data = &net->xfrm.sysctl_aevent_rseqth; + table[2].data = &net->xfrm.sysctl_larval_drop; + table[3].data = &net->xfrm.sysctl_acq_expires; + + net->xfrm.sysctl_hdr = register_net_sysctl_table(net, net_core_path, table); + if (!net->xfrm.sysctl_hdr) + goto out_register; + return 0; + +out_register: + kfree(table); +out_kmemdup: + return -ENOMEM; +} + +void xfrm_sysctl_fini(struct net *net) +{ + struct ctl_table *table; + + table = net->xfrm.sysctl_hdr->ctl_table_arg; + unregister_net_sysctl_table(net->xfrm.sysctl_hdr); + kfree(table); +} +#else +int __net_init xfrm_sysctl_init(struct net *net) +{ + __xfrm_sysctl_init(net); + return 0; +} +#endif diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index b7240d5b77a..38ffaf33312 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -368,9 +368,9 @@ static struct xfrm_state *xfrm_state_construct(struct net *net, goto error; x->km.seq = p->seq; - x->replay_maxdiff = sysctl_xfrm_aevent_rseqth; + x->replay_maxdiff = net->xfrm.sysctl_aevent_rseqth; /* sysctl_xfrm_aevent_etime is in 100ms units */ - x->replay_maxage = (sysctl_xfrm_aevent_etime*HZ)/XFRM_AE_ETH_M; + x->replay_maxage = (net->xfrm.sysctl_aevent_etime*HZ)/XFRM_AE_ETH_M; x->preplay.bitmap = 0; x->preplay.seq = x->replay.seq+x->replay_maxdiff; x->preplay.oseq = x->replay.oseq +x->replay_maxdiff; -- cgit v1.2.3-70-g09d2 From d8eb93078cedbbf4b7e18e1d7054171c7b70b442 Mon Sep 17 00:00:00 2001 From: Ilpo Järvinen Date: Sun, 14 Dec 2008 23:16:22 -0800 Subject: xfrm: join error paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/xfrm/xfrm_user.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'net/xfrm/xfrm_user.c') diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 38ffaf33312..b95a2d64eb5 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -1688,21 +1688,16 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, int err = -ENOMEM; if (!x) - return err; + goto nomem; err = verify_newpolicy_info(&ua->policy); - if (err) { - printk("BAD policy passed\n"); - kfree(x); - return err; - } + if (err) + goto bad_policy; /* build an XP */ xp = xfrm_policy_construct(net, &ua->policy, attrs, &err); - if (!xp) { - kfree(x); - return err; - } + if (!xp) + goto free_state; memcpy(&x->id, &ua->id, sizeof(ua->id)); memcpy(&x->props.saddr, &ua->saddr, sizeof(ua->saddr)); @@ -1727,6 +1722,13 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, kfree(xp); return 0; + +bad_policy: + printk("BAD policy passed\n"); +free_state: + kfree(x); +nomem: + return err; } #ifdef CONFIG_XFRM_MIGRATE -- cgit v1.2.3-70-g09d2