diff options
Diffstat (limited to 'net/xfrm')
-rw-r--r-- | net/xfrm/Makefile | 4 | ||||
-rw-r--r-- | net/xfrm/xfrm_input.c | 25 | ||||
-rw-r--r-- | net/xfrm/xfrm_output.c | 18 | ||||
-rw-r--r-- | net/xfrm/xfrm_policy.c | 484 | ||||
-rw-r--r-- | net/xfrm/xfrm_proc.c | 26 | ||||
-rw-r--r-- | net/xfrm/xfrm_state.c | 381 | ||||
-rw-r--r-- | net/xfrm/xfrm_sysctl.c | 85 | ||||
-rw-r--r-- | net/xfrm/xfrm_user.c | 227 |
8 files changed, 776 insertions, 474 deletions
diff --git a/net/xfrm/Makefile b/net/xfrm/Makefile index 0f439a72ccab..c631047e1b27 100644 --- a/net/xfrm/Makefile +++ b/net/xfrm/Makefile | |||
@@ -3,8 +3,8 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_hash.o \ | 5 | obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_hash.o \ |
6 | xfrm_input.o xfrm_output.o xfrm_algo.o | 6 | xfrm_input.o xfrm_output.o xfrm_algo.o \ |
7 | xfrm_sysctl.o | ||
7 | obj-$(CONFIG_XFRM_STATISTICS) += xfrm_proc.o | 8 | obj-$(CONFIG_XFRM_STATISTICS) += xfrm_proc.o |
8 | obj-$(CONFIG_XFRM_USER) += xfrm_user.o | 9 | obj-$(CONFIG_XFRM_USER) += xfrm_user.o |
9 | obj-$(CONFIG_XFRM_IPCOMP) += xfrm_ipcomp.o | 10 | obj-$(CONFIG_XFRM_IPCOMP) += xfrm_ipcomp.o |
10 | |||
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index 75279402ccf4..b4a13178fb40 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c | |||
@@ -104,6 +104,7 @@ EXPORT_SYMBOL(xfrm_prepare_input); | |||
104 | 104 | ||
105 | int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | 105 | int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) |
106 | { | 106 | { |
107 | struct net *net = dev_net(skb->dev); | ||
107 | int err; | 108 | int err; |
108 | __be32 seq; | 109 | __be32 seq; |
109 | struct xfrm_state *x; | 110 | struct xfrm_state *x; |
@@ -127,7 +128,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | |||
127 | 128 | ||
128 | sp = secpath_dup(skb->sp); | 129 | sp = secpath_dup(skb->sp); |
129 | if (!sp) { | 130 | if (!sp) { |
130 | XFRM_INC_STATS(LINUX_MIB_XFRMINERROR); | 131 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINERROR); |
131 | goto drop; | 132 | goto drop; |
132 | } | 133 | } |
133 | if (skb->sp) | 134 | if (skb->sp) |
@@ -141,19 +142,19 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | |||
141 | 142 | ||
142 | seq = 0; | 143 | seq = 0; |
143 | if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) { | 144 | if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) { |
144 | XFRM_INC_STATS(LINUX_MIB_XFRMINHDRERROR); | 145 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINHDRERROR); |
145 | goto drop; | 146 | goto drop; |
146 | } | 147 | } |
147 | 148 | ||
148 | do { | 149 | do { |
149 | if (skb->sp->len == XFRM_MAX_DEPTH) { | 150 | if (skb->sp->len == XFRM_MAX_DEPTH) { |
150 | XFRM_INC_STATS(LINUX_MIB_XFRMINBUFFERERROR); | 151 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINBUFFERERROR); |
151 | goto drop; | 152 | goto drop; |
152 | } | 153 | } |
153 | 154 | ||
154 | x = xfrm_state_lookup(daddr, spi, nexthdr, family); | 155 | x = xfrm_state_lookup(net, daddr, spi, nexthdr, family); |
155 | if (x == NULL) { | 156 | if (x == NULL) { |
156 | XFRM_INC_STATS(LINUX_MIB_XFRMINNOSTATES); | 157 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOSTATES); |
157 | xfrm_audit_state_notfound(skb, family, spi, seq); | 158 | xfrm_audit_state_notfound(skb, family, spi, seq); |
158 | goto drop; | 159 | goto drop; |
159 | } | 160 | } |
@@ -162,22 +163,22 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | |||
162 | 163 | ||
163 | spin_lock(&x->lock); | 164 | spin_lock(&x->lock); |
164 | if (unlikely(x->km.state != XFRM_STATE_VALID)) { | 165 | if (unlikely(x->km.state != XFRM_STATE_VALID)) { |
165 | XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEINVALID); | 166 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEINVALID); |
166 | goto drop_unlock; | 167 | goto drop_unlock; |
167 | } | 168 | } |
168 | 169 | ||
169 | if ((x->encap ? x->encap->encap_type : 0) != encap_type) { | 170 | if ((x->encap ? x->encap->encap_type : 0) != encap_type) { |
170 | XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEMISMATCH); | 171 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEMISMATCH); |
171 | goto drop_unlock; | 172 | goto drop_unlock; |
172 | } | 173 | } |
173 | 174 | ||
174 | if (x->props.replay_window && xfrm_replay_check(x, skb, seq)) { | 175 | if (x->props.replay_window && xfrm_replay_check(x, skb, seq)) { |
175 | XFRM_INC_STATS(LINUX_MIB_XFRMINSTATESEQERROR); | 176 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR); |
176 | goto drop_unlock; | 177 | goto drop_unlock; |
177 | } | 178 | } |
178 | 179 | ||
179 | if (xfrm_state_check_expire(x)) { | 180 | if (xfrm_state_check_expire(x)) { |
180 | XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEEXPIRED); | 181 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEEXPIRED); |
181 | goto drop_unlock; | 182 | goto drop_unlock; |
182 | } | 183 | } |
183 | 184 | ||
@@ -198,7 +199,7 @@ resume: | |||
198 | x->type->proto); | 199 | x->type->proto); |
199 | x->stats.integrity_failed++; | 200 | x->stats.integrity_failed++; |
200 | } | 201 | } |
201 | XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEPROTOERROR); | 202 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEPROTOERROR); |
202 | goto drop_unlock; | 203 | goto drop_unlock; |
203 | } | 204 | } |
204 | 205 | ||
@@ -224,7 +225,7 @@ resume: | |||
224 | } | 225 | } |
225 | 226 | ||
226 | if (inner_mode->input(x, skb)) { | 227 | if (inner_mode->input(x, skb)) { |
227 | XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEMODEERROR); | 228 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEMODEERROR); |
228 | goto drop; | 229 | goto drop; |
229 | } | 230 | } |
230 | 231 | ||
@@ -242,7 +243,7 @@ resume: | |||
242 | 243 | ||
243 | err = xfrm_parse_spi(skb, nexthdr, &spi, &seq); | 244 | err = xfrm_parse_spi(skb, nexthdr, &spi, &seq); |
244 | if (err < 0) { | 245 | if (err < 0) { |
245 | XFRM_INC_STATS(LINUX_MIB_XFRMINHDRERROR); | 246 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINHDRERROR); |
246 | goto drop; | 247 | goto drop; |
247 | } | 248 | } |
248 | } while (!err); | 249 | } while (!err); |
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index dc50f1e71f76..c235597ba8dd 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) | |||
41 | { | 41 | { |
42 | struct dst_entry *dst = skb->dst; | 42 | struct dst_entry *dst = skb->dst; |
43 | struct xfrm_state *x = dst->xfrm; | 43 | struct xfrm_state *x = dst->xfrm; |
44 | struct net *net = xs_net(x); | ||
44 | 45 | ||
45 | if (err <= 0) | 46 | if (err <= 0) |
46 | goto resume; | 47 | goto resume; |
@@ -48,33 +49,33 @@ static int xfrm_output_one(struct sk_buff *skb, int err) | |||
48 | do { | 49 | do { |
49 | err = xfrm_state_check_space(x, skb); | 50 | err = xfrm_state_check_space(x, skb); |
50 | if (err) { | 51 | if (err) { |
51 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTERROR); | 52 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTERROR); |
52 | goto error_nolock; | 53 | goto error_nolock; |
53 | } | 54 | } |
54 | 55 | ||
55 | err = x->outer_mode->output(x, skb); | 56 | err = x->outer_mode->output(x, skb); |
56 | if (err) { | 57 | if (err) { |
57 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTSTATEMODEERROR); | 58 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEMODEERROR); |
58 | goto error_nolock; | 59 | goto error_nolock; |
59 | } | 60 | } |
60 | 61 | ||
61 | spin_lock_bh(&x->lock); | 62 | spin_lock_bh(&x->lock); |
62 | err = xfrm_state_check_expire(x); | 63 | err = xfrm_state_check_expire(x); |
63 | if (err) { | 64 | if (err) { |
64 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTSTATEEXPIRED); | 65 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEEXPIRED); |
65 | goto error; | 66 | goto error; |
66 | } | 67 | } |
67 | 68 | ||
68 | if (x->type->flags & XFRM_TYPE_REPLAY_PROT) { | 69 | if (x->type->flags & XFRM_TYPE_REPLAY_PROT) { |
69 | XFRM_SKB_CB(skb)->seq.output = ++x->replay.oseq; | 70 | XFRM_SKB_CB(skb)->seq.output = ++x->replay.oseq; |
70 | if (unlikely(x->replay.oseq == 0)) { | 71 | if (unlikely(x->replay.oseq == 0)) { |
71 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTSTATESEQERROR); | 72 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATESEQERROR); |
72 | x->replay.oseq--; | 73 | x->replay.oseq--; |
73 | xfrm_audit_state_replay_overflow(x, skb); | 74 | xfrm_audit_state_replay_overflow(x, skb); |
74 | err = -EOVERFLOW; | 75 | err = -EOVERFLOW; |
75 | goto error; | 76 | goto error; |
76 | } | 77 | } |
77 | if (xfrm_aevent_is_on()) | 78 | if (xfrm_aevent_is_on(net)) |
78 | xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); | 79 | xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); |
79 | } | 80 | } |
80 | 81 | ||
@@ -89,12 +90,12 @@ static int xfrm_output_one(struct sk_buff *skb, int err) | |||
89 | 90 | ||
90 | resume: | 91 | resume: |
91 | if (err) { | 92 | if (err) { |
92 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTSTATEPROTOERROR); | 93 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEPROTOERROR); |
93 | goto error_nolock; | 94 | goto error_nolock; |
94 | } | 95 | } |
95 | 96 | ||
96 | if (!(skb->dst = dst_pop(dst))) { | 97 | if (!(skb->dst = dst_pop(dst))) { |
97 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTERROR); | 98 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTERROR); |
98 | err = -EHOSTUNREACH; | 99 | err = -EHOSTUNREACH; |
99 | goto error_nolock; | 100 | goto error_nolock; |
100 | } | 101 | } |
@@ -178,6 +179,7 @@ static int xfrm_output_gso(struct sk_buff *skb) | |||
178 | 179 | ||
179 | int xfrm_output(struct sk_buff *skb) | 180 | int xfrm_output(struct sk_buff *skb) |
180 | { | 181 | { |
182 | struct net *net = dev_net(skb->dst->dev); | ||
181 | int err; | 183 | int err; |
182 | 184 | ||
183 | if (skb_is_gso(skb)) | 185 | if (skb_is_gso(skb)) |
@@ -186,7 +188,7 @@ int xfrm_output(struct sk_buff *skb) | |||
186 | if (skb->ip_summed == CHECKSUM_PARTIAL) { | 188 | if (skb->ip_summed == CHECKSUM_PARTIAL) { |
187 | err = skb_checksum_help(skb); | 189 | err = skb_checksum_help(skb); |
188 | if (err) { | 190 | if (err) { |
189 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTERROR); | 191 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTERROR); |
190 | kfree_skb(skb); | 192 | kfree_skb(skb); |
191 | return err; | 193 | return err; |
192 | } | 194 | } |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index fb216c9adf86..62a49a1f2475 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -34,28 +34,16 @@ | |||
34 | 34 | ||
35 | #include "xfrm_hash.h" | 35 | #include "xfrm_hash.h" |
36 | 36 | ||
37 | int sysctl_xfrm_larval_drop __read_mostly = 1; | ||
38 | |||
39 | #ifdef CONFIG_XFRM_STATISTICS | ||
40 | DEFINE_SNMP_STAT(struct linux_xfrm_mib, xfrm_statistics) __read_mostly; | ||
41 | EXPORT_SYMBOL(xfrm_statistics); | ||
42 | #endif | ||
43 | |||
44 | DEFINE_MUTEX(xfrm_cfg_mutex); | 37 | DEFINE_MUTEX(xfrm_cfg_mutex); |
45 | EXPORT_SYMBOL(xfrm_cfg_mutex); | 38 | EXPORT_SYMBOL(xfrm_cfg_mutex); |
46 | 39 | ||
47 | static DEFINE_RWLOCK(xfrm_policy_lock); | 40 | static DEFINE_RWLOCK(xfrm_policy_lock); |
48 | 41 | ||
49 | static struct list_head xfrm_policy_all; | ||
50 | unsigned int xfrm_policy_count[XFRM_POLICY_MAX*2]; | ||
51 | EXPORT_SYMBOL(xfrm_policy_count); | ||
52 | |||
53 | static DEFINE_RWLOCK(xfrm_policy_afinfo_lock); | 42 | static DEFINE_RWLOCK(xfrm_policy_afinfo_lock); |
54 | static struct xfrm_policy_afinfo *xfrm_policy_afinfo[NPROTO]; | 43 | static struct xfrm_policy_afinfo *xfrm_policy_afinfo[NPROTO]; |
55 | 44 | ||
56 | static struct kmem_cache *xfrm_dst_cache __read_mostly; | 45 | static struct kmem_cache *xfrm_dst_cache __read_mostly; |
57 | 46 | ||
58 | static struct work_struct xfrm_policy_gc_work; | ||
59 | static HLIST_HEAD(xfrm_policy_gc_list); | 47 | static HLIST_HEAD(xfrm_policy_gc_list); |
60 | static DEFINE_SPINLOCK(xfrm_policy_gc_lock); | 48 | static DEFINE_SPINLOCK(xfrm_policy_gc_lock); |
61 | 49 | ||
@@ -97,7 +85,7 @@ int xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl, | |||
97 | return 0; | 85 | return 0; |
98 | } | 86 | } |
99 | 87 | ||
100 | static inline struct dst_entry *__xfrm_dst_lookup(int tos, | 88 | static inline struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos, |
101 | xfrm_address_t *saddr, | 89 | xfrm_address_t *saddr, |
102 | xfrm_address_t *daddr, | 90 | xfrm_address_t *daddr, |
103 | int family) | 91 | int family) |
@@ -109,7 +97,7 @@ static inline struct dst_entry *__xfrm_dst_lookup(int tos, | |||
109 | if (unlikely(afinfo == NULL)) | 97 | if (unlikely(afinfo == NULL)) |
110 | return ERR_PTR(-EAFNOSUPPORT); | 98 | return ERR_PTR(-EAFNOSUPPORT); |
111 | 99 | ||
112 | dst = afinfo->dst_lookup(tos, saddr, daddr); | 100 | dst = afinfo->dst_lookup(net, tos, saddr, daddr); |
113 | 101 | ||
114 | xfrm_policy_put_afinfo(afinfo); | 102 | xfrm_policy_put_afinfo(afinfo); |
115 | 103 | ||
@@ -121,6 +109,7 @@ static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x, int tos, | |||
121 | xfrm_address_t *prev_daddr, | 109 | xfrm_address_t *prev_daddr, |
122 | int family) | 110 | int family) |
123 | { | 111 | { |
112 | struct net *net = xs_net(x); | ||
124 | xfrm_address_t *saddr = &x->props.saddr; | 113 | xfrm_address_t *saddr = &x->props.saddr; |
125 | xfrm_address_t *daddr = &x->id.daddr; | 114 | xfrm_address_t *daddr = &x->id.daddr; |
126 | struct dst_entry *dst; | 115 | struct dst_entry *dst; |
@@ -134,7 +123,7 @@ static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x, int tos, | |||
134 | daddr = x->coaddr; | 123 | daddr = x->coaddr; |
135 | } | 124 | } |
136 | 125 | ||
137 | dst = __xfrm_dst_lookup(tos, saddr, daddr, family); | 126 | dst = __xfrm_dst_lookup(net, tos, saddr, daddr, family); |
138 | 127 | ||
139 | if (!IS_ERR(dst)) { | 128 | if (!IS_ERR(dst)) { |
140 | if (prev_saddr != saddr) | 129 | if (prev_saddr != saddr) |
@@ -229,13 +218,14 @@ expired: | |||
229 | * SPD calls. | 218 | * SPD calls. |
230 | */ | 219 | */ |
231 | 220 | ||
232 | struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp) | 221 | struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp) |
233 | { | 222 | { |
234 | struct xfrm_policy *policy; | 223 | struct xfrm_policy *policy; |
235 | 224 | ||
236 | policy = kzalloc(sizeof(struct xfrm_policy), gfp); | 225 | policy = kzalloc(sizeof(struct xfrm_policy), gfp); |
237 | 226 | ||
238 | if (policy) { | 227 | if (policy) { |
228 | write_pnet(&policy->xp_net, net); | ||
239 | INIT_LIST_HEAD(&policy->walk.all); | 229 | INIT_LIST_HEAD(&policy->walk.all); |
240 | INIT_HLIST_NODE(&policy->bydst); | 230 | INIT_HLIST_NODE(&policy->bydst); |
241 | INIT_HLIST_NODE(&policy->byidx); | 231 | INIT_HLIST_NODE(&policy->byidx); |
@@ -296,6 +286,7 @@ static void xfrm_policy_gc_task(struct work_struct *work) | |||
296 | hlist_for_each_entry_safe(policy, entry, tmp, &gc_list, bydst) | 286 | hlist_for_each_entry_safe(policy, entry, tmp, &gc_list, bydst) |
297 | xfrm_policy_gc_kill(policy); | 287 | xfrm_policy_gc_kill(policy); |
298 | } | 288 | } |
289 | static DECLARE_WORK(xfrm_policy_gc_work, xfrm_policy_gc_task); | ||
299 | 290 | ||
300 | /* Rule must be locked. Release descentant resources, announce | 291 | /* Rule must be locked. Release descentant resources, announce |
301 | * entry dead. The rule must be unlinked from lists to the moment. | 292 | * entry dead. The rule must be unlinked from lists to the moment. |
@@ -322,38 +313,29 @@ static void xfrm_policy_kill(struct xfrm_policy *policy) | |||
322 | schedule_work(&xfrm_policy_gc_work); | 313 | schedule_work(&xfrm_policy_gc_work); |
323 | } | 314 | } |
324 | 315 | ||
325 | struct xfrm_policy_hash { | ||
326 | struct hlist_head *table; | ||
327 | unsigned int hmask; | ||
328 | }; | ||
329 | |||
330 | static struct hlist_head xfrm_policy_inexact[XFRM_POLICY_MAX*2]; | ||
331 | static struct xfrm_policy_hash xfrm_policy_bydst[XFRM_POLICY_MAX*2] __read_mostly; | ||
332 | static struct hlist_head *xfrm_policy_byidx __read_mostly; | ||
333 | static unsigned int xfrm_idx_hmask __read_mostly; | ||
334 | static unsigned int xfrm_policy_hashmax __read_mostly = 1 * 1024 * 1024; | 316 | static unsigned int xfrm_policy_hashmax __read_mostly = 1 * 1024 * 1024; |
335 | 317 | ||
336 | static inline unsigned int idx_hash(u32 index) | 318 | static inline unsigned int idx_hash(struct net *net, u32 index) |
337 | { | 319 | { |
338 | return __idx_hash(index, xfrm_idx_hmask); | 320 | return __idx_hash(index, net->xfrm.policy_idx_hmask); |
339 | } | 321 | } |
340 | 322 | ||
341 | static struct hlist_head *policy_hash_bysel(struct xfrm_selector *sel, unsigned short family, int dir) | 323 | static struct hlist_head *policy_hash_bysel(struct net *net, struct xfrm_selector *sel, unsigned short family, int dir) |
342 | { | 324 | { |
343 | unsigned int hmask = xfrm_policy_bydst[dir].hmask; | 325 | unsigned int hmask = net->xfrm.policy_bydst[dir].hmask; |
344 | unsigned int hash = __sel_hash(sel, family, hmask); | 326 | unsigned int hash = __sel_hash(sel, family, hmask); |
345 | 327 | ||
346 | return (hash == hmask + 1 ? | 328 | return (hash == hmask + 1 ? |
347 | &xfrm_policy_inexact[dir] : | 329 | &net->xfrm.policy_inexact[dir] : |
348 | xfrm_policy_bydst[dir].table + hash); | 330 | net->xfrm.policy_bydst[dir].table + hash); |
349 | } | 331 | } |
350 | 332 | ||
351 | static struct hlist_head *policy_hash_direct(xfrm_address_t *daddr, xfrm_address_t *saddr, unsigned short family, int dir) | 333 | static struct hlist_head *policy_hash_direct(struct net *net, xfrm_address_t *daddr, xfrm_address_t *saddr, unsigned short family, int dir) |
352 | { | 334 | { |
353 | unsigned int hmask = xfrm_policy_bydst[dir].hmask; | 335 | unsigned int hmask = net->xfrm.policy_bydst[dir].hmask; |
354 | unsigned int hash = __addr_hash(daddr, saddr, family, hmask); | 336 | unsigned int hash = __addr_hash(daddr, saddr, family, hmask); |
355 | 337 | ||
356 | return xfrm_policy_bydst[dir].table + hash; | 338 | return net->xfrm.policy_bydst[dir].table + hash; |
357 | } | 339 | } |
358 | 340 | ||
359 | static void xfrm_dst_hash_transfer(struct hlist_head *list, | 341 | static void xfrm_dst_hash_transfer(struct hlist_head *list, |
@@ -408,12 +390,12 @@ static unsigned long xfrm_new_hash_mask(unsigned int old_hmask) | |||
408 | return ((old_hmask + 1) << 1) - 1; | 390 | return ((old_hmask + 1) << 1) - 1; |
409 | } | 391 | } |
410 | 392 | ||
411 | static void xfrm_bydst_resize(int dir) | 393 | static void xfrm_bydst_resize(struct net *net, int dir) |
412 | { | 394 | { |
413 | unsigned int hmask = xfrm_policy_bydst[dir].hmask; | 395 | unsigned int hmask = net->xfrm.policy_bydst[dir].hmask; |
414 | unsigned int nhashmask = xfrm_new_hash_mask(hmask); | 396 | unsigned int nhashmask = xfrm_new_hash_mask(hmask); |
415 | unsigned int nsize = (nhashmask + 1) * sizeof(struct hlist_head); | 397 | unsigned int nsize = (nhashmask + 1) * sizeof(struct hlist_head); |
416 | struct hlist_head *odst = xfrm_policy_bydst[dir].table; | 398 | struct hlist_head *odst = net->xfrm.policy_bydst[dir].table; |
417 | struct hlist_head *ndst = xfrm_hash_alloc(nsize); | 399 | struct hlist_head *ndst = xfrm_hash_alloc(nsize); |
418 | int i; | 400 | int i; |
419 | 401 | ||
@@ -425,20 +407,20 @@ static void xfrm_bydst_resize(int dir) | |||
425 | for (i = hmask; i >= 0; i--) | 407 | for (i = hmask; i >= 0; i--) |
426 | xfrm_dst_hash_transfer(odst + i, ndst, nhashmask); | 408 | xfrm_dst_hash_transfer(odst + i, ndst, nhashmask); |
427 | 409 | ||
428 | xfrm_policy_bydst[dir].table = ndst; | 410 | net->xfrm.policy_bydst[dir].table = ndst; |
429 | xfrm_policy_bydst[dir].hmask = nhashmask; | 411 | net->xfrm.policy_bydst[dir].hmask = nhashmask; |
430 | 412 | ||
431 | write_unlock_bh(&xfrm_policy_lock); | 413 | write_unlock_bh(&xfrm_policy_lock); |
432 | 414 | ||
433 | xfrm_hash_free(odst, (hmask + 1) * sizeof(struct hlist_head)); | 415 | xfrm_hash_free(odst, (hmask + 1) * sizeof(struct hlist_head)); |
434 | } | 416 | } |
435 | 417 | ||
436 | static void xfrm_byidx_resize(int total) | 418 | static void xfrm_byidx_resize(struct net *net, int total) |
437 | { | 419 | { |
438 | unsigned int hmask = xfrm_idx_hmask; | 420 | unsigned int hmask = net->xfrm.policy_idx_hmask; |
439 | unsigned int nhashmask = xfrm_new_hash_mask(hmask); | 421 | unsigned int nhashmask = xfrm_new_hash_mask(hmask); |
440 | unsigned int nsize = (nhashmask + 1) * sizeof(struct hlist_head); | 422 | unsigned int nsize = (nhashmask + 1) * sizeof(struct hlist_head); |
441 | struct hlist_head *oidx = xfrm_policy_byidx; | 423 | struct hlist_head *oidx = net->xfrm.policy_byidx; |
442 | struct hlist_head *nidx = xfrm_hash_alloc(nsize); | 424 | struct hlist_head *nidx = xfrm_hash_alloc(nsize); |
443 | int i; | 425 | int i; |
444 | 426 | ||
@@ -450,18 +432,18 @@ static void xfrm_byidx_resize(int total) | |||
450 | for (i = hmask; i >= 0; i--) | 432 | for (i = hmask; i >= 0; i--) |
451 | xfrm_idx_hash_transfer(oidx + i, nidx, nhashmask); | 433 | xfrm_idx_hash_transfer(oidx + i, nidx, nhashmask); |
452 | 434 | ||
453 | xfrm_policy_byidx = nidx; | 435 | net->xfrm.policy_byidx = nidx; |
454 | xfrm_idx_hmask = nhashmask; | 436 | net->xfrm.policy_idx_hmask = nhashmask; |
455 | 437 | ||
456 | write_unlock_bh(&xfrm_policy_lock); | 438 | write_unlock_bh(&xfrm_policy_lock); |
457 | 439 | ||
458 | xfrm_hash_free(oidx, (hmask + 1) * sizeof(struct hlist_head)); | 440 | xfrm_hash_free(oidx, (hmask + 1) * sizeof(struct hlist_head)); |
459 | } | 441 | } |
460 | 442 | ||
461 | static inline int xfrm_bydst_should_resize(int dir, int *total) | 443 | static inline int xfrm_bydst_should_resize(struct net *net, int dir, int *total) |
462 | { | 444 | { |
463 | unsigned int cnt = xfrm_policy_count[dir]; | 445 | unsigned int cnt = net->xfrm.policy_count[dir]; |
464 | unsigned int hmask = xfrm_policy_bydst[dir].hmask; | 446 | unsigned int hmask = net->xfrm.policy_bydst[dir].hmask; |
465 | 447 | ||
466 | if (total) | 448 | if (total) |
467 | *total += cnt; | 449 | *total += cnt; |
@@ -473,9 +455,9 @@ static inline int xfrm_bydst_should_resize(int dir, int *total) | |||
473 | return 0; | 455 | return 0; |
474 | } | 456 | } |
475 | 457 | ||
476 | static inline int xfrm_byidx_should_resize(int total) | 458 | static inline int xfrm_byidx_should_resize(struct net *net, int total) |
477 | { | 459 | { |
478 | unsigned int hmask = xfrm_idx_hmask; | 460 | unsigned int hmask = net->xfrm.policy_idx_hmask; |
479 | 461 | ||
480 | if ((hmask + 1) < xfrm_policy_hashmax && | 462 | if ((hmask + 1) < xfrm_policy_hashmax && |
481 | total > hmask) | 463 | total > hmask) |
@@ -487,41 +469,40 @@ static inline int xfrm_byidx_should_resize(int total) | |||
487 | void xfrm_spd_getinfo(struct xfrmk_spdinfo *si) | 469 | void xfrm_spd_getinfo(struct xfrmk_spdinfo *si) |
488 | { | 470 | { |
489 | read_lock_bh(&xfrm_policy_lock); | 471 | read_lock_bh(&xfrm_policy_lock); |
490 | si->incnt = xfrm_policy_count[XFRM_POLICY_IN]; | 472 | si->incnt = init_net.xfrm.policy_count[XFRM_POLICY_IN]; |
491 | si->outcnt = xfrm_policy_count[XFRM_POLICY_OUT]; | 473 | si->outcnt = init_net.xfrm.policy_count[XFRM_POLICY_OUT]; |
492 | si->fwdcnt = xfrm_policy_count[XFRM_POLICY_FWD]; | 474 | si->fwdcnt = init_net.xfrm.policy_count[XFRM_POLICY_FWD]; |
493 | si->inscnt = xfrm_policy_count[XFRM_POLICY_IN+XFRM_POLICY_MAX]; | 475 | si->inscnt = init_net.xfrm.policy_count[XFRM_POLICY_IN+XFRM_POLICY_MAX]; |
494 | si->outscnt = xfrm_policy_count[XFRM_POLICY_OUT+XFRM_POLICY_MAX]; | 476 | si->outscnt = init_net.xfrm.policy_count[XFRM_POLICY_OUT+XFRM_POLICY_MAX]; |
495 | si->fwdscnt = xfrm_policy_count[XFRM_POLICY_FWD+XFRM_POLICY_MAX]; | 477 | si->fwdscnt = init_net.xfrm.policy_count[XFRM_POLICY_FWD+XFRM_POLICY_MAX]; |
496 | si->spdhcnt = xfrm_idx_hmask; | 478 | si->spdhcnt = init_net.xfrm.policy_idx_hmask; |
497 | si->spdhmcnt = xfrm_policy_hashmax; | 479 | si->spdhmcnt = xfrm_policy_hashmax; |
498 | read_unlock_bh(&xfrm_policy_lock); | 480 | read_unlock_bh(&xfrm_policy_lock); |
499 | } | 481 | } |
500 | EXPORT_SYMBOL(xfrm_spd_getinfo); | 482 | EXPORT_SYMBOL(xfrm_spd_getinfo); |
501 | 483 | ||
502 | static DEFINE_MUTEX(hash_resize_mutex); | 484 | static DEFINE_MUTEX(hash_resize_mutex); |
503 | static void xfrm_hash_resize(struct work_struct *__unused) | 485 | static void xfrm_hash_resize(struct work_struct *work) |
504 | { | 486 | { |
487 | struct net *net = container_of(work, struct net, xfrm.policy_hash_work); | ||
505 | int dir, total; | 488 | int dir, total; |
506 | 489 | ||
507 | mutex_lock(&hash_resize_mutex); | 490 | mutex_lock(&hash_resize_mutex); |
508 | 491 | ||
509 | total = 0; | 492 | total = 0; |
510 | for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) { | 493 | for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) { |
511 | if (xfrm_bydst_should_resize(dir, &total)) | 494 | if (xfrm_bydst_should_resize(net, dir, &total)) |
512 | xfrm_bydst_resize(dir); | 495 | xfrm_bydst_resize(net, dir); |
513 | } | 496 | } |
514 | if (xfrm_byidx_should_resize(total)) | 497 | if (xfrm_byidx_should_resize(net, total)) |
515 | xfrm_byidx_resize(total); | 498 | xfrm_byidx_resize(net, total); |
516 | 499 | ||
517 | mutex_unlock(&hash_resize_mutex); | 500 | mutex_unlock(&hash_resize_mutex); |
518 | } | 501 | } |
519 | 502 | ||
520 | static DECLARE_WORK(xfrm_hash_work, xfrm_hash_resize); | ||
521 | |||
522 | /* Generate new index... KAME seems to generate them ordered by cost | 503 | /* Generate new index... KAME seems to generate them ordered by cost |
523 | * of an absolute inpredictability of ordering of rules. This will not pass. */ | 504 | * of an absolute inpredictability of ordering of rules. This will not pass. */ |
524 | static u32 xfrm_gen_index(u8 type, int dir) | 505 | static u32 xfrm_gen_index(struct net *net, int dir) |
525 | { | 506 | { |
526 | static u32 idx_generator; | 507 | static u32 idx_generator; |
527 | 508 | ||
@@ -536,7 +517,7 @@ static u32 xfrm_gen_index(u8 type, int dir) | |||
536 | idx_generator += 8; | 517 | idx_generator += 8; |
537 | if (idx == 0) | 518 | if (idx == 0) |
538 | idx = 8; | 519 | idx = 8; |
539 | list = xfrm_policy_byidx + idx_hash(idx); | 520 | list = net->xfrm.policy_byidx + idx_hash(net, idx); |
540 | found = 0; | 521 | found = 0; |
541 | hlist_for_each_entry(p, entry, list, byidx) { | 522 | hlist_for_each_entry(p, entry, list, byidx) { |
542 | if (p->index == idx) { | 523 | if (p->index == idx) { |
@@ -566,6 +547,7 @@ static inline int selector_cmp(struct xfrm_selector *s1, struct xfrm_selector *s | |||
566 | 547 | ||
567 | int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) | 548 | int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) |
568 | { | 549 | { |
550 | struct net *net = xp_net(policy); | ||
569 | struct xfrm_policy *pol; | 551 | struct xfrm_policy *pol; |
570 | struct xfrm_policy *delpol; | 552 | struct xfrm_policy *delpol; |
571 | struct hlist_head *chain; | 553 | struct hlist_head *chain; |
@@ -573,7 +555,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) | |||
573 | struct dst_entry *gc_list; | 555 | struct dst_entry *gc_list; |
574 | 556 | ||
575 | write_lock_bh(&xfrm_policy_lock); | 557 | write_lock_bh(&xfrm_policy_lock); |
576 | chain = policy_hash_bysel(&policy->selector, policy->family, dir); | 558 | chain = policy_hash_bysel(net, &policy->selector, policy->family, dir); |
577 | delpol = NULL; | 559 | delpol = NULL; |
578 | newpos = NULL; | 560 | newpos = NULL; |
579 | hlist_for_each_entry(pol, entry, chain, bydst) { | 561 | hlist_for_each_entry(pol, entry, chain, bydst) { |
@@ -600,27 +582,27 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) | |||
600 | else | 582 | else |
601 | hlist_add_head(&policy->bydst, chain); | 583 | hlist_add_head(&policy->bydst, chain); |
602 | xfrm_pol_hold(policy); | 584 | xfrm_pol_hold(policy); |
603 | xfrm_policy_count[dir]++; | 585 | net->xfrm.policy_count[dir]++; |
604 | atomic_inc(&flow_cache_genid); | 586 | atomic_inc(&flow_cache_genid); |
605 | if (delpol) { | 587 | if (delpol) { |
606 | hlist_del(&delpol->bydst); | 588 | hlist_del(&delpol->bydst); |
607 | hlist_del(&delpol->byidx); | 589 | hlist_del(&delpol->byidx); |
608 | list_del(&delpol->walk.all); | 590 | list_del(&delpol->walk.all); |
609 | xfrm_policy_count[dir]--; | 591 | net->xfrm.policy_count[dir]--; |
610 | } | 592 | } |
611 | policy->index = delpol ? delpol->index : xfrm_gen_index(policy->type, dir); | 593 | policy->index = delpol ? delpol->index : xfrm_gen_index(net, dir); |
612 | hlist_add_head(&policy->byidx, xfrm_policy_byidx+idx_hash(policy->index)); | 594 | hlist_add_head(&policy->byidx, net->xfrm.policy_byidx+idx_hash(net, policy->index)); |
613 | policy->curlft.add_time = get_seconds(); | 595 | policy->curlft.add_time = get_seconds(); |
614 | policy->curlft.use_time = 0; | 596 | policy->curlft.use_time = 0; |
615 | if (!mod_timer(&policy->timer, jiffies + HZ)) | 597 | if (!mod_timer(&policy->timer, jiffies + HZ)) |
616 | xfrm_pol_hold(policy); | 598 | xfrm_pol_hold(policy); |
617 | list_add(&policy->walk.all, &xfrm_policy_all); | 599 | list_add(&policy->walk.all, &net->xfrm.policy_all); |
618 | write_unlock_bh(&xfrm_policy_lock); | 600 | write_unlock_bh(&xfrm_policy_lock); |
619 | 601 | ||
620 | if (delpol) | 602 | if (delpol) |
621 | xfrm_policy_kill(delpol); | 603 | xfrm_policy_kill(delpol); |
622 | else if (xfrm_bydst_should_resize(dir, NULL)) | 604 | else if (xfrm_bydst_should_resize(net, dir, NULL)) |
623 | schedule_work(&xfrm_hash_work); | 605 | schedule_work(&net->xfrm.policy_hash_work); |
624 | 606 | ||
625 | read_lock_bh(&xfrm_policy_lock); | 607 | read_lock_bh(&xfrm_policy_lock); |
626 | gc_list = NULL; | 608 | gc_list = NULL; |
@@ -654,7 +636,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) | |||
654 | } | 636 | } |
655 | EXPORT_SYMBOL(xfrm_policy_insert); | 637 | EXPORT_SYMBOL(xfrm_policy_insert); |
656 | 638 | ||
657 | struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, | 639 | struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u8 type, int dir, |
658 | struct xfrm_selector *sel, | 640 | struct xfrm_selector *sel, |
659 | struct xfrm_sec_ctx *ctx, int delete, | 641 | struct xfrm_sec_ctx *ctx, int delete, |
660 | int *err) | 642 | int *err) |
@@ -665,7 +647,7 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, | |||
665 | 647 | ||
666 | *err = 0; | 648 | *err = 0; |
667 | write_lock_bh(&xfrm_policy_lock); | 649 | write_lock_bh(&xfrm_policy_lock); |
668 | chain = policy_hash_bysel(sel, sel->family, dir); | 650 | chain = policy_hash_bysel(net, sel, sel->family, dir); |
669 | ret = NULL; | 651 | ret = NULL; |
670 | hlist_for_each_entry(pol, entry, chain, bydst) { | 652 | hlist_for_each_entry(pol, entry, chain, bydst) { |
671 | if (pol->type == type && | 653 | if (pol->type == type && |
@@ -682,7 +664,7 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, | |||
682 | hlist_del(&pol->bydst); | 664 | hlist_del(&pol->bydst); |
683 | hlist_del(&pol->byidx); | 665 | hlist_del(&pol->byidx); |
684 | list_del(&pol->walk.all); | 666 | list_del(&pol->walk.all); |
685 | xfrm_policy_count[dir]--; | 667 | net->xfrm.policy_count[dir]--; |
686 | } | 668 | } |
687 | ret = pol; | 669 | ret = pol; |
688 | break; | 670 | break; |
@@ -698,8 +680,8 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, | |||
698 | } | 680 | } |
699 | EXPORT_SYMBOL(xfrm_policy_bysel_ctx); | 681 | EXPORT_SYMBOL(xfrm_policy_bysel_ctx); |
700 | 682 | ||
701 | struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete, | 683 | struct xfrm_policy *xfrm_policy_byid(struct net *net, u8 type, int dir, u32 id, |
702 | int *err) | 684 | int delete, int *err) |
703 | { | 685 | { |
704 | struct xfrm_policy *pol, *ret; | 686 | struct xfrm_policy *pol, *ret; |
705 | struct hlist_head *chain; | 687 | struct hlist_head *chain; |
@@ -711,7 +693,7 @@ struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete, | |||
711 | 693 | ||
712 | *err = 0; | 694 | *err = 0; |
713 | write_lock_bh(&xfrm_policy_lock); | 695 | write_lock_bh(&xfrm_policy_lock); |
714 | chain = xfrm_policy_byidx + idx_hash(id); | 696 | chain = net->xfrm.policy_byidx + idx_hash(net, id); |
715 | ret = NULL; | 697 | ret = NULL; |
716 | hlist_for_each_entry(pol, entry, chain, byidx) { | 698 | hlist_for_each_entry(pol, entry, chain, byidx) { |
717 | if (pol->type == type && pol->index == id) { | 699 | if (pol->type == type && pol->index == id) { |
@@ -726,7 +708,7 @@ struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete, | |||
726 | hlist_del(&pol->bydst); | 708 | hlist_del(&pol->bydst); |
727 | hlist_del(&pol->byidx); | 709 | hlist_del(&pol->byidx); |
728 | list_del(&pol->walk.all); | 710 | list_del(&pol->walk.all); |
729 | xfrm_policy_count[dir]--; | 711 | net->xfrm.policy_count[dir]--; |
730 | } | 712 | } |
731 | ret = pol; | 713 | ret = pol; |
732 | break; | 714 | break; |
@@ -744,7 +726,7 @@ EXPORT_SYMBOL(xfrm_policy_byid); | |||
744 | 726 | ||
745 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 727 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
746 | static inline int | 728 | static inline int |
747 | xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info) | 729 | xfrm_policy_flush_secctx_check(struct net *net, u8 type, struct xfrm_audit *audit_info) |
748 | { | 730 | { |
749 | int dir, err = 0; | 731 | int dir, err = 0; |
750 | 732 | ||
@@ -754,7 +736,7 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info) | |||
754 | int i; | 736 | int i; |
755 | 737 | ||
756 | hlist_for_each_entry(pol, entry, | 738 | hlist_for_each_entry(pol, entry, |
757 | &xfrm_policy_inexact[dir], bydst) { | 739 | &net->xfrm.policy_inexact[dir], bydst) { |
758 | if (pol->type != type) | 740 | if (pol->type != type) |
759 | continue; | 741 | continue; |
760 | err = security_xfrm_policy_delete(pol->security); | 742 | err = security_xfrm_policy_delete(pol->security); |
@@ -766,9 +748,9 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info) | |||
766 | return err; | 748 | return err; |
767 | } | 749 | } |
768 | } | 750 | } |
769 | for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) { | 751 | for (i = net->xfrm.policy_bydst[dir].hmask; i >= 0; i--) { |
770 | hlist_for_each_entry(pol, entry, | 752 | hlist_for_each_entry(pol, entry, |
771 | xfrm_policy_bydst[dir].table + i, | 753 | net->xfrm.policy_bydst[dir].table + i, |
772 | bydst) { | 754 | bydst) { |
773 | if (pol->type != type) | 755 | if (pol->type != type) |
774 | continue; | 756 | continue; |
@@ -788,19 +770,19 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info) | |||
788 | } | 770 | } |
789 | #else | 771 | #else |
790 | static inline int | 772 | static inline int |
791 | xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info) | 773 | xfrm_policy_flush_secctx_check(struct net *net, u8 type, struct xfrm_audit *audit_info) |
792 | { | 774 | { |
793 | return 0; | 775 | return 0; |
794 | } | 776 | } |
795 | #endif | 777 | #endif |
796 | 778 | ||
797 | int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info) | 779 | int xfrm_policy_flush(struct net *net, u8 type, struct xfrm_audit *audit_info) |
798 | { | 780 | { |
799 | int dir, err = 0; | 781 | int dir, err = 0; |
800 | 782 | ||
801 | write_lock_bh(&xfrm_policy_lock); | 783 | write_lock_bh(&xfrm_policy_lock); |
802 | 784 | ||
803 | err = xfrm_policy_flush_secctx_check(type, audit_info); | 785 | err = xfrm_policy_flush_secctx_check(net, type, audit_info); |
804 | if (err) | 786 | if (err) |
805 | goto out; | 787 | goto out; |
806 | 788 | ||
@@ -812,7 +794,7 @@ int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info) | |||
812 | killed = 0; | 794 | killed = 0; |
813 | again1: | 795 | again1: |
814 | hlist_for_each_entry(pol, entry, | 796 | hlist_for_each_entry(pol, entry, |
815 | &xfrm_policy_inexact[dir], bydst) { | 797 | &net->xfrm.policy_inexact[dir], bydst) { |
816 | if (pol->type != type) | 798 | if (pol->type != type) |
817 | continue; | 799 | continue; |
818 | hlist_del(&pol->bydst); | 800 | hlist_del(&pol->bydst); |
@@ -831,10 +813,10 @@ int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info) | |||
831 | goto again1; | 813 | goto again1; |
832 | } | 814 | } |
833 | 815 | ||
834 | for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) { | 816 | for (i = net->xfrm.policy_bydst[dir].hmask; i >= 0; i--) { |
835 | again2: | 817 | again2: |
836 | hlist_for_each_entry(pol, entry, | 818 | hlist_for_each_entry(pol, entry, |
837 | xfrm_policy_bydst[dir].table + i, | 819 | net->xfrm.policy_bydst[dir].table + i, |
838 | bydst) { | 820 | bydst) { |
839 | if (pol->type != type) | 821 | if (pol->type != type) |
840 | continue; | 822 | continue; |
@@ -855,7 +837,7 @@ int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info) | |||
855 | } | 837 | } |
856 | } | 838 | } |
857 | 839 | ||
858 | xfrm_policy_count[dir] -= killed; | 840 | net->xfrm.policy_count[dir] -= killed; |
859 | } | 841 | } |
860 | atomic_inc(&flow_cache_genid); | 842 | atomic_inc(&flow_cache_genid); |
861 | out: | 843 | out: |
@@ -864,7 +846,7 @@ out: | |||
864 | } | 846 | } |
865 | EXPORT_SYMBOL(xfrm_policy_flush); | 847 | EXPORT_SYMBOL(xfrm_policy_flush); |
866 | 848 | ||
867 | int xfrm_policy_walk(struct xfrm_policy_walk *walk, | 849 | int xfrm_policy_walk(struct net *net, struct xfrm_policy_walk *walk, |
868 | int (*func)(struct xfrm_policy *, int, int, void*), | 850 | int (*func)(struct xfrm_policy *, int, int, void*), |
869 | void *data) | 851 | void *data) |
870 | { | 852 | { |
@@ -881,10 +863,10 @@ int xfrm_policy_walk(struct xfrm_policy_walk *walk, | |||
881 | 863 | ||
882 | write_lock_bh(&xfrm_policy_lock); | 864 | write_lock_bh(&xfrm_policy_lock); |
883 | if (list_empty(&walk->walk.all)) | 865 | if (list_empty(&walk->walk.all)) |
884 | x = list_first_entry(&xfrm_policy_all, struct xfrm_policy_walk_entry, all); | 866 | x = list_first_entry(&net->xfrm.policy_all, struct xfrm_policy_walk_entry, all); |
885 | else | 867 | else |
886 | x = list_entry(&walk->walk.all, struct xfrm_policy_walk_entry, all); | 868 | x = list_entry(&walk->walk.all, struct xfrm_policy_walk_entry, all); |
887 | list_for_each_entry_from(x, &xfrm_policy_all, all) { | 869 | list_for_each_entry_from(x, &net->xfrm.policy_all, all) { |
888 | if (x->dead) | 870 | if (x->dead) |
889 | continue; | 871 | continue; |
890 | pol = container_of(x, struct xfrm_policy, walk); | 872 | pol = container_of(x, struct xfrm_policy, walk); |
@@ -953,7 +935,8 @@ static int xfrm_policy_match(struct xfrm_policy *pol, struct flowi *fl, | |||
953 | return ret; | 935 | return ret; |
954 | } | 936 | } |
955 | 937 | ||
956 | static struct xfrm_policy *xfrm_policy_lookup_bytype(u8 type, struct flowi *fl, | 938 | static struct xfrm_policy *xfrm_policy_lookup_bytype(struct net *net, u8 type, |
939 | struct flowi *fl, | ||
957 | u16 family, u8 dir) | 940 | u16 family, u8 dir) |
958 | { | 941 | { |
959 | int err; | 942 | int err; |
@@ -969,7 +952,7 @@ static struct xfrm_policy *xfrm_policy_lookup_bytype(u8 type, struct flowi *fl, | |||
969 | return NULL; | 952 | return NULL; |
970 | 953 | ||
971 | read_lock_bh(&xfrm_policy_lock); | 954 | read_lock_bh(&xfrm_policy_lock); |
972 | chain = policy_hash_direct(daddr, saddr, family, dir); | 955 | chain = policy_hash_direct(net, daddr, saddr, family, dir); |
973 | ret = NULL; | 956 | ret = NULL; |
974 | hlist_for_each_entry(pol, entry, chain, bydst) { | 957 | hlist_for_each_entry(pol, entry, chain, bydst) { |
975 | err = xfrm_policy_match(pol, fl, type, family, dir); | 958 | err = xfrm_policy_match(pol, fl, type, family, dir); |
@@ -986,7 +969,7 @@ static struct xfrm_policy *xfrm_policy_lookup_bytype(u8 type, struct flowi *fl, | |||
986 | break; | 969 | break; |
987 | } | 970 | } |
988 | } | 971 | } |
989 | chain = &xfrm_policy_inexact[dir]; | 972 | chain = &net->xfrm.policy_inexact[dir]; |
990 | hlist_for_each_entry(pol, entry, chain, bydst) { | 973 | hlist_for_each_entry(pol, entry, chain, bydst) { |
991 | err = xfrm_policy_match(pol, fl, type, family, dir); | 974 | err = xfrm_policy_match(pol, fl, type, family, dir); |
992 | if (err) { | 975 | if (err) { |
@@ -1009,14 +992,14 @@ fail: | |||
1009 | return ret; | 992 | return ret; |
1010 | } | 993 | } |
1011 | 994 | ||
1012 | static int xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir, | 995 | static int xfrm_policy_lookup(struct net *net, struct flowi *fl, u16 family, |
1013 | void **objp, atomic_t **obj_refp) | 996 | u8 dir, void **objp, atomic_t **obj_refp) |
1014 | { | 997 | { |
1015 | struct xfrm_policy *pol; | 998 | struct xfrm_policy *pol; |
1016 | int err = 0; | 999 | int err = 0; |
1017 | 1000 | ||
1018 | #ifdef CONFIG_XFRM_SUB_POLICY | 1001 | #ifdef CONFIG_XFRM_SUB_POLICY |
1019 | pol = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_SUB, fl, family, dir); | 1002 | pol = xfrm_policy_lookup_bytype(net, XFRM_POLICY_TYPE_SUB, fl, family, dir); |
1020 | if (IS_ERR(pol)) { | 1003 | if (IS_ERR(pol)) { |
1021 | err = PTR_ERR(pol); | 1004 | err = PTR_ERR(pol); |
1022 | pol = NULL; | 1005 | pol = NULL; |
@@ -1024,7 +1007,7 @@ static int xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir, | |||
1024 | if (pol || err) | 1007 | if (pol || err) |
1025 | goto end; | 1008 | goto end; |
1026 | #endif | 1009 | #endif |
1027 | pol = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_MAIN, fl, family, dir); | 1010 | pol = xfrm_policy_lookup_bytype(net, XFRM_POLICY_TYPE_MAIN, fl, family, dir); |
1028 | if (IS_ERR(pol)) { | 1011 | if (IS_ERR(pol)) { |
1029 | err = PTR_ERR(pol); | 1012 | err = PTR_ERR(pol); |
1030 | pol = NULL; | 1013 | pol = NULL; |
@@ -1083,29 +1066,32 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struc | |||
1083 | 1066 | ||
1084 | static void __xfrm_policy_link(struct xfrm_policy *pol, int dir) | 1067 | static void __xfrm_policy_link(struct xfrm_policy *pol, int dir) |
1085 | { | 1068 | { |
1086 | struct hlist_head *chain = policy_hash_bysel(&pol->selector, | 1069 | struct net *net = xp_net(pol); |
1070 | struct hlist_head *chain = policy_hash_bysel(net, &pol->selector, | ||
1087 | pol->family, dir); | 1071 | pol->family, dir); |
1088 | 1072 | ||
1089 | list_add(&pol->walk.all, &xfrm_policy_all); | 1073 | list_add(&pol->walk.all, &net->xfrm.policy_all); |
1090 | hlist_add_head(&pol->bydst, chain); | 1074 | hlist_add_head(&pol->bydst, chain); |
1091 | hlist_add_head(&pol->byidx, xfrm_policy_byidx+idx_hash(pol->index)); | 1075 | hlist_add_head(&pol->byidx, net->xfrm.policy_byidx+idx_hash(net, pol->index)); |
1092 | xfrm_policy_count[dir]++; | 1076 | net->xfrm.policy_count[dir]++; |
1093 | xfrm_pol_hold(pol); | 1077 | xfrm_pol_hold(pol); |
1094 | 1078 | ||
1095 | if (xfrm_bydst_should_resize(dir, NULL)) | 1079 | if (xfrm_bydst_should_resize(net, dir, NULL)) |
1096 | schedule_work(&xfrm_hash_work); | 1080 | schedule_work(&net->xfrm.policy_hash_work); |
1097 | } | 1081 | } |
1098 | 1082 | ||
1099 | static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol, | 1083 | static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol, |
1100 | int dir) | 1084 | int dir) |
1101 | { | 1085 | { |
1086 | struct net *net = xp_net(pol); | ||
1087 | |||
1102 | if (hlist_unhashed(&pol->bydst)) | 1088 | if (hlist_unhashed(&pol->bydst)) |
1103 | return NULL; | 1089 | return NULL; |
1104 | 1090 | ||
1105 | hlist_del(&pol->bydst); | 1091 | hlist_del(&pol->bydst); |
1106 | hlist_del(&pol->byidx); | 1092 | hlist_del(&pol->byidx); |
1107 | list_del(&pol->walk.all); | 1093 | list_del(&pol->walk.all); |
1108 | xfrm_policy_count[dir]--; | 1094 | net->xfrm.policy_count[dir]--; |
1109 | 1095 | ||
1110 | return pol; | 1096 | return pol; |
1111 | } | 1097 | } |
@@ -1127,6 +1113,7 @@ EXPORT_SYMBOL(xfrm_policy_delete); | |||
1127 | 1113 | ||
1128 | int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol) | 1114 | int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol) |
1129 | { | 1115 | { |
1116 | struct net *net = xp_net(pol); | ||
1130 | struct xfrm_policy *old_pol; | 1117 | struct xfrm_policy *old_pol; |
1131 | 1118 | ||
1132 | #ifdef CONFIG_XFRM_SUB_POLICY | 1119 | #ifdef CONFIG_XFRM_SUB_POLICY |
@@ -1139,7 +1126,7 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol) | |||
1139 | sk->sk_policy[dir] = pol; | 1126 | sk->sk_policy[dir] = pol; |
1140 | if (pol) { | 1127 | if (pol) { |
1141 | pol->curlft.add_time = get_seconds(); | 1128 | pol->curlft.add_time = get_seconds(); |
1142 | pol->index = xfrm_gen_index(pol->type, XFRM_POLICY_MAX+dir); | 1129 | pol->index = xfrm_gen_index(net, XFRM_POLICY_MAX+dir); |
1143 | __xfrm_policy_link(pol, XFRM_POLICY_MAX+dir); | 1130 | __xfrm_policy_link(pol, XFRM_POLICY_MAX+dir); |
1144 | } | 1131 | } |
1145 | if (old_pol) | 1132 | if (old_pol) |
@@ -1154,7 +1141,7 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol) | |||
1154 | 1141 | ||
1155 | static struct xfrm_policy *clone_policy(struct xfrm_policy *old, int dir) | 1142 | static struct xfrm_policy *clone_policy(struct xfrm_policy *old, int dir) |
1156 | { | 1143 | { |
1157 | struct xfrm_policy *newp = xfrm_policy_alloc(GFP_ATOMIC); | 1144 | struct xfrm_policy *newp = xfrm_policy_alloc(xp_net(old), GFP_ATOMIC); |
1158 | 1145 | ||
1159 | if (newp) { | 1146 | if (newp) { |
1160 | newp->selector = old->selector; | 1147 | newp->selector = old->selector; |
@@ -1194,7 +1181,7 @@ int __xfrm_sk_clone_policy(struct sock *sk) | |||
1194 | } | 1181 | } |
1195 | 1182 | ||
1196 | static int | 1183 | static int |
1197 | xfrm_get_saddr(xfrm_address_t *local, xfrm_address_t *remote, | 1184 | xfrm_get_saddr(struct net *net, xfrm_address_t *local, xfrm_address_t *remote, |
1198 | unsigned short family) | 1185 | unsigned short family) |
1199 | { | 1186 | { |
1200 | int err; | 1187 | int err; |
@@ -1202,7 +1189,7 @@ xfrm_get_saddr(xfrm_address_t *local, xfrm_address_t *remote, | |||
1202 | 1189 | ||
1203 | if (unlikely(afinfo == NULL)) | 1190 | if (unlikely(afinfo == NULL)) |
1204 | return -EINVAL; | 1191 | return -EINVAL; |
1205 | err = afinfo->get_saddr(local, remote); | 1192 | err = afinfo->get_saddr(net, local, remote); |
1206 | xfrm_policy_put_afinfo(afinfo); | 1193 | xfrm_policy_put_afinfo(afinfo); |
1207 | return err; | 1194 | return err; |
1208 | } | 1195 | } |
@@ -1214,6 +1201,7 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, struct flowi *fl, | |||
1214 | struct xfrm_state **xfrm, | 1201 | struct xfrm_state **xfrm, |
1215 | unsigned short family) | 1202 | unsigned short family) |
1216 | { | 1203 | { |
1204 | struct net *net = xp_net(policy); | ||
1217 | int nx; | 1205 | int nx; |
1218 | int i, error; | 1206 | int i, error; |
1219 | xfrm_address_t *daddr = xfrm_flowi_daddr(fl, family); | 1207 | xfrm_address_t *daddr = xfrm_flowi_daddr(fl, family); |
@@ -1232,7 +1220,7 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, struct flowi *fl, | |||
1232 | local = &tmpl->saddr; | 1220 | local = &tmpl->saddr; |
1233 | family = tmpl->encap_family; | 1221 | family = tmpl->encap_family; |
1234 | if (xfrm_addr_any(local, family)) { | 1222 | if (xfrm_addr_any(local, family)) { |
1235 | error = xfrm_get_saddr(&tmp, remote, family); | 1223 | error = xfrm_get_saddr(net, &tmp, remote, family); |
1236 | if (error) | 1224 | if (error) |
1237 | goto fail; | 1225 | goto fail; |
1238 | local = &tmp; | 1226 | local = &tmp; |
@@ -1546,7 +1534,7 @@ static int stale_bundle(struct dst_entry *dst); | |||
1546 | * At the moment we eat a raw IP route. Mostly to speed up lookups | 1534 | * At the moment we eat a raw IP route. Mostly to speed up lookups |
1547 | * on interfaces with disabled IPsec. | 1535 | * on interfaces with disabled IPsec. |
1548 | */ | 1536 | */ |
1549 | int __xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, | 1537 | int __xfrm_lookup(struct net *net, struct dst_entry **dst_p, struct flowi *fl, |
1550 | struct sock *sk, int flags) | 1538 | struct sock *sk, int flags) |
1551 | { | 1539 | { |
1552 | struct xfrm_policy *policy; | 1540 | struct xfrm_policy *policy; |
@@ -1576,7 +1564,7 @@ restart: | |||
1576 | policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl); | 1564 | policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl); |
1577 | err = PTR_ERR(policy); | 1565 | err = PTR_ERR(policy); |
1578 | if (IS_ERR(policy)) { | 1566 | if (IS_ERR(policy)) { |
1579 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLERROR); | 1567 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLERROR); |
1580 | goto dropdst; | 1568 | goto dropdst; |
1581 | } | 1569 | } |
1582 | } | 1570 | } |
@@ -1584,14 +1572,14 @@ restart: | |||
1584 | if (!policy) { | 1572 | if (!policy) { |
1585 | /* To accelerate a bit... */ | 1573 | /* To accelerate a bit... */ |
1586 | if ((dst_orig->flags & DST_NOXFRM) || | 1574 | if ((dst_orig->flags & DST_NOXFRM) || |
1587 | !xfrm_policy_count[XFRM_POLICY_OUT]) | 1575 | !net->xfrm.policy_count[XFRM_POLICY_OUT]) |
1588 | goto nopol; | 1576 | goto nopol; |
1589 | 1577 | ||
1590 | policy = flow_cache_lookup(fl, dst_orig->ops->family, | 1578 | policy = flow_cache_lookup(net, fl, dst_orig->ops->family, |
1591 | dir, xfrm_policy_lookup); | 1579 | dir, xfrm_policy_lookup); |
1592 | err = PTR_ERR(policy); | 1580 | err = PTR_ERR(policy); |
1593 | if (IS_ERR(policy)) { | 1581 | if (IS_ERR(policy)) { |
1594 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLERROR); | 1582 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLERROR); |
1595 | goto dropdst; | 1583 | goto dropdst; |
1596 | } | 1584 | } |
1597 | } | 1585 | } |
@@ -1614,7 +1602,7 @@ restart: | |||
1614 | default: | 1602 | default: |
1615 | case XFRM_POLICY_BLOCK: | 1603 | case XFRM_POLICY_BLOCK: |
1616 | /* Prohibit the flow */ | 1604 | /* Prohibit the flow */ |
1617 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLBLOCK); | 1605 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLBLOCK); |
1618 | err = -EPERM; | 1606 | err = -EPERM; |
1619 | goto error; | 1607 | goto error; |
1620 | 1608 | ||
@@ -1634,7 +1622,7 @@ restart: | |||
1634 | */ | 1622 | */ |
1635 | dst = xfrm_find_bundle(fl, policy, family); | 1623 | dst = xfrm_find_bundle(fl, policy, family); |
1636 | if (IS_ERR(dst)) { | 1624 | if (IS_ERR(dst)) { |
1637 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTBUNDLECHECKERROR); | 1625 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLECHECKERROR); |
1638 | err = PTR_ERR(dst); | 1626 | err = PTR_ERR(dst); |
1639 | goto error; | 1627 | goto error; |
1640 | } | 1628 | } |
@@ -1644,17 +1632,18 @@ restart: | |||
1644 | 1632 | ||
1645 | #ifdef CONFIG_XFRM_SUB_POLICY | 1633 | #ifdef CONFIG_XFRM_SUB_POLICY |
1646 | if (pols[0]->type != XFRM_POLICY_TYPE_MAIN) { | 1634 | if (pols[0]->type != XFRM_POLICY_TYPE_MAIN) { |
1647 | pols[1] = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_MAIN, | 1635 | pols[1] = xfrm_policy_lookup_bytype(net, |
1636 | XFRM_POLICY_TYPE_MAIN, | ||
1648 | fl, family, | 1637 | fl, family, |
1649 | XFRM_POLICY_OUT); | 1638 | XFRM_POLICY_OUT); |
1650 | if (pols[1]) { | 1639 | if (pols[1]) { |
1651 | if (IS_ERR(pols[1])) { | 1640 | if (IS_ERR(pols[1])) { |
1652 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLERROR); | 1641 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLERROR); |
1653 | err = PTR_ERR(pols[1]); | 1642 | err = PTR_ERR(pols[1]); |
1654 | goto error; | 1643 | goto error; |
1655 | } | 1644 | } |
1656 | if (pols[1]->action == XFRM_POLICY_BLOCK) { | 1645 | if (pols[1]->action == XFRM_POLICY_BLOCK) { |
1657 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLBLOCK); | 1646 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLBLOCK); |
1658 | err = -EPERM; | 1647 | err = -EPERM; |
1659 | goto error; | 1648 | goto error; |
1660 | } | 1649 | } |
@@ -1681,27 +1670,27 @@ restart: | |||
1681 | 1670 | ||
1682 | if (unlikely(nx<0)) { | 1671 | if (unlikely(nx<0)) { |
1683 | err = nx; | 1672 | err = nx; |
1684 | if (err == -EAGAIN && sysctl_xfrm_larval_drop) { | 1673 | if (err == -EAGAIN && net->xfrm.sysctl_larval_drop) { |
1685 | /* EREMOTE tells the caller to generate | 1674 | /* EREMOTE tells the caller to generate |
1686 | * a one-shot blackhole route. | 1675 | * a one-shot blackhole route. |
1687 | */ | 1676 | */ |
1688 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTNOSTATES); | 1677 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES); |
1689 | xfrm_pol_put(policy); | 1678 | xfrm_pol_put(policy); |
1690 | return -EREMOTE; | 1679 | return -EREMOTE; |
1691 | } | 1680 | } |
1692 | if (err == -EAGAIN && (flags & XFRM_LOOKUP_WAIT)) { | 1681 | if (err == -EAGAIN && (flags & XFRM_LOOKUP_WAIT)) { |
1693 | DECLARE_WAITQUEUE(wait, current); | 1682 | DECLARE_WAITQUEUE(wait, current); |
1694 | 1683 | ||
1695 | add_wait_queue(&km_waitq, &wait); | 1684 | add_wait_queue(&net->xfrm.km_waitq, &wait); |
1696 | set_current_state(TASK_INTERRUPTIBLE); | 1685 | set_current_state(TASK_INTERRUPTIBLE); |
1697 | schedule(); | 1686 | schedule(); |
1698 | set_current_state(TASK_RUNNING); | 1687 | set_current_state(TASK_RUNNING); |
1699 | remove_wait_queue(&km_waitq, &wait); | 1688 | remove_wait_queue(&net->xfrm.km_waitq, &wait); |
1700 | 1689 | ||
1701 | nx = xfrm_tmpl_resolve(pols, npols, fl, xfrm, family); | 1690 | nx = xfrm_tmpl_resolve(pols, npols, fl, xfrm, family); |
1702 | 1691 | ||
1703 | if (nx == -EAGAIN && signal_pending(current)) { | 1692 | if (nx == -EAGAIN && signal_pending(current)) { |
1704 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTNOSTATES); | 1693 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES); |
1705 | err = -ERESTART; | 1694 | err = -ERESTART; |
1706 | goto error; | 1695 | goto error; |
1707 | } | 1696 | } |
@@ -1713,7 +1702,7 @@ restart: | |||
1713 | err = nx; | 1702 | err = nx; |
1714 | } | 1703 | } |
1715 | if (err < 0) { | 1704 | if (err < 0) { |
1716 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTNOSTATES); | 1705 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES); |
1717 | goto error; | 1706 | goto error; |
1718 | } | 1707 | } |
1719 | } | 1708 | } |
@@ -1726,7 +1715,7 @@ restart: | |||
1726 | dst = xfrm_bundle_create(policy, xfrm, nx, fl, dst_orig); | 1715 | dst = xfrm_bundle_create(policy, xfrm, nx, fl, dst_orig); |
1727 | err = PTR_ERR(dst); | 1716 | err = PTR_ERR(dst); |
1728 | if (IS_ERR(dst)) { | 1717 | if (IS_ERR(dst)) { |
1729 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTBUNDLEGENERROR); | 1718 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLEGENERROR); |
1730 | goto error; | 1719 | goto error; |
1731 | } | 1720 | } |
1732 | 1721 | ||
@@ -1747,9 +1736,9 @@ restart: | |||
1747 | dst_free(dst); | 1736 | dst_free(dst); |
1748 | 1737 | ||
1749 | if (pol_dead) | 1738 | if (pol_dead) |
1750 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTPOLDEAD); | 1739 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLDEAD); |
1751 | else | 1740 | else |
1752 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTBUNDLECHECKERROR); | 1741 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLECHECKERROR); |
1753 | err = -EHOSTUNREACH; | 1742 | err = -EHOSTUNREACH; |
1754 | goto error; | 1743 | goto error; |
1755 | } | 1744 | } |
@@ -1761,7 +1750,7 @@ restart: | |||
1761 | if (unlikely(err)) { | 1750 | if (unlikely(err)) { |
1762 | write_unlock_bh(&policy->lock); | 1751 | write_unlock_bh(&policy->lock); |
1763 | dst_free(dst); | 1752 | dst_free(dst); |
1764 | XFRM_INC_STATS(LINUX_MIB_XFRMOUTBUNDLECHECKERROR); | 1753 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLECHECKERROR); |
1765 | goto error; | 1754 | goto error; |
1766 | } | 1755 | } |
1767 | 1756 | ||
@@ -1790,10 +1779,10 @@ nopol: | |||
1790 | } | 1779 | } |
1791 | EXPORT_SYMBOL(__xfrm_lookup); | 1780 | EXPORT_SYMBOL(__xfrm_lookup); |
1792 | 1781 | ||
1793 | int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, | 1782 | int xfrm_lookup(struct net *net, struct dst_entry **dst_p, struct flowi *fl, |
1794 | struct sock *sk, int flags) | 1783 | struct sock *sk, int flags) |
1795 | { | 1784 | { |
1796 | int err = __xfrm_lookup(dst_p, fl, sk, flags); | 1785 | int err = __xfrm_lookup(net, dst_p, fl, sk, flags); |
1797 | 1786 | ||
1798 | if (err == -EREMOTE) { | 1787 | if (err == -EREMOTE) { |
1799 | dst_release(*dst_p); | 1788 | dst_release(*dst_p); |
@@ -1901,6 +1890,7 @@ static inline int secpath_has_nontransport(struct sec_path *sp, int k, int *idxp | |||
1901 | int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | 1890 | int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, |
1902 | unsigned short family) | 1891 | unsigned short family) |
1903 | { | 1892 | { |
1893 | struct net *net = dev_net(skb->dev); | ||
1904 | struct xfrm_policy *pol; | 1894 | struct xfrm_policy *pol; |
1905 | struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX]; | 1895 | struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX]; |
1906 | int npols = 0; | 1896 | int npols = 0; |
@@ -1916,7 +1906,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
1916 | fl_dir = policy_to_flow_dir(dir); | 1906 | fl_dir = policy_to_flow_dir(dir); |
1917 | 1907 | ||
1918 | if (__xfrm_decode_session(skb, &fl, family, reverse) < 0) { | 1908 | if (__xfrm_decode_session(skb, &fl, family, reverse) < 0) { |
1919 | XFRM_INC_STATS(LINUX_MIB_XFRMINHDRERROR); | 1909 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINHDRERROR); |
1920 | return 0; | 1910 | return 0; |
1921 | } | 1911 | } |
1922 | 1912 | ||
@@ -1929,7 +1919,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
1929 | for (i=skb->sp->len-1; i>=0; i--) { | 1919 | for (i=skb->sp->len-1; i>=0; i--) { |
1930 | struct xfrm_state *x = skb->sp->xvec[i]; | 1920 | struct xfrm_state *x = skb->sp->xvec[i]; |
1931 | if (!xfrm_selector_match(&x->sel, &fl, family)) { | 1921 | if (!xfrm_selector_match(&x->sel, &fl, family)) { |
1932 | XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEMISMATCH); | 1922 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEMISMATCH); |
1933 | return 0; | 1923 | return 0; |
1934 | } | 1924 | } |
1935 | } | 1925 | } |
@@ -1939,24 +1929,24 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
1939 | if (sk && sk->sk_policy[dir]) { | 1929 | if (sk && sk->sk_policy[dir]) { |
1940 | pol = xfrm_sk_policy_lookup(sk, dir, &fl); | 1930 | pol = xfrm_sk_policy_lookup(sk, dir, &fl); |
1941 | if (IS_ERR(pol)) { | 1931 | if (IS_ERR(pol)) { |
1942 | XFRM_INC_STATS(LINUX_MIB_XFRMINPOLERROR); | 1932 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLERROR); |
1943 | return 0; | 1933 | return 0; |
1944 | } | 1934 | } |
1945 | } | 1935 | } |
1946 | 1936 | ||
1947 | if (!pol) | 1937 | if (!pol) |
1948 | pol = flow_cache_lookup(&fl, family, fl_dir, | 1938 | pol = flow_cache_lookup(net, &fl, family, fl_dir, |
1949 | xfrm_policy_lookup); | 1939 | xfrm_policy_lookup); |
1950 | 1940 | ||
1951 | if (IS_ERR(pol)) { | 1941 | if (IS_ERR(pol)) { |
1952 | XFRM_INC_STATS(LINUX_MIB_XFRMINPOLERROR); | 1942 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLERROR); |
1953 | return 0; | 1943 | return 0; |
1954 | } | 1944 | } |
1955 | 1945 | ||
1956 | if (!pol) { | 1946 | if (!pol) { |
1957 | if (skb->sp && secpath_has_nontransport(skb->sp, 0, &xerr_idx)) { | 1947 | if (skb->sp && secpath_has_nontransport(skb->sp, 0, &xerr_idx)) { |
1958 | xfrm_secpath_reject(xerr_idx, skb, &fl); | 1948 | xfrm_secpath_reject(xerr_idx, skb, &fl); |
1959 | XFRM_INC_STATS(LINUX_MIB_XFRMINNOPOLS); | 1949 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOPOLS); |
1960 | return 0; | 1950 | return 0; |
1961 | } | 1951 | } |
1962 | return 1; | 1952 | return 1; |
@@ -1968,12 +1958,12 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
1968 | npols ++; | 1958 | npols ++; |
1969 | #ifdef CONFIG_XFRM_SUB_POLICY | 1959 | #ifdef CONFIG_XFRM_SUB_POLICY |
1970 | if (pols[0]->type != XFRM_POLICY_TYPE_MAIN) { | 1960 | if (pols[0]->type != XFRM_POLICY_TYPE_MAIN) { |
1971 | pols[1] = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_MAIN, | 1961 | pols[1] = xfrm_policy_lookup_bytype(net, XFRM_POLICY_TYPE_MAIN, |
1972 | &fl, family, | 1962 | &fl, family, |
1973 | XFRM_POLICY_IN); | 1963 | XFRM_POLICY_IN); |
1974 | if (pols[1]) { | 1964 | if (pols[1]) { |
1975 | if (IS_ERR(pols[1])) { | 1965 | if (IS_ERR(pols[1])) { |
1976 | XFRM_INC_STATS(LINUX_MIB_XFRMINPOLERROR); | 1966 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLERROR); |
1977 | return 0; | 1967 | return 0; |
1978 | } | 1968 | } |
1979 | pols[1]->curlft.use_time = get_seconds(); | 1969 | pols[1]->curlft.use_time = get_seconds(); |
@@ -1997,11 +1987,11 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
1997 | for (pi = 0; pi < npols; pi++) { | 1987 | for (pi = 0; pi < npols; pi++) { |
1998 | if (pols[pi] != pol && | 1988 | if (pols[pi] != pol && |
1999 | pols[pi]->action != XFRM_POLICY_ALLOW) { | 1989 | pols[pi]->action != XFRM_POLICY_ALLOW) { |
2000 | XFRM_INC_STATS(LINUX_MIB_XFRMINPOLBLOCK); | 1990 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLBLOCK); |
2001 | goto reject; | 1991 | goto reject; |
2002 | } | 1992 | } |
2003 | if (ti + pols[pi]->xfrm_nr >= XFRM_MAX_DEPTH) { | 1993 | if (ti + pols[pi]->xfrm_nr >= XFRM_MAX_DEPTH) { |
2004 | XFRM_INC_STATS(LINUX_MIB_XFRMINBUFFERERROR); | 1994 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINBUFFERERROR); |
2005 | goto reject_error; | 1995 | goto reject_error; |
2006 | } | 1996 | } |
2007 | for (i = 0; i < pols[pi]->xfrm_nr; i++) | 1997 | for (i = 0; i < pols[pi]->xfrm_nr; i++) |
@@ -2025,20 +2015,20 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, | |||
2025 | if (k < -1) | 2015 | if (k < -1) |
2026 | /* "-2 - errored_index" returned */ | 2016 | /* "-2 - errored_index" returned */ |
2027 | xerr_idx = -(2+k); | 2017 | xerr_idx = -(2+k); |
2028 | XFRM_INC_STATS(LINUX_MIB_XFRMINTMPLMISMATCH); | 2018 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINTMPLMISMATCH); |
2029 | goto reject; | 2019 | goto reject; |
2030 | } | 2020 | } |
2031 | } | 2021 | } |
2032 | 2022 | ||
2033 | if (secpath_has_nontransport(sp, k, &xerr_idx)) { | 2023 | if (secpath_has_nontransport(sp, k, &xerr_idx)) { |
2034 | XFRM_INC_STATS(LINUX_MIB_XFRMINTMPLMISMATCH); | 2024 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINTMPLMISMATCH); |
2035 | goto reject; | 2025 | goto reject; |
2036 | } | 2026 | } |
2037 | 2027 | ||
2038 | xfrm_pols_put(pols, npols); | 2028 | xfrm_pols_put(pols, npols); |
2039 | return 1; | 2029 | return 1; |
2040 | } | 2030 | } |
2041 | XFRM_INC_STATS(LINUX_MIB_XFRMINPOLBLOCK); | 2031 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLBLOCK); |
2042 | 2032 | ||
2043 | reject: | 2033 | reject: |
2044 | xfrm_secpath_reject(xerr_idx, skb, &fl); | 2034 | xfrm_secpath_reject(xerr_idx, skb, &fl); |
@@ -2050,15 +2040,16 @@ EXPORT_SYMBOL(__xfrm_policy_check); | |||
2050 | 2040 | ||
2051 | int __xfrm_route_forward(struct sk_buff *skb, unsigned short family) | 2041 | int __xfrm_route_forward(struct sk_buff *skb, unsigned short family) |
2052 | { | 2042 | { |
2043 | struct net *net = dev_net(skb->dev); | ||
2053 | struct flowi fl; | 2044 | struct flowi fl; |
2054 | 2045 | ||
2055 | if (xfrm_decode_session(skb, &fl, family) < 0) { | 2046 | if (xfrm_decode_session(skb, &fl, family) < 0) { |
2056 | /* XXX: we should have something like FWDHDRERROR here. */ | 2047 | /* XXX: we should have something like FWDHDRERROR here. */ |
2057 | XFRM_INC_STATS(LINUX_MIB_XFRMINHDRERROR); | 2048 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINHDRERROR); |
2058 | return 0; | 2049 | return 0; |
2059 | } | 2050 | } |
2060 | 2051 | ||
2061 | return xfrm_lookup(&skb->dst, &fl, NULL, 0) == 0; | 2052 | return xfrm_lookup(net, &skb->dst, &fl, NULL, 0) == 0; |
2062 | } | 2053 | } |
2063 | EXPORT_SYMBOL(__xfrm_route_forward); | 2054 | EXPORT_SYMBOL(__xfrm_route_forward); |
2064 | 2055 | ||
@@ -2142,7 +2133,7 @@ static void prune_one_bundle(struct xfrm_policy *pol, int (*func)(struct dst_ent | |||
2142 | write_unlock(&pol->lock); | 2133 | write_unlock(&pol->lock); |
2143 | } | 2134 | } |
2144 | 2135 | ||
2145 | static void xfrm_prune_bundles(int (*func)(struct dst_entry *)) | 2136 | static void xfrm_prune_bundles(struct net *net, int (*func)(struct dst_entry *)) |
2146 | { | 2137 | { |
2147 | struct dst_entry *gc_list = NULL; | 2138 | struct dst_entry *gc_list = NULL; |
2148 | int dir; | 2139 | int dir; |
@@ -2155,11 +2146,11 @@ static void xfrm_prune_bundles(int (*func)(struct dst_entry *)) | |||
2155 | int i; | 2146 | int i; |
2156 | 2147 | ||
2157 | hlist_for_each_entry(pol, entry, | 2148 | hlist_for_each_entry(pol, entry, |
2158 | &xfrm_policy_inexact[dir], bydst) | 2149 | &net->xfrm.policy_inexact[dir], bydst) |
2159 | prune_one_bundle(pol, func, &gc_list); | 2150 | prune_one_bundle(pol, func, &gc_list); |
2160 | 2151 | ||
2161 | table = xfrm_policy_bydst[dir].table; | 2152 | table = net->xfrm.policy_bydst[dir].table; |
2162 | for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) { | 2153 | for (i = net->xfrm.policy_bydst[dir].hmask; i >= 0; i--) { |
2163 | hlist_for_each_entry(pol, entry, table + i, bydst) | 2154 | hlist_for_each_entry(pol, entry, table + i, bydst) |
2164 | prune_one_bundle(pol, func, &gc_list); | 2155 | prune_one_bundle(pol, func, &gc_list); |
2165 | } | 2156 | } |
@@ -2178,14 +2169,14 @@ static int unused_bundle(struct dst_entry *dst) | |||
2178 | return !atomic_read(&dst->__refcnt); | 2169 | return !atomic_read(&dst->__refcnt); |
2179 | } | 2170 | } |
2180 | 2171 | ||
2181 | static void __xfrm_garbage_collect(void) | 2172 | static void __xfrm_garbage_collect(struct net *net) |
2182 | { | 2173 | { |
2183 | xfrm_prune_bundles(unused_bundle); | 2174 | xfrm_prune_bundles(net, unused_bundle); |
2184 | } | 2175 | } |
2185 | 2176 | ||
2186 | static int xfrm_flush_bundles(void) | 2177 | static int xfrm_flush_bundles(struct net *net) |
2187 | { | 2178 | { |
2188 | xfrm_prune_bundles(stale_bundle); | 2179 | xfrm_prune_bundles(net, stale_bundle); |
2189 | return 0; | 2180 | return 0; |
2190 | } | 2181 | } |
2191 | 2182 | ||
@@ -2371,38 +2362,54 @@ static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void | |||
2371 | { | 2362 | { |
2372 | struct net_device *dev = ptr; | 2363 | struct net_device *dev = ptr; |
2373 | 2364 | ||
2374 | if (!net_eq(dev_net(dev), &init_net)) | ||
2375 | return NOTIFY_DONE; | ||
2376 | |||
2377 | switch (event) { | 2365 | switch (event) { |
2378 | case NETDEV_DOWN: | 2366 | case NETDEV_DOWN: |
2379 | xfrm_flush_bundles(); | 2367 | xfrm_flush_bundles(dev_net(dev)); |
2380 | } | 2368 | } |
2381 | return NOTIFY_DONE; | 2369 | return NOTIFY_DONE; |
2382 | } | 2370 | } |
2383 | 2371 | ||
2384 | static struct notifier_block xfrm_dev_notifier = { | 2372 | static struct notifier_block xfrm_dev_notifier = { |
2385 | xfrm_dev_event, | 2373 | .notifier_call = xfrm_dev_event, |
2386 | NULL, | ||
2387 | 0 | ||
2388 | }; | 2374 | }; |
2389 | 2375 | ||
2390 | #ifdef CONFIG_XFRM_STATISTICS | 2376 | #ifdef CONFIG_XFRM_STATISTICS |
2391 | static int __init xfrm_statistics_init(void) | 2377 | static int __net_init xfrm_statistics_init(struct net *net) |
2392 | { | 2378 | { |
2393 | if (snmp_mib_init((void **)xfrm_statistics, | 2379 | int rv; |
2380 | |||
2381 | if (snmp_mib_init((void **)net->mib.xfrm_statistics, | ||
2394 | sizeof(struct linux_xfrm_mib)) < 0) | 2382 | sizeof(struct linux_xfrm_mib)) < 0) |
2395 | return -ENOMEM; | 2383 | return -ENOMEM; |
2384 | rv = xfrm_proc_init(net); | ||
2385 | if (rv < 0) | ||
2386 | snmp_mib_free((void **)net->mib.xfrm_statistics); | ||
2387 | return rv; | ||
2388 | } | ||
2389 | |||
2390 | static void xfrm_statistics_fini(struct net *net) | ||
2391 | { | ||
2392 | xfrm_proc_fini(net); | ||
2393 | snmp_mib_free((void **)net->mib.xfrm_statistics); | ||
2394 | } | ||
2395 | #else | ||
2396 | static int __net_init xfrm_statistics_init(struct net *net) | ||
2397 | { | ||
2396 | return 0; | 2398 | return 0; |
2397 | } | 2399 | } |
2400 | |||
2401 | static void xfrm_statistics_fini(struct net *net) | ||
2402 | { | ||
2403 | } | ||
2398 | #endif | 2404 | #endif |
2399 | 2405 | ||
2400 | static void __init xfrm_policy_init(void) | 2406 | static int __net_init xfrm_policy_init(struct net *net) |
2401 | { | 2407 | { |
2402 | unsigned int hmask, sz; | 2408 | unsigned int hmask, sz; |
2403 | int dir; | 2409 | int dir; |
2404 | 2410 | ||
2405 | xfrm_dst_cache = kmem_cache_create("xfrm_dst_cache", | 2411 | if (net_eq(net, &init_net)) |
2412 | xfrm_dst_cache = kmem_cache_create("xfrm_dst_cache", | ||
2406 | sizeof(struct xfrm_dst), | 2413 | sizeof(struct xfrm_dst), |
2407 | 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, | 2414 | 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, |
2408 | NULL); | 2415 | NULL); |
@@ -2410,39 +2417,124 @@ static void __init xfrm_policy_init(void) | |||
2410 | hmask = 8 - 1; | 2417 | hmask = 8 - 1; |
2411 | sz = (hmask+1) * sizeof(struct hlist_head); | 2418 | sz = (hmask+1) * sizeof(struct hlist_head); |
2412 | 2419 | ||
2413 | xfrm_policy_byidx = xfrm_hash_alloc(sz); | 2420 | net->xfrm.policy_byidx = xfrm_hash_alloc(sz); |
2414 | xfrm_idx_hmask = hmask; | 2421 | if (!net->xfrm.policy_byidx) |
2415 | if (!xfrm_policy_byidx) | 2422 | goto out_byidx; |
2416 | panic("XFRM: failed to allocate byidx hash\n"); | 2423 | net->xfrm.policy_idx_hmask = hmask; |
2417 | 2424 | ||
2418 | for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) { | 2425 | for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) { |
2419 | struct xfrm_policy_hash *htab; | 2426 | struct xfrm_policy_hash *htab; |
2420 | 2427 | ||
2421 | INIT_HLIST_HEAD(&xfrm_policy_inexact[dir]); | 2428 | net->xfrm.policy_count[dir] = 0; |
2429 | INIT_HLIST_HEAD(&net->xfrm.policy_inexact[dir]); | ||
2422 | 2430 | ||
2423 | htab = &xfrm_policy_bydst[dir]; | 2431 | htab = &net->xfrm.policy_bydst[dir]; |
2424 | htab->table = xfrm_hash_alloc(sz); | 2432 | htab->table = xfrm_hash_alloc(sz); |
2425 | htab->hmask = hmask; | ||
2426 | if (!htab->table) | 2433 | if (!htab->table) |
2427 | panic("XFRM: failed to allocate bydst hash\n"); | 2434 | goto out_bydst; |
2435 | htab->hmask = hmask; | ||
2428 | } | 2436 | } |
2429 | 2437 | ||
2430 | INIT_LIST_HEAD(&xfrm_policy_all); | 2438 | INIT_LIST_HEAD(&net->xfrm.policy_all); |
2431 | INIT_WORK(&xfrm_policy_gc_work, xfrm_policy_gc_task); | 2439 | INIT_WORK(&net->xfrm.policy_hash_work, xfrm_hash_resize); |
2432 | register_netdevice_notifier(&xfrm_dev_notifier); | 2440 | if (net_eq(net, &init_net)) |
2441 | register_netdevice_notifier(&xfrm_dev_notifier); | ||
2442 | return 0; | ||
2443 | |||
2444 | out_bydst: | ||
2445 | for (dir--; dir >= 0; dir--) { | ||
2446 | struct xfrm_policy_hash *htab; | ||
2447 | |||
2448 | htab = &net->xfrm.policy_bydst[dir]; | ||
2449 | xfrm_hash_free(htab->table, sz); | ||
2450 | } | ||
2451 | xfrm_hash_free(net->xfrm.policy_byidx, sz); | ||
2452 | out_byidx: | ||
2453 | return -ENOMEM; | ||
2433 | } | 2454 | } |
2434 | 2455 | ||
2435 | void __init xfrm_init(void) | 2456 | static void xfrm_policy_fini(struct net *net) |
2436 | { | 2457 | { |
2437 | #ifdef CONFIG_XFRM_STATISTICS | 2458 | struct xfrm_audit audit_info; |
2438 | xfrm_statistics_init(); | 2459 | unsigned int sz; |
2460 | int dir; | ||
2461 | |||
2462 | flush_work(&net->xfrm.policy_hash_work); | ||
2463 | #ifdef CONFIG_XFRM_SUB_POLICY | ||
2464 | audit_info.loginuid = -1; | ||
2465 | audit_info.sessionid = -1; | ||
2466 | audit_info.secid = 0; | ||
2467 | xfrm_policy_flush(net, XFRM_POLICY_TYPE_SUB, &audit_info); | ||
2439 | #endif | 2468 | #endif |
2440 | xfrm_state_init(); | 2469 | audit_info.loginuid = -1; |
2441 | xfrm_policy_init(); | 2470 | audit_info.sessionid = -1; |
2471 | audit_info.secid = 0; | ||
2472 | xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, &audit_info); | ||
2473 | flush_work(&xfrm_policy_gc_work); | ||
2474 | |||
2475 | WARN_ON(!list_empty(&net->xfrm.policy_all)); | ||
2476 | |||
2477 | for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) { | ||
2478 | struct xfrm_policy_hash *htab; | ||
2479 | |||
2480 | WARN_ON(!hlist_empty(&net->xfrm.policy_inexact[dir])); | ||
2481 | |||
2482 | htab = &net->xfrm.policy_bydst[dir]; | ||
2483 | sz = (htab->hmask + 1); | ||
2484 | WARN_ON(!hlist_empty(htab->table)); | ||
2485 | xfrm_hash_free(htab->table, sz); | ||
2486 | } | ||
2487 | |||
2488 | sz = (net->xfrm.policy_idx_hmask + 1) * sizeof(struct hlist_head); | ||
2489 | WARN_ON(!hlist_empty(net->xfrm.policy_byidx)); | ||
2490 | xfrm_hash_free(net->xfrm.policy_byidx, sz); | ||
2491 | } | ||
2492 | |||
2493 | static int __net_init xfrm_net_init(struct net *net) | ||
2494 | { | ||
2495 | int rv; | ||
2496 | |||
2497 | rv = xfrm_statistics_init(net); | ||
2498 | if (rv < 0) | ||
2499 | goto out_statistics; | ||
2500 | rv = xfrm_state_init(net); | ||
2501 | if (rv < 0) | ||
2502 | goto out_state; | ||
2503 | rv = xfrm_policy_init(net); | ||
2504 | if (rv < 0) | ||
2505 | goto out_policy; | ||
2506 | rv = xfrm_sysctl_init(net); | ||
2507 | if (rv < 0) | ||
2508 | goto out_sysctl; | ||
2509 | return 0; | ||
2510 | |||
2511 | out_sysctl: | ||
2512 | xfrm_policy_fini(net); | ||
2513 | out_policy: | ||
2514 | xfrm_state_fini(net); | ||
2515 | out_state: | ||
2516 | xfrm_statistics_fini(net); | ||
2517 | out_statistics: | ||
2518 | return rv; | ||
2519 | } | ||
2520 | |||
2521 | static void __net_exit xfrm_net_exit(struct net *net) | ||
2522 | { | ||
2523 | xfrm_sysctl_fini(net); | ||
2524 | xfrm_policy_fini(net); | ||
2525 | xfrm_state_fini(net); | ||
2526 | xfrm_statistics_fini(net); | ||
2527 | } | ||
2528 | |||
2529 | static struct pernet_operations __net_initdata xfrm_net_ops = { | ||
2530 | .init = xfrm_net_init, | ||
2531 | .exit = xfrm_net_exit, | ||
2532 | }; | ||
2533 | |||
2534 | void __init xfrm_init(void) | ||
2535 | { | ||
2536 | register_pernet_subsys(&xfrm_net_ops); | ||
2442 | xfrm_input_init(); | 2537 | xfrm_input_init(); |
2443 | #ifdef CONFIG_XFRM_STATISTICS | ||
2444 | xfrm_proc_init(); | ||
2445 | #endif | ||
2446 | } | 2538 | } |
2447 | 2539 | ||
2448 | #ifdef CONFIG_AUDITSYSCALL | 2540 | #ifdef CONFIG_AUDITSYSCALL |
@@ -2458,25 +2550,21 @@ static void xfrm_audit_common_policyinfo(struct xfrm_policy *xp, | |||
2458 | 2550 | ||
2459 | switch(sel->family) { | 2551 | switch(sel->family) { |
2460 | case AF_INET: | 2552 | case AF_INET: |
2461 | audit_log_format(audit_buf, " src=" NIPQUAD_FMT, | 2553 | audit_log_format(audit_buf, " src=%pI4", &sel->saddr.a4); |
2462 | NIPQUAD(sel->saddr.a4)); | ||
2463 | if (sel->prefixlen_s != 32) | 2554 | if (sel->prefixlen_s != 32) |
2464 | audit_log_format(audit_buf, " src_prefixlen=%d", | 2555 | audit_log_format(audit_buf, " src_prefixlen=%d", |
2465 | sel->prefixlen_s); | 2556 | sel->prefixlen_s); |
2466 | audit_log_format(audit_buf, " dst=" NIPQUAD_FMT, | 2557 | audit_log_format(audit_buf, " dst=%pI4", &sel->daddr.a4); |
2467 | NIPQUAD(sel->daddr.a4)); | ||
2468 | if (sel->prefixlen_d != 32) | 2558 | if (sel->prefixlen_d != 32) |
2469 | audit_log_format(audit_buf, " dst_prefixlen=%d", | 2559 | audit_log_format(audit_buf, " dst_prefixlen=%d", |
2470 | sel->prefixlen_d); | 2560 | sel->prefixlen_d); |
2471 | break; | 2561 | break; |
2472 | case AF_INET6: | 2562 | case AF_INET6: |
2473 | audit_log_format(audit_buf, " src=" NIP6_FMT, | 2563 | audit_log_format(audit_buf, " src=%pI6", sel->saddr.a6); |
2474 | NIP6(*(struct in6_addr *)sel->saddr.a6)); | ||
2475 | if (sel->prefixlen_s != 128) | 2564 | if (sel->prefixlen_s != 128) |
2476 | audit_log_format(audit_buf, " src_prefixlen=%d", | 2565 | audit_log_format(audit_buf, " src_prefixlen=%d", |
2477 | sel->prefixlen_s); | 2566 | sel->prefixlen_s); |
2478 | audit_log_format(audit_buf, " dst=" NIP6_FMT, | 2567 | audit_log_format(audit_buf, " dst=%pI6", sel->daddr.a6); |
2479 | NIP6(*(struct in6_addr *)sel->daddr.a6)); | ||
2480 | if (sel->prefixlen_d != 128) | 2568 | if (sel->prefixlen_d != 128) |
2481 | audit_log_format(audit_buf, " dst_prefixlen=%d", | 2569 | audit_log_format(audit_buf, " dst_prefixlen=%d", |
2482 | sel->prefixlen_d); | 2570 | sel->prefixlen_d); |
@@ -2546,7 +2634,7 @@ static struct xfrm_policy * xfrm_migrate_policy_find(struct xfrm_selector *sel, | |||
2546 | u32 priority = ~0U; | 2634 | u32 priority = ~0U; |
2547 | 2635 | ||
2548 | read_lock_bh(&xfrm_policy_lock); | 2636 | read_lock_bh(&xfrm_policy_lock); |
2549 | chain = policy_hash_direct(&sel->daddr, &sel->saddr, sel->family, dir); | 2637 | chain = policy_hash_direct(&init_net, &sel->daddr, &sel->saddr, sel->family, dir); |
2550 | hlist_for_each_entry(pol, entry, chain, bydst) { | 2638 | hlist_for_each_entry(pol, entry, chain, bydst) { |
2551 | if (xfrm_migrate_selector_match(sel, &pol->selector) && | 2639 | if (xfrm_migrate_selector_match(sel, &pol->selector) && |
2552 | pol->type == type) { | 2640 | pol->type == type) { |
@@ -2555,7 +2643,7 @@ static struct xfrm_policy * xfrm_migrate_policy_find(struct xfrm_selector *sel, | |||
2555 | break; | 2643 | break; |
2556 | } | 2644 | } |
2557 | } | 2645 | } |
2558 | chain = &xfrm_policy_inexact[dir]; | 2646 | chain = &init_net.xfrm.policy_inexact[dir]; |
2559 | hlist_for_each_entry(pol, entry, chain, bydst) { | 2647 | hlist_for_each_entry(pol, entry, chain, bydst) { |
2560 | if (xfrm_migrate_selector_match(sel, &pol->selector) && | 2648 | if (xfrm_migrate_selector_match(sel, &pol->selector) && |
2561 | pol->type == type && | 2649 | pol->type == type && |
diff --git a/net/xfrm/xfrm_proc.c b/net/xfrm/xfrm_proc.c index 2b0db13f0cda..284eaef1dbf2 100644 --- a/net/xfrm/xfrm_proc.c +++ b/net/xfrm/xfrm_proc.c | |||
@@ -59,17 +59,18 @@ fold_field(void *mib[], int offt) | |||
59 | 59 | ||
60 | static int xfrm_statistics_seq_show(struct seq_file *seq, void *v) | 60 | static int xfrm_statistics_seq_show(struct seq_file *seq, void *v) |
61 | { | 61 | { |
62 | struct net *net = seq->private; | ||
62 | int i; | 63 | int i; |
63 | for (i=0; xfrm_mib_list[i].name; i++) | 64 | for (i=0; xfrm_mib_list[i].name; i++) |
64 | seq_printf(seq, "%-24s\t%lu\n", xfrm_mib_list[i].name, | 65 | seq_printf(seq, "%-24s\t%lu\n", xfrm_mib_list[i].name, |
65 | fold_field((void **)xfrm_statistics, | 66 | fold_field((void **)net->mib.xfrm_statistics, |
66 | xfrm_mib_list[i].entry)); | 67 | xfrm_mib_list[i].entry)); |
67 | return 0; | 68 | return 0; |
68 | } | 69 | } |
69 | 70 | ||
70 | static int xfrm_statistics_seq_open(struct inode *inode, struct file *file) | 71 | static int xfrm_statistics_seq_open(struct inode *inode, struct file *file) |
71 | { | 72 | { |
72 | return single_open(file, xfrm_statistics_seq_show, NULL); | 73 | return single_open_net(inode, file, xfrm_statistics_seq_show); |
73 | } | 74 | } |
74 | 75 | ||
75 | static struct file_operations xfrm_statistics_seq_fops = { | 76 | static struct file_operations xfrm_statistics_seq_fops = { |
@@ -77,21 +78,18 @@ static struct file_operations xfrm_statistics_seq_fops = { | |||
77 | .open = xfrm_statistics_seq_open, | 78 | .open = xfrm_statistics_seq_open, |
78 | .read = seq_read, | 79 | .read = seq_read, |
79 | .llseek = seq_lseek, | 80 | .llseek = seq_lseek, |
80 | .release = single_release, | 81 | .release = single_release_net, |
81 | }; | 82 | }; |
82 | 83 | ||
83 | int __init xfrm_proc_init(void) | 84 | int __net_init xfrm_proc_init(struct net *net) |
84 | { | 85 | { |
85 | int rc = 0; | 86 | if (!proc_net_fops_create(net, "xfrm_stat", S_IRUGO, |
86 | |||
87 | if (!proc_net_fops_create(&init_net, "xfrm_stat", S_IRUGO, | ||
88 | &xfrm_statistics_seq_fops)) | 87 | &xfrm_statistics_seq_fops)) |
89 | goto stat_fail; | 88 | return -ENOMEM; |
90 | 89 | return 0; | |
91 | out: | 90 | } |
92 | return rc; | ||
93 | 91 | ||
94 | stat_fail: | 92 | void xfrm_proc_fini(struct net *net) |
95 | rc = -ENOMEM; | 93 | { |
96 | goto out; | 94 | proc_net_remove(net, "xfrm_stat"); |
97 | } | 95 | } |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 508337f97249..2fd57f8f77c1 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -24,17 +24,6 @@ | |||
24 | 24 | ||
25 | #include "xfrm_hash.h" | 25 | #include "xfrm_hash.h" |
26 | 26 | ||
27 | struct sock *xfrm_nl; | ||
28 | EXPORT_SYMBOL(xfrm_nl); | ||
29 | |||
30 | u32 sysctl_xfrm_aevent_etime __read_mostly = XFRM_AE_ETIME; | ||
31 | EXPORT_SYMBOL(sysctl_xfrm_aevent_etime); | ||
32 | |||
33 | u32 sysctl_xfrm_aevent_rseqth __read_mostly = XFRM_AE_SEQT_SIZE; | ||
34 | EXPORT_SYMBOL(sysctl_xfrm_aevent_rseqth); | ||
35 | |||
36 | u32 sysctl_xfrm_acq_expires __read_mostly = 30; | ||
37 | |||
38 | /* Each xfrm_state may be linked to two tables: | 27 | /* Each xfrm_state may be linked to two tables: |
39 | 28 | ||
40 | 1. Hash table by (spi,daddr,ah/esp) to find SA by SPI. (input,ctl) | 29 | 1. Hash table by (spi,daddr,ah/esp) to find SA by SPI. (input,ctl) |
@@ -44,19 +33,7 @@ u32 sysctl_xfrm_acq_expires __read_mostly = 30; | |||
44 | 33 | ||
45 | static DEFINE_SPINLOCK(xfrm_state_lock); | 34 | static DEFINE_SPINLOCK(xfrm_state_lock); |
46 | 35 | ||
47 | /* Hash table to find appropriate SA towards given target (endpoint | ||
48 | * of tunnel or destination of transport mode) allowed by selector. | ||
49 | * | ||
50 | * Main use is finding SA after policy selected tunnel or transport mode. | ||
51 | * Also, it can be used by ah/esp icmp error handler to find offending SA. | ||
52 | */ | ||
53 | static LIST_HEAD(xfrm_state_all); | ||
54 | static struct hlist_head *xfrm_state_bydst __read_mostly; | ||
55 | static struct hlist_head *xfrm_state_bysrc __read_mostly; | ||
56 | static struct hlist_head *xfrm_state_byspi __read_mostly; | ||
57 | static unsigned int xfrm_state_hmask __read_mostly; | ||
58 | static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024; | 36 | static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024; |
59 | static unsigned int xfrm_state_num; | ||
60 | static unsigned int xfrm_state_genid; | 37 | static unsigned int xfrm_state_genid; |
61 | 38 | ||
62 | static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family); | 39 | static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family); |
@@ -69,25 +46,27 @@ static void xfrm_audit_state_replay(struct xfrm_state *x, | |||
69 | #define xfrm_audit_state_replay(x, s, sq) do { ; } while (0) | 46 | #define xfrm_audit_state_replay(x, s, sq) do { ; } while (0) |
70 | #endif /* CONFIG_AUDITSYSCALL */ | 47 | #endif /* CONFIG_AUDITSYSCALL */ |
71 | 48 | ||
72 | static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr, | 49 | static inline unsigned int xfrm_dst_hash(struct net *net, |
50 | xfrm_address_t *daddr, | ||
73 | xfrm_address_t *saddr, | 51 | xfrm_address_t *saddr, |
74 | u32 reqid, | 52 | u32 reqid, |
75 | unsigned short family) | 53 | unsigned short family) |
76 | { | 54 | { |
77 | return __xfrm_dst_hash(daddr, saddr, reqid, family, xfrm_state_hmask); | 55 | return __xfrm_dst_hash(daddr, saddr, reqid, family, net->xfrm.state_hmask); |
78 | } | 56 | } |
79 | 57 | ||
80 | static inline unsigned int xfrm_src_hash(xfrm_address_t *daddr, | 58 | static inline unsigned int xfrm_src_hash(struct net *net, |
59 | xfrm_address_t *daddr, | ||
81 | xfrm_address_t *saddr, | 60 | xfrm_address_t *saddr, |
82 | unsigned short family) | 61 | unsigned short family) |
83 | { | 62 | { |
84 | return __xfrm_src_hash(daddr, saddr, family, xfrm_state_hmask); | 63 | return __xfrm_src_hash(daddr, saddr, family, net->xfrm.state_hmask); |
85 | } | 64 | } |
86 | 65 | ||
87 | static inline unsigned int | 66 | static inline unsigned int |
88 | xfrm_spi_hash(xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family) | 67 | xfrm_spi_hash(struct net *net, xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family) |
89 | { | 68 | { |
90 | return __xfrm_spi_hash(daddr, spi, proto, family, xfrm_state_hmask); | 69 | return __xfrm_spi_hash(daddr, spi, proto, family, net->xfrm.state_hmask); |
91 | } | 70 | } |
92 | 71 | ||
93 | static void xfrm_hash_transfer(struct hlist_head *list, | 72 | static void xfrm_hash_transfer(struct hlist_head *list, |
@@ -121,16 +100,16 @@ static void xfrm_hash_transfer(struct hlist_head *list, | |||
121 | } | 100 | } |
122 | } | 101 | } |
123 | 102 | ||
124 | static unsigned long xfrm_hash_new_size(void) | 103 | static unsigned long xfrm_hash_new_size(unsigned int state_hmask) |
125 | { | 104 | { |
126 | return ((xfrm_state_hmask + 1) << 1) * | 105 | return ((state_hmask + 1) << 1) * sizeof(struct hlist_head); |
127 | sizeof(struct hlist_head); | ||
128 | } | 106 | } |
129 | 107 | ||
130 | static DEFINE_MUTEX(hash_resize_mutex); | 108 | static DEFINE_MUTEX(hash_resize_mutex); |
131 | 109 | ||
132 | static void xfrm_hash_resize(struct work_struct *__unused) | 110 | static void xfrm_hash_resize(struct work_struct *work) |
133 | { | 111 | { |
112 | struct net *net = container_of(work, struct net, xfrm.state_hash_work); | ||
134 | struct hlist_head *ndst, *nsrc, *nspi, *odst, *osrc, *ospi; | 113 | struct hlist_head *ndst, *nsrc, *nspi, *odst, *osrc, *ospi; |
135 | unsigned long nsize, osize; | 114 | unsigned long nsize, osize; |
136 | unsigned int nhashmask, ohashmask; | 115 | unsigned int nhashmask, ohashmask; |
@@ -138,7 +117,7 @@ static void xfrm_hash_resize(struct work_struct *__unused) | |||
138 | 117 | ||
139 | mutex_lock(&hash_resize_mutex); | 118 | mutex_lock(&hash_resize_mutex); |
140 | 119 | ||
141 | nsize = xfrm_hash_new_size(); | 120 | nsize = xfrm_hash_new_size(net->xfrm.state_hmask); |
142 | ndst = xfrm_hash_alloc(nsize); | 121 | ndst = xfrm_hash_alloc(nsize); |
143 | if (!ndst) | 122 | if (!ndst) |
144 | goto out_unlock; | 123 | goto out_unlock; |
@@ -157,19 +136,19 @@ static void xfrm_hash_resize(struct work_struct *__unused) | |||
157 | spin_lock_bh(&xfrm_state_lock); | 136 | spin_lock_bh(&xfrm_state_lock); |
158 | 137 | ||
159 | nhashmask = (nsize / sizeof(struct hlist_head)) - 1U; | 138 | nhashmask = (nsize / sizeof(struct hlist_head)) - 1U; |
160 | for (i = xfrm_state_hmask; i >= 0; i--) | 139 | for (i = net->xfrm.state_hmask; i >= 0; i--) |
161 | xfrm_hash_transfer(xfrm_state_bydst+i, ndst, nsrc, nspi, | 140 | xfrm_hash_transfer(net->xfrm.state_bydst+i, ndst, nsrc, nspi, |
162 | nhashmask); | 141 | nhashmask); |
163 | 142 | ||
164 | odst = xfrm_state_bydst; | 143 | odst = net->xfrm.state_bydst; |
165 | osrc = xfrm_state_bysrc; | 144 | osrc = net->xfrm.state_bysrc; |
166 | ospi = xfrm_state_byspi; | 145 | ospi = net->xfrm.state_byspi; |
167 | ohashmask = xfrm_state_hmask; | 146 | ohashmask = net->xfrm.state_hmask; |
168 | 147 | ||
169 | xfrm_state_bydst = ndst; | 148 | net->xfrm.state_bydst = ndst; |
170 | xfrm_state_bysrc = nsrc; | 149 | net->xfrm.state_bysrc = nsrc; |
171 | xfrm_state_byspi = nspi; | 150 | net->xfrm.state_byspi = nspi; |
172 | xfrm_state_hmask = nhashmask; | 151 | net->xfrm.state_hmask = nhashmask; |
173 | 152 | ||
174 | spin_unlock_bh(&xfrm_state_lock); | 153 | spin_unlock_bh(&xfrm_state_lock); |
175 | 154 | ||
@@ -182,16 +161,9 @@ out_unlock: | |||
182 | mutex_unlock(&hash_resize_mutex); | 161 | mutex_unlock(&hash_resize_mutex); |
183 | } | 162 | } |
184 | 163 | ||
185 | static DECLARE_WORK(xfrm_hash_work, xfrm_hash_resize); | ||
186 | |||
187 | DECLARE_WAIT_QUEUE_HEAD(km_waitq); | ||
188 | EXPORT_SYMBOL(km_waitq); | ||
189 | |||
190 | static DEFINE_RWLOCK(xfrm_state_afinfo_lock); | 164 | static DEFINE_RWLOCK(xfrm_state_afinfo_lock); |
191 | static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO]; | 165 | static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO]; |
192 | 166 | ||
193 | static struct work_struct xfrm_state_gc_work; | ||
194 | static HLIST_HEAD(xfrm_state_gc_list); | ||
195 | static DEFINE_SPINLOCK(xfrm_state_gc_lock); | 167 | static DEFINE_SPINLOCK(xfrm_state_gc_lock); |
196 | 168 | ||
197 | int __xfrm_state_delete(struct xfrm_state *x); | 169 | int __xfrm_state_delete(struct xfrm_state *x); |
@@ -401,20 +373,21 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x) | |||
401 | kfree(x); | 373 | kfree(x); |
402 | } | 374 | } |
403 | 375 | ||
404 | static void xfrm_state_gc_task(struct work_struct *data) | 376 | static void xfrm_state_gc_task(struct work_struct *work) |
405 | { | 377 | { |
378 | struct net *net = container_of(work, struct net, xfrm.state_gc_work); | ||
406 | struct xfrm_state *x; | 379 | struct xfrm_state *x; |
407 | struct hlist_node *entry, *tmp; | 380 | struct hlist_node *entry, *tmp; |
408 | struct hlist_head gc_list; | 381 | struct hlist_head gc_list; |
409 | 382 | ||
410 | spin_lock_bh(&xfrm_state_gc_lock); | 383 | spin_lock_bh(&xfrm_state_gc_lock); |
411 | hlist_move_list(&xfrm_state_gc_list, &gc_list); | 384 | hlist_move_list(&net->xfrm.state_gc_list, &gc_list); |
412 | spin_unlock_bh(&xfrm_state_gc_lock); | 385 | spin_unlock_bh(&xfrm_state_gc_lock); |
413 | 386 | ||
414 | hlist_for_each_entry_safe(x, entry, tmp, &gc_list, gclist) | 387 | hlist_for_each_entry_safe(x, entry, tmp, &gc_list, gclist) |
415 | xfrm_state_gc_destroy(x); | 388 | xfrm_state_gc_destroy(x); |
416 | 389 | ||
417 | wake_up(&km_waitq); | 390 | wake_up(&net->xfrm.km_waitq); |
418 | } | 391 | } |
419 | 392 | ||
420 | static inline unsigned long make_jiffies(long secs) | 393 | static inline unsigned long make_jiffies(long secs) |
@@ -428,6 +401,7 @@ static inline unsigned long make_jiffies(long secs) | |||
428 | static void xfrm_timer_handler(unsigned long data) | 401 | static void xfrm_timer_handler(unsigned long data) |
429 | { | 402 | { |
430 | struct xfrm_state *x = (struct xfrm_state*)data; | 403 | struct xfrm_state *x = (struct xfrm_state*)data; |
404 | struct net *net = xs_net(x); | ||
431 | unsigned long now = get_seconds(); | 405 | unsigned long now = get_seconds(); |
432 | long next = LONG_MAX; | 406 | long next = LONG_MAX; |
433 | int warn = 0; | 407 | int warn = 0; |
@@ -485,7 +459,7 @@ resched: | |||
485 | expired: | 459 | expired: |
486 | if (x->km.state == XFRM_STATE_ACQ && x->id.spi == 0) { | 460 | if (x->km.state == XFRM_STATE_ACQ && x->id.spi == 0) { |
487 | x->km.state = XFRM_STATE_EXPIRED; | 461 | x->km.state = XFRM_STATE_EXPIRED; |
488 | wake_up(&km_waitq); | 462 | wake_up(&net->xfrm.km_waitq); |
489 | next = 2; | 463 | next = 2; |
490 | goto resched; | 464 | goto resched; |
491 | } | 465 | } |
@@ -504,13 +478,14 @@ out: | |||
504 | 478 | ||
505 | static void xfrm_replay_timer_handler(unsigned long data); | 479 | static void xfrm_replay_timer_handler(unsigned long data); |
506 | 480 | ||
507 | struct xfrm_state *xfrm_state_alloc(void) | 481 | struct xfrm_state *xfrm_state_alloc(struct net *net) |
508 | { | 482 | { |
509 | struct xfrm_state *x; | 483 | struct xfrm_state *x; |
510 | 484 | ||
511 | x = kzalloc(sizeof(struct xfrm_state), GFP_ATOMIC); | 485 | x = kzalloc(sizeof(struct xfrm_state), GFP_ATOMIC); |
512 | 486 | ||
513 | if (x) { | 487 | if (x) { |
488 | write_pnet(&x->xs_net, net); | ||
514 | atomic_set(&x->refcnt, 1); | 489 | atomic_set(&x->refcnt, 1); |
515 | atomic_set(&x->tunnel_users, 0); | 490 | atomic_set(&x->tunnel_users, 0); |
516 | INIT_LIST_HEAD(&x->km.all); | 491 | INIT_LIST_HEAD(&x->km.all); |
@@ -537,17 +512,20 @@ EXPORT_SYMBOL(xfrm_state_alloc); | |||
537 | 512 | ||
538 | void __xfrm_state_destroy(struct xfrm_state *x) | 513 | void __xfrm_state_destroy(struct xfrm_state *x) |
539 | { | 514 | { |
515 | struct net *net = xs_net(x); | ||
516 | |||
540 | WARN_ON(x->km.state != XFRM_STATE_DEAD); | 517 | WARN_ON(x->km.state != XFRM_STATE_DEAD); |
541 | 518 | ||
542 | spin_lock_bh(&xfrm_state_gc_lock); | 519 | spin_lock_bh(&xfrm_state_gc_lock); |
543 | hlist_add_head(&x->gclist, &xfrm_state_gc_list); | 520 | hlist_add_head(&x->gclist, &net->xfrm.state_gc_list); |
544 | spin_unlock_bh(&xfrm_state_gc_lock); | 521 | spin_unlock_bh(&xfrm_state_gc_lock); |
545 | schedule_work(&xfrm_state_gc_work); | 522 | schedule_work(&net->xfrm.state_gc_work); |
546 | } | 523 | } |
547 | EXPORT_SYMBOL(__xfrm_state_destroy); | 524 | EXPORT_SYMBOL(__xfrm_state_destroy); |
548 | 525 | ||
549 | int __xfrm_state_delete(struct xfrm_state *x) | 526 | int __xfrm_state_delete(struct xfrm_state *x) |
550 | { | 527 | { |
528 | struct net *net = xs_net(x); | ||
551 | int err = -ESRCH; | 529 | int err = -ESRCH; |
552 | 530 | ||
553 | if (x->km.state != XFRM_STATE_DEAD) { | 531 | if (x->km.state != XFRM_STATE_DEAD) { |
@@ -558,7 +536,7 @@ int __xfrm_state_delete(struct xfrm_state *x) | |||
558 | hlist_del(&x->bysrc); | 536 | hlist_del(&x->bysrc); |
559 | if (x->id.spi) | 537 | if (x->id.spi) |
560 | hlist_del(&x->byspi); | 538 | hlist_del(&x->byspi); |
561 | xfrm_state_num--; | 539 | net->xfrm.state_num--; |
562 | spin_unlock(&xfrm_state_lock); | 540 | spin_unlock(&xfrm_state_lock); |
563 | 541 | ||
564 | /* All xfrm_state objects are created by xfrm_state_alloc. | 542 | /* All xfrm_state objects are created by xfrm_state_alloc. |
@@ -587,15 +565,15 @@ EXPORT_SYMBOL(xfrm_state_delete); | |||
587 | 565 | ||
588 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 566 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
589 | static inline int | 567 | static inline int |
590 | xfrm_state_flush_secctx_check(u8 proto, struct xfrm_audit *audit_info) | 568 | xfrm_state_flush_secctx_check(struct net *net, u8 proto, struct xfrm_audit *audit_info) |
591 | { | 569 | { |
592 | int i, err = 0; | 570 | int i, err = 0; |
593 | 571 | ||
594 | for (i = 0; i <= xfrm_state_hmask; i++) { | 572 | for (i = 0; i <= net->xfrm.state_hmask; i++) { |
595 | struct hlist_node *entry; | 573 | struct hlist_node *entry; |
596 | struct xfrm_state *x; | 574 | struct xfrm_state *x; |
597 | 575 | ||
598 | hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) { | 576 | hlist_for_each_entry(x, entry, net->xfrm.state_bydst+i, bydst) { |
599 | if (xfrm_id_proto_match(x->id.proto, proto) && | 577 | if (xfrm_id_proto_match(x->id.proto, proto) && |
600 | (err = security_xfrm_state_delete(x)) != 0) { | 578 | (err = security_xfrm_state_delete(x)) != 0) { |
601 | xfrm_audit_state_delete(x, 0, | 579 | xfrm_audit_state_delete(x, 0, |
@@ -611,26 +589,26 @@ xfrm_state_flush_secctx_check(u8 proto, struct xfrm_audit *audit_info) | |||
611 | } | 589 | } |
612 | #else | 590 | #else |
613 | static inline int | 591 | static inline int |
614 | xfrm_state_flush_secctx_check(u8 proto, struct xfrm_audit *audit_info) | 592 | xfrm_state_flush_secctx_check(struct net *net, u8 proto, struct xfrm_audit *audit_info) |
615 | { | 593 | { |
616 | return 0; | 594 | return 0; |
617 | } | 595 | } |
618 | #endif | 596 | #endif |
619 | 597 | ||
620 | int xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info) | 598 | int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info) |
621 | { | 599 | { |
622 | int i, err = 0; | 600 | int i, err = 0; |
623 | 601 | ||
624 | spin_lock_bh(&xfrm_state_lock); | 602 | spin_lock_bh(&xfrm_state_lock); |
625 | err = xfrm_state_flush_secctx_check(proto, audit_info); | 603 | err = xfrm_state_flush_secctx_check(net, proto, audit_info); |
626 | if (err) | 604 | if (err) |
627 | goto out; | 605 | goto out; |
628 | 606 | ||
629 | for (i = 0; i <= xfrm_state_hmask; i++) { | 607 | for (i = 0; i <= net->xfrm.state_hmask; i++) { |
630 | struct hlist_node *entry; | 608 | struct hlist_node *entry; |
631 | struct xfrm_state *x; | 609 | struct xfrm_state *x; |
632 | restart: | 610 | restart: |
633 | hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) { | 611 | hlist_for_each_entry(x, entry, net->xfrm.state_bydst+i, bydst) { |
634 | if (!xfrm_state_kern(x) && | 612 | if (!xfrm_state_kern(x) && |
635 | xfrm_id_proto_match(x->id.proto, proto)) { | 613 | xfrm_id_proto_match(x->id.proto, proto)) { |
636 | xfrm_state_hold(x); | 614 | xfrm_state_hold(x); |
@@ -652,7 +630,7 @@ restart: | |||
652 | 630 | ||
653 | out: | 631 | out: |
654 | spin_unlock_bh(&xfrm_state_lock); | 632 | spin_unlock_bh(&xfrm_state_lock); |
655 | wake_up(&km_waitq); | 633 | wake_up(&net->xfrm.km_waitq); |
656 | return err; | 634 | return err; |
657 | } | 635 | } |
658 | EXPORT_SYMBOL(xfrm_state_flush); | 636 | EXPORT_SYMBOL(xfrm_state_flush); |
@@ -660,8 +638,8 @@ EXPORT_SYMBOL(xfrm_state_flush); | |||
660 | void xfrm_sad_getinfo(struct xfrmk_sadinfo *si) | 638 | void xfrm_sad_getinfo(struct xfrmk_sadinfo *si) |
661 | { | 639 | { |
662 | spin_lock_bh(&xfrm_state_lock); | 640 | spin_lock_bh(&xfrm_state_lock); |
663 | si->sadcnt = xfrm_state_num; | 641 | si->sadcnt = init_net.xfrm.state_num; |
664 | si->sadhcnt = xfrm_state_hmask; | 642 | si->sadhcnt = init_net.xfrm.state_hmask; |
665 | si->sadhmcnt = xfrm_state_hashmax; | 643 | si->sadhmcnt = xfrm_state_hashmax; |
666 | spin_unlock_bh(&xfrm_state_lock); | 644 | spin_unlock_bh(&xfrm_state_lock); |
667 | } | 645 | } |
@@ -681,13 +659,13 @@ xfrm_init_tempsel(struct xfrm_state *x, struct flowi *fl, | |||
681 | return 0; | 659 | return 0; |
682 | } | 660 | } |
683 | 661 | ||
684 | static struct xfrm_state *__xfrm_state_lookup(xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family) | 662 | static struct xfrm_state *__xfrm_state_lookup(struct net *net, xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family) |
685 | { | 663 | { |
686 | unsigned int h = xfrm_spi_hash(daddr, spi, proto, family); | 664 | unsigned int h = xfrm_spi_hash(net, daddr, spi, proto, family); |
687 | struct xfrm_state *x; | 665 | struct xfrm_state *x; |
688 | struct hlist_node *entry; | 666 | struct hlist_node *entry; |
689 | 667 | ||
690 | hlist_for_each_entry(x, entry, xfrm_state_byspi+h, byspi) { | 668 | hlist_for_each_entry(x, entry, net->xfrm.state_byspi+h, byspi) { |
691 | if (x->props.family != family || | 669 | if (x->props.family != family || |
692 | x->id.spi != spi || | 670 | x->id.spi != spi || |
693 | x->id.proto != proto) | 671 | x->id.proto != proto) |
@@ -713,13 +691,13 @@ static struct xfrm_state *__xfrm_state_lookup(xfrm_address_t *daddr, __be32 spi, | |||
713 | return NULL; | 691 | return NULL; |
714 | } | 692 | } |
715 | 693 | ||
716 | static struct xfrm_state *__xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family) | 694 | static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family) |
717 | { | 695 | { |
718 | unsigned int h = xfrm_src_hash(daddr, saddr, family); | 696 | unsigned int h = xfrm_src_hash(net, daddr, saddr, family); |
719 | struct xfrm_state *x; | 697 | struct xfrm_state *x; |
720 | struct hlist_node *entry; | 698 | struct hlist_node *entry; |
721 | 699 | ||
722 | hlist_for_each_entry(x, entry, xfrm_state_bysrc+h, bysrc) { | 700 | hlist_for_each_entry(x, entry, net->xfrm.state_bysrc+h, bysrc) { |
723 | if (x->props.family != family || | 701 | if (x->props.family != family || |
724 | x->id.proto != proto) | 702 | x->id.proto != proto) |
725 | continue; | 703 | continue; |
@@ -751,21 +729,23 @@ static struct xfrm_state *__xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm | |||
751 | static inline struct xfrm_state * | 729 | static inline struct xfrm_state * |
752 | __xfrm_state_locate(struct xfrm_state *x, int use_spi, int family) | 730 | __xfrm_state_locate(struct xfrm_state *x, int use_spi, int family) |
753 | { | 731 | { |
732 | struct net *net = xs_net(x); | ||
733 | |||
754 | if (use_spi) | 734 | if (use_spi) |
755 | return __xfrm_state_lookup(&x->id.daddr, x->id.spi, | 735 | return __xfrm_state_lookup(net, &x->id.daddr, x->id.spi, |
756 | x->id.proto, family); | 736 | x->id.proto, family); |
757 | else | 737 | else |
758 | return __xfrm_state_lookup_byaddr(&x->id.daddr, | 738 | return __xfrm_state_lookup_byaddr(net, &x->id.daddr, |
759 | &x->props.saddr, | 739 | &x->props.saddr, |
760 | x->id.proto, family); | 740 | x->id.proto, family); |
761 | } | 741 | } |
762 | 742 | ||
763 | static void xfrm_hash_grow_check(int have_hash_collision) | 743 | static void xfrm_hash_grow_check(struct net *net, int have_hash_collision) |
764 | { | 744 | { |
765 | if (have_hash_collision && | 745 | if (have_hash_collision && |
766 | (xfrm_state_hmask + 1) < xfrm_state_hashmax && | 746 | (net->xfrm.state_hmask + 1) < xfrm_state_hashmax && |
767 | xfrm_state_num > xfrm_state_hmask) | 747 | net->xfrm.state_num > net->xfrm.state_hmask) |
768 | schedule_work(&xfrm_hash_work); | 748 | schedule_work(&net->xfrm.state_hash_work); |
769 | } | 749 | } |
770 | 750 | ||
771 | struct xfrm_state * | 751 | struct xfrm_state * |
@@ -774,6 +754,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
774 | struct xfrm_policy *pol, int *err, | 754 | struct xfrm_policy *pol, int *err, |
775 | unsigned short family) | 755 | unsigned short family) |
776 | { | 756 | { |
757 | struct net *net = xp_net(pol); | ||
777 | unsigned int h; | 758 | unsigned int h; |
778 | struct hlist_node *entry; | 759 | struct hlist_node *entry; |
779 | struct xfrm_state *x, *x0, *to_put; | 760 | struct xfrm_state *x, *x0, *to_put; |
@@ -784,8 +765,8 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
784 | to_put = NULL; | 765 | to_put = NULL; |
785 | 766 | ||
786 | spin_lock_bh(&xfrm_state_lock); | 767 | spin_lock_bh(&xfrm_state_lock); |
787 | h = xfrm_dst_hash(daddr, saddr, tmpl->reqid, family); | 768 | h = xfrm_dst_hash(net, daddr, saddr, tmpl->reqid, family); |
788 | hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) { | 769 | hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { |
789 | if (x->props.family == family && | 770 | if (x->props.family == family && |
790 | x->props.reqid == tmpl->reqid && | 771 | x->props.reqid == tmpl->reqid && |
791 | !(x->props.flags & XFRM_STATE_WILDRECV) && | 772 | !(x->props.flags & XFRM_STATE_WILDRECV) && |
@@ -829,13 +810,13 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
829 | x = best; | 810 | x = best; |
830 | if (!x && !error && !acquire_in_progress) { | 811 | if (!x && !error && !acquire_in_progress) { |
831 | if (tmpl->id.spi && | 812 | if (tmpl->id.spi && |
832 | (x0 = __xfrm_state_lookup(daddr, tmpl->id.spi, | 813 | (x0 = __xfrm_state_lookup(net, daddr, tmpl->id.spi, |
833 | tmpl->id.proto, family)) != NULL) { | 814 | tmpl->id.proto, family)) != NULL) { |
834 | to_put = x0; | 815 | to_put = x0; |
835 | error = -EEXIST; | 816 | error = -EEXIST; |
836 | goto out; | 817 | goto out; |
837 | } | 818 | } |
838 | x = xfrm_state_alloc(); | 819 | x = xfrm_state_alloc(net); |
839 | if (x == NULL) { | 820 | if (x == NULL) { |
840 | error = -ENOMEM; | 821 | error = -ENOMEM; |
841 | goto out; | 822 | goto out; |
@@ -854,19 +835,19 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
854 | 835 | ||
855 | if (km_query(x, tmpl, pol) == 0) { | 836 | if (km_query(x, tmpl, pol) == 0) { |
856 | x->km.state = XFRM_STATE_ACQ; | 837 | x->km.state = XFRM_STATE_ACQ; |
857 | list_add(&x->km.all, &xfrm_state_all); | 838 | list_add(&x->km.all, &net->xfrm.state_all); |
858 | hlist_add_head(&x->bydst, xfrm_state_bydst+h); | 839 | hlist_add_head(&x->bydst, net->xfrm.state_bydst+h); |
859 | h = xfrm_src_hash(daddr, saddr, family); | 840 | h = xfrm_src_hash(net, daddr, saddr, family); |
860 | hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); | 841 | hlist_add_head(&x->bysrc, net->xfrm.state_bysrc+h); |
861 | if (x->id.spi) { | 842 | if (x->id.spi) { |
862 | h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, family); | 843 | h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, family); |
863 | hlist_add_head(&x->byspi, xfrm_state_byspi+h); | 844 | hlist_add_head(&x->byspi, net->xfrm.state_byspi+h); |
864 | } | 845 | } |
865 | x->lft.hard_add_expires_seconds = sysctl_xfrm_acq_expires; | 846 | x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires; |
866 | x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ; | 847 | x->timer.expires = jiffies + net->xfrm.sysctl_acq_expires*HZ; |
867 | add_timer(&x->timer); | 848 | add_timer(&x->timer); |
868 | xfrm_state_num++; | 849 | net->xfrm.state_num++; |
869 | xfrm_hash_grow_check(x->bydst.next != NULL); | 850 | xfrm_hash_grow_check(net, x->bydst.next != NULL); |
870 | } else { | 851 | } else { |
871 | x->km.state = XFRM_STATE_DEAD; | 852 | x->km.state = XFRM_STATE_DEAD; |
872 | to_put = x; | 853 | to_put = x; |
@@ -886,7 +867,8 @@ out: | |||
886 | } | 867 | } |
887 | 868 | ||
888 | struct xfrm_state * | 869 | struct xfrm_state * |
889 | xfrm_stateonly_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | 870 | xfrm_stateonly_find(struct net *net, |
871 | xfrm_address_t *daddr, xfrm_address_t *saddr, | ||
890 | unsigned short family, u8 mode, u8 proto, u32 reqid) | 872 | unsigned short family, u8 mode, u8 proto, u32 reqid) |
891 | { | 873 | { |
892 | unsigned int h; | 874 | unsigned int h; |
@@ -894,8 +876,8 @@ xfrm_stateonly_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
894 | struct hlist_node *entry; | 876 | struct hlist_node *entry; |
895 | 877 | ||
896 | spin_lock(&xfrm_state_lock); | 878 | spin_lock(&xfrm_state_lock); |
897 | h = xfrm_dst_hash(daddr, saddr, reqid, family); | 879 | h = xfrm_dst_hash(net, daddr, saddr, reqid, family); |
898 | hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) { | 880 | hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { |
899 | if (x->props.family == family && | 881 | if (x->props.family == family && |
900 | x->props.reqid == reqid && | 882 | x->props.reqid == reqid && |
901 | !(x->props.flags & XFRM_STATE_WILDRECV) && | 883 | !(x->props.flags & XFRM_STATE_WILDRECV) && |
@@ -919,48 +901,50 @@ EXPORT_SYMBOL(xfrm_stateonly_find); | |||
919 | 901 | ||
920 | static void __xfrm_state_insert(struct xfrm_state *x) | 902 | static void __xfrm_state_insert(struct xfrm_state *x) |
921 | { | 903 | { |
904 | struct net *net = xs_net(x); | ||
922 | unsigned int h; | 905 | unsigned int h; |
923 | 906 | ||
924 | x->genid = ++xfrm_state_genid; | 907 | x->genid = ++xfrm_state_genid; |
925 | 908 | ||
926 | list_add(&x->km.all, &xfrm_state_all); | 909 | list_add(&x->km.all, &net->xfrm.state_all); |
927 | 910 | ||
928 | h = xfrm_dst_hash(&x->id.daddr, &x->props.saddr, | 911 | h = xfrm_dst_hash(net, &x->id.daddr, &x->props.saddr, |
929 | x->props.reqid, x->props.family); | 912 | x->props.reqid, x->props.family); |
930 | hlist_add_head(&x->bydst, xfrm_state_bydst+h); | 913 | hlist_add_head(&x->bydst, net->xfrm.state_bydst+h); |
931 | 914 | ||
932 | h = xfrm_src_hash(&x->id.daddr, &x->props.saddr, x->props.family); | 915 | h = xfrm_src_hash(net, &x->id.daddr, &x->props.saddr, x->props.family); |
933 | hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); | 916 | hlist_add_head(&x->bysrc, net->xfrm.state_bysrc+h); |
934 | 917 | ||
935 | if (x->id.spi) { | 918 | if (x->id.spi) { |
936 | h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, | 919 | h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, |
937 | x->props.family); | 920 | x->props.family); |
938 | 921 | ||
939 | hlist_add_head(&x->byspi, xfrm_state_byspi+h); | 922 | hlist_add_head(&x->byspi, net->xfrm.state_byspi+h); |
940 | } | 923 | } |
941 | 924 | ||
942 | mod_timer(&x->timer, jiffies + HZ); | 925 | mod_timer(&x->timer, jiffies + HZ); |
943 | if (x->replay_maxage) | 926 | if (x->replay_maxage) |
944 | mod_timer(&x->rtimer, jiffies + x->replay_maxage); | 927 | mod_timer(&x->rtimer, jiffies + x->replay_maxage); |
945 | 928 | ||
946 | wake_up(&km_waitq); | 929 | wake_up(&net->xfrm.km_waitq); |
947 | 930 | ||
948 | xfrm_state_num++; | 931 | net->xfrm.state_num++; |
949 | 932 | ||
950 | xfrm_hash_grow_check(x->bydst.next != NULL); | 933 | xfrm_hash_grow_check(net, x->bydst.next != NULL); |
951 | } | 934 | } |
952 | 935 | ||
953 | /* xfrm_state_lock is held */ | 936 | /* xfrm_state_lock is held */ |
954 | static void __xfrm_state_bump_genids(struct xfrm_state *xnew) | 937 | static void __xfrm_state_bump_genids(struct xfrm_state *xnew) |
955 | { | 938 | { |
939 | struct net *net = xs_net(xnew); | ||
956 | unsigned short family = xnew->props.family; | 940 | unsigned short family = xnew->props.family; |
957 | u32 reqid = xnew->props.reqid; | 941 | u32 reqid = xnew->props.reqid; |
958 | struct xfrm_state *x; | 942 | struct xfrm_state *x; |
959 | struct hlist_node *entry; | 943 | struct hlist_node *entry; |
960 | unsigned int h; | 944 | unsigned int h; |
961 | 945 | ||
962 | h = xfrm_dst_hash(&xnew->id.daddr, &xnew->props.saddr, reqid, family); | 946 | h = xfrm_dst_hash(net, &xnew->id.daddr, &xnew->props.saddr, reqid, family); |
963 | hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) { | 947 | hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { |
964 | if (x->props.family == family && | 948 | if (x->props.family == family && |
965 | x->props.reqid == reqid && | 949 | x->props.reqid == reqid && |
966 | !xfrm_addr_cmp(&x->id.daddr, &xnew->id.daddr, family) && | 950 | !xfrm_addr_cmp(&x->id.daddr, &xnew->id.daddr, family) && |
@@ -979,13 +963,13 @@ void xfrm_state_insert(struct xfrm_state *x) | |||
979 | EXPORT_SYMBOL(xfrm_state_insert); | 963 | EXPORT_SYMBOL(xfrm_state_insert); |
980 | 964 | ||
981 | /* xfrm_state_lock is held */ | 965 | /* xfrm_state_lock is held */ |
982 | 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) | 966 | 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) |
983 | { | 967 | { |
984 | unsigned int h = xfrm_dst_hash(daddr, saddr, reqid, family); | 968 | unsigned int h = xfrm_dst_hash(net, daddr, saddr, reqid, family); |
985 | struct hlist_node *entry; | 969 | struct hlist_node *entry; |
986 | struct xfrm_state *x; | 970 | struct xfrm_state *x; |
987 | 971 | ||
988 | hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) { | 972 | hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { |
989 | if (x->props.reqid != reqid || | 973 | if (x->props.reqid != reqid || |
990 | x->props.mode != mode || | 974 | x->props.mode != mode || |
991 | x->props.family != family || | 975 | x->props.family != family || |
@@ -1017,7 +1001,7 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re | |||
1017 | if (!create) | 1001 | if (!create) |
1018 | return NULL; | 1002 | return NULL; |
1019 | 1003 | ||
1020 | x = xfrm_state_alloc(); | 1004 | x = xfrm_state_alloc(net); |
1021 | if (likely(x)) { | 1005 | if (likely(x)) { |
1022 | switch (family) { | 1006 | switch (family) { |
1023 | case AF_INET: | 1007 | case AF_INET: |
@@ -1048,27 +1032,28 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re | |||
1048 | x->props.family = family; | 1032 | x->props.family = family; |
1049 | x->props.mode = mode; | 1033 | x->props.mode = mode; |
1050 | x->props.reqid = reqid; | 1034 | x->props.reqid = reqid; |
1051 | x->lft.hard_add_expires_seconds = sysctl_xfrm_acq_expires; | 1035 | x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires; |
1052 | xfrm_state_hold(x); | 1036 | xfrm_state_hold(x); |
1053 | x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ; | 1037 | x->timer.expires = jiffies + net->xfrm.sysctl_acq_expires*HZ; |
1054 | add_timer(&x->timer); | 1038 | add_timer(&x->timer); |
1055 | list_add(&x->km.all, &xfrm_state_all); | 1039 | list_add(&x->km.all, &net->xfrm.state_all); |
1056 | hlist_add_head(&x->bydst, xfrm_state_bydst+h); | 1040 | hlist_add_head(&x->bydst, net->xfrm.state_bydst+h); |
1057 | h = xfrm_src_hash(daddr, saddr, family); | 1041 | h = xfrm_src_hash(net, daddr, saddr, family); |
1058 | hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); | 1042 | hlist_add_head(&x->bysrc, net->xfrm.state_bysrc+h); |
1059 | 1043 | ||
1060 | xfrm_state_num++; | 1044 | net->xfrm.state_num++; |
1061 | 1045 | ||
1062 | xfrm_hash_grow_check(x->bydst.next != NULL); | 1046 | xfrm_hash_grow_check(net, x->bydst.next != NULL); |
1063 | } | 1047 | } |
1064 | 1048 | ||
1065 | return x; | 1049 | return x; |
1066 | } | 1050 | } |
1067 | 1051 | ||
1068 | static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq); | 1052 | static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 seq); |
1069 | 1053 | ||
1070 | int xfrm_state_add(struct xfrm_state *x) | 1054 | int xfrm_state_add(struct xfrm_state *x) |
1071 | { | 1055 | { |
1056 | struct net *net = xs_net(x); | ||
1072 | struct xfrm_state *x1, *to_put; | 1057 | struct xfrm_state *x1, *to_put; |
1073 | int family; | 1058 | int family; |
1074 | int err; | 1059 | int err; |
@@ -1089,7 +1074,7 @@ int xfrm_state_add(struct xfrm_state *x) | |||
1089 | } | 1074 | } |
1090 | 1075 | ||
1091 | if (use_spi && x->km.seq) { | 1076 | if (use_spi && x->km.seq) { |
1092 | x1 = __xfrm_find_acq_byseq(x->km.seq); | 1077 | x1 = __xfrm_find_acq_byseq(net, x->km.seq); |
1093 | if (x1 && ((x1->id.proto != x->id.proto) || | 1078 | if (x1 && ((x1->id.proto != x->id.proto) || |
1094 | xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family))) { | 1079 | xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family))) { |
1095 | to_put = x1; | 1080 | to_put = x1; |
@@ -1098,7 +1083,7 @@ int xfrm_state_add(struct xfrm_state *x) | |||
1098 | } | 1083 | } |
1099 | 1084 | ||
1100 | if (use_spi && !x1) | 1085 | if (use_spi && !x1) |
1101 | x1 = __find_acq_core(family, x->props.mode, x->props.reqid, | 1086 | x1 = __find_acq_core(net, family, x->props.mode, x->props.reqid, |
1102 | x->id.proto, | 1087 | x->id.proto, |
1103 | &x->id.daddr, &x->props.saddr, 0); | 1088 | &x->id.daddr, &x->props.saddr, 0); |
1104 | 1089 | ||
@@ -1124,8 +1109,9 @@ EXPORT_SYMBOL(xfrm_state_add); | |||
1124 | #ifdef CONFIG_XFRM_MIGRATE | 1109 | #ifdef CONFIG_XFRM_MIGRATE |
1125 | static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp) | 1110 | static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp) |
1126 | { | 1111 | { |
1112 | struct net *net = xs_net(orig); | ||
1127 | int err = -ENOMEM; | 1113 | int err = -ENOMEM; |
1128 | struct xfrm_state *x = xfrm_state_alloc(); | 1114 | struct xfrm_state *x = xfrm_state_alloc(net); |
1129 | if (!x) | 1115 | if (!x) |
1130 | goto error; | 1116 | goto error; |
1131 | 1117 | ||
@@ -1206,9 +1192,9 @@ struct xfrm_state * xfrm_migrate_state_find(struct xfrm_migrate *m) | |||
1206 | struct hlist_node *entry; | 1192 | struct hlist_node *entry; |
1207 | 1193 | ||
1208 | if (m->reqid) { | 1194 | if (m->reqid) { |
1209 | h = xfrm_dst_hash(&m->old_daddr, &m->old_saddr, | 1195 | h = xfrm_dst_hash(&init_net, &m->old_daddr, &m->old_saddr, |
1210 | m->reqid, m->old_family); | 1196 | m->reqid, m->old_family); |
1211 | hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) { | 1197 | hlist_for_each_entry(x, entry, init_net.xfrm.state_bydst+h, bydst) { |
1212 | if (x->props.mode != m->mode || | 1198 | if (x->props.mode != m->mode || |
1213 | x->id.proto != m->proto) | 1199 | x->id.proto != m->proto) |
1214 | continue; | 1200 | continue; |
@@ -1223,9 +1209,9 @@ struct xfrm_state * xfrm_migrate_state_find(struct xfrm_migrate *m) | |||
1223 | return x; | 1209 | return x; |
1224 | } | 1210 | } |
1225 | } else { | 1211 | } else { |
1226 | h = xfrm_src_hash(&m->old_daddr, &m->old_saddr, | 1212 | h = xfrm_src_hash(&init_net, &m->old_daddr, &m->old_saddr, |
1227 | m->old_family); | 1213 | m->old_family); |
1228 | hlist_for_each_entry(x, entry, xfrm_state_bysrc+h, bysrc) { | 1214 | hlist_for_each_entry(x, entry, init_net.xfrm.state_bysrc+h, bysrc) { |
1229 | if (x->props.mode != m->mode || | 1215 | if (x->props.mode != m->mode || |
1230 | x->id.proto != m->proto) | 1216 | x->id.proto != m->proto) |
1231 | continue; | 1217 | continue; |
@@ -1369,40 +1355,41 @@ int xfrm_state_check_expire(struct xfrm_state *x) | |||
1369 | EXPORT_SYMBOL(xfrm_state_check_expire); | 1355 | EXPORT_SYMBOL(xfrm_state_check_expire); |
1370 | 1356 | ||
1371 | struct xfrm_state * | 1357 | struct xfrm_state * |
1372 | xfrm_state_lookup(xfrm_address_t *daddr, __be32 spi, u8 proto, | 1358 | xfrm_state_lookup(struct net *net, xfrm_address_t *daddr, __be32 spi, u8 proto, |
1373 | unsigned short family) | 1359 | unsigned short family) |
1374 | { | 1360 | { |
1375 | struct xfrm_state *x; | 1361 | struct xfrm_state *x; |
1376 | 1362 | ||
1377 | spin_lock_bh(&xfrm_state_lock); | 1363 | spin_lock_bh(&xfrm_state_lock); |
1378 | x = __xfrm_state_lookup(daddr, spi, proto, family); | 1364 | x = __xfrm_state_lookup(net, daddr, spi, proto, family); |
1379 | spin_unlock_bh(&xfrm_state_lock); | 1365 | spin_unlock_bh(&xfrm_state_lock); |
1380 | return x; | 1366 | return x; |
1381 | } | 1367 | } |
1382 | EXPORT_SYMBOL(xfrm_state_lookup); | 1368 | EXPORT_SYMBOL(xfrm_state_lookup); |
1383 | 1369 | ||
1384 | struct xfrm_state * | 1370 | struct xfrm_state * |
1385 | xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, | 1371 | xfrm_state_lookup_byaddr(struct net *net, |
1372 | xfrm_address_t *daddr, xfrm_address_t *saddr, | ||
1386 | u8 proto, unsigned short family) | 1373 | u8 proto, unsigned short family) |
1387 | { | 1374 | { |
1388 | struct xfrm_state *x; | 1375 | struct xfrm_state *x; |
1389 | 1376 | ||
1390 | spin_lock_bh(&xfrm_state_lock); | 1377 | spin_lock_bh(&xfrm_state_lock); |
1391 | x = __xfrm_state_lookup_byaddr(daddr, saddr, proto, family); | 1378 | x = __xfrm_state_lookup_byaddr(net, daddr, saddr, proto, family); |
1392 | spin_unlock_bh(&xfrm_state_lock); | 1379 | spin_unlock_bh(&xfrm_state_lock); |
1393 | return x; | 1380 | return x; |
1394 | } | 1381 | } |
1395 | EXPORT_SYMBOL(xfrm_state_lookup_byaddr); | 1382 | EXPORT_SYMBOL(xfrm_state_lookup_byaddr); |
1396 | 1383 | ||
1397 | struct xfrm_state * | 1384 | struct xfrm_state * |
1398 | xfrm_find_acq(u8 mode, u32 reqid, u8 proto, | 1385 | xfrm_find_acq(struct net *net, u8 mode, u32 reqid, u8 proto, |
1399 | xfrm_address_t *daddr, xfrm_address_t *saddr, | 1386 | xfrm_address_t *daddr, xfrm_address_t *saddr, |
1400 | int create, unsigned short family) | 1387 | int create, unsigned short family) |
1401 | { | 1388 | { |
1402 | struct xfrm_state *x; | 1389 | struct xfrm_state *x; |
1403 | 1390 | ||
1404 | spin_lock_bh(&xfrm_state_lock); | 1391 | spin_lock_bh(&xfrm_state_lock); |
1405 | x = __find_acq_core(family, mode, reqid, proto, daddr, saddr, create); | 1392 | x = __find_acq_core(net, family, mode, reqid, proto, daddr, saddr, create); |
1406 | spin_unlock_bh(&xfrm_state_lock); | 1393 | spin_unlock_bh(&xfrm_state_lock); |
1407 | 1394 | ||
1408 | return x; | 1395 | return x; |
@@ -1449,15 +1436,15 @@ EXPORT_SYMBOL(xfrm_state_sort); | |||
1449 | 1436 | ||
1450 | /* Silly enough, but I'm lazy to build resolution list */ | 1437 | /* Silly enough, but I'm lazy to build resolution list */ |
1451 | 1438 | ||
1452 | static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq) | 1439 | static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 seq) |
1453 | { | 1440 | { |
1454 | int i; | 1441 | int i; |
1455 | 1442 | ||
1456 | for (i = 0; i <= xfrm_state_hmask; i++) { | 1443 | for (i = 0; i <= net->xfrm.state_hmask; i++) { |
1457 | struct hlist_node *entry; | 1444 | struct hlist_node *entry; |
1458 | struct xfrm_state *x; | 1445 | struct xfrm_state *x; |
1459 | 1446 | ||
1460 | hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) { | 1447 | hlist_for_each_entry(x, entry, net->xfrm.state_bydst+i, bydst) { |
1461 | if (x->km.seq == seq && | 1448 | if (x->km.seq == seq && |
1462 | x->km.state == XFRM_STATE_ACQ) { | 1449 | x->km.state == XFRM_STATE_ACQ) { |
1463 | xfrm_state_hold(x); | 1450 | xfrm_state_hold(x); |
@@ -1468,12 +1455,12 @@ static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq) | |||
1468 | return NULL; | 1455 | return NULL; |
1469 | } | 1456 | } |
1470 | 1457 | ||
1471 | struct xfrm_state *xfrm_find_acq_byseq(u32 seq) | 1458 | struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 seq) |
1472 | { | 1459 | { |
1473 | struct xfrm_state *x; | 1460 | struct xfrm_state *x; |
1474 | 1461 | ||
1475 | spin_lock_bh(&xfrm_state_lock); | 1462 | spin_lock_bh(&xfrm_state_lock); |
1476 | x = __xfrm_find_acq_byseq(seq); | 1463 | x = __xfrm_find_acq_byseq(net, seq); |
1477 | spin_unlock_bh(&xfrm_state_lock); | 1464 | spin_unlock_bh(&xfrm_state_lock); |
1478 | return x; | 1465 | return x; |
1479 | } | 1466 | } |
@@ -1494,6 +1481,7 @@ EXPORT_SYMBOL(xfrm_get_acqseq); | |||
1494 | 1481 | ||
1495 | int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high) | 1482 | int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high) |
1496 | { | 1483 | { |
1484 | struct net *net = xs_net(x); | ||
1497 | unsigned int h; | 1485 | unsigned int h; |
1498 | struct xfrm_state *x0; | 1486 | struct xfrm_state *x0; |
1499 | int err = -ENOENT; | 1487 | int err = -ENOENT; |
@@ -1511,7 +1499,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high) | |||
1511 | err = -ENOENT; | 1499 | err = -ENOENT; |
1512 | 1500 | ||
1513 | if (minspi == maxspi) { | 1501 | if (minspi == maxspi) { |
1514 | x0 = xfrm_state_lookup(&x->id.daddr, minspi, x->id.proto, x->props.family); | 1502 | x0 = xfrm_state_lookup(net, &x->id.daddr, minspi, x->id.proto, x->props.family); |
1515 | if (x0) { | 1503 | if (x0) { |
1516 | xfrm_state_put(x0); | 1504 | xfrm_state_put(x0); |
1517 | goto unlock; | 1505 | goto unlock; |
@@ -1521,7 +1509,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high) | |||
1521 | u32 spi = 0; | 1509 | u32 spi = 0; |
1522 | for (h=0; h<high-low+1; h++) { | 1510 | for (h=0; h<high-low+1; h++) { |
1523 | spi = low + net_random()%(high-low+1); | 1511 | spi = low + net_random()%(high-low+1); |
1524 | x0 = xfrm_state_lookup(&x->id.daddr, htonl(spi), x->id.proto, x->props.family); | 1512 | x0 = xfrm_state_lookup(net, &x->id.daddr, htonl(spi), x->id.proto, x->props.family); |
1525 | if (x0 == NULL) { | 1513 | if (x0 == NULL) { |
1526 | x->id.spi = htonl(spi); | 1514 | x->id.spi = htonl(spi); |
1527 | break; | 1515 | break; |
@@ -1531,8 +1519,8 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high) | |||
1531 | } | 1519 | } |
1532 | if (x->id.spi) { | 1520 | if (x->id.spi) { |
1533 | spin_lock_bh(&xfrm_state_lock); | 1521 | spin_lock_bh(&xfrm_state_lock); |
1534 | h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, x->props.family); | 1522 | h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, x->props.family); |
1535 | hlist_add_head(&x->byspi, xfrm_state_byspi+h); | 1523 | hlist_add_head(&x->byspi, net->xfrm.state_byspi+h); |
1536 | spin_unlock_bh(&xfrm_state_lock); | 1524 | spin_unlock_bh(&xfrm_state_lock); |
1537 | 1525 | ||
1538 | err = 0; | 1526 | err = 0; |
@@ -1545,7 +1533,7 @@ unlock: | |||
1545 | } | 1533 | } |
1546 | EXPORT_SYMBOL(xfrm_alloc_spi); | 1534 | EXPORT_SYMBOL(xfrm_alloc_spi); |
1547 | 1535 | ||
1548 | int xfrm_state_walk(struct xfrm_state_walk *walk, | 1536 | int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk, |
1549 | int (*func)(struct xfrm_state *, int, void*), | 1537 | int (*func)(struct xfrm_state *, int, void*), |
1550 | void *data) | 1538 | void *data) |
1551 | { | 1539 | { |
@@ -1558,10 +1546,10 @@ int xfrm_state_walk(struct xfrm_state_walk *walk, | |||
1558 | 1546 | ||
1559 | spin_lock_bh(&xfrm_state_lock); | 1547 | spin_lock_bh(&xfrm_state_lock); |
1560 | if (list_empty(&walk->all)) | 1548 | if (list_empty(&walk->all)) |
1561 | x = list_first_entry(&xfrm_state_all, struct xfrm_state_walk, all); | 1549 | x = list_first_entry(&net->xfrm.state_all, struct xfrm_state_walk, all); |
1562 | else | 1550 | else |
1563 | x = list_entry(&walk->all, struct xfrm_state_walk, all); | 1551 | x = list_entry(&walk->all, struct xfrm_state_walk, all); |
1564 | list_for_each_entry_from(x, &xfrm_state_all, all) { | 1552 | list_for_each_entry_from(x, &net->xfrm.state_all, all) { |
1565 | if (x->state == XFRM_STATE_DEAD) | 1553 | if (x->state == XFRM_STATE_DEAD) |
1566 | continue; | 1554 | continue; |
1567 | state = container_of(x, struct xfrm_state, km); | 1555 | state = container_of(x, struct xfrm_state, km); |
@@ -1660,7 +1648,7 @@ static void xfrm_replay_timer_handler(unsigned long data) | |||
1660 | spin_lock(&x->lock); | 1648 | spin_lock(&x->lock); |
1661 | 1649 | ||
1662 | if (x->km.state == XFRM_STATE_VALID) { | 1650 | if (x->km.state == XFRM_STATE_VALID) { |
1663 | if (xfrm_aevent_is_on()) | 1651 | if (xfrm_aevent_is_on(xs_net(x))) |
1664 | xfrm_replay_notify(x, XFRM_REPLAY_TIMEOUT); | 1652 | xfrm_replay_notify(x, XFRM_REPLAY_TIMEOUT); |
1665 | else | 1653 | else |
1666 | x->xflags |= XFRM_TIME_DEFER; | 1654 | x->xflags |= XFRM_TIME_DEFER; |
@@ -1716,7 +1704,7 @@ void xfrm_replay_advance(struct xfrm_state *x, __be32 net_seq) | |||
1716 | x->replay.bitmap |= (1U << diff); | 1704 | x->replay.bitmap |= (1U << diff); |
1717 | } | 1705 | } |
1718 | 1706 | ||
1719 | if (xfrm_aevent_is_on()) | 1707 | if (xfrm_aevent_is_on(xs_net(x))) |
1720 | xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); | 1708 | xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); |
1721 | } | 1709 | } |
1722 | 1710 | ||
@@ -1749,6 +1737,7 @@ EXPORT_SYMBOL(km_state_notify); | |||
1749 | 1737 | ||
1750 | void km_state_expired(struct xfrm_state *x, int hard, u32 pid) | 1738 | void km_state_expired(struct xfrm_state *x, int hard, u32 pid) |
1751 | { | 1739 | { |
1740 | struct net *net = xs_net(x); | ||
1752 | struct km_event c; | 1741 | struct km_event c; |
1753 | 1742 | ||
1754 | c.data.hard = hard; | 1743 | c.data.hard = hard; |
@@ -1757,7 +1746,7 @@ void km_state_expired(struct xfrm_state *x, int hard, u32 pid) | |||
1757 | km_state_notify(x, &c); | 1746 | km_state_notify(x, &c); |
1758 | 1747 | ||
1759 | if (hard) | 1748 | if (hard) |
1760 | wake_up(&km_waitq); | 1749 | wake_up(&net->xfrm.km_waitq); |
1761 | } | 1750 | } |
1762 | 1751 | ||
1763 | EXPORT_SYMBOL(km_state_expired); | 1752 | EXPORT_SYMBOL(km_state_expired); |
@@ -1800,6 +1789,7 @@ EXPORT_SYMBOL(km_new_mapping); | |||
1800 | 1789 | ||
1801 | void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid) | 1790 | void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid) |
1802 | { | 1791 | { |
1792 | struct net *net = xp_net(pol); | ||
1803 | struct km_event c; | 1793 | struct km_event c; |
1804 | 1794 | ||
1805 | c.data.hard = hard; | 1795 | c.data.hard = hard; |
@@ -1808,7 +1798,7 @@ void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid) | |||
1808 | km_policy_notify(pol, dir, &c); | 1798 | km_policy_notify(pol, dir, &c); |
1809 | 1799 | ||
1810 | if (hard) | 1800 | if (hard) |
1811 | wake_up(&km_waitq); | 1801 | wake_up(&net->xfrm.km_waitq); |
1812 | } | 1802 | } |
1813 | EXPORT_SYMBOL(km_policy_expired); | 1803 | EXPORT_SYMBOL(km_policy_expired); |
1814 | 1804 | ||
@@ -1835,7 +1825,7 @@ int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | |||
1835 | EXPORT_SYMBOL(km_migrate); | 1825 | EXPORT_SYMBOL(km_migrate); |
1836 | #endif | 1826 | #endif |
1837 | 1827 | ||
1838 | int km_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr) | 1828 | int km_report(struct net *net, u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr) |
1839 | { | 1829 | { |
1840 | int err = -EINVAL; | 1830 | int err = -EINVAL; |
1841 | int ret; | 1831 | int ret; |
@@ -1844,7 +1834,7 @@ int km_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr) | |||
1844 | read_lock(&xfrm_km_lock); | 1834 | read_lock(&xfrm_km_lock); |
1845 | list_for_each_entry(km, &xfrm_km_list, list) { | 1835 | list_for_each_entry(km, &xfrm_km_list, list) { |
1846 | if (km->report) { | 1836 | if (km->report) { |
1847 | ret = km->report(proto, sel, addr); | 1837 | ret = km->report(net, proto, sel, addr); |
1848 | if (!ret) | 1838 | if (!ret) |
1849 | err = ret; | 1839 | err = ret; |
1850 | } | 1840 | } |
@@ -2080,20 +2070,61 @@ error: | |||
2080 | 2070 | ||
2081 | EXPORT_SYMBOL(xfrm_init_state); | 2071 | EXPORT_SYMBOL(xfrm_init_state); |
2082 | 2072 | ||
2083 | void __init xfrm_state_init(void) | 2073 | int __net_init xfrm_state_init(struct net *net) |
2084 | { | 2074 | { |
2085 | unsigned int sz; | 2075 | unsigned int sz; |
2086 | 2076 | ||
2077 | INIT_LIST_HEAD(&net->xfrm.state_all); | ||
2078 | |||
2087 | sz = sizeof(struct hlist_head) * 8; | 2079 | sz = sizeof(struct hlist_head) * 8; |
2088 | 2080 | ||
2089 | xfrm_state_bydst = xfrm_hash_alloc(sz); | 2081 | net->xfrm.state_bydst = xfrm_hash_alloc(sz); |
2090 | xfrm_state_bysrc = xfrm_hash_alloc(sz); | 2082 | if (!net->xfrm.state_bydst) |
2091 | xfrm_state_byspi = xfrm_hash_alloc(sz); | 2083 | goto out_bydst; |
2092 | if (!xfrm_state_bydst || !xfrm_state_bysrc || !xfrm_state_byspi) | 2084 | net->xfrm.state_bysrc = xfrm_hash_alloc(sz); |
2093 | panic("XFRM: Cannot allocate bydst/bysrc/byspi hashes."); | 2085 | if (!net->xfrm.state_bysrc) |
2094 | xfrm_state_hmask = ((sz / sizeof(struct hlist_head)) - 1); | 2086 | goto out_bysrc; |
2087 | net->xfrm.state_byspi = xfrm_hash_alloc(sz); | ||
2088 | if (!net->xfrm.state_byspi) | ||
2089 | goto out_byspi; | ||
2090 | net->xfrm.state_hmask = ((sz / sizeof(struct hlist_head)) - 1); | ||
2091 | |||
2092 | net->xfrm.state_num = 0; | ||
2093 | INIT_WORK(&net->xfrm.state_hash_work, xfrm_hash_resize); | ||
2094 | INIT_HLIST_HEAD(&net->xfrm.state_gc_list); | ||
2095 | INIT_WORK(&net->xfrm.state_gc_work, xfrm_state_gc_task); | ||
2096 | init_waitqueue_head(&net->xfrm.km_waitq); | ||
2097 | return 0; | ||
2095 | 2098 | ||
2096 | INIT_WORK(&xfrm_state_gc_work, xfrm_state_gc_task); | 2099 | out_byspi: |
2100 | xfrm_hash_free(net->xfrm.state_bysrc, sz); | ||
2101 | out_bysrc: | ||
2102 | xfrm_hash_free(net->xfrm.state_bydst, sz); | ||
2103 | out_bydst: | ||
2104 | return -ENOMEM; | ||
2105 | } | ||
2106 | |||
2107 | void xfrm_state_fini(struct net *net) | ||
2108 | { | ||
2109 | struct xfrm_audit audit_info; | ||
2110 | unsigned int sz; | ||
2111 | |||
2112 | flush_work(&net->xfrm.state_hash_work); | ||
2113 | audit_info.loginuid = -1; | ||
2114 | audit_info.sessionid = -1; | ||
2115 | audit_info.secid = 0; | ||
2116 | xfrm_state_flush(net, IPSEC_PROTO_ANY, &audit_info); | ||
2117 | flush_work(&net->xfrm.state_gc_work); | ||
2118 | |||
2119 | WARN_ON(!list_empty(&net->xfrm.state_all)); | ||
2120 | |||
2121 | sz = (net->xfrm.state_hmask + 1) * sizeof(struct hlist_head); | ||
2122 | WARN_ON(!hlist_empty(net->xfrm.state_byspi)); | ||
2123 | xfrm_hash_free(net->xfrm.state_byspi, sz); | ||
2124 | WARN_ON(!hlist_empty(net->xfrm.state_bysrc)); | ||
2125 | xfrm_hash_free(net->xfrm.state_bysrc, sz); | ||
2126 | WARN_ON(!hlist_empty(net->xfrm.state_bydst)); | ||
2127 | xfrm_hash_free(net->xfrm.state_bydst, sz); | ||
2097 | } | 2128 | } |
2098 | 2129 | ||
2099 | #ifdef CONFIG_AUDITSYSCALL | 2130 | #ifdef CONFIG_AUDITSYSCALL |
@@ -2109,16 +2140,12 @@ static void xfrm_audit_helper_sainfo(struct xfrm_state *x, | |||
2109 | 2140 | ||
2110 | switch(x->props.family) { | 2141 | switch(x->props.family) { |
2111 | case AF_INET: | 2142 | case AF_INET: |
2112 | audit_log_format(audit_buf, | 2143 | audit_log_format(audit_buf, " src=%pI4 dst=%pI4", |
2113 | " src=" NIPQUAD_FMT " dst=" NIPQUAD_FMT, | 2144 | &x->props.saddr.a4, &x->id.daddr.a4); |
2114 | NIPQUAD(x->props.saddr.a4), | ||
2115 | NIPQUAD(x->id.daddr.a4)); | ||
2116 | break; | 2145 | break; |
2117 | case AF_INET6: | 2146 | case AF_INET6: |
2118 | audit_log_format(audit_buf, | 2147 | audit_log_format(audit_buf, " src=%pI6 dst=%pI6", |
2119 | " src=" NIP6_FMT " dst=" NIP6_FMT, | 2148 | x->props.saddr.a6, x->id.daddr.a6); |
2120 | NIP6(*(struct in6_addr *)x->props.saddr.a6), | ||
2121 | NIP6(*(struct in6_addr *)x->id.daddr.a6)); | ||
2122 | break; | 2149 | break; |
2123 | } | 2150 | } |
2124 | 2151 | ||
@@ -2134,18 +2161,14 @@ static void xfrm_audit_helper_pktinfo(struct sk_buff *skb, u16 family, | |||
2134 | switch (family) { | 2161 | switch (family) { |
2135 | case AF_INET: | 2162 | case AF_INET: |
2136 | iph4 = ip_hdr(skb); | 2163 | iph4 = ip_hdr(skb); |
2137 | audit_log_format(audit_buf, | 2164 | audit_log_format(audit_buf, " src=%pI4 dst=%pI4", |
2138 | " src=" NIPQUAD_FMT " dst=" NIPQUAD_FMT, | 2165 | &iph4->saddr, &iph4->daddr); |
2139 | NIPQUAD(iph4->saddr), | ||
2140 | NIPQUAD(iph4->daddr)); | ||
2141 | break; | 2166 | break; |
2142 | case AF_INET6: | 2167 | case AF_INET6: |
2143 | iph6 = ipv6_hdr(skb); | 2168 | iph6 = ipv6_hdr(skb); |
2144 | audit_log_format(audit_buf, | 2169 | audit_log_format(audit_buf, |
2145 | " src=" NIP6_FMT " dst=" NIP6_FMT | 2170 | " src=%pI6 dst=%pI6 flowlbl=0x%x%02x%02x", |
2146 | " flowlbl=0x%x%02x%02x", | 2171 | &iph6->saddr,&iph6->daddr, |
2147 | NIP6(iph6->saddr), | ||
2148 | NIP6(iph6->daddr), | ||
2149 | iph6->flow_lbl[0] & 0x0f, | 2172 | iph6->flow_lbl[0] & 0x0f, |
2150 | iph6->flow_lbl[1], | 2173 | iph6->flow_lbl[1], |
2151 | iph6->flow_lbl[2]); | 2174 | iph6->flow_lbl[2]); |
diff --git a/net/xfrm/xfrm_sysctl.c b/net/xfrm/xfrm_sysctl.c new file mode 100644 index 000000000000..2e6ffb66f06f --- /dev/null +++ b/net/xfrm/xfrm_sysctl.c | |||
@@ -0,0 +1,85 @@ | |||
1 | #include <linux/sysctl.h> | ||
2 | #include <net/net_namespace.h> | ||
3 | #include <net/xfrm.h> | ||
4 | |||
5 | static void __xfrm_sysctl_init(struct net *net) | ||
6 | { | ||
7 | net->xfrm.sysctl_aevent_etime = XFRM_AE_ETIME; | ||
8 | net->xfrm.sysctl_aevent_rseqth = XFRM_AE_SEQT_SIZE; | ||
9 | net->xfrm.sysctl_larval_drop = 1; | ||
10 | net->xfrm.sysctl_acq_expires = 30; | ||
11 | } | ||
12 | |||
13 | #ifdef CONFIG_SYSCTL | ||
14 | static struct ctl_table xfrm_table[] = { | ||
15 | { | ||
16 | .ctl_name = NET_CORE_AEVENT_ETIME, | ||
17 | .procname = "xfrm_aevent_etime", | ||
18 | .maxlen = sizeof(u32), | ||
19 | .mode = 0644, | ||
20 | .proc_handler = proc_dointvec | ||
21 | }, | ||
22 | { | ||
23 | .ctl_name = NET_CORE_AEVENT_RSEQTH, | ||
24 | .procname = "xfrm_aevent_rseqth", | ||
25 | .maxlen = sizeof(u32), | ||
26 | .mode = 0644, | ||
27 | .proc_handler = proc_dointvec | ||
28 | }, | ||
29 | { | ||
30 | .ctl_name = CTL_UNNUMBERED, | ||
31 | .procname = "xfrm_larval_drop", | ||
32 | .maxlen = sizeof(int), | ||
33 | .mode = 0644, | ||
34 | .proc_handler = proc_dointvec | ||
35 | }, | ||
36 | { | ||
37 | .ctl_name = CTL_UNNUMBERED, | ||
38 | .procname = "xfrm_acq_expires", | ||
39 | .maxlen = sizeof(int), | ||
40 | .mode = 0644, | ||
41 | .proc_handler = proc_dointvec | ||
42 | }, | ||
43 | {} | ||
44 | }; | ||
45 | |||
46 | int __net_init xfrm_sysctl_init(struct net *net) | ||
47 | { | ||
48 | struct ctl_table *table; | ||
49 | |||
50 | __xfrm_sysctl_init(net); | ||
51 | |||
52 | table = kmemdup(xfrm_table, sizeof(xfrm_table), GFP_KERNEL); | ||
53 | if (!table) | ||
54 | goto out_kmemdup; | ||
55 | table[0].data = &net->xfrm.sysctl_aevent_etime; | ||
56 | table[1].data = &net->xfrm.sysctl_aevent_rseqth; | ||
57 | table[2].data = &net->xfrm.sysctl_larval_drop; | ||
58 | table[3].data = &net->xfrm.sysctl_acq_expires; | ||
59 | |||
60 | net->xfrm.sysctl_hdr = register_net_sysctl_table(net, net_core_path, table); | ||
61 | if (!net->xfrm.sysctl_hdr) | ||
62 | goto out_register; | ||
63 | return 0; | ||
64 | |||
65 | out_register: | ||
66 | kfree(table); | ||
67 | out_kmemdup: | ||
68 | return -ENOMEM; | ||
69 | } | ||
70 | |||
71 | void xfrm_sysctl_fini(struct net *net) | ||
72 | { | ||
73 | struct ctl_table *table; | ||
74 | |||
75 | table = net->xfrm.sysctl_hdr->ctl_table_arg; | ||
76 | unregister_net_sysctl_table(net->xfrm.sysctl_hdr); | ||
77 | kfree(table); | ||
78 | } | ||
79 | #else | ||
80 | int __net_init xfrm_sysctl_init(struct net *net) | ||
81 | { | ||
82 | __xfrm_sysctl_init(net); | ||
83 | return 0; | ||
84 | } | ||
85 | #endif | ||
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index a278a6f3b991..38ffaf33312e 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) | |||
316 | x->replay_maxdiff = nla_get_u32(rt); | 316 | x->replay_maxdiff = nla_get_u32(rt); |
317 | } | 317 | } |
318 | 318 | ||
319 | static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p, | 319 | static struct xfrm_state *xfrm_state_construct(struct net *net, |
320 | struct xfrm_usersa_info *p, | ||
320 | struct nlattr **attrs, | 321 | struct nlattr **attrs, |
321 | int *errp) | 322 | int *errp) |
322 | { | 323 | { |
323 | struct xfrm_state *x = xfrm_state_alloc(); | 324 | struct xfrm_state *x = xfrm_state_alloc(net); |
324 | int err = -ENOMEM; | 325 | int err = -ENOMEM; |
325 | 326 | ||
326 | if (!x) | 327 | if (!x) |
@@ -367,9 +368,9 @@ static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p, | |||
367 | goto error; | 368 | goto error; |
368 | 369 | ||
369 | x->km.seq = p->seq; | 370 | x->km.seq = p->seq; |
370 | x->replay_maxdiff = sysctl_xfrm_aevent_rseqth; | 371 | x->replay_maxdiff = net->xfrm.sysctl_aevent_rseqth; |
371 | /* sysctl_xfrm_aevent_etime is in 100ms units */ | 372 | /* sysctl_xfrm_aevent_etime is in 100ms units */ |
372 | x->replay_maxage = (sysctl_xfrm_aevent_etime*HZ)/XFRM_AE_ETH_M; | 373 | x->replay_maxage = (net->xfrm.sysctl_aevent_etime*HZ)/XFRM_AE_ETH_M; |
373 | x->preplay.bitmap = 0; | 374 | x->preplay.bitmap = 0; |
374 | x->preplay.seq = x->replay.seq+x->replay_maxdiff; | 375 | x->preplay.seq = x->replay.seq+x->replay_maxdiff; |
375 | x->preplay.oseq = x->replay.oseq +x->replay_maxdiff; | 376 | x->preplay.oseq = x->replay.oseq +x->replay_maxdiff; |
@@ -391,6 +392,7 @@ error_no_put: | |||
391 | static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, | 392 | static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, |
392 | struct nlattr **attrs) | 393 | struct nlattr **attrs) |
393 | { | 394 | { |
395 | struct net *net = sock_net(skb->sk); | ||
394 | struct xfrm_usersa_info *p = nlmsg_data(nlh); | 396 | struct xfrm_usersa_info *p = nlmsg_data(nlh); |
395 | struct xfrm_state *x; | 397 | struct xfrm_state *x; |
396 | int err; | 398 | int err; |
@@ -403,7 +405,7 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
403 | if (err) | 405 | if (err) |
404 | return err; | 406 | return err; |
405 | 407 | ||
406 | x = xfrm_state_construct(p, attrs, &err); | 408 | x = xfrm_state_construct(net, p, attrs, &err); |
407 | if (!x) | 409 | if (!x) |
408 | return err; | 410 | return err; |
409 | 411 | ||
@@ -431,7 +433,8 @@ out: | |||
431 | return err; | 433 | return err; |
432 | } | 434 | } |
433 | 435 | ||
434 | static struct xfrm_state *xfrm_user_state_lookup(struct xfrm_usersa_id *p, | 436 | static struct xfrm_state *xfrm_user_state_lookup(struct net *net, |
437 | struct xfrm_usersa_id *p, | ||
435 | struct nlattr **attrs, | 438 | struct nlattr **attrs, |
436 | int *errp) | 439 | int *errp) |
437 | { | 440 | { |
@@ -440,7 +443,7 @@ static struct xfrm_state *xfrm_user_state_lookup(struct xfrm_usersa_id *p, | |||
440 | 443 | ||
441 | if (xfrm_id_proto_match(p->proto, IPSEC_PROTO_ANY)) { | 444 | if (xfrm_id_proto_match(p->proto, IPSEC_PROTO_ANY)) { |
442 | err = -ESRCH; | 445 | err = -ESRCH; |
443 | x = xfrm_state_lookup(&p->daddr, p->spi, p->proto, p->family); | 446 | x = xfrm_state_lookup(net, &p->daddr, p->spi, p->proto, p->family); |
444 | } else { | 447 | } else { |
445 | xfrm_address_t *saddr = NULL; | 448 | xfrm_address_t *saddr = NULL; |
446 | 449 | ||
@@ -451,8 +454,8 @@ static struct xfrm_state *xfrm_user_state_lookup(struct xfrm_usersa_id *p, | |||
451 | } | 454 | } |
452 | 455 | ||
453 | err = -ESRCH; | 456 | err = -ESRCH; |
454 | x = xfrm_state_lookup_byaddr(&p->daddr, saddr, p->proto, | 457 | x = xfrm_state_lookup_byaddr(net, &p->daddr, saddr, |
455 | p->family); | 458 | p->proto, p->family); |
456 | } | 459 | } |
457 | 460 | ||
458 | out: | 461 | out: |
@@ -464,6 +467,7 @@ static struct xfrm_state *xfrm_user_state_lookup(struct xfrm_usersa_id *p, | |||
464 | static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, | 467 | static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, |
465 | struct nlattr **attrs) | 468 | struct nlattr **attrs) |
466 | { | 469 | { |
470 | struct net *net = sock_net(skb->sk); | ||
467 | struct xfrm_state *x; | 471 | struct xfrm_state *x; |
468 | int err = -ESRCH; | 472 | int err = -ESRCH; |
469 | struct km_event c; | 473 | struct km_event c; |
@@ -472,7 +476,7 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
472 | u32 sessionid = NETLINK_CB(skb).sessionid; | 476 | u32 sessionid = NETLINK_CB(skb).sessionid; |
473 | u32 sid = NETLINK_CB(skb).sid; | 477 | u32 sid = NETLINK_CB(skb).sid; |
474 | 478 | ||
475 | x = xfrm_user_state_lookup(p, attrs, &err); | 479 | x = xfrm_user_state_lookup(net, p, attrs, &err); |
476 | if (x == NULL) | 480 | if (x == NULL) |
477 | return err; | 481 | return err; |
478 | 482 | ||
@@ -615,6 +619,7 @@ static int xfrm_dump_sa_done(struct netlink_callback *cb) | |||
615 | 619 | ||
616 | static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb) | 620 | static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb) |
617 | { | 621 | { |
622 | struct net *net = sock_net(skb->sk); | ||
618 | struct xfrm_state_walk *walk = (struct xfrm_state_walk *) &cb->args[1]; | 623 | struct xfrm_state_walk *walk = (struct xfrm_state_walk *) &cb->args[1]; |
619 | struct xfrm_dump_info info; | 624 | struct xfrm_dump_info info; |
620 | 625 | ||
@@ -631,7 +636,7 @@ static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb) | |||
631 | xfrm_state_walk_init(walk, 0); | 636 | xfrm_state_walk_init(walk, 0); |
632 | } | 637 | } |
633 | 638 | ||
634 | (void) xfrm_state_walk(walk, dump_one_state, &info); | 639 | (void) xfrm_state_walk(net, walk, dump_one_state, &info); |
635 | 640 | ||
636 | return skb->len; | 641 | return skb->len; |
637 | } | 642 | } |
@@ -703,6 +708,7 @@ nla_put_failure: | |||
703 | static int xfrm_get_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh, | 708 | static int xfrm_get_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh, |
704 | struct nlattr **attrs) | 709 | struct nlattr **attrs) |
705 | { | 710 | { |
711 | struct net *net = sock_net(skb->sk); | ||
706 | struct sk_buff *r_skb; | 712 | struct sk_buff *r_skb; |
707 | u32 *flags = nlmsg_data(nlh); | 713 | u32 *flags = nlmsg_data(nlh); |
708 | u32 spid = NETLINK_CB(skb).pid; | 714 | u32 spid = NETLINK_CB(skb).pid; |
@@ -715,7 +721,7 @@ static int xfrm_get_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
715 | if (build_spdinfo(r_skb, spid, seq, *flags) < 0) | 721 | if (build_spdinfo(r_skb, spid, seq, *flags) < 0) |
716 | BUG(); | 722 | BUG(); |
717 | 723 | ||
718 | return nlmsg_unicast(xfrm_nl, r_skb, spid); | 724 | return nlmsg_unicast(net->xfrm.nlsk, r_skb, spid); |
719 | } | 725 | } |
720 | 726 | ||
721 | static inline size_t xfrm_sadinfo_msgsize(void) | 727 | static inline size_t xfrm_sadinfo_msgsize(void) |
@@ -756,6 +762,7 @@ nla_put_failure: | |||
756 | static int xfrm_get_sadinfo(struct sk_buff *skb, struct nlmsghdr *nlh, | 762 | static int xfrm_get_sadinfo(struct sk_buff *skb, struct nlmsghdr *nlh, |
757 | struct nlattr **attrs) | 763 | struct nlattr **attrs) |
758 | { | 764 | { |
765 | struct net *net = sock_net(skb->sk); | ||
759 | struct sk_buff *r_skb; | 766 | struct sk_buff *r_skb; |
760 | u32 *flags = nlmsg_data(nlh); | 767 | u32 *flags = nlmsg_data(nlh); |
761 | u32 spid = NETLINK_CB(skb).pid; | 768 | u32 spid = NETLINK_CB(skb).pid; |
@@ -768,18 +775,19 @@ static int xfrm_get_sadinfo(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
768 | if (build_sadinfo(r_skb, spid, seq, *flags) < 0) | 775 | if (build_sadinfo(r_skb, spid, seq, *flags) < 0) |
769 | BUG(); | 776 | BUG(); |
770 | 777 | ||
771 | return nlmsg_unicast(xfrm_nl, r_skb, spid); | 778 | return nlmsg_unicast(net->xfrm.nlsk, r_skb, spid); |
772 | } | 779 | } |
773 | 780 | ||
774 | static int xfrm_get_sa(struct sk_buff *skb, struct nlmsghdr *nlh, | 781 | static int xfrm_get_sa(struct sk_buff *skb, struct nlmsghdr *nlh, |
775 | struct nlattr **attrs) | 782 | struct nlattr **attrs) |
776 | { | 783 | { |
784 | struct net *net = sock_net(skb->sk); | ||
777 | struct xfrm_usersa_id *p = nlmsg_data(nlh); | 785 | struct xfrm_usersa_id *p = nlmsg_data(nlh); |
778 | struct xfrm_state *x; | 786 | struct xfrm_state *x; |
779 | struct sk_buff *resp_skb; | 787 | struct sk_buff *resp_skb; |
780 | int err = -ESRCH; | 788 | int err = -ESRCH; |
781 | 789 | ||
782 | x = xfrm_user_state_lookup(p, attrs, &err); | 790 | x = xfrm_user_state_lookup(net, p, attrs, &err); |
783 | if (x == NULL) | 791 | if (x == NULL) |
784 | goto out_noput; | 792 | goto out_noput; |
785 | 793 | ||
@@ -787,7 +795,7 @@ static int xfrm_get_sa(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
787 | if (IS_ERR(resp_skb)) { | 795 | if (IS_ERR(resp_skb)) { |
788 | err = PTR_ERR(resp_skb); | 796 | err = PTR_ERR(resp_skb); |
789 | } else { | 797 | } else { |
790 | err = nlmsg_unicast(xfrm_nl, resp_skb, NETLINK_CB(skb).pid); | 798 | err = nlmsg_unicast(net->xfrm.nlsk, resp_skb, NETLINK_CB(skb).pid); |
791 | } | 799 | } |
792 | xfrm_state_put(x); | 800 | xfrm_state_put(x); |
793 | out_noput: | 801 | out_noput: |
@@ -820,6 +828,7 @@ static int verify_userspi_info(struct xfrm_userspi_info *p) | |||
820 | static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, | 828 | static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, |
821 | struct nlattr **attrs) | 829 | struct nlattr **attrs) |
822 | { | 830 | { |
831 | struct net *net = sock_net(skb->sk); | ||
823 | struct xfrm_state *x; | 832 | struct xfrm_state *x; |
824 | struct xfrm_userspi_info *p; | 833 | struct xfrm_userspi_info *p; |
825 | struct sk_buff *resp_skb; | 834 | struct sk_buff *resp_skb; |
@@ -837,7 +846,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
837 | 846 | ||
838 | x = NULL; | 847 | x = NULL; |
839 | if (p->info.seq) { | 848 | if (p->info.seq) { |
840 | x = xfrm_find_acq_byseq(p->info.seq); | 849 | x = xfrm_find_acq_byseq(net, p->info.seq); |
841 | if (x && xfrm_addr_cmp(&x->id.daddr, daddr, family)) { | 850 | if (x && xfrm_addr_cmp(&x->id.daddr, daddr, family)) { |
842 | xfrm_state_put(x); | 851 | xfrm_state_put(x); |
843 | x = NULL; | 852 | x = NULL; |
@@ -845,7 +854,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
845 | } | 854 | } |
846 | 855 | ||
847 | if (!x) | 856 | if (!x) |
848 | x = xfrm_find_acq(p->info.mode, p->info.reqid, | 857 | x = xfrm_find_acq(net, p->info.mode, p->info.reqid, |
849 | p->info.id.proto, daddr, | 858 | p->info.id.proto, daddr, |
850 | &p->info.saddr, 1, | 859 | &p->info.saddr, 1, |
851 | family); | 860 | family); |
@@ -863,7 +872,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
863 | goto out; | 872 | goto out; |
864 | } | 873 | } |
865 | 874 | ||
866 | err = nlmsg_unicast(xfrm_nl, resp_skb, NETLINK_CB(skb).pid); | 875 | err = nlmsg_unicast(net->xfrm.nlsk, resp_skb, NETLINK_CB(skb).pid); |
867 | 876 | ||
868 | out: | 877 | out: |
869 | xfrm_state_put(x); | 878 | xfrm_state_put(x); |
@@ -1078,9 +1087,9 @@ static void copy_to_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_i | |||
1078 | p->share = XFRM_SHARE_ANY; /* XXX xp->share */ | 1087 | p->share = XFRM_SHARE_ANY; /* XXX xp->share */ |
1079 | } | 1088 | } |
1080 | 1089 | ||
1081 | static struct xfrm_policy *xfrm_policy_construct(struct xfrm_userpolicy_info *p, struct nlattr **attrs, int *errp) | 1090 | static struct xfrm_policy *xfrm_policy_construct(struct net *net, struct xfrm_userpolicy_info *p, struct nlattr **attrs, int *errp) |
1082 | { | 1091 | { |
1083 | struct xfrm_policy *xp = xfrm_policy_alloc(GFP_KERNEL); | 1092 | struct xfrm_policy *xp = xfrm_policy_alloc(net, GFP_KERNEL); |
1084 | int err; | 1093 | int err; |
1085 | 1094 | ||
1086 | if (!xp) { | 1095 | if (!xp) { |
@@ -1110,6 +1119,7 @@ static struct xfrm_policy *xfrm_policy_construct(struct xfrm_userpolicy_info *p, | |||
1110 | static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | 1119 | static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, |
1111 | struct nlattr **attrs) | 1120 | struct nlattr **attrs) |
1112 | { | 1121 | { |
1122 | struct net *net = sock_net(skb->sk); | ||
1113 | struct xfrm_userpolicy_info *p = nlmsg_data(nlh); | 1123 | struct xfrm_userpolicy_info *p = nlmsg_data(nlh); |
1114 | struct xfrm_policy *xp; | 1124 | struct xfrm_policy *xp; |
1115 | struct km_event c; | 1125 | struct km_event c; |
@@ -1126,7 +1136,7 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1126 | if (err) | 1136 | if (err) |
1127 | return err; | 1137 | return err; |
1128 | 1138 | ||
1129 | xp = xfrm_policy_construct(p, attrs, &err); | 1139 | xp = xfrm_policy_construct(net, p, attrs, &err); |
1130 | if (!xp) | 1140 | if (!xp) |
1131 | return err; | 1141 | return err; |
1132 | 1142 | ||
@@ -1263,6 +1273,7 @@ static int xfrm_dump_policy_done(struct netlink_callback *cb) | |||
1263 | 1273 | ||
1264 | static int xfrm_dump_policy(struct sk_buff *skb, struct netlink_callback *cb) | 1274 | static int xfrm_dump_policy(struct sk_buff *skb, struct netlink_callback *cb) |
1265 | { | 1275 | { |
1276 | struct net *net = sock_net(skb->sk); | ||
1266 | struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1]; | 1277 | struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1]; |
1267 | struct xfrm_dump_info info; | 1278 | struct xfrm_dump_info info; |
1268 | 1279 | ||
@@ -1279,7 +1290,7 @@ static int xfrm_dump_policy(struct sk_buff *skb, struct netlink_callback *cb) | |||
1279 | xfrm_policy_walk_init(walk, XFRM_POLICY_TYPE_ANY); | 1290 | xfrm_policy_walk_init(walk, XFRM_POLICY_TYPE_ANY); |
1280 | } | 1291 | } |
1281 | 1292 | ||
1282 | (void) xfrm_policy_walk(walk, dump_one_policy, &info); | 1293 | (void) xfrm_policy_walk(net, walk, dump_one_policy, &info); |
1283 | 1294 | ||
1284 | return skb->len; | 1295 | return skb->len; |
1285 | } | 1296 | } |
@@ -1311,6 +1322,7 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb, | |||
1311 | static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | 1322 | static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, |
1312 | struct nlattr **attrs) | 1323 | struct nlattr **attrs) |
1313 | { | 1324 | { |
1325 | struct net *net = sock_net(skb->sk); | ||
1314 | struct xfrm_policy *xp; | 1326 | struct xfrm_policy *xp; |
1315 | struct xfrm_userpolicy_id *p; | 1327 | struct xfrm_userpolicy_id *p; |
1316 | u8 type = XFRM_POLICY_TYPE_MAIN; | 1328 | u8 type = XFRM_POLICY_TYPE_MAIN; |
@@ -1330,7 +1342,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1330 | return err; | 1342 | return err; |
1331 | 1343 | ||
1332 | if (p->index) | 1344 | if (p->index) |
1333 | xp = xfrm_policy_byid(type, p->dir, p->index, delete, &err); | 1345 | xp = xfrm_policy_byid(net, type, p->dir, p->index, delete, &err); |
1334 | else { | 1346 | else { |
1335 | struct nlattr *rt = attrs[XFRMA_SEC_CTX]; | 1347 | struct nlattr *rt = attrs[XFRMA_SEC_CTX]; |
1336 | struct xfrm_sec_ctx *ctx; | 1348 | struct xfrm_sec_ctx *ctx; |
@@ -1347,7 +1359,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1347 | if (err) | 1359 | if (err) |
1348 | return err; | 1360 | return err; |
1349 | } | 1361 | } |
1350 | xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, ctx, | 1362 | xp = xfrm_policy_bysel_ctx(net, type, p->dir, &p->sel, ctx, |
1351 | delete, &err); | 1363 | delete, &err); |
1352 | security_xfrm_policy_free(ctx); | 1364 | security_xfrm_policy_free(ctx); |
1353 | } | 1365 | } |
@@ -1361,7 +1373,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1361 | if (IS_ERR(resp_skb)) { | 1373 | if (IS_ERR(resp_skb)) { |
1362 | err = PTR_ERR(resp_skb); | 1374 | err = PTR_ERR(resp_skb); |
1363 | } else { | 1375 | } else { |
1364 | err = nlmsg_unicast(xfrm_nl, resp_skb, | 1376 | err = nlmsg_unicast(net->xfrm.nlsk, resp_skb, |
1365 | NETLINK_CB(skb).pid); | 1377 | NETLINK_CB(skb).pid); |
1366 | } | 1378 | } |
1367 | } else { | 1379 | } else { |
@@ -1390,6 +1402,7 @@ out: | |||
1390 | static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, | 1402 | static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, |
1391 | struct nlattr **attrs) | 1403 | struct nlattr **attrs) |
1392 | { | 1404 | { |
1405 | struct net *net = sock_net(skb->sk); | ||
1393 | struct km_event c; | 1406 | struct km_event c; |
1394 | struct xfrm_usersa_flush *p = nlmsg_data(nlh); | 1407 | struct xfrm_usersa_flush *p = nlmsg_data(nlh); |
1395 | struct xfrm_audit audit_info; | 1408 | struct xfrm_audit audit_info; |
@@ -1398,13 +1411,14 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1398 | audit_info.loginuid = NETLINK_CB(skb).loginuid; | 1411 | audit_info.loginuid = NETLINK_CB(skb).loginuid; |
1399 | audit_info.sessionid = NETLINK_CB(skb).sessionid; | 1412 | audit_info.sessionid = NETLINK_CB(skb).sessionid; |
1400 | audit_info.secid = NETLINK_CB(skb).sid; | 1413 | audit_info.secid = NETLINK_CB(skb).sid; |
1401 | err = xfrm_state_flush(p->proto, &audit_info); | 1414 | err = xfrm_state_flush(net, p->proto, &audit_info); |
1402 | if (err) | 1415 | if (err) |
1403 | return err; | 1416 | return err; |
1404 | c.data.proto = p->proto; | 1417 | c.data.proto = p->proto; |
1405 | c.event = nlh->nlmsg_type; | 1418 | c.event = nlh->nlmsg_type; |
1406 | c.seq = nlh->nlmsg_seq; | 1419 | c.seq = nlh->nlmsg_seq; |
1407 | c.pid = nlh->nlmsg_pid; | 1420 | c.pid = nlh->nlmsg_pid; |
1421 | c.net = net; | ||
1408 | km_state_notify(NULL, &c); | 1422 | km_state_notify(NULL, &c); |
1409 | 1423 | ||
1410 | return 0; | 1424 | return 0; |
@@ -1457,6 +1471,7 @@ nla_put_failure: | |||
1457 | static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, | 1471 | static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, |
1458 | struct nlattr **attrs) | 1472 | struct nlattr **attrs) |
1459 | { | 1473 | { |
1474 | struct net *net = sock_net(skb->sk); | ||
1460 | struct xfrm_state *x; | 1475 | struct xfrm_state *x; |
1461 | struct sk_buff *r_skb; | 1476 | struct sk_buff *r_skb; |
1462 | int err; | 1477 | int err; |
@@ -1468,7 +1483,7 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1468 | if (r_skb == NULL) | 1483 | if (r_skb == NULL) |
1469 | return -ENOMEM; | 1484 | return -ENOMEM; |
1470 | 1485 | ||
1471 | x = xfrm_state_lookup(&id->daddr, id->spi, id->proto, id->family); | 1486 | x = xfrm_state_lookup(net, &id->daddr, id->spi, id->proto, id->family); |
1472 | if (x == NULL) { | 1487 | if (x == NULL) { |
1473 | kfree_skb(r_skb); | 1488 | kfree_skb(r_skb); |
1474 | return -ESRCH; | 1489 | return -ESRCH; |
@@ -1486,7 +1501,7 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1486 | 1501 | ||
1487 | if (build_aevent(r_skb, x, &c) < 0) | 1502 | if (build_aevent(r_skb, x, &c) < 0) |
1488 | BUG(); | 1503 | BUG(); |
1489 | err = nlmsg_unicast(xfrm_nl, r_skb, NETLINK_CB(skb).pid); | 1504 | err = nlmsg_unicast(net->xfrm.nlsk, r_skb, NETLINK_CB(skb).pid); |
1490 | spin_unlock_bh(&x->lock); | 1505 | spin_unlock_bh(&x->lock); |
1491 | xfrm_state_put(x); | 1506 | xfrm_state_put(x); |
1492 | return err; | 1507 | return err; |
@@ -1495,6 +1510,7 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1495 | static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, | 1510 | static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, |
1496 | struct nlattr **attrs) | 1511 | struct nlattr **attrs) |
1497 | { | 1512 | { |
1513 | struct net *net = sock_net(skb->sk); | ||
1498 | struct xfrm_state *x; | 1514 | struct xfrm_state *x; |
1499 | struct km_event c; | 1515 | struct km_event c; |
1500 | int err = - EINVAL; | 1516 | int err = - EINVAL; |
@@ -1509,7 +1525,7 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1509 | if (!(nlh->nlmsg_flags&NLM_F_REPLACE)) | 1525 | if (!(nlh->nlmsg_flags&NLM_F_REPLACE)) |
1510 | return err; | 1526 | return err; |
1511 | 1527 | ||
1512 | x = xfrm_state_lookup(&p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family); | 1528 | x = xfrm_state_lookup(net, &p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family); |
1513 | if (x == NULL) | 1529 | if (x == NULL) |
1514 | return -ESRCH; | 1530 | return -ESRCH; |
1515 | 1531 | ||
@@ -1534,6 +1550,7 @@ out: | |||
1534 | static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | 1550 | static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, |
1535 | struct nlattr **attrs) | 1551 | struct nlattr **attrs) |
1536 | { | 1552 | { |
1553 | struct net *net = sock_net(skb->sk); | ||
1537 | struct km_event c; | 1554 | struct km_event c; |
1538 | u8 type = XFRM_POLICY_TYPE_MAIN; | 1555 | u8 type = XFRM_POLICY_TYPE_MAIN; |
1539 | int err; | 1556 | int err; |
@@ -1546,13 +1563,14 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1546 | audit_info.loginuid = NETLINK_CB(skb).loginuid; | 1563 | audit_info.loginuid = NETLINK_CB(skb).loginuid; |
1547 | audit_info.sessionid = NETLINK_CB(skb).sessionid; | 1564 | audit_info.sessionid = NETLINK_CB(skb).sessionid; |
1548 | audit_info.secid = NETLINK_CB(skb).sid; | 1565 | audit_info.secid = NETLINK_CB(skb).sid; |
1549 | err = xfrm_policy_flush(type, &audit_info); | 1566 | err = xfrm_policy_flush(net, type, &audit_info); |
1550 | if (err) | 1567 | if (err) |
1551 | return err; | 1568 | return err; |
1552 | c.data.type = type; | 1569 | c.data.type = type; |
1553 | c.event = nlh->nlmsg_type; | 1570 | c.event = nlh->nlmsg_type; |
1554 | c.seq = nlh->nlmsg_seq; | 1571 | c.seq = nlh->nlmsg_seq; |
1555 | c.pid = nlh->nlmsg_pid; | 1572 | c.pid = nlh->nlmsg_pid; |
1573 | c.net = net; | ||
1556 | km_policy_notify(NULL, 0, &c); | 1574 | km_policy_notify(NULL, 0, &c); |
1557 | return 0; | 1575 | return 0; |
1558 | } | 1576 | } |
@@ -1560,6 +1578,7 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1560 | static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, | 1578 | static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, |
1561 | struct nlattr **attrs) | 1579 | struct nlattr **attrs) |
1562 | { | 1580 | { |
1581 | struct net *net = sock_net(skb->sk); | ||
1563 | struct xfrm_policy *xp; | 1582 | struct xfrm_policy *xp; |
1564 | struct xfrm_user_polexpire *up = nlmsg_data(nlh); | 1583 | struct xfrm_user_polexpire *up = nlmsg_data(nlh); |
1565 | struct xfrm_userpolicy_info *p = &up->pol; | 1584 | struct xfrm_userpolicy_info *p = &up->pol; |
@@ -1571,7 +1590,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1571 | return err; | 1590 | return err; |
1572 | 1591 | ||
1573 | if (p->index) | 1592 | if (p->index) |
1574 | xp = xfrm_policy_byid(type, p->dir, p->index, 0, &err); | 1593 | xp = xfrm_policy_byid(net, type, p->dir, p->index, 0, &err); |
1575 | else { | 1594 | else { |
1576 | struct nlattr *rt = attrs[XFRMA_SEC_CTX]; | 1595 | struct nlattr *rt = attrs[XFRMA_SEC_CTX]; |
1577 | struct xfrm_sec_ctx *ctx; | 1596 | struct xfrm_sec_ctx *ctx; |
@@ -1588,7 +1607,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1588 | if (err) | 1607 | if (err) |
1589 | return err; | 1608 | return err; |
1590 | } | 1609 | } |
1591 | xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, ctx, 0, &err); | 1610 | xp = xfrm_policy_bysel_ctx(net, type, p->dir, &p->sel, ctx, 0, &err); |
1592 | security_xfrm_policy_free(ctx); | 1611 | security_xfrm_policy_free(ctx); |
1593 | } | 1612 | } |
1594 | if (xp == NULL) | 1613 | if (xp == NULL) |
@@ -1623,12 +1642,13 @@ out: | |||
1623 | static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, | 1642 | static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, |
1624 | struct nlattr **attrs) | 1643 | struct nlattr **attrs) |
1625 | { | 1644 | { |
1645 | struct net *net = sock_net(skb->sk); | ||
1626 | struct xfrm_state *x; | 1646 | struct xfrm_state *x; |
1627 | int err; | 1647 | int err; |
1628 | struct xfrm_user_expire *ue = nlmsg_data(nlh); | 1648 | struct xfrm_user_expire *ue = nlmsg_data(nlh); |
1629 | struct xfrm_usersa_info *p = &ue->state; | 1649 | struct xfrm_usersa_info *p = &ue->state; |
1630 | 1650 | ||
1631 | x = xfrm_state_lookup(&p->id.daddr, p->id.spi, p->id.proto, p->family); | 1651 | x = xfrm_state_lookup(net, &p->id.daddr, p->id.spi, p->id.proto, p->family); |
1632 | 1652 | ||
1633 | err = -ENOENT; | 1653 | err = -ENOENT; |
1634 | if (x == NULL) | 1654 | if (x == NULL) |
@@ -1657,13 +1677,14 @@ out: | |||
1657 | static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, | 1677 | static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, |
1658 | struct nlattr **attrs) | 1678 | struct nlattr **attrs) |
1659 | { | 1679 | { |
1680 | struct net *net = sock_net(skb->sk); | ||
1660 | struct xfrm_policy *xp; | 1681 | struct xfrm_policy *xp; |
1661 | struct xfrm_user_tmpl *ut; | 1682 | struct xfrm_user_tmpl *ut; |
1662 | int i; | 1683 | int i; |
1663 | struct nlattr *rt = attrs[XFRMA_TMPL]; | 1684 | struct nlattr *rt = attrs[XFRMA_TMPL]; |
1664 | 1685 | ||
1665 | struct xfrm_user_acquire *ua = nlmsg_data(nlh); | 1686 | struct xfrm_user_acquire *ua = nlmsg_data(nlh); |
1666 | struct xfrm_state *x = xfrm_state_alloc(); | 1687 | struct xfrm_state *x = xfrm_state_alloc(net); |
1667 | int err = -ENOMEM; | 1688 | int err = -ENOMEM; |
1668 | 1689 | ||
1669 | if (!x) | 1690 | if (!x) |
@@ -1677,7 +1698,7 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1677 | } | 1698 | } |
1678 | 1699 | ||
1679 | /* build an XP */ | 1700 | /* build an XP */ |
1680 | xp = xfrm_policy_construct(&ua->policy, attrs, &err); | 1701 | xp = xfrm_policy_construct(net, &ua->policy, attrs, &err); |
1681 | if (!xp) { | 1702 | if (!xp) { |
1682 | kfree(x); | 1703 | kfree(x); |
1683 | return err; | 1704 | return err; |
@@ -1869,6 +1890,7 @@ static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | |||
1869 | struct xfrm_migrate *m, int num_migrate, | 1890 | struct xfrm_migrate *m, int num_migrate, |
1870 | struct xfrm_kmaddress *k) | 1891 | struct xfrm_kmaddress *k) |
1871 | { | 1892 | { |
1893 | struct net *net = &init_net; | ||
1872 | struct sk_buff *skb; | 1894 | struct sk_buff *skb; |
1873 | 1895 | ||
1874 | skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate, !!k), GFP_ATOMIC); | 1896 | skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate, !!k), GFP_ATOMIC); |
@@ -1879,7 +1901,7 @@ static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | |||
1879 | if (build_migrate(skb, m, num_migrate, k, sel, dir, type) < 0) | 1901 | if (build_migrate(skb, m, num_migrate, k, sel, dir, type) < 0) |
1880 | BUG(); | 1902 | BUG(); |
1881 | 1903 | ||
1882 | return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_MIGRATE, GFP_ATOMIC); | 1904 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_MIGRATE, GFP_ATOMIC); |
1883 | } | 1905 | } |
1884 | #else | 1906 | #else |
1885 | static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, | 1907 | static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type, |
@@ -1968,6 +1990,7 @@ static struct xfrm_link { | |||
1968 | 1990 | ||
1969 | static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | 1991 | static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) |
1970 | { | 1992 | { |
1993 | struct net *net = sock_net(skb->sk); | ||
1971 | struct nlattr *attrs[XFRMA_MAX+1]; | 1994 | struct nlattr *attrs[XFRMA_MAX+1]; |
1972 | struct xfrm_link *link; | 1995 | struct xfrm_link *link; |
1973 | int type, err; | 1996 | int type, err; |
@@ -1989,7 +2012,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
1989 | if (link->dump == NULL) | 2012 | if (link->dump == NULL) |
1990 | return -EINVAL; | 2013 | return -EINVAL; |
1991 | 2014 | ||
1992 | return netlink_dump_start(xfrm_nl, skb, nlh, link->dump, link->done); | 2015 | return netlink_dump_start(net->xfrm.nlsk, skb, nlh, link->dump, link->done); |
1993 | } | 2016 | } |
1994 | 2017 | ||
1995 | err = nlmsg_parse(nlh, xfrm_msg_min[type], attrs, XFRMA_MAX, | 2018 | err = nlmsg_parse(nlh, xfrm_msg_min[type], attrs, XFRMA_MAX, |
@@ -2033,6 +2056,7 @@ static int build_expire(struct sk_buff *skb, struct xfrm_state *x, struct km_eve | |||
2033 | 2056 | ||
2034 | static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c) | 2057 | static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c) |
2035 | { | 2058 | { |
2059 | struct net *net = xs_net(x); | ||
2036 | struct sk_buff *skb; | 2060 | struct sk_buff *skb; |
2037 | 2061 | ||
2038 | skb = nlmsg_new(xfrm_expire_msgsize(), GFP_ATOMIC); | 2062 | skb = nlmsg_new(xfrm_expire_msgsize(), GFP_ATOMIC); |
@@ -2042,11 +2066,12 @@ static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c) | |||
2042 | if (build_expire(skb, x, c) < 0) | 2066 | if (build_expire(skb, x, c) < 0) |
2043 | BUG(); | 2067 | BUG(); |
2044 | 2068 | ||
2045 | return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); | 2069 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); |
2046 | } | 2070 | } |
2047 | 2071 | ||
2048 | static int xfrm_aevent_state_notify(struct xfrm_state *x, struct km_event *c) | 2072 | static int xfrm_aevent_state_notify(struct xfrm_state *x, struct km_event *c) |
2049 | { | 2073 | { |
2074 | struct net *net = xs_net(x); | ||
2050 | struct sk_buff *skb; | 2075 | struct sk_buff *skb; |
2051 | 2076 | ||
2052 | skb = nlmsg_new(xfrm_aevent_msgsize(), GFP_ATOMIC); | 2077 | skb = nlmsg_new(xfrm_aevent_msgsize(), GFP_ATOMIC); |
@@ -2056,11 +2081,12 @@ static int xfrm_aevent_state_notify(struct xfrm_state *x, struct km_event *c) | |||
2056 | if (build_aevent(skb, x, c) < 0) | 2081 | if (build_aevent(skb, x, c) < 0) |
2057 | BUG(); | 2082 | BUG(); |
2058 | 2083 | ||
2059 | return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_AEVENTS, GFP_ATOMIC); | 2084 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_AEVENTS, GFP_ATOMIC); |
2060 | } | 2085 | } |
2061 | 2086 | ||
2062 | static int xfrm_notify_sa_flush(struct km_event *c) | 2087 | static int xfrm_notify_sa_flush(struct km_event *c) |
2063 | { | 2088 | { |
2089 | struct net *net = c->net; | ||
2064 | struct xfrm_usersa_flush *p; | 2090 | struct xfrm_usersa_flush *p; |
2065 | struct nlmsghdr *nlh; | 2091 | struct nlmsghdr *nlh; |
2066 | struct sk_buff *skb; | 2092 | struct sk_buff *skb; |
@@ -2081,7 +2107,7 @@ static int xfrm_notify_sa_flush(struct km_event *c) | |||
2081 | 2107 | ||
2082 | nlmsg_end(skb, nlh); | 2108 | nlmsg_end(skb, nlh); |
2083 | 2109 | ||
2084 | return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC); | 2110 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC); |
2085 | } | 2111 | } |
2086 | 2112 | ||
2087 | static inline size_t xfrm_sa_len(struct xfrm_state *x) | 2113 | static inline size_t xfrm_sa_len(struct xfrm_state *x) |
@@ -2111,6 +2137,7 @@ static inline size_t xfrm_sa_len(struct xfrm_state *x) | |||
2111 | 2137 | ||
2112 | static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c) | 2138 | static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c) |
2113 | { | 2139 | { |
2140 | struct net *net = xs_net(x); | ||
2114 | struct xfrm_usersa_info *p; | 2141 | struct xfrm_usersa_info *p; |
2115 | struct xfrm_usersa_id *id; | 2142 | struct xfrm_usersa_id *id; |
2116 | struct nlmsghdr *nlh; | 2143 | struct nlmsghdr *nlh; |
@@ -2155,7 +2182,7 @@ static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c) | |||
2155 | 2182 | ||
2156 | nlmsg_end(skb, nlh); | 2183 | nlmsg_end(skb, nlh); |
2157 | 2184 | ||
2158 | return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC); | 2185 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC); |
2159 | 2186 | ||
2160 | nla_put_failure: | 2187 | nla_put_failure: |
2161 | /* Somebody screwed up with xfrm_sa_len! */ | 2188 | /* Somebody screwed up with xfrm_sa_len! */ |
@@ -2235,6 +2262,7 @@ nlmsg_failure: | |||
2235 | static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt, | 2262 | static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt, |
2236 | struct xfrm_policy *xp, int dir) | 2263 | struct xfrm_policy *xp, int dir) |
2237 | { | 2264 | { |
2265 | struct net *net = xs_net(x); | ||
2238 | struct sk_buff *skb; | 2266 | struct sk_buff *skb; |
2239 | 2267 | ||
2240 | skb = nlmsg_new(xfrm_acquire_msgsize(x, xp), GFP_ATOMIC); | 2268 | skb = nlmsg_new(xfrm_acquire_msgsize(x, xp), GFP_ATOMIC); |
@@ -2244,7 +2272,7 @@ static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt, | |||
2244 | if (build_acquire(skb, x, xt, xp, dir) < 0) | 2272 | if (build_acquire(skb, x, xt, xp, dir) < 0) |
2245 | BUG(); | 2273 | BUG(); |
2246 | 2274 | ||
2247 | return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_ACQUIRE, GFP_ATOMIC); | 2275 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_ACQUIRE, GFP_ATOMIC); |
2248 | } | 2276 | } |
2249 | 2277 | ||
2250 | /* User gives us xfrm_user_policy_info followed by an array of 0 | 2278 | /* User gives us xfrm_user_policy_info followed by an array of 0 |
@@ -2253,6 +2281,7 @@ static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt, | |||
2253 | static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt, | 2281 | static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt, |
2254 | u8 *data, int len, int *dir) | 2282 | u8 *data, int len, int *dir) |
2255 | { | 2283 | { |
2284 | struct net *net = sock_net(sk); | ||
2256 | struct xfrm_userpolicy_info *p = (struct xfrm_userpolicy_info *)data; | 2285 | struct xfrm_userpolicy_info *p = (struct xfrm_userpolicy_info *)data; |
2257 | struct xfrm_user_tmpl *ut = (struct xfrm_user_tmpl *) (p + 1); | 2286 | struct xfrm_user_tmpl *ut = (struct xfrm_user_tmpl *) (p + 1); |
2258 | struct xfrm_policy *xp; | 2287 | struct xfrm_policy *xp; |
@@ -2291,7 +2320,7 @@ static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt, | |||
2291 | if (p->dir > XFRM_POLICY_OUT) | 2320 | if (p->dir > XFRM_POLICY_OUT) |
2292 | return NULL; | 2321 | return NULL; |
2293 | 2322 | ||
2294 | xp = xfrm_policy_alloc(GFP_KERNEL); | 2323 | xp = xfrm_policy_alloc(net, GFP_KERNEL); |
2295 | if (xp == NULL) { | 2324 | if (xp == NULL) { |
2296 | *dir = -ENOBUFS; | 2325 | *dir = -ENOBUFS; |
2297 | return NULL; | 2326 | return NULL; |
@@ -2344,6 +2373,7 @@ nlmsg_failure: | |||
2344 | 2373 | ||
2345 | static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c) | 2374 | static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c) |
2346 | { | 2375 | { |
2376 | struct net *net = xp_net(xp); | ||
2347 | struct sk_buff *skb; | 2377 | struct sk_buff *skb; |
2348 | 2378 | ||
2349 | skb = nlmsg_new(xfrm_polexpire_msgsize(xp), GFP_ATOMIC); | 2379 | skb = nlmsg_new(xfrm_polexpire_msgsize(xp), GFP_ATOMIC); |
@@ -2353,11 +2383,12 @@ static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_eve | |||
2353 | if (build_polexpire(skb, xp, dir, c) < 0) | 2383 | if (build_polexpire(skb, xp, dir, c) < 0) |
2354 | BUG(); | 2384 | BUG(); |
2355 | 2385 | ||
2356 | return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); | 2386 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); |
2357 | } | 2387 | } |
2358 | 2388 | ||
2359 | static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c) | 2389 | static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c) |
2360 | { | 2390 | { |
2391 | struct net *net = xp_net(xp); | ||
2361 | struct xfrm_userpolicy_info *p; | 2392 | struct xfrm_userpolicy_info *p; |
2362 | struct xfrm_userpolicy_id *id; | 2393 | struct xfrm_userpolicy_id *id; |
2363 | struct nlmsghdr *nlh; | 2394 | struct nlmsghdr *nlh; |
@@ -2408,7 +2439,7 @@ static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event * | |||
2408 | 2439 | ||
2409 | nlmsg_end(skb, nlh); | 2440 | nlmsg_end(skb, nlh); |
2410 | 2441 | ||
2411 | return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC); | 2442 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC); |
2412 | 2443 | ||
2413 | nlmsg_failure: | 2444 | nlmsg_failure: |
2414 | kfree_skb(skb); | 2445 | kfree_skb(skb); |
@@ -2417,6 +2448,7 @@ nlmsg_failure: | |||
2417 | 2448 | ||
2418 | static int xfrm_notify_policy_flush(struct km_event *c) | 2449 | static int xfrm_notify_policy_flush(struct km_event *c) |
2419 | { | 2450 | { |
2451 | struct net *net = c->net; | ||
2420 | struct nlmsghdr *nlh; | 2452 | struct nlmsghdr *nlh; |
2421 | struct sk_buff *skb; | 2453 | struct sk_buff *skb; |
2422 | 2454 | ||
@@ -2432,7 +2464,7 @@ static int xfrm_notify_policy_flush(struct km_event *c) | |||
2432 | 2464 | ||
2433 | nlmsg_end(skb, nlh); | 2465 | nlmsg_end(skb, nlh); |
2434 | 2466 | ||
2435 | return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC); | 2467 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC); |
2436 | 2468 | ||
2437 | nlmsg_failure: | 2469 | nlmsg_failure: |
2438 | kfree_skb(skb); | 2470 | kfree_skb(skb); |
@@ -2488,8 +2520,8 @@ nla_put_failure: | |||
2488 | return -EMSGSIZE; | 2520 | return -EMSGSIZE; |
2489 | } | 2521 | } |
2490 | 2522 | ||
2491 | static int xfrm_send_report(u8 proto, struct xfrm_selector *sel, | 2523 | static int xfrm_send_report(struct net *net, u8 proto, |
2492 | xfrm_address_t *addr) | 2524 | struct xfrm_selector *sel, xfrm_address_t *addr) |
2493 | { | 2525 | { |
2494 | struct sk_buff *skb; | 2526 | struct sk_buff *skb; |
2495 | 2527 | ||
@@ -2500,7 +2532,59 @@ static int xfrm_send_report(u8 proto, struct xfrm_selector *sel, | |||
2500 | if (build_report(skb, proto, sel, addr) < 0) | 2532 | if (build_report(skb, proto, sel, addr) < 0) |
2501 | BUG(); | 2533 | BUG(); |
2502 | 2534 | ||
2503 | return nlmsg_multicast(xfrm_nl, skb, 0, XFRMNLGRP_REPORT, GFP_ATOMIC); | 2535 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_REPORT, GFP_ATOMIC); |
2536 | } | ||
2537 | |||
2538 | static inline size_t xfrm_mapping_msgsize(void) | ||
2539 | { | ||
2540 | return NLMSG_ALIGN(sizeof(struct xfrm_user_mapping)); | ||
2541 | } | ||
2542 | |||
2543 | static int build_mapping(struct sk_buff *skb, struct xfrm_state *x, | ||
2544 | xfrm_address_t *new_saddr, __be16 new_sport) | ||
2545 | { | ||
2546 | struct xfrm_user_mapping *um; | ||
2547 | struct nlmsghdr *nlh; | ||
2548 | |||
2549 | nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_MAPPING, sizeof(*um), 0); | ||
2550 | if (nlh == NULL) | ||
2551 | return -EMSGSIZE; | ||
2552 | |||
2553 | um = nlmsg_data(nlh); | ||
2554 | |||
2555 | memcpy(&um->id.daddr, &x->id.daddr, sizeof(um->id.daddr)); | ||
2556 | um->id.spi = x->id.spi; | ||
2557 | um->id.family = x->props.family; | ||
2558 | um->id.proto = x->id.proto; | ||
2559 | memcpy(&um->new_saddr, new_saddr, sizeof(um->new_saddr)); | ||
2560 | memcpy(&um->old_saddr, &x->props.saddr, sizeof(um->old_saddr)); | ||
2561 | um->new_sport = new_sport; | ||
2562 | um->old_sport = x->encap->encap_sport; | ||
2563 | um->reqid = x->props.reqid; | ||
2564 | |||
2565 | return nlmsg_end(skb, nlh); | ||
2566 | } | ||
2567 | |||
2568 | static int xfrm_send_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, | ||
2569 | __be16 sport) | ||
2570 | { | ||
2571 | struct net *net = xs_net(x); | ||
2572 | struct sk_buff *skb; | ||
2573 | |||
2574 | if (x->id.proto != IPPROTO_ESP) | ||
2575 | return -EINVAL; | ||
2576 | |||
2577 | if (!x->encap) | ||
2578 | return -EINVAL; | ||
2579 | |||
2580 | skb = nlmsg_new(xfrm_mapping_msgsize(), GFP_ATOMIC); | ||
2581 | if (skb == NULL) | ||
2582 | return -ENOMEM; | ||
2583 | |||
2584 | if (build_mapping(skb, x, ipaddr, sport) < 0) | ||
2585 | BUG(); | ||
2586 | |||
2587 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_MAPPING, GFP_ATOMIC); | ||
2504 | } | 2588 | } |
2505 | 2589 | ||
2506 | static struct xfrm_mgr netlink_mgr = { | 2590 | static struct xfrm_mgr netlink_mgr = { |
@@ -2511,35 +2595,56 @@ static struct xfrm_mgr netlink_mgr = { | |||
2511 | .notify_policy = xfrm_send_policy_notify, | 2595 | .notify_policy = xfrm_send_policy_notify, |
2512 | .report = xfrm_send_report, | 2596 | .report = xfrm_send_report, |
2513 | .migrate = xfrm_send_migrate, | 2597 | .migrate = xfrm_send_migrate, |
2598 | .new_mapping = xfrm_send_mapping, | ||
2514 | }; | 2599 | }; |
2515 | 2600 | ||
2516 | static int __init xfrm_user_init(void) | 2601 | static int __net_init xfrm_user_net_init(struct net *net) |
2517 | { | 2602 | { |
2518 | struct sock *nlsk; | 2603 | struct sock *nlsk; |
2519 | 2604 | ||
2520 | printk(KERN_INFO "Initializing XFRM netlink socket\n"); | 2605 | nlsk = netlink_kernel_create(net, NETLINK_XFRM, XFRMNLGRP_MAX, |
2521 | |||
2522 | nlsk = netlink_kernel_create(&init_net, NETLINK_XFRM, XFRMNLGRP_MAX, | ||
2523 | xfrm_netlink_rcv, NULL, THIS_MODULE); | 2606 | xfrm_netlink_rcv, NULL, THIS_MODULE); |
2524 | if (nlsk == NULL) | 2607 | if (nlsk == NULL) |
2525 | return -ENOMEM; | 2608 | return -ENOMEM; |
2526 | rcu_assign_pointer(xfrm_nl, nlsk); | 2609 | rcu_assign_pointer(net->xfrm.nlsk, nlsk); |
2527 | |||
2528 | xfrm_register_km(&netlink_mgr); | ||
2529 | |||
2530 | return 0; | 2610 | return 0; |
2531 | } | 2611 | } |
2532 | 2612 | ||
2533 | static void __exit xfrm_user_exit(void) | 2613 | static void __net_exit xfrm_user_net_exit(struct net *net) |
2534 | { | 2614 | { |
2535 | struct sock *nlsk = xfrm_nl; | 2615 | struct sock *nlsk = net->xfrm.nlsk; |
2536 | 2616 | ||
2537 | xfrm_unregister_km(&netlink_mgr); | 2617 | rcu_assign_pointer(net->xfrm.nlsk, NULL); |
2538 | rcu_assign_pointer(xfrm_nl, NULL); | ||
2539 | synchronize_rcu(); | 2618 | synchronize_rcu(); |
2540 | netlink_kernel_release(nlsk); | 2619 | netlink_kernel_release(nlsk); |
2541 | } | 2620 | } |
2542 | 2621 | ||
2622 | static struct pernet_operations xfrm_user_net_ops = { | ||
2623 | .init = xfrm_user_net_init, | ||
2624 | .exit = xfrm_user_net_exit, | ||
2625 | }; | ||
2626 | |||
2627 | static int __init xfrm_user_init(void) | ||
2628 | { | ||
2629 | int rv; | ||
2630 | |||
2631 | printk(KERN_INFO "Initializing XFRM netlink socket\n"); | ||
2632 | |||
2633 | rv = register_pernet_subsys(&xfrm_user_net_ops); | ||
2634 | if (rv < 0) | ||
2635 | return rv; | ||
2636 | rv = xfrm_register_km(&netlink_mgr); | ||
2637 | if (rv < 0) | ||
2638 | unregister_pernet_subsys(&xfrm_user_net_ops); | ||
2639 | return rv; | ||
2640 | } | ||
2641 | |||
2642 | static void __exit xfrm_user_exit(void) | ||
2643 | { | ||
2644 | xfrm_unregister_km(&netlink_mgr); | ||
2645 | unregister_pernet_subsys(&xfrm_user_net_ops); | ||
2646 | } | ||
2647 | |||
2543 | module_init(xfrm_user_init); | 2648 | module_init(xfrm_user_init); |
2544 | module_exit(xfrm_user_exit); | 2649 | module_exit(xfrm_user_exit); |
2545 | MODULE_LICENSE("GPL"); | 2650 | MODULE_LICENSE("GPL"); |