Blame view
net/xfrm/xfrm_user.c
68.8 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 8 9 |
/* xfrm_user.c: User interface to configure xfrm engine. * * Copyright (C) 2002 David S. Miller (davem@redhat.com) * * Changes: * Mitsuru KANDA @USAGI * Kazunori MIYAZAWA @USAGI * Kunihiro Ishiguro <kunihiro@ipinfusion.com> * IPv6 support |
df71837d5 [LSM-IPSec]: Secu... |
10 |
* |
1da177e4c Linux-2.6.12-rc2 |
11 |
*/ |
9409f38a0 [IPSEC]: Move lin... |
12 |
#include <linux/crypto.h> |
1da177e4c Linux-2.6.12-rc2 |
13 14 15 16 17 18 19 20 |
#include <linux/module.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/slab.h> #include <linux/socket.h> #include <linux/string.h> #include <linux/net.h> #include <linux/skbuff.h> |
1da177e4c Linux-2.6.12-rc2 |
21 22 23 24 25 26 |
#include <linux/pfkeyv2.h> #include <linux/ipsec.h> #include <linux/init.h> #include <linux/security.h> #include <net/sock.h> #include <net/xfrm.h> |
88fc2c843 [XFRM]: Use gener... |
27 |
#include <net/netlink.h> |
fa6dd8a2c xfrm: check trunc... |
28 |
#include <net/ah.h> |
1da177e4c Linux-2.6.12-rc2 |
29 |
#include <asm/uaccess.h> |
dfd56b8b3 net: use IS_ENABL... |
30 |
#if IS_ENABLED(CONFIG_IPV6) |
e23c7194a [XFRM] STATE: Add... |
31 32 |
#include <linux/in6.h> #endif |
1da177e4c Linux-2.6.12-rc2 |
33 |
|
1a6509d99 [IPSEC]: Add supp... |
34 35 36 37 |
static inline int aead_len(struct xfrm_algo_aead *alg) { return sizeof(*alg) + ((alg->alg_key_len + 7) / 8); } |
5424f32e4 [XFRM] netlink: U... |
38 |
static int verify_one_alg(struct nlattr **attrs, enum xfrm_attr_type_t type) |
1da177e4c Linux-2.6.12-rc2 |
39 |
{ |
5424f32e4 [XFRM] netlink: U... |
40 |
struct nlattr *rt = attrs[type]; |
1da177e4c Linux-2.6.12-rc2 |
41 42 43 44 |
struct xfrm_algo *algp; if (!rt) return 0; |
5424f32e4 [XFRM] netlink: U... |
45 |
algp = nla_data(rt); |
0f99be0d1 [XFRM]: xfrm_algo... |
46 |
if (nla_len(rt) < xfrm_alg_len(algp)) |
31c26852c [IPSEC]: Verify k... |
47 |
return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
48 49 |
switch (type) { case XFRMA_ALG_AUTH: |
1da177e4c Linux-2.6.12-rc2 |
50 |
case XFRMA_ALG_CRYPT: |
1da177e4c Linux-2.6.12-rc2 |
51 |
case XFRMA_ALG_COMP: |
1da177e4c Linux-2.6.12-rc2 |
52 53 54 55 |
break; default: return -EINVAL; |
3ff50b799 [NET]: cleanup ex... |
56 |
} |
1da177e4c Linux-2.6.12-rc2 |
57 58 59 60 |
algp->alg_name[CRYPTO_MAX_ALG_NAME - 1] = '\0'; return 0; } |
4447bb33f xfrm: Store aalg ... |
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
static int verify_auth_trunc(struct nlattr **attrs) { struct nlattr *rt = attrs[XFRMA_ALG_AUTH_TRUNC]; struct xfrm_algo_auth *algp; if (!rt) return 0; algp = nla_data(rt); if (nla_len(rt) < xfrm_alg_auth_len(algp)) return -EINVAL; algp->alg_name[CRYPTO_MAX_ALG_NAME - 1] = '\0'; return 0; } |
1a6509d99 [IPSEC]: Add supp... |
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
static int verify_aead(struct nlattr **attrs) { struct nlattr *rt = attrs[XFRMA_ALG_AEAD]; struct xfrm_algo_aead *algp; if (!rt) return 0; algp = nla_data(rt); if (nla_len(rt) < aead_len(algp)) return -EINVAL; algp->alg_name[CRYPTO_MAX_ALG_NAME - 1] = '\0'; return 0; } |
5424f32e4 [XFRM] netlink: U... |
91 |
static void verify_one_addr(struct nlattr **attrs, enum xfrm_attr_type_t type, |
eb2971b68 [XFRM] STATE: Sea... |
92 93 |
xfrm_address_t **addrp) { |
5424f32e4 [XFRM] netlink: U... |
94 |
struct nlattr *rt = attrs[type]; |
eb2971b68 [XFRM] STATE: Sea... |
95 |
|
cf5cb79f6 [XFRM] netlink: E... |
96 |
if (rt && addrp) |
5424f32e4 [XFRM] netlink: U... |
97 |
*addrp = nla_data(rt); |
eb2971b68 [XFRM] STATE: Sea... |
98 |
} |
df71837d5 [LSM-IPSec]: Secu... |
99 |
|
5424f32e4 [XFRM] netlink: U... |
100 |
static inline int verify_sec_ctx_len(struct nlattr **attrs) |
df71837d5 [LSM-IPSec]: Secu... |
101 |
{ |
5424f32e4 [XFRM] netlink: U... |
102 |
struct nlattr *rt = attrs[XFRMA_SEC_CTX]; |
df71837d5 [LSM-IPSec]: Secu... |
103 |
struct xfrm_user_sec_ctx *uctx; |
df71837d5 [LSM-IPSec]: Secu... |
104 105 106 |
if (!rt) return 0; |
5424f32e4 [XFRM] netlink: U... |
107 |
uctx = nla_data(rt); |
cf5cb79f6 [XFRM] netlink: E... |
108 |
if (uctx->len != (sizeof(struct xfrm_user_sec_ctx) + uctx->ctx_len)) |
df71837d5 [LSM-IPSec]: Secu... |
109 110 111 112 |
return -EINVAL; return 0; } |
d8647b79c xfrm: Add user in... |
113 114 115 116 |
static inline int verify_replay(struct xfrm_usersa_info *p, struct nlattr **attrs) { struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL]; |
7833aa05b xfrm: Check for t... |
117 118 |
if ((p->flags & XFRM_STATE_ESN) && !rt) return -EINVAL; |
d8647b79c xfrm: Add user in... |
119 120 |
if (!rt) return 0; |
02aadf72f xfrm: Restrict ex... |
121 122 |
if (p->id.proto != IPPROTO_ESP) return -EINVAL; |
d8647b79c xfrm: Add user in... |
123 124 125 126 127 |
if (p->replay_window != 0) return -EINVAL; return 0; } |
df71837d5 [LSM-IPSec]: Secu... |
128 |
|
1da177e4c Linux-2.6.12-rc2 |
129 |
static int verify_newsa_info(struct xfrm_usersa_info *p, |
5424f32e4 [XFRM] netlink: U... |
130 |
struct nlattr **attrs) |
1da177e4c Linux-2.6.12-rc2 |
131 132 133 134 135 136 137 138 139 |
{ int err; err = -EINVAL; switch (p->family) { case AF_INET: break; case AF_INET6: |
dfd56b8b3 net: use IS_ENABL... |
140 |
#if IS_ENABLED(CONFIG_IPV6) |
1da177e4c Linux-2.6.12-rc2 |
141 142 143 144 145 146 147 148 |
break; #else err = -EAFNOSUPPORT; goto out; #endif default: goto out; |
3ff50b799 [NET]: cleanup ex... |
149 |
} |
1da177e4c Linux-2.6.12-rc2 |
150 151 152 153 |
err = -EINVAL; switch (p->id.proto) { case IPPROTO_AH: |
4447bb33f xfrm: Store aalg ... |
154 155 |
if ((!attrs[XFRMA_ALG_AUTH] && !attrs[XFRMA_ALG_AUTH_TRUNC]) || |
1a6509d99 [IPSEC]: Add supp... |
156 |
attrs[XFRMA_ALG_AEAD] || |
35a7aa08b [XFRM] netlink: R... |
157 |
attrs[XFRMA_ALG_CRYPT] || |
35d2856b4 xfrm: Add Traffic... |
158 159 |
attrs[XFRMA_ALG_COMP] || attrs[XFRMA_TFCPAD]) |
1da177e4c Linux-2.6.12-rc2 |
160 161 162 163 |
goto out; break; case IPPROTO_ESP: |
1a6509d99 [IPSEC]: Add supp... |
164 165 166 |
if (attrs[XFRMA_ALG_COMP]) goto out; if (!attrs[XFRMA_ALG_AUTH] && |
4447bb33f xfrm: Store aalg ... |
167 |
!attrs[XFRMA_ALG_AUTH_TRUNC] && |
1a6509d99 [IPSEC]: Add supp... |
168 169 170 171 |
!attrs[XFRMA_ALG_CRYPT] && !attrs[XFRMA_ALG_AEAD]) goto out; if ((attrs[XFRMA_ALG_AUTH] || |
4447bb33f xfrm: Store aalg ... |
172 |
attrs[XFRMA_ALG_AUTH_TRUNC] || |
1a6509d99 [IPSEC]: Add supp... |
173 174 |
attrs[XFRMA_ALG_CRYPT]) && attrs[XFRMA_ALG_AEAD]) |
1da177e4c Linux-2.6.12-rc2 |
175 |
goto out; |
35d2856b4 xfrm: Add Traffic... |
176 177 178 |
if (attrs[XFRMA_TFCPAD] && p->mode != XFRM_MODE_TUNNEL) goto out; |
1da177e4c Linux-2.6.12-rc2 |
179 180 181 |
break; case IPPROTO_COMP: |
35a7aa08b [XFRM] netlink: R... |
182 |
if (!attrs[XFRMA_ALG_COMP] || |
1a6509d99 [IPSEC]: Add supp... |
183 |
attrs[XFRMA_ALG_AEAD] || |
35a7aa08b [XFRM] netlink: R... |
184 |
attrs[XFRMA_ALG_AUTH] || |
4447bb33f xfrm: Store aalg ... |
185 |
attrs[XFRMA_ALG_AUTH_TRUNC] || |
35d2856b4 xfrm: Add Traffic... |
186 187 |
attrs[XFRMA_ALG_CRYPT] || attrs[XFRMA_TFCPAD]) |
1da177e4c Linux-2.6.12-rc2 |
188 189 |
goto out; break; |
dfd56b8b3 net: use IS_ENABL... |
190 |
#if IS_ENABLED(CONFIG_IPV6) |
e23c7194a [XFRM] STATE: Add... |
191 192 |
case IPPROTO_DSTOPTS: case IPPROTO_ROUTING: |
35a7aa08b [XFRM] netlink: R... |
193 194 |
if (attrs[XFRMA_ALG_COMP] || attrs[XFRMA_ALG_AUTH] || |
4447bb33f xfrm: Store aalg ... |
195 |
attrs[XFRMA_ALG_AUTH_TRUNC] || |
1a6509d99 [IPSEC]: Add supp... |
196 |
attrs[XFRMA_ALG_AEAD] || |
35a7aa08b [XFRM] netlink: R... |
197 198 199 |
attrs[XFRMA_ALG_CRYPT] || attrs[XFRMA_ENCAP] || attrs[XFRMA_SEC_CTX] || |
35d2856b4 xfrm: Add Traffic... |
200 |
attrs[XFRMA_TFCPAD] || |
35a7aa08b [XFRM] netlink: R... |
201 |
!attrs[XFRMA_COADDR]) |
e23c7194a [XFRM] STATE: Add... |
202 203 204 |
goto out; break; #endif |
1da177e4c Linux-2.6.12-rc2 |
205 206 |
default: goto out; |
3ff50b799 [NET]: cleanup ex... |
207 |
} |
1da177e4c Linux-2.6.12-rc2 |
208 |
|
1a6509d99 [IPSEC]: Add supp... |
209 210 |
if ((err = verify_aead(attrs))) goto out; |
4447bb33f xfrm: Store aalg ... |
211 212 |
if ((err = verify_auth_trunc(attrs))) goto out; |
35a7aa08b [XFRM] netlink: R... |
213 |
if ((err = verify_one_alg(attrs, XFRMA_ALG_AUTH))) |
1da177e4c Linux-2.6.12-rc2 |
214 |
goto out; |
35a7aa08b [XFRM] netlink: R... |
215 |
if ((err = verify_one_alg(attrs, XFRMA_ALG_CRYPT))) |
1da177e4c Linux-2.6.12-rc2 |
216 |
goto out; |
35a7aa08b [XFRM] netlink: R... |
217 |
if ((err = verify_one_alg(attrs, XFRMA_ALG_COMP))) |
1da177e4c Linux-2.6.12-rc2 |
218 |
goto out; |
35a7aa08b [XFRM] netlink: R... |
219 |
if ((err = verify_sec_ctx_len(attrs))) |
df71837d5 [LSM-IPSec]: Secu... |
220 |
goto out; |
d8647b79c xfrm: Add user in... |
221 222 |
if ((err = verify_replay(p, attrs))) goto out; |
1da177e4c Linux-2.6.12-rc2 |
223 224 225 |
err = -EINVAL; switch (p->mode) { |
7e49e6de3 [XFRM]: Add XFRM_... |
226 227 |
case XFRM_MODE_TRANSPORT: case XFRM_MODE_TUNNEL: |
060f02a3b [XFRM] STATE: Int... |
228 |
case XFRM_MODE_ROUTEOPTIMIZATION: |
0a69452cb [XFRM]: BEET mode |
229 |
case XFRM_MODE_BEET: |
1da177e4c Linux-2.6.12-rc2 |
230 231 232 233 |
break; default: goto out; |
3ff50b799 [NET]: cleanup ex... |
234 |
} |
1da177e4c Linux-2.6.12-rc2 |
235 236 237 238 239 240 241 242 |
err = 0; out: return err; } static int attach_one_algo(struct xfrm_algo **algpp, u8 *props, |
6f2f19ed9 xfrm: Pass name a... |
243 |
struct xfrm_algo_desc *(*get_byname)(const char *, int), |
5424f32e4 [XFRM] netlink: U... |
244 |
struct nlattr *rta) |
1da177e4c Linux-2.6.12-rc2 |
245 |
{ |
1da177e4c Linux-2.6.12-rc2 |
246 247 248 249 250 |
struct xfrm_algo *p, *ualg; struct xfrm_algo_desc *algo; if (!rta) return 0; |
5424f32e4 [XFRM] netlink: U... |
251 |
ualg = nla_data(rta); |
1da177e4c Linux-2.6.12-rc2 |
252 253 254 255 256 |
algo = get_byname(ualg->alg_name, 1); if (!algo) return -ENOSYS; *props = algo->desc.sadb_alg_id; |
0f99be0d1 [XFRM]: xfrm_algo... |
257 |
p = kmemdup(ualg, xfrm_alg_len(ualg), GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
258 259 |
if (!p) return -ENOMEM; |
04ff12609 [IPSEC]: Add comp... |
260 |
strcpy(p->alg_name, algo->name); |
1da177e4c Linux-2.6.12-rc2 |
261 262 263 |
*algpp = p; return 0; } |
4447bb33f xfrm: Store aalg ... |
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 |
static int attach_auth(struct xfrm_algo_auth **algpp, u8 *props, struct nlattr *rta) { struct xfrm_algo *ualg; struct xfrm_algo_auth *p; struct xfrm_algo_desc *algo; if (!rta) return 0; ualg = nla_data(rta); algo = xfrm_aalg_get_byname(ualg->alg_name, 1); if (!algo) return -ENOSYS; *props = algo->desc.sadb_alg_id; p = kmalloc(sizeof(*p) + (ualg->alg_key_len + 7) / 8, GFP_KERNEL); if (!p) return -ENOMEM; strcpy(p->alg_name, algo->name); p->alg_key_len = ualg->alg_key_len; p->alg_trunc_len = algo->uinfo.auth.icv_truncbits; memcpy(p->alg_key, ualg->alg_key, (ualg->alg_key_len + 7) / 8); *algpp = p; return 0; } static int attach_auth_trunc(struct xfrm_algo_auth **algpp, u8 *props, struct nlattr *rta) { struct xfrm_algo_auth *p, *ualg; struct xfrm_algo_desc *algo; if (!rta) return 0; ualg = nla_data(rta); algo = xfrm_aalg_get_byname(ualg->alg_name, 1); if (!algo) return -ENOSYS; |
fa6dd8a2c xfrm: check trunc... |
308 309 |
if ((ualg->alg_trunc_len / 8) > MAX_AH_AUTH_LEN || ualg->alg_trunc_len > algo->uinfo.auth.icv_fullbits) |
4447bb33f xfrm: Store aalg ... |
310 311 312 313 314 315 316 317 318 319 320 321 322 323 |
return -EINVAL; *props = algo->desc.sadb_alg_id; p = kmemdup(ualg, xfrm_alg_auth_len(ualg), GFP_KERNEL); if (!p) return -ENOMEM; strcpy(p->alg_name, algo->name); if (!p->alg_trunc_len) p->alg_trunc_len = algo->uinfo.auth.icv_truncbits; *algpp = p; return 0; } |
1a6509d99 [IPSEC]: Add supp... |
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 |
static int attach_aead(struct xfrm_algo_aead **algpp, u8 *props, struct nlattr *rta) { struct xfrm_algo_aead *p, *ualg; struct xfrm_algo_desc *algo; if (!rta) return 0; ualg = nla_data(rta); algo = xfrm_aead_get_byname(ualg->alg_name, ualg->alg_icv_len, 1); if (!algo) return -ENOSYS; *props = algo->desc.sadb_alg_id; p = kmemdup(ualg, aead_len(ualg), GFP_KERNEL); if (!p) return -ENOMEM; strcpy(p->alg_name, algo->name); *algpp = p; return 0; } |
e2b19125e xfrm: Check for e... |
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 |
static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_esn, struct nlattr *rp) { struct xfrm_replay_state_esn *up; if (!replay_esn || !rp) return 0; up = nla_data(rp); if (xfrm_replay_state_esn_len(replay_esn) != xfrm_replay_state_esn_len(up)) return -EINVAL; return 0; } |
d8647b79c xfrm: Add user in... |
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 |
static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn, struct xfrm_replay_state_esn **preplay_esn, struct nlattr *rta) { struct xfrm_replay_state_esn *p, *pp, *up; if (!rta) return 0; up = nla_data(rta); p = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL); if (!p) return -ENOMEM; pp = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL); if (!pp) { kfree(p); return -ENOMEM; } *replay_esn = p; *preplay_esn = pp; return 0; } |
661697f72 [IPSEC] XFRM_USER... |
390 |
static inline int xfrm_user_sec_ctx_size(struct xfrm_sec_ctx *xfrm_ctx) |
df71837d5 [LSM-IPSec]: Secu... |
391 |
{ |
df71837d5 [LSM-IPSec]: Secu... |
392 393 394 395 396 397 398 399 |
int len = 0; if (xfrm_ctx) { len += sizeof(struct xfrm_user_sec_ctx); len += xfrm_ctx->ctx_len; } return len; } |
1da177e4c Linux-2.6.12-rc2 |
400 401 402 403 404 405 406 407 408 |
static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p) { memcpy(&x->id, &p->id, sizeof(x->id)); memcpy(&x->sel, &p->sel, sizeof(x->sel)); memcpy(&x->lft, &p->lft, sizeof(x->lft)); x->props.mode = p->mode; x->props.replay_window = p->replay_window; x->props.reqid = p->reqid; x->props.family = p->family; |
54489c14c [XFRM] xfrm_user:... |
409 |
memcpy(&x->props.saddr, &p->saddr, sizeof(x->props.saddr)); |
1da177e4c Linux-2.6.12-rc2 |
410 |
x->props.flags = p->flags; |
196b00362 [IPSEC]: Ensure t... |
411 |
|
ccf9b3b83 xfrm: Add a XFRM_... |
412 |
if (!x->sel.family && !(p->flags & XFRM_STATE_AF_UNSPEC)) |
196b00362 [IPSEC]: Ensure t... |
413 |
x->sel.family = p->family; |
1da177e4c Linux-2.6.12-rc2 |
414 |
} |
d51d081d6 [IPSEC]: Sync ser... |
415 416 417 418 419 |
/* * someday when pfkey also has support, we could have the code * somehow made shareable and move it to xfrm_state.c - JHS * */ |
5424f32e4 [XFRM] netlink: U... |
420 |
static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs) |
d51d081d6 [IPSEC]: Sync ser... |
421 |
{ |
5424f32e4 [XFRM] netlink: U... |
422 |
struct nlattr *rp = attrs[XFRMA_REPLAY_VAL]; |
d8647b79c xfrm: Add user in... |
423 |
struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL]; |
5424f32e4 [XFRM] netlink: U... |
424 425 426 |
struct nlattr *lt = attrs[XFRMA_LTIME_VAL]; struct nlattr *et = attrs[XFRMA_ETIMER_THRESH]; struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH]; |
d51d081d6 [IPSEC]: Sync ser... |
427 |
|
d8647b79c xfrm: Add user in... |
428 429 430 431 432 433 434 435 |
if (re) { struct xfrm_replay_state_esn *replay_esn; replay_esn = nla_data(re); memcpy(x->replay_esn, replay_esn, xfrm_replay_state_esn_len(replay_esn)); memcpy(x->preplay_esn, replay_esn, xfrm_replay_state_esn_len(replay_esn)); } |
d51d081d6 [IPSEC]: Sync ser... |
436 437 |
if (rp) { struct xfrm_replay_state *replay; |
5424f32e4 [XFRM] netlink: U... |
438 |
replay = nla_data(rp); |
d51d081d6 [IPSEC]: Sync ser... |
439 440 441 442 443 444 |
memcpy(&x->replay, replay, sizeof(*replay)); memcpy(&x->preplay, replay, sizeof(*replay)); } if (lt) { struct xfrm_lifetime_cur *ltime; |
5424f32e4 [XFRM] netlink: U... |
445 |
ltime = nla_data(lt); |
d51d081d6 [IPSEC]: Sync ser... |
446 447 448 449 450 |
x->curlft.bytes = ltime->bytes; x->curlft.packets = ltime->packets; x->curlft.add_time = ltime->add_time; x->curlft.use_time = ltime->use_time; } |
cf5cb79f6 [XFRM] netlink: E... |
451 |
if (et) |
5424f32e4 [XFRM] netlink: U... |
452 |
x->replay_maxage = nla_get_u32(et); |
d51d081d6 [IPSEC]: Sync ser... |
453 |
|
cf5cb79f6 [XFRM] netlink: E... |
454 |
if (rt) |
5424f32e4 [XFRM] netlink: U... |
455 |
x->replay_maxdiff = nla_get_u32(rt); |
d51d081d6 [IPSEC]: Sync ser... |
456 |
} |
fc34acd36 netns xfrm: xfrm_... |
457 458 |
static struct xfrm_state *xfrm_state_construct(struct net *net, struct xfrm_usersa_info *p, |
5424f32e4 [XFRM] netlink: U... |
459 |
struct nlattr **attrs, |
1da177e4c Linux-2.6.12-rc2 |
460 461 |
int *errp) { |
fc34acd36 netns xfrm: xfrm_... |
462 |
struct xfrm_state *x = xfrm_state_alloc(net); |
1da177e4c Linux-2.6.12-rc2 |
463 464 465 466 467 468 |
int err = -ENOMEM; if (!x) goto error_no_put; copy_from_user_state(x, p); |
1a6509d99 [IPSEC]: Add supp... |
469 470 471 |
if ((err = attach_aead(&x->aead, &x->props.ealgo, attrs[XFRMA_ALG_AEAD]))) goto error; |
4447bb33f xfrm: Store aalg ... |
472 473 |
if ((err = attach_auth_trunc(&x->aalg, &x->props.aalgo, attrs[XFRMA_ALG_AUTH_TRUNC]))) |
1da177e4c Linux-2.6.12-rc2 |
474 |
goto error; |
4447bb33f xfrm: Store aalg ... |
475 476 477 478 479 |
if (!x->props.aalgo) { if ((err = attach_auth(&x->aalg, &x->props.aalgo, attrs[XFRMA_ALG_AUTH]))) goto error; } |
1da177e4c Linux-2.6.12-rc2 |
480 481 |
if ((err = attach_one_algo(&x->ealg, &x->props.ealgo, xfrm_ealg_get_byname, |
35a7aa08b [XFRM] netlink: R... |
482 |
attrs[XFRMA_ALG_CRYPT]))) |
1da177e4c Linux-2.6.12-rc2 |
483 484 485 |
goto error; if ((err = attach_one_algo(&x->calg, &x->props.calgo, xfrm_calg_get_byname, |
35a7aa08b [XFRM] netlink: R... |
486 |
attrs[XFRMA_ALG_COMP]))) |
1da177e4c Linux-2.6.12-rc2 |
487 |
goto error; |
fd21150a0 [XFRM] netlink: I... |
488 489 490 491 492 493 494 |
if (attrs[XFRMA_ENCAP]) { x->encap = kmemdup(nla_data(attrs[XFRMA_ENCAP]), sizeof(*x->encap), GFP_KERNEL); if (x->encap == NULL) goto error; } |
35d2856b4 xfrm: Add Traffic... |
495 496 |
if (attrs[XFRMA_TFCPAD]) x->tfcpad = nla_get_u32(attrs[XFRMA_TFCPAD]); |
fd21150a0 [XFRM] netlink: I... |
497 498 499 500 501 502 |
if (attrs[XFRMA_COADDR]) { x->coaddr = kmemdup(nla_data(attrs[XFRMA_COADDR]), sizeof(*x->coaddr), GFP_KERNEL); if (x->coaddr == NULL) goto error; } |
6f26b61e1 xfrm: Allow user ... |
503 |
xfrm_mark_get(attrs, &x->mark); |
a454f0cce xfrm: Fix initial... |
504 |
err = __xfrm_init_state(x, false); |
1da177e4c Linux-2.6.12-rc2 |
505 506 |
if (err) goto error; |
fd21150a0 [XFRM] netlink: I... |
507 508 |
if (attrs[XFRMA_SEC_CTX] && security_xfrm_state_alloc(x, nla_data(attrs[XFRMA_SEC_CTX]))) |
df71837d5 [LSM-IPSec]: Secu... |
509 |
goto error; |
d8647b79c xfrm: Add user in... |
510 511 512 |
if ((err = xfrm_alloc_replay_state_esn(&x->replay_esn, &x->preplay_esn, attrs[XFRMA_REPLAY_ESN_VAL]))) goto error; |
1da177e4c Linux-2.6.12-rc2 |
513 |
x->km.seq = p->seq; |
b27aeadb5 netns xfrm: per-n... |
514 |
x->replay_maxdiff = net->xfrm.sysctl_aevent_rseqth; |
d51d081d6 [IPSEC]: Sync ser... |
515 |
/* sysctl_xfrm_aevent_etime is in 100ms units */ |
b27aeadb5 netns xfrm: per-n... |
516 |
x->replay_maxage = (net->xfrm.sysctl_aevent_etime*HZ)/XFRM_AE_ETH_M; |
d51d081d6 [IPSEC]: Sync ser... |
517 |
|
9fdc4883d xfrm: Move IPsec ... |
518 519 |
if ((err = xfrm_init_replay(x))) goto error; |
d51d081d6 [IPSEC]: Sync ser... |
520 |
|
9fdc4883d xfrm: Move IPsec ... |
521 |
/* override default values from above */ |
5424f32e4 [XFRM] netlink: U... |
522 |
xfrm_update_ae_params(x, attrs); |
1da177e4c Linux-2.6.12-rc2 |
523 524 525 526 527 528 529 530 531 532 |
return x; error: x->km.state = XFRM_STATE_DEAD; xfrm_state_put(x); error_no_put: *errp = err; return NULL; } |
22e700502 [XFRM_USER]: avoi... |
533 |
static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, |
5424f32e4 [XFRM] netlink: U... |
534 |
struct nlattr **attrs) |
1da177e4c Linux-2.6.12-rc2 |
535 |
{ |
fc34acd36 netns xfrm: xfrm_... |
536 |
struct net *net = sock_net(skb->sk); |
7b67c8575 [XFRM] netlink: U... |
537 |
struct xfrm_usersa_info *p = nlmsg_data(nlh); |
1da177e4c Linux-2.6.12-rc2 |
538 539 |
struct xfrm_state *x; int err; |
26b15dad9 [IPSEC] Add compl... |
540 |
struct km_event c; |
c53fa1ed9 netlink: kill log... |
541 542 543 |
uid_t loginuid = audit_get_loginuid(current); u32 sessionid = audit_get_sessionid(current); u32 sid; |
1da177e4c Linux-2.6.12-rc2 |
544 |
|
35a7aa08b [XFRM] netlink: R... |
545 |
err = verify_newsa_info(p, attrs); |
1da177e4c Linux-2.6.12-rc2 |
546 547 |
if (err) return err; |
fc34acd36 netns xfrm: xfrm_... |
548 |
x = xfrm_state_construct(net, p, attrs, &err); |
1da177e4c Linux-2.6.12-rc2 |
549 550 |
if (!x) return err; |
26b15dad9 [IPSEC] Add compl... |
551 |
xfrm_state_hold(x); |
1da177e4c Linux-2.6.12-rc2 |
552 553 554 555 |
if (nlh->nlmsg_type == XFRM_MSG_NEWSA) err = xfrm_state_add(x); else err = xfrm_state_update(x); |
c53fa1ed9 netlink: kill log... |
556 |
security_task_getsecid(current, &sid); |
2532386f4 Audit: collect se... |
557 |
xfrm_audit_state_add(x, err ? 0 : 1, loginuid, sessionid, sid); |
161a09e73 audit: Add auditi... |
558 |
|
1da177e4c Linux-2.6.12-rc2 |
559 560 |
if (err < 0) { x->km.state = XFRM_STATE_DEAD; |
21380b81e [XFRM]: Eliminate... |
561 |
__xfrm_state_put(x); |
7d6dfe1f5 [IPSEC] Fix xfrm_... |
562 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
563 |
} |
26b15dad9 [IPSEC] Add compl... |
564 565 |
c.seq = nlh->nlmsg_seq; c.pid = nlh->nlmsg_pid; |
f60f6b8f7 [IPSEC] Use XFRM_... |
566 |
c.event = nlh->nlmsg_type; |
26b15dad9 [IPSEC] Add compl... |
567 568 |
km_state_notify(x, &c); |
7d6dfe1f5 [IPSEC] Fix xfrm_... |
569 |
out: |
26b15dad9 [IPSEC] Add compl... |
570 |
xfrm_state_put(x); |
1da177e4c Linux-2.6.12-rc2 |
571 572 |
return err; } |
fc34acd36 netns xfrm: xfrm_... |
573 574 |
static struct xfrm_state *xfrm_user_state_lookup(struct net *net, struct xfrm_usersa_id *p, |
5424f32e4 [XFRM] netlink: U... |
575 |
struct nlattr **attrs, |
eb2971b68 [XFRM] STATE: Sea... |
576 577 578 |
int *errp) { struct xfrm_state *x = NULL; |
6f26b61e1 xfrm: Allow user ... |
579 |
struct xfrm_mark m; |
eb2971b68 [XFRM] STATE: Sea... |
580 |
int err; |
6f26b61e1 xfrm: Allow user ... |
581 |
u32 mark = xfrm_mark_get(attrs, &m); |
eb2971b68 [XFRM] STATE: Sea... |
582 583 584 |
if (xfrm_id_proto_match(p->proto, IPSEC_PROTO_ANY)) { err = -ESRCH; |
6f26b61e1 xfrm: Allow user ... |
585 |
x = xfrm_state_lookup(net, mark, &p->daddr, p->spi, p->proto, p->family); |
eb2971b68 [XFRM] STATE: Sea... |
586 587 |
} else { xfrm_address_t *saddr = NULL; |
35a7aa08b [XFRM] netlink: R... |
588 |
verify_one_addr(attrs, XFRMA_SRCADDR, &saddr); |
eb2971b68 [XFRM] STATE: Sea... |
589 590 591 592 |
if (!saddr) { err = -EINVAL; goto out; } |
9abbffee8 [XFRM] STATE: Fix... |
593 |
err = -ESRCH; |
6f26b61e1 xfrm: Allow user ... |
594 595 |
x = xfrm_state_lookup_byaddr(net, mark, &p->daddr, saddr, |
221df1ed3 netns xfrm: state... |
596 |
p->proto, p->family); |
eb2971b68 [XFRM] STATE: Sea... |
597 598 599 600 601 602 603 |
} out: if (!x && errp) *errp = err; return x; } |
22e700502 [XFRM_USER]: avoi... |
604 |
static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, |
5424f32e4 [XFRM] netlink: U... |
605 |
struct nlattr **attrs) |
1da177e4c Linux-2.6.12-rc2 |
606 |
{ |
fc34acd36 netns xfrm: xfrm_... |
607 |
struct net *net = sock_net(skb->sk); |
1da177e4c Linux-2.6.12-rc2 |
608 |
struct xfrm_state *x; |
eb2971b68 [XFRM] STATE: Sea... |
609 |
int err = -ESRCH; |
26b15dad9 [IPSEC] Add compl... |
610 |
struct km_event c; |
7b67c8575 [XFRM] netlink: U... |
611 |
struct xfrm_usersa_id *p = nlmsg_data(nlh); |
c53fa1ed9 netlink: kill log... |
612 613 614 |
uid_t loginuid = audit_get_loginuid(current); u32 sessionid = audit_get_sessionid(current); u32 sid; |
1da177e4c Linux-2.6.12-rc2 |
615 |
|
fc34acd36 netns xfrm: xfrm_... |
616 |
x = xfrm_user_state_lookup(net, p, attrs, &err); |
1da177e4c Linux-2.6.12-rc2 |
617 |
if (x == NULL) |
eb2971b68 [XFRM] STATE: Sea... |
618 |
return err; |
1da177e4c Linux-2.6.12-rc2 |
619 |
|
6f68dc377 [NET]: Fix warnin... |
620 |
if ((err = security_xfrm_state_delete(x)) != 0) |
c8c05a8ee [LSM-IPsec]: SELi... |
621 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
622 |
if (xfrm_state_kern(x)) { |
c8c05a8ee [LSM-IPsec]: SELi... |
623 624 |
err = -EPERM; goto out; |
1da177e4c Linux-2.6.12-rc2 |
625 |
} |
26b15dad9 [IPSEC] Add compl... |
626 |
err = xfrm_state_delete(x); |
161a09e73 audit: Add auditi... |
627 |
|
c8c05a8ee [LSM-IPsec]: SELi... |
628 629 |
if (err < 0) goto out; |
26b15dad9 [IPSEC] Add compl... |
630 631 632 |
c.seq = nlh->nlmsg_seq; c.pid = nlh->nlmsg_pid; |
f60f6b8f7 [IPSEC] Use XFRM_... |
633 |
c.event = nlh->nlmsg_type; |
26b15dad9 [IPSEC] Add compl... |
634 |
km_state_notify(x, &c); |
1da177e4c Linux-2.6.12-rc2 |
635 |
|
c8c05a8ee [LSM-IPsec]: SELi... |
636 |
out: |
c53fa1ed9 netlink: kill log... |
637 |
security_task_getsecid(current, &sid); |
2532386f4 Audit: collect se... |
638 |
xfrm_audit_state_delete(x, err ? 0 : 1, loginuid, sessionid, sid); |
c8c05a8ee [LSM-IPsec]: SELi... |
639 |
xfrm_state_put(x); |
26b15dad9 [IPSEC] Add compl... |
640 |
return err; |
1da177e4c Linux-2.6.12-rc2 |
641 642 643 644 645 646 647 648 649 |
} static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p) { memcpy(&p->id, &x->id, sizeof(p->id)); memcpy(&p->sel, &x->sel, sizeof(p->sel)); memcpy(&p->lft, &x->lft, sizeof(p->lft)); memcpy(&p->curlft, &x->curlft, sizeof(p->curlft)); memcpy(&p->stats, &x->stats, sizeof(p->stats)); |
54489c14c [XFRM] xfrm_user:... |
650 |
memcpy(&p->saddr, &x->props.saddr, sizeof(p->saddr)); |
1da177e4c Linux-2.6.12-rc2 |
651 652 653 654 655 656 657 658 659 660 661 662 663 |
p->mode = x->props.mode; p->replay_window = x->props.replay_window; p->reqid = x->props.reqid; p->family = x->props.family; p->flags = x->props.flags; p->seq = x->km.seq; } struct xfrm_dump_info { struct sk_buff *in_skb; struct sk_buff *out_skb; u32 nlmsg_seq; u16 nlmsg_flags; |
1da177e4c Linux-2.6.12-rc2 |
664 |
}; |
c0144beae [XFRM] netlink: U... |
665 666 |
static int copy_sec_ctx(struct xfrm_sec_ctx *s, struct sk_buff *skb) { |
c0144beae [XFRM] netlink: U... |
667 668 |
struct xfrm_user_sec_ctx *uctx; struct nlattr *attr; |
68325d3b1 [XFRM] user: Move... |
669 |
int ctx_size = sizeof(*uctx) + s->ctx_len; |
c0144beae [XFRM] netlink: U... |
670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 |
attr = nla_reserve(skb, XFRMA_SEC_CTX, ctx_size); if (attr == NULL) return -EMSGSIZE; uctx = nla_data(attr); uctx->exttype = XFRMA_SEC_CTX; uctx->len = ctx_size; uctx->ctx_doi = s->ctx_doi; uctx->ctx_alg = s->ctx_alg; uctx->ctx_len = s->ctx_len; memcpy(uctx + 1, s->ctx_str, s->ctx_len); return 0; } |
4447bb33f xfrm: Store aalg ... |
685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 |
static int copy_to_user_auth(struct xfrm_algo_auth *auth, struct sk_buff *skb) { struct xfrm_algo *algo; struct nlattr *nla; nla = nla_reserve(skb, XFRMA_ALG_AUTH, sizeof(*algo) + (auth->alg_key_len + 7) / 8); if (!nla) return -EMSGSIZE; algo = nla_data(nla); strcpy(algo->alg_name, auth->alg_name); memcpy(algo->alg_key, auth->alg_key, (auth->alg_key_len + 7) / 8); algo->alg_key_len = auth->alg_key_len; return 0; } |
68325d3b1 [XFRM] user: Move... |
702 703 704 705 |
/* Don't change this without updating xfrm_sa_len! */ static int copy_to_user_state_extra(struct xfrm_state *x, struct xfrm_usersa_info *p, struct sk_buff *skb) |
1da177e4c Linux-2.6.12-rc2 |
706 |
{ |
1da177e4c Linux-2.6.12-rc2 |
707 |
copy_to_user_state(x, p); |
050f009e1 [IPSEC]: Lock sta... |
708 709 710 711 712 |
if (x->coaddr) NLA_PUT(skb, XFRMA_COADDR, sizeof(*x->coaddr), x->coaddr); if (x->lastused) NLA_PUT_U64(skb, XFRMA_LASTUSED, x->lastused); |
050f009e1 [IPSEC]: Lock sta... |
713 |
|
1a6509d99 [IPSEC]: Add supp... |
714 715 |
if (x->aead) NLA_PUT(skb, XFRMA_ALG_AEAD, aead_len(x->aead), x->aead); |
4447bb33f xfrm: Store aalg ... |
716 717 718 719 720 721 722 |
if (x->aalg) { if (copy_to_user_auth(x->aalg, skb)) goto nla_put_failure; NLA_PUT(skb, XFRMA_ALG_AUTH_TRUNC, xfrm_alg_auth_len(x->aalg), x->aalg); } |
1da177e4c Linux-2.6.12-rc2 |
723 |
if (x->ealg) |
0f99be0d1 [XFRM]: xfrm_algo... |
724 |
NLA_PUT(skb, XFRMA_ALG_CRYPT, xfrm_alg_len(x->ealg), x->ealg); |
1da177e4c Linux-2.6.12-rc2 |
725 |
if (x->calg) |
c0144beae [XFRM] netlink: U... |
726 |
NLA_PUT(skb, XFRMA_ALG_COMP, sizeof(*(x->calg)), x->calg); |
1da177e4c Linux-2.6.12-rc2 |
727 728 |
if (x->encap) |
c0144beae [XFRM] netlink: U... |
729 |
NLA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap); |
1da177e4c Linux-2.6.12-rc2 |
730 |
|
35d2856b4 xfrm: Add Traffic... |
731 732 |
if (x->tfcpad) NLA_PUT_U32(skb, XFRMA_TFCPAD, x->tfcpad); |
6f26b61e1 xfrm: Allow user ... |
733 734 |
if (xfrm_mark_put(skb, &x->mark)) goto nla_put_failure; |
d8647b79c xfrm: Add user in... |
735 736 737 |
if (x->replay_esn) NLA_PUT(skb, XFRMA_REPLAY_ESN_VAL, xfrm_replay_state_esn_len(x->replay_esn), x->replay_esn); |
c0144beae [XFRM] netlink: U... |
738 739 |
if (x->security && copy_sec_ctx(x->security, skb) < 0) goto nla_put_failure; |
060f02a3b [XFRM] STATE: Int... |
740 |
|
68325d3b1 [XFRM] user: Move... |
741 742 743 744 745 746 747 748 749 750 751 752 753 754 |
return 0; nla_put_failure: return -EMSGSIZE; } static int dump_one_state(struct xfrm_state *x, int count, void *ptr) { struct xfrm_dump_info *sp = ptr; struct sk_buff *in_skb = sp->in_skb; struct sk_buff *skb = sp->out_skb; struct xfrm_usersa_info *p; struct nlmsghdr *nlh; int err; |
68325d3b1 [XFRM] user: Move... |
755 756 757 758 759 760 761 762 763 764 |
nlh = nlmsg_put(skb, NETLINK_CB(in_skb).pid, sp->nlmsg_seq, XFRM_MSG_NEWSA, sizeof(*p), sp->nlmsg_flags); if (nlh == NULL) return -EMSGSIZE; p = nlmsg_data(nlh); err = copy_to_user_state_extra(x, p, skb); if (err) goto nla_put_failure; |
9825069d0 [XFRM] netlink: U... |
765 |
nlmsg_end(skb, nlh); |
1da177e4c Linux-2.6.12-rc2 |
766 |
return 0; |
c0144beae [XFRM] netlink: U... |
767 |
nla_put_failure: |
9825069d0 [XFRM] netlink: U... |
768 |
nlmsg_cancel(skb, nlh); |
68325d3b1 [XFRM] user: Move... |
769 |
return err; |
1da177e4c Linux-2.6.12-rc2 |
770 |
} |
4c563f766 [XFRM]: Speed up ... |
771 772 773 774 775 776 |
static int xfrm_dump_sa_done(struct netlink_callback *cb) { struct xfrm_state_walk *walk = (struct xfrm_state_walk *) &cb->args[1]; xfrm_state_walk_done(walk); return 0; } |
1da177e4c Linux-2.6.12-rc2 |
777 778 |
static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb) { |
fc34acd36 netns xfrm: xfrm_... |
779 |
struct net *net = sock_net(skb->sk); |
4c563f766 [XFRM]: Speed up ... |
780 |
struct xfrm_state_walk *walk = (struct xfrm_state_walk *) &cb->args[1]; |
1da177e4c Linux-2.6.12-rc2 |
781 |
struct xfrm_dump_info info; |
4c563f766 [XFRM]: Speed up ... |
782 783 |
BUILD_BUG_ON(sizeof(struct xfrm_state_walk) > sizeof(cb->args) - sizeof(cb->args[0])); |
1da177e4c Linux-2.6.12-rc2 |
784 785 786 787 |
info.in_skb = cb->skb; info.out_skb = skb; info.nlmsg_seq = cb->nlh->nlmsg_seq; info.nlmsg_flags = NLM_F_MULTI; |
4c563f766 [XFRM]: Speed up ... |
788 789 790 791 792 |
if (!cb->args[0]) { cb->args[0] = 1; xfrm_state_walk_init(walk, 0); } |
fc34acd36 netns xfrm: xfrm_... |
793 |
(void) xfrm_state_walk(net, walk, dump_one_state, &info); |
1da177e4c Linux-2.6.12-rc2 |
794 795 796 797 798 799 800 801 802 |
return skb->len; } static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb, struct xfrm_state *x, u32 seq) { struct xfrm_dump_info info; struct sk_buff *skb; |
7deb22649 [XFRM] netlink: U... |
803 |
skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); |
1da177e4c Linux-2.6.12-rc2 |
804 805 |
if (!skb) return ERR_PTR(-ENOMEM); |
1da177e4c Linux-2.6.12-rc2 |
806 807 808 809 |
info.in_skb = in_skb; info.out_skb = skb; info.nlmsg_seq = seq; info.nlmsg_flags = 0; |
1da177e4c Linux-2.6.12-rc2 |
810 811 812 813 814 815 816 817 |
if (dump_one_state(x, 0, &info)) { kfree_skb(skb); return NULL; } return skb; } |
7deb22649 [XFRM] netlink: U... |
818 819 820 821 822 823 |
static inline size_t xfrm_spdinfo_msgsize(void) { return NLMSG_ALIGN(4) + nla_total_size(sizeof(struct xfrmu_spdinfo)) + nla_total_size(sizeof(struct xfrmu_spdhinfo)); } |
e071041be netns xfrm: fix "... |
824 825 |
static int build_spdinfo(struct sk_buff *skb, struct net *net, u32 pid, u32 seq, u32 flags) |
ecfd6b183 [XFRM]: Export SP... |
826 |
{ |
5a6d34162 [XFRM] SPD info T... |
827 828 829 |
struct xfrmk_spdinfo si; struct xfrmu_spdinfo spc; struct xfrmu_spdhinfo sph; |
ecfd6b183 [XFRM]: Export SP... |
830 831 832 833 |
struct nlmsghdr *nlh; u32 *f; nlh = nlmsg_put(skb, pid, seq, XFRM_MSG_NEWSPDINFO, sizeof(u32), 0); |
25985edce Fix common misspe... |
834 |
if (nlh == NULL) /* shouldn't really happen ... */ |
ecfd6b183 [XFRM]: Export SP... |
835 836 837 838 |
return -EMSGSIZE; f = nlmsg_data(nlh); *f = flags; |
e071041be netns xfrm: fix "... |
839 |
xfrm_spd_getinfo(net, &si); |
5a6d34162 [XFRM] SPD info T... |
840 841 842 843 844 845 846 847 848 849 850 |
spc.incnt = si.incnt; spc.outcnt = si.outcnt; spc.fwdcnt = si.fwdcnt; spc.inscnt = si.inscnt; spc.outscnt = si.outscnt; spc.fwdscnt = si.fwdscnt; sph.spdhcnt = si.spdhcnt; sph.spdhmcnt = si.spdhmcnt; NLA_PUT(skb, XFRMA_SPD_INFO, sizeof(spc), &spc); NLA_PUT(skb, XFRMA_SPD_HINFO, sizeof(sph), &sph); |
ecfd6b183 [XFRM]: Export SP... |
851 852 853 854 855 856 857 858 859 |
return nlmsg_end(skb, nlh); nla_put_failure: nlmsg_cancel(skb, nlh); return -EMSGSIZE; } static int xfrm_get_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh, |
5424f32e4 [XFRM] netlink: U... |
860 |
struct nlattr **attrs) |
ecfd6b183 [XFRM]: Export SP... |
861 |
{ |
a6483b790 netns xfrm: per-n... |
862 |
struct net *net = sock_net(skb->sk); |
ecfd6b183 [XFRM]: Export SP... |
863 |
struct sk_buff *r_skb; |
7b67c8575 [XFRM] netlink: U... |
864 |
u32 *flags = nlmsg_data(nlh); |
ecfd6b183 [XFRM]: Export SP... |
865 866 |
u32 spid = NETLINK_CB(skb).pid; u32 seq = nlh->nlmsg_seq; |
ecfd6b183 [XFRM]: Export SP... |
867 |
|
7deb22649 [XFRM] netlink: U... |
868 |
r_skb = nlmsg_new(xfrm_spdinfo_msgsize(), GFP_ATOMIC); |
ecfd6b183 [XFRM]: Export SP... |
869 870 |
if (r_skb == NULL) return -ENOMEM; |
e071041be netns xfrm: fix "... |
871 |
if (build_spdinfo(r_skb, net, spid, seq, *flags) < 0) |
ecfd6b183 [XFRM]: Export SP... |
872 |
BUG(); |
a6483b790 netns xfrm: per-n... |
873 |
return nlmsg_unicast(net->xfrm.nlsk, r_skb, spid); |
ecfd6b183 [XFRM]: Export SP... |
874 |
} |
7deb22649 [XFRM] netlink: U... |
875 876 877 878 879 880 |
static inline size_t xfrm_sadinfo_msgsize(void) { return NLMSG_ALIGN(4) + nla_total_size(sizeof(struct xfrmu_sadhinfo)) + nla_total_size(4); /* XFRMA_SAD_CNT */ } |
e071041be netns xfrm: fix "... |
881 882 |
static int build_sadinfo(struct sk_buff *skb, struct net *net, u32 pid, u32 seq, u32 flags) |
28d8909bc [XFRM]: Export SA... |
883 |
{ |
af11e3160 [XFRM] SAD info T... |
884 885 |
struct xfrmk_sadinfo si; struct xfrmu_sadhinfo sh; |
28d8909bc [XFRM]: Export SA... |
886 887 888 889 |
struct nlmsghdr *nlh; u32 *f; nlh = nlmsg_put(skb, pid, seq, XFRM_MSG_NEWSADINFO, sizeof(u32), 0); |
25985edce Fix common misspe... |
890 |
if (nlh == NULL) /* shouldn't really happen ... */ |
28d8909bc [XFRM]: Export SA... |
891 892 893 894 |
return -EMSGSIZE; f = nlmsg_data(nlh); *f = flags; |
e071041be netns xfrm: fix "... |
895 |
xfrm_sad_getinfo(net, &si); |
28d8909bc [XFRM]: Export SA... |
896 |
|
af11e3160 [XFRM] SAD info T... |
897 898 899 900 901 |
sh.sadhmcnt = si.sadhmcnt; sh.sadhcnt = si.sadhcnt; NLA_PUT_U32(skb, XFRMA_SAD_CNT, si.sadcnt); NLA_PUT(skb, XFRMA_SAD_HINFO, sizeof(sh), &sh); |
28d8909bc [XFRM]: Export SA... |
902 903 904 905 906 907 908 909 910 |
return nlmsg_end(skb, nlh); nla_put_failure: nlmsg_cancel(skb, nlh); return -EMSGSIZE; } static int xfrm_get_sadinfo(struct sk_buff *skb, struct nlmsghdr *nlh, |
5424f32e4 [XFRM] netlink: U... |
911 |
struct nlattr **attrs) |
28d8909bc [XFRM]: Export SA... |
912 |
{ |
a6483b790 netns xfrm: per-n... |
913 |
struct net *net = sock_net(skb->sk); |
28d8909bc [XFRM]: Export SA... |
914 |
struct sk_buff *r_skb; |
7b67c8575 [XFRM] netlink: U... |
915 |
u32 *flags = nlmsg_data(nlh); |
28d8909bc [XFRM]: Export SA... |
916 917 |
u32 spid = NETLINK_CB(skb).pid; u32 seq = nlh->nlmsg_seq; |
28d8909bc [XFRM]: Export SA... |
918 |
|
7deb22649 [XFRM] netlink: U... |
919 |
r_skb = nlmsg_new(xfrm_sadinfo_msgsize(), GFP_ATOMIC); |
28d8909bc [XFRM]: Export SA... |
920 921 |
if (r_skb == NULL) return -ENOMEM; |
e071041be netns xfrm: fix "... |
922 |
if (build_sadinfo(r_skb, net, spid, seq, *flags) < 0) |
28d8909bc [XFRM]: Export SA... |
923 |
BUG(); |
a6483b790 netns xfrm: per-n... |
924 |
return nlmsg_unicast(net->xfrm.nlsk, r_skb, spid); |
28d8909bc [XFRM]: Export SA... |
925 |
} |
22e700502 [XFRM_USER]: avoi... |
926 |
static int xfrm_get_sa(struct sk_buff *skb, struct nlmsghdr *nlh, |
5424f32e4 [XFRM] netlink: U... |
927 |
struct nlattr **attrs) |
1da177e4c Linux-2.6.12-rc2 |
928 |
{ |
fc34acd36 netns xfrm: xfrm_... |
929 |
struct net *net = sock_net(skb->sk); |
7b67c8575 [XFRM] netlink: U... |
930 |
struct xfrm_usersa_id *p = nlmsg_data(nlh); |
1da177e4c Linux-2.6.12-rc2 |
931 932 |
struct xfrm_state *x; struct sk_buff *resp_skb; |
eb2971b68 [XFRM] STATE: Sea... |
933 |
int err = -ESRCH; |
1da177e4c Linux-2.6.12-rc2 |
934 |
|
fc34acd36 netns xfrm: xfrm_... |
935 |
x = xfrm_user_state_lookup(net, p, attrs, &err); |
1da177e4c Linux-2.6.12-rc2 |
936 937 938 939 940 941 942 |
if (x == NULL) goto out_noput; resp_skb = xfrm_state_netlink(skb, x, nlh->nlmsg_seq); if (IS_ERR(resp_skb)) { err = PTR_ERR(resp_skb); } else { |
a6483b790 netns xfrm: per-n... |
943 |
err = nlmsg_unicast(net->xfrm.nlsk, resp_skb, NETLINK_CB(skb).pid); |
1da177e4c Linux-2.6.12-rc2 |
944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 |
} xfrm_state_put(x); out_noput: return err; } static int verify_userspi_info(struct xfrm_userspi_info *p) { switch (p->info.id.proto) { case IPPROTO_AH: case IPPROTO_ESP: break; case IPPROTO_COMP: /* IPCOMP spi is 16-bits. */ if (p->max >= 0x10000) return -EINVAL; break; default: return -EINVAL; |
3ff50b799 [NET]: cleanup ex... |
965 |
} |
1da177e4c Linux-2.6.12-rc2 |
966 967 968 969 970 971 |
if (p->min > p->max) return -EINVAL; return 0; } |
22e700502 [XFRM_USER]: avoi... |
972 |
static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, |
5424f32e4 [XFRM] netlink: U... |
973 |
struct nlattr **attrs) |
1da177e4c Linux-2.6.12-rc2 |
974 |
{ |
fc34acd36 netns xfrm: xfrm_... |
975 |
struct net *net = sock_net(skb->sk); |
1da177e4c Linux-2.6.12-rc2 |
976 977 978 979 980 981 |
struct xfrm_state *x; struct xfrm_userspi_info *p; struct sk_buff *resp_skb; xfrm_address_t *daddr; int family; int err; |
6f26b61e1 xfrm: Allow user ... |
982 983 |
u32 mark; struct xfrm_mark m; |
1da177e4c Linux-2.6.12-rc2 |
984 |
|
7b67c8575 [XFRM] netlink: U... |
985 |
p = nlmsg_data(nlh); |
1da177e4c Linux-2.6.12-rc2 |
986 987 988 989 990 991 992 993 |
err = verify_userspi_info(p); if (err) goto out_noput; family = p->info.family; daddr = &p->info.id.daddr; x = NULL; |
6f26b61e1 xfrm: Allow user ... |
994 995 |
mark = xfrm_mark_get(attrs, &m); |
1da177e4c Linux-2.6.12-rc2 |
996 |
if (p->info.seq) { |
6f26b61e1 xfrm: Allow user ... |
997 |
x = xfrm_find_acq_byseq(net, mark, p->info.seq); |
1da177e4c Linux-2.6.12-rc2 |
998 999 1000 1001 1002 1003 1004 |
if (x && xfrm_addr_cmp(&x->id.daddr, daddr, family)) { xfrm_state_put(x); x = NULL; } } if (!x) |
6f26b61e1 xfrm: Allow user ... |
1005 |
x = xfrm_find_acq(net, &m, p->info.mode, p->info.reqid, |
1da177e4c Linux-2.6.12-rc2 |
1006 1007 1008 1009 1010 1011 |
p->info.id.proto, daddr, &p->info.saddr, 1, family); err = -ENOENT; if (x == NULL) goto out_noput; |
658b219e9 [IPSEC]: Move com... |
1012 1013 1014 |
err = xfrm_alloc_spi(x, p->min, p->max); if (err) goto out; |
1da177e4c Linux-2.6.12-rc2 |
1015 |
|
658b219e9 [IPSEC]: Move com... |
1016 |
resp_skb = xfrm_state_netlink(skb, x, nlh->nlmsg_seq); |
1da177e4c Linux-2.6.12-rc2 |
1017 1018 1019 1020 |
if (IS_ERR(resp_skb)) { err = PTR_ERR(resp_skb); goto out; } |
a6483b790 netns xfrm: per-n... |
1021 |
err = nlmsg_unicast(net->xfrm.nlsk, resp_skb, NETLINK_CB(skb).pid); |
1da177e4c Linux-2.6.12-rc2 |
1022 1023 1024 1025 1026 1027 |
out: xfrm_state_put(x); out_noput: return err; } |
b798a9ede [XFRM]: Convert a... |
1028 |
static int verify_policy_dir(u8 dir) |
1da177e4c Linux-2.6.12-rc2 |
1029 1030 1031 1032 1033 1034 1035 1036 1037 |
{ switch (dir) { case XFRM_POLICY_IN: case XFRM_POLICY_OUT: case XFRM_POLICY_FWD: break; default: return -EINVAL; |
3ff50b799 [NET]: cleanup ex... |
1038 |
} |
1da177e4c Linux-2.6.12-rc2 |
1039 1040 1041 |
return 0; } |
b798a9ede [XFRM]: Convert a... |
1042 |
static int verify_policy_type(u8 type) |
f7b6983f0 [XFRM] POLICY: Su... |
1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 |
{ switch (type) { case XFRM_POLICY_TYPE_MAIN: #ifdef CONFIG_XFRM_SUB_POLICY case XFRM_POLICY_TYPE_SUB: #endif break; default: return -EINVAL; |
3ff50b799 [NET]: cleanup ex... |
1053 |
} |
f7b6983f0 [XFRM] POLICY: Su... |
1054 1055 1056 |
return 0; } |
1da177e4c Linux-2.6.12-rc2 |
1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 |
static int verify_newpolicy_info(struct xfrm_userpolicy_info *p) { switch (p->share) { case XFRM_SHARE_ANY: case XFRM_SHARE_SESSION: case XFRM_SHARE_USER: case XFRM_SHARE_UNIQUE: break; default: return -EINVAL; |
3ff50b799 [NET]: cleanup ex... |
1068 |
} |
1da177e4c Linux-2.6.12-rc2 |
1069 1070 1071 1072 1073 1074 1075 1076 |
switch (p->action) { case XFRM_POLICY_ALLOW: case XFRM_POLICY_BLOCK: break; default: return -EINVAL; |
3ff50b799 [NET]: cleanup ex... |
1077 |
} |
1da177e4c Linux-2.6.12-rc2 |
1078 1079 1080 1081 1082 1083 |
switch (p->sel.family) { case AF_INET: break; case AF_INET6: |
dfd56b8b3 net: use IS_ENABL... |
1084 |
#if IS_ENABLED(CONFIG_IPV6) |
1da177e4c Linux-2.6.12-rc2 |
1085 1086 1087 1088 1089 1090 1091 |
break; #else return -EAFNOSUPPORT; #endif default: return -EINVAL; |
3ff50b799 [NET]: cleanup ex... |
1092 |
} |
1da177e4c Linux-2.6.12-rc2 |
1093 1094 1095 |
return verify_policy_dir(p->dir); } |
5424f32e4 [XFRM] netlink: U... |
1096 |
static int copy_from_user_sec_ctx(struct xfrm_policy *pol, struct nlattr **attrs) |
df71837d5 [LSM-IPSec]: Secu... |
1097 |
{ |
5424f32e4 [XFRM] netlink: U... |
1098 |
struct nlattr *rt = attrs[XFRMA_SEC_CTX]; |
df71837d5 [LSM-IPSec]: Secu... |
1099 1100 1101 1102 |
struct xfrm_user_sec_ctx *uctx; if (!rt) return 0; |
5424f32e4 [XFRM] netlink: U... |
1103 |
uctx = nla_data(rt); |
03e1ad7b5 LSM: Make the Lab... |
1104 |
return security_xfrm_policy_alloc(&pol->security, uctx); |
df71837d5 [LSM-IPSec]: Secu... |
1105 |
} |
1da177e4c Linux-2.6.12-rc2 |
1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 |
static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut, int nr) { int i; xp->xfrm_nr = nr; for (i = 0; i < nr; i++, ut++) { struct xfrm_tmpl *t = &xp->xfrm_vec[i]; memcpy(&t->id, &ut->id, sizeof(struct xfrm_id)); memcpy(&t->saddr, &ut->saddr, sizeof(xfrm_address_t)); t->reqid = ut->reqid; t->mode = ut->mode; t->share = ut->share; t->optional = ut->optional; t->aalgos = ut->aalgos; t->ealgos = ut->ealgos; t->calgos = ut->calgos; |
c5d18e984 [IPSEC]: Fix catc... |
1125 1126 |
/* If all masks are ~0, then we allow all algorithms. */ t->allalgs = !~(t->aalgos & t->ealgos & t->calgos); |
8511d01d7 [IPSEC]: Add netl... |
1127 |
t->encap_family = ut->family; |
1da177e4c Linux-2.6.12-rc2 |
1128 1129 |
} } |
b4ad86bf5 [XFRM] xfrm_user:... |
1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 |
static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family) { int i; if (nr > XFRM_MAX_DEPTH) return -EINVAL; for (i = 0; i < nr; i++) { /* We never validated the ut->family value, so many * applications simply leave it at zero. The check was * never made and ut->family was ignored because all * templates could be assumed to have the same family as * the policy itself. Now that we will have ipv4-in-ipv6 * and ipv6-in-ipv4 tunnels, this is no longer true. */ if (!ut[i].family) ut[i].family = family; switch (ut[i].family) { case AF_INET: break; |
dfd56b8b3 net: use IS_ENABL... |
1151 |
#if IS_ENABLED(CONFIG_IPV6) |
b4ad86bf5 [XFRM] xfrm_user:... |
1152 1153 1154 1155 1156 |
case AF_INET6: break; #endif default: return -EINVAL; |
3ff50b799 [NET]: cleanup ex... |
1157 |
} |
b4ad86bf5 [XFRM] xfrm_user:... |
1158 1159 1160 1161 |
} return 0; } |
5424f32e4 [XFRM] netlink: U... |
1162 |
static int copy_from_user_tmpl(struct xfrm_policy *pol, struct nlattr **attrs) |
1da177e4c Linux-2.6.12-rc2 |
1163 |
{ |
5424f32e4 [XFRM] netlink: U... |
1164 |
struct nlattr *rt = attrs[XFRMA_TMPL]; |
1da177e4c Linux-2.6.12-rc2 |
1165 1166 1167 1168 |
if (!rt) { pol->xfrm_nr = 0; } else { |
5424f32e4 [XFRM] netlink: U... |
1169 1170 |
struct xfrm_user_tmpl *utmpl = nla_data(rt); int nr = nla_len(rt) / sizeof(*utmpl); |
b4ad86bf5 [XFRM] xfrm_user:... |
1171 |
int err; |
1da177e4c Linux-2.6.12-rc2 |
1172 |
|
b4ad86bf5 [XFRM] xfrm_user:... |
1173 1174 1175 |
err = validate_tmpl(nr, utmpl, pol->family); if (err) return err; |
1da177e4c Linux-2.6.12-rc2 |
1176 |
|
5424f32e4 [XFRM] netlink: U... |
1177 |
copy_templates(pol, utmpl, nr); |
1da177e4c Linux-2.6.12-rc2 |
1178 1179 1180 |
} return 0; } |
5424f32e4 [XFRM] netlink: U... |
1181 |
static int copy_from_user_policy_type(u8 *tp, struct nlattr **attrs) |
f7b6983f0 [XFRM] POLICY: Su... |
1182 |
{ |
5424f32e4 [XFRM] netlink: U... |
1183 |
struct nlattr *rt = attrs[XFRMA_POLICY_TYPE]; |
f7b6983f0 [XFRM] POLICY: Su... |
1184 |
struct xfrm_userpolicy_type *upt; |
b798a9ede [XFRM]: Convert a... |
1185 |
u8 type = XFRM_POLICY_TYPE_MAIN; |
f7b6983f0 [XFRM] POLICY: Su... |
1186 1187 1188 |
int err; if (rt) { |
5424f32e4 [XFRM] netlink: U... |
1189 |
upt = nla_data(rt); |
f7b6983f0 [XFRM] POLICY: Su... |
1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 |
type = upt->type; } err = verify_policy_type(type); if (err) return err; *tp = type; return 0; } |
1da177e4c Linux-2.6.12-rc2 |
1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 |
static void copy_from_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_info *p) { xp->priority = p->priority; xp->index = p->index; memcpy(&xp->selector, &p->sel, sizeof(xp->selector)); memcpy(&xp->lft, &p->lft, sizeof(xp->lft)); xp->action = p->action; xp->flags = p->flags; xp->family = p->sel.family; /* XXX xp->share = p->share; */ } static void copy_to_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_info *p, int dir) { memcpy(&p->sel, &xp->selector, sizeof(p->sel)); memcpy(&p->lft, &xp->lft, sizeof(p->lft)); memcpy(&p->curlft, &xp->curlft, sizeof(p->curlft)); p->priority = xp->priority; p->index = xp->index; p->sel.family = xp->family; p->dir = dir; p->action = xp->action; p->flags = xp->flags; p->share = XFRM_SHARE_ANY; /* XXX xp->share */ } |
fc34acd36 netns xfrm: xfrm_... |
1225 |
static struct xfrm_policy *xfrm_policy_construct(struct net *net, struct xfrm_userpolicy_info *p, struct nlattr **attrs, int *errp) |
1da177e4c Linux-2.6.12-rc2 |
1226 |
{ |
fc34acd36 netns xfrm: xfrm_... |
1227 |
struct xfrm_policy *xp = xfrm_policy_alloc(net, GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
1228 1229 1230 1231 1232 1233 1234 1235 |
int err; if (!xp) { *errp = -ENOMEM; return NULL; } copy_from_user_policy(xp, p); |
df71837d5 [LSM-IPSec]: Secu... |
1236 |
|
35a7aa08b [XFRM] netlink: R... |
1237 |
err = copy_from_user_policy_type(&xp->type, attrs); |
f7b6983f0 [XFRM] POLICY: Su... |
1238 1239 |
if (err) goto error; |
35a7aa08b [XFRM] netlink: R... |
1240 1241 |
if (!(err = copy_from_user_tmpl(xp, attrs))) err = copy_from_user_sec_ctx(xp, attrs); |
f7b6983f0 [XFRM] POLICY: Su... |
1242 1243 |
if (err) goto error; |
1da177e4c Linux-2.6.12-rc2 |
1244 |
|
295fae568 xfrm: Allow user ... |
1245 |
xfrm_mark_get(attrs, &xp->mark); |
1da177e4c Linux-2.6.12-rc2 |
1246 |
return xp; |
f7b6983f0 [XFRM] POLICY: Su... |
1247 1248 |
error: *errp = err; |
12a169e7d ipsec: Put dumper... |
1249 |
xp->walk.dead = 1; |
64c31b3f7 [XFRM] xfrm_polic... |
1250 |
xfrm_policy_destroy(xp); |
f7b6983f0 [XFRM] POLICY: Su... |
1251 |
return NULL; |
1da177e4c Linux-2.6.12-rc2 |
1252 |
} |
22e700502 [XFRM_USER]: avoi... |
1253 |
static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, |
5424f32e4 [XFRM] netlink: U... |
1254 |
struct nlattr **attrs) |
1da177e4c Linux-2.6.12-rc2 |
1255 |
{ |
fc34acd36 netns xfrm: xfrm_... |
1256 |
struct net *net = sock_net(skb->sk); |
7b67c8575 [XFRM] netlink: U... |
1257 |
struct xfrm_userpolicy_info *p = nlmsg_data(nlh); |
1da177e4c Linux-2.6.12-rc2 |
1258 |
struct xfrm_policy *xp; |
26b15dad9 [IPSEC] Add compl... |
1259 |
struct km_event c; |
1da177e4c Linux-2.6.12-rc2 |
1260 1261 |
int err; int excl; |
c53fa1ed9 netlink: kill log... |
1262 1263 1264 |
uid_t loginuid = audit_get_loginuid(current); u32 sessionid = audit_get_sessionid(current); u32 sid; |
1da177e4c Linux-2.6.12-rc2 |
1265 1266 1267 1268 |
err = verify_newpolicy_info(p); if (err) return err; |
35a7aa08b [XFRM] netlink: R... |
1269 |
err = verify_sec_ctx_len(attrs); |
df71837d5 [LSM-IPSec]: Secu... |
1270 1271 |
if (err) return err; |
1da177e4c Linux-2.6.12-rc2 |
1272 |
|
fc34acd36 netns xfrm: xfrm_... |
1273 |
xp = xfrm_policy_construct(net, p, attrs, &err); |
1da177e4c Linux-2.6.12-rc2 |
1274 1275 |
if (!xp) return err; |
25985edce Fix common misspe... |
1276 |
/* shouldn't excl be based on nlh flags?? |
26b15dad9 [IPSEC] Add compl... |
1277 1278 1279 |
* Aha! this is anti-netlink really i.e more pfkey derived * in netlink excl is a flag and you wouldnt need * a type XFRM_MSG_UPDPOLICY - JHS */ |
1da177e4c Linux-2.6.12-rc2 |
1280 1281 |
excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY; err = xfrm_policy_insert(p->dir, xp, excl); |
c53fa1ed9 netlink: kill log... |
1282 |
security_task_getsecid(current, &sid); |
2532386f4 Audit: collect se... |
1283 |
xfrm_audit_policy_add(xp, err ? 0 : 1, loginuid, sessionid, sid); |
161a09e73 audit: Add auditi... |
1284 |
|
1da177e4c Linux-2.6.12-rc2 |
1285 |
if (err) { |
03e1ad7b5 LSM: Make the Lab... |
1286 |
security_xfrm_policy_free(xp->security); |
1da177e4c Linux-2.6.12-rc2 |
1287 1288 1289 |
kfree(xp); return err; } |
f60f6b8f7 [IPSEC] Use XFRM_... |
1290 |
c.event = nlh->nlmsg_type; |
26b15dad9 [IPSEC] Add compl... |
1291 1292 1293 |
c.seq = nlh->nlmsg_seq; c.pid = nlh->nlmsg_pid; km_policy_notify(xp, p->dir, &c); |
1da177e4c Linux-2.6.12-rc2 |
1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 |
xfrm_pol_put(xp); return 0; } static int copy_to_user_tmpl(struct xfrm_policy *xp, struct sk_buff *skb) { struct xfrm_user_tmpl vec[XFRM_MAX_DEPTH]; int i; if (xp->xfrm_nr == 0) return 0; for (i = 0; i < xp->xfrm_nr; i++) { struct xfrm_user_tmpl *up = &vec[i]; struct xfrm_tmpl *kp = &xp->xfrm_vec[i]; memcpy(&up->id, &kp->id, sizeof(up->id)); |
8511d01d7 [IPSEC]: Add netl... |
1312 |
up->family = kp->encap_family; |
1da177e4c Linux-2.6.12-rc2 |
1313 1314 1315 1316 1317 1318 1319 1320 1321 |
memcpy(&up->saddr, &kp->saddr, sizeof(up->saddr)); up->reqid = kp->reqid; up->mode = kp->mode; up->share = kp->share; up->optional = kp->optional; up->aalgos = kp->aalgos; up->ealgos = kp->ealgos; up->calgos = kp->calgos; } |
df71837d5 [LSM-IPSec]: Secu... |
1322 |
|
c0144beae [XFRM] netlink: U... |
1323 1324 |
return nla_put(skb, XFRMA_TMPL, sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr, vec); |
0d681623d [MLSXFRM]: Add se... |
1325 1326 1327 1328 1329 1330 |
} static inline int copy_to_user_state_sec_ctx(struct xfrm_state *x, struct sk_buff *skb) { if (x->security) { return copy_sec_ctx(x->security, skb); |
df71837d5 [LSM-IPSec]: Secu... |
1331 1332 |
} return 0; |
0d681623d [MLSXFRM]: Add se... |
1333 |
} |
df71837d5 [LSM-IPSec]: Secu... |
1334 |
|
0d681623d [MLSXFRM]: Add se... |
1335 1336 1337 1338 1339 1340 |
static inline int copy_to_user_sec_ctx(struct xfrm_policy *xp, struct sk_buff *skb) { if (xp->security) { return copy_sec_ctx(xp->security, skb); } return 0; |
df71837d5 [LSM-IPSec]: Secu... |
1341 |
} |
cfbfd45a8 [XFRM] netlink: C... |
1342 1343 1344 1345 1346 1347 1348 1349 |
static inline size_t userpolicy_type_attrsize(void) { #ifdef CONFIG_XFRM_SUB_POLICY return nla_total_size(sizeof(struct xfrm_userpolicy_type)); #else return 0; #endif } |
df71837d5 [LSM-IPSec]: Secu... |
1350 |
|
f7b6983f0 [XFRM] POLICY: Su... |
1351 |
#ifdef CONFIG_XFRM_SUB_POLICY |
b798a9ede [XFRM]: Convert a... |
1352 |
static int copy_to_user_policy_type(u8 type, struct sk_buff *skb) |
f7b6983f0 [XFRM] POLICY: Su... |
1353 |
{ |
c0144beae [XFRM] netlink: U... |
1354 1355 1356 |
struct xfrm_userpolicy_type upt = { .type = type, }; |
f7b6983f0 [XFRM] POLICY: Su... |
1357 |
|
c0144beae [XFRM] netlink: U... |
1358 |
return nla_put(skb, XFRMA_POLICY_TYPE, sizeof(upt), &upt); |
f7b6983f0 [XFRM] POLICY: Su... |
1359 1360 1361 |
} #else |
b798a9ede [XFRM]: Convert a... |
1362 |
static inline int copy_to_user_policy_type(u8 type, struct sk_buff *skb) |
f7b6983f0 [XFRM] POLICY: Su... |
1363 1364 1365 1366 |
{ return 0; } #endif |
1da177e4c Linux-2.6.12-rc2 |
1367 1368 1369 1370 1371 1372 1373 |
static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr) { struct xfrm_dump_info *sp = ptr; struct xfrm_userpolicy_info *p; struct sk_buff *in_skb = sp->in_skb; struct sk_buff *skb = sp->out_skb; struct nlmsghdr *nlh; |
1da177e4c Linux-2.6.12-rc2 |
1374 |
|
79b8b7f4a [XFRM] netlink: U... |
1375 1376 1377 1378 |
nlh = nlmsg_put(skb, NETLINK_CB(in_skb).pid, sp->nlmsg_seq, XFRM_MSG_NEWPOLICY, sizeof(*p), sp->nlmsg_flags); if (nlh == NULL) return -EMSGSIZE; |
1da177e4c Linux-2.6.12-rc2 |
1379 |
|
7b67c8575 [XFRM] netlink: U... |
1380 |
p = nlmsg_data(nlh); |
1da177e4c Linux-2.6.12-rc2 |
1381 1382 1383 |
copy_to_user_policy(xp, p, dir); if (copy_to_user_tmpl(xp, skb) < 0) goto nlmsg_failure; |
df71837d5 [LSM-IPSec]: Secu... |
1384 1385 |
if (copy_to_user_sec_ctx(xp, skb)) goto nlmsg_failure; |
1459bb36b [XFRM]: Make copy... |
1386 |
if (copy_to_user_policy_type(xp->type, skb) < 0) |
f7b6983f0 [XFRM] POLICY: Su... |
1387 |
goto nlmsg_failure; |
295fae568 xfrm: Allow user ... |
1388 1389 |
if (xfrm_mark_put(skb, &xp->mark)) goto nla_put_failure; |
1da177e4c Linux-2.6.12-rc2 |
1390 |
|
9825069d0 [XFRM] netlink: U... |
1391 |
nlmsg_end(skb, nlh); |
1da177e4c Linux-2.6.12-rc2 |
1392 |
return 0; |
295fae568 xfrm: Allow user ... |
1393 |
nla_put_failure: |
1da177e4c Linux-2.6.12-rc2 |
1394 |
nlmsg_failure: |
9825069d0 [XFRM] netlink: U... |
1395 1396 |
nlmsg_cancel(skb, nlh); return -EMSGSIZE; |
1da177e4c Linux-2.6.12-rc2 |
1397 |
} |
4c563f766 [XFRM]: Speed up ... |
1398 1399 1400 1401 1402 1403 1404 |
static int xfrm_dump_policy_done(struct netlink_callback *cb) { struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1]; xfrm_policy_walk_done(walk); return 0; } |
1da177e4c Linux-2.6.12-rc2 |
1405 1406 |
static int xfrm_dump_policy(struct sk_buff *skb, struct netlink_callback *cb) { |
fc34acd36 netns xfrm: xfrm_... |
1407 |
struct net *net = sock_net(skb->sk); |
4c563f766 [XFRM]: Speed up ... |
1408 |
struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1]; |
1da177e4c Linux-2.6.12-rc2 |
1409 |
struct xfrm_dump_info info; |
4c563f766 [XFRM]: Speed up ... |
1410 1411 |
BUILD_BUG_ON(sizeof(struct xfrm_policy_walk) > sizeof(cb->args) - sizeof(cb->args[0])); |
1da177e4c Linux-2.6.12-rc2 |
1412 1413 1414 1415 |
info.in_skb = cb->skb; info.out_skb = skb; info.nlmsg_seq = cb->nlh->nlmsg_seq; info.nlmsg_flags = NLM_F_MULTI; |
4c563f766 [XFRM]: Speed up ... |
1416 1417 1418 1419 1420 |
if (!cb->args[0]) { cb->args[0] = 1; xfrm_policy_walk_init(walk, XFRM_POLICY_TYPE_ANY); } |
fc34acd36 netns xfrm: xfrm_... |
1421 |
(void) xfrm_policy_walk(net, walk, dump_one_policy, &info); |
1da177e4c Linux-2.6.12-rc2 |
1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 |
return skb->len; } static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb, struct xfrm_policy *xp, int dir, u32 seq) { struct xfrm_dump_info info; struct sk_buff *skb; |
7deb22649 [XFRM] netlink: U... |
1432 |
skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
1433 1434 |
if (!skb) return ERR_PTR(-ENOMEM); |
1da177e4c Linux-2.6.12-rc2 |
1435 1436 1437 1438 |
info.in_skb = in_skb; info.out_skb = skb; info.nlmsg_seq = seq; info.nlmsg_flags = 0; |
1da177e4c Linux-2.6.12-rc2 |
1439 1440 1441 1442 1443 1444 1445 1446 |
if (dump_one_policy(xp, dir, 0, &info) < 0) { kfree_skb(skb); return NULL; } return skb; } |
22e700502 [XFRM_USER]: avoi... |
1447 |
static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, |
5424f32e4 [XFRM] netlink: U... |
1448 |
struct nlattr **attrs) |
1da177e4c Linux-2.6.12-rc2 |
1449 |
{ |
fc34acd36 netns xfrm: xfrm_... |
1450 |
struct net *net = sock_net(skb->sk); |
1da177e4c Linux-2.6.12-rc2 |
1451 1452 |
struct xfrm_policy *xp; struct xfrm_userpolicy_id *p; |
b798a9ede [XFRM]: Convert a... |
1453 |
u8 type = XFRM_POLICY_TYPE_MAIN; |
1da177e4c Linux-2.6.12-rc2 |
1454 |
int err; |
26b15dad9 [IPSEC] Add compl... |
1455 |
struct km_event c; |
1da177e4c Linux-2.6.12-rc2 |
1456 |
int delete; |
295fae568 xfrm: Allow user ... |
1457 1458 |
struct xfrm_mark m; u32 mark = xfrm_mark_get(attrs, &m); |
1da177e4c Linux-2.6.12-rc2 |
1459 |
|
7b67c8575 [XFRM] netlink: U... |
1460 |
p = nlmsg_data(nlh); |
1da177e4c Linux-2.6.12-rc2 |
1461 |
delete = nlh->nlmsg_type == XFRM_MSG_DELPOLICY; |
35a7aa08b [XFRM] netlink: R... |
1462 |
err = copy_from_user_policy_type(&type, attrs); |
f7b6983f0 [XFRM] POLICY: Su... |
1463 1464 |
if (err) return err; |
1da177e4c Linux-2.6.12-rc2 |
1465 1466 1467 1468 1469 |
err = verify_policy_dir(p->dir); if (err) return err; if (p->index) |
295fae568 xfrm: Allow user ... |
1470 |
xp = xfrm_policy_byid(net, mark, type, p->dir, p->index, delete, &err); |
df71837d5 [LSM-IPSec]: Secu... |
1471 |
else { |
5424f32e4 [XFRM] netlink: U... |
1472 |
struct nlattr *rt = attrs[XFRMA_SEC_CTX]; |
03e1ad7b5 LSM: Make the Lab... |
1473 |
struct xfrm_sec_ctx *ctx; |
df71837d5 [LSM-IPSec]: Secu... |
1474 |
|
35a7aa08b [XFRM] netlink: R... |
1475 |
err = verify_sec_ctx_len(attrs); |
df71837d5 [LSM-IPSec]: Secu... |
1476 1477 |
if (err) return err; |
2c8dd1163 [XFRM]: Compilati... |
1478 |
ctx = NULL; |
df71837d5 [LSM-IPSec]: Secu... |
1479 |
if (rt) { |
5424f32e4 [XFRM] netlink: U... |
1480 |
struct xfrm_user_sec_ctx *uctx = nla_data(rt); |
df71837d5 [LSM-IPSec]: Secu... |
1481 |
|
03e1ad7b5 LSM: Make the Lab... |
1482 1483 |
err = security_xfrm_policy_alloc(&ctx, uctx); if (err) |
df71837d5 [LSM-IPSec]: Secu... |
1484 |
return err; |
2c8dd1163 [XFRM]: Compilati... |
1485 |
} |
295fae568 xfrm: Allow user ... |
1486 |
xp = xfrm_policy_bysel_ctx(net, mark, type, p->dir, &p->sel, |
6f26b61e1 xfrm: Allow user ... |
1487 |
ctx, delete, &err); |
03e1ad7b5 LSM: Make the Lab... |
1488 |
security_xfrm_policy_free(ctx); |
df71837d5 [LSM-IPSec]: Secu... |
1489 |
} |
1da177e4c Linux-2.6.12-rc2 |
1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 |
if (xp == NULL) return -ENOENT; if (!delete) { struct sk_buff *resp_skb; resp_skb = xfrm_policy_netlink(skb, xp, p->dir, nlh->nlmsg_seq); if (IS_ERR(resp_skb)) { err = PTR_ERR(resp_skb); } else { |
a6483b790 netns xfrm: per-n... |
1500 |
err = nlmsg_unicast(net->xfrm.nlsk, resp_skb, |
082a1ad57 [XFRM] netlink: U... |
1501 |
NETLINK_CB(skb).pid); |
1da177e4c Linux-2.6.12-rc2 |
1502 |
} |
26b15dad9 [IPSEC] Add compl... |
1503 |
} else { |
c53fa1ed9 netlink: kill log... |
1504 1505 1506 |
uid_t loginuid = audit_get_loginuid(current); u32 sessionid = audit_get_sessionid(current); u32 sid; |
2532386f4 Audit: collect se... |
1507 |
|
c53fa1ed9 netlink: kill log... |
1508 |
security_task_getsecid(current, &sid); |
2532386f4 Audit: collect se... |
1509 1510 |
xfrm_audit_policy_delete(xp, err ? 0 : 1, loginuid, sessionid, sid); |
13fcfbb06 [XFRM]: Fix OOPSe... |
1511 1512 |
if (err != 0) |
c8c05a8ee [LSM-IPsec]: SELi... |
1513 |
goto out; |
13fcfbb06 [XFRM]: Fix OOPSe... |
1514 |
|
e7443892f [IPSEC] Set byid ... |
1515 |
c.data.byid = p->index; |
f60f6b8f7 [IPSEC] Use XFRM_... |
1516 |
c.event = nlh->nlmsg_type; |
26b15dad9 [IPSEC] Add compl... |
1517 1518 1519 |
c.seq = nlh->nlmsg_seq; c.pid = nlh->nlmsg_pid; km_policy_notify(xp, p->dir, &c); |
1da177e4c Linux-2.6.12-rc2 |
1520 |
} |
c8c05a8ee [LSM-IPsec]: SELi... |
1521 |
out: |
ef41aaa0b [IPSEC]: xfrm_pol... |
1522 |
xfrm_pol_put(xp); |
1da177e4c Linux-2.6.12-rc2 |
1523 1524 |
return err; } |
22e700502 [XFRM_USER]: avoi... |
1525 |
static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, |
5424f32e4 [XFRM] netlink: U... |
1526 |
struct nlattr **attrs) |
1da177e4c Linux-2.6.12-rc2 |
1527 |
{ |
fc34acd36 netns xfrm: xfrm_... |
1528 |
struct net *net = sock_net(skb->sk); |
26b15dad9 [IPSEC] Add compl... |
1529 |
struct km_event c; |
7b67c8575 [XFRM] netlink: U... |
1530 |
struct xfrm_usersa_flush *p = nlmsg_data(nlh); |
161a09e73 audit: Add auditi... |
1531 |
struct xfrm_audit audit_info; |
4aa2e62c4 xfrm: Add securit... |
1532 |
int err; |
1da177e4c Linux-2.6.12-rc2 |
1533 |
|
c53fa1ed9 netlink: kill log... |
1534 1535 1536 |
audit_info.loginuid = audit_get_loginuid(current); audit_info.sessionid = audit_get_sessionid(current); security_task_getsecid(current, &audit_info.secid); |
fc34acd36 netns xfrm: xfrm_... |
1537 |
err = xfrm_state_flush(net, p->proto, &audit_info); |
9e64cc957 xfrm: Flushing em... |
1538 1539 1540 |
if (err) { if (err == -ESRCH) /* empty table */ return 0; |
069c474e8 xfrm: Revert fals... |
1541 |
return err; |
9e64cc957 xfrm: Flushing em... |
1542 |
} |
bf08867f9 [IPSEC] Turn km_e... |
1543 |
c.data.proto = p->proto; |
f60f6b8f7 [IPSEC] Use XFRM_... |
1544 |
c.event = nlh->nlmsg_type; |
26b15dad9 [IPSEC] Add compl... |
1545 1546 |
c.seq = nlh->nlmsg_seq; c.pid = nlh->nlmsg_pid; |
7067802e2 netns xfrm: pass ... |
1547 |
c.net = net; |
26b15dad9 [IPSEC] Add compl... |
1548 |
km_state_notify(NULL, &c); |
1da177e4c Linux-2.6.12-rc2 |
1549 1550 |
return 0; } |
d8647b79c xfrm: Add user in... |
1551 |
static inline size_t xfrm_aevent_msgsize(struct xfrm_state *x) |
7deb22649 [XFRM] netlink: U... |
1552 |
{ |
d8647b79c xfrm: Add user in... |
1553 1554 1555 |
size_t replay_size = x->replay_esn ? xfrm_replay_state_esn_len(x->replay_esn) : sizeof(struct xfrm_replay_state); |
7deb22649 [XFRM] netlink: U... |
1556 |
return NLMSG_ALIGN(sizeof(struct xfrm_aevent_id)) |
d8647b79c xfrm: Add user in... |
1557 |
+ nla_total_size(replay_size) |
7deb22649 [XFRM] netlink: U... |
1558 |
+ nla_total_size(sizeof(struct xfrm_lifetime_cur)) |
6f26b61e1 xfrm: Allow user ... |
1559 |
+ nla_total_size(sizeof(struct xfrm_mark)) |
7deb22649 [XFRM] netlink: U... |
1560 1561 1562 |
+ nla_total_size(4) /* XFRM_AE_RTHR */ + nla_total_size(4); /* XFRM_AE_ETHR */ } |
d51d081d6 [IPSEC]: Sync ser... |
1563 |
|
214e005bc xfrm: Pass km_eve... |
1564 |
static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, const struct km_event *c) |
d51d081d6 [IPSEC]: Sync ser... |
1565 1566 1567 |
{ struct xfrm_aevent_id *id; struct nlmsghdr *nlh; |
d51d081d6 [IPSEC]: Sync ser... |
1568 |
|
79b8b7f4a [XFRM] netlink: U... |
1569 1570 1571 |
nlh = nlmsg_put(skb, c->pid, c->seq, XFRM_MSG_NEWAE, sizeof(*id), 0); if (nlh == NULL) return -EMSGSIZE; |
d51d081d6 [IPSEC]: Sync ser... |
1572 |
|
7b67c8575 [XFRM] netlink: U... |
1573 |
id = nlmsg_data(nlh); |
2b5f6dcce [XFRM]: Fix aeven... |
1574 |
memcpy(&id->sa_id.daddr, &x->id.daddr,sizeof(x->id.daddr)); |
d51d081d6 [IPSEC]: Sync ser... |
1575 1576 1577 |
id->sa_id.spi = x->id.spi; id->sa_id.family = x->props.family; id->sa_id.proto = x->id.proto; |
2b5f6dcce [XFRM]: Fix aeven... |
1578 1579 |
memcpy(&id->saddr, &x->props.saddr,sizeof(x->props.saddr)); id->reqid = x->props.reqid; |
d51d081d6 [IPSEC]: Sync ser... |
1580 |
id->flags = c->data.aevent; |
d8647b79c xfrm: Add user in... |
1581 1582 1583 1584 1585 1586 |
if (x->replay_esn) NLA_PUT(skb, XFRMA_REPLAY_ESN_VAL, xfrm_replay_state_esn_len(x->replay_esn), x->replay_esn); else NLA_PUT(skb, XFRMA_REPLAY_VAL, sizeof(x->replay), &x->replay); |
c0144beae [XFRM] netlink: U... |
1587 |
NLA_PUT(skb, XFRMA_LTIME_VAL, sizeof(x->curlft), &x->curlft); |
d51d081d6 [IPSEC]: Sync ser... |
1588 |
|
c0144beae [XFRM] netlink: U... |
1589 1590 |
if (id->flags & XFRM_AE_RTHR) NLA_PUT_U32(skb, XFRMA_REPLAY_THRESH, x->replay_maxdiff); |
d51d081d6 [IPSEC]: Sync ser... |
1591 |
|
c0144beae [XFRM] netlink: U... |
1592 1593 1594 |
if (id->flags & XFRM_AE_ETHR) NLA_PUT_U32(skb, XFRMA_ETIMER_THRESH, x->replay_maxage * 10 / HZ); |
d51d081d6 [IPSEC]: Sync ser... |
1595 |
|
6f26b61e1 xfrm: Allow user ... |
1596 1597 |
if (xfrm_mark_put(skb, &x->mark)) goto nla_put_failure; |
9825069d0 [XFRM] netlink: U... |
1598 |
return nlmsg_end(skb, nlh); |
d51d081d6 [IPSEC]: Sync ser... |
1599 |
|
c0144beae [XFRM] netlink: U... |
1600 |
nla_put_failure: |
9825069d0 [XFRM] netlink: U... |
1601 1602 |
nlmsg_cancel(skb, nlh); return -EMSGSIZE; |
d51d081d6 [IPSEC]: Sync ser... |
1603 |
} |
22e700502 [XFRM_USER]: avoi... |
1604 |
static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, |
5424f32e4 [XFRM] netlink: U... |
1605 |
struct nlattr **attrs) |
d51d081d6 [IPSEC]: Sync ser... |
1606 |
{ |
fc34acd36 netns xfrm: xfrm_... |
1607 |
struct net *net = sock_net(skb->sk); |
d51d081d6 [IPSEC]: Sync ser... |
1608 1609 1610 1611 |
struct xfrm_state *x; struct sk_buff *r_skb; int err; struct km_event c; |
6f26b61e1 xfrm: Allow user ... |
1612 1613 |
u32 mark; struct xfrm_mark m; |
7b67c8575 [XFRM] netlink: U... |
1614 |
struct xfrm_aevent_id *p = nlmsg_data(nlh); |
d51d081d6 [IPSEC]: Sync ser... |
1615 |
struct xfrm_usersa_id *id = &p->sa_id; |
6f26b61e1 xfrm: Allow user ... |
1616 1617 1618 |
mark = xfrm_mark_get(attrs, &m); x = xfrm_state_lookup(net, mark, &id->daddr, id->spi, id->proto, id->family); |
d8647b79c xfrm: Add user in... |
1619 |
if (x == NULL) |
d51d081d6 [IPSEC]: Sync ser... |
1620 |
return -ESRCH; |
d8647b79c xfrm: Add user in... |
1621 1622 1623 1624 1625 |
r_skb = nlmsg_new(xfrm_aevent_msgsize(x), GFP_ATOMIC); if (r_skb == NULL) { xfrm_state_put(x); return -ENOMEM; |
d51d081d6 [IPSEC]: Sync ser... |
1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 |
} /* * XXX: is this lock really needed - none of the other * gets lock (the concern is things getting updated * while we are still reading) - jhs */ spin_lock_bh(&x->lock); c.data.aevent = p->flags; c.seq = nlh->nlmsg_seq; c.pid = nlh->nlmsg_pid; if (build_aevent(r_skb, x, &c) < 0) BUG(); |
a6483b790 netns xfrm: per-n... |
1640 |
err = nlmsg_unicast(net->xfrm.nlsk, r_skb, NETLINK_CB(skb).pid); |
d51d081d6 [IPSEC]: Sync ser... |
1641 1642 1643 1644 |
spin_unlock_bh(&x->lock); xfrm_state_put(x); return err; } |
22e700502 [XFRM_USER]: avoi... |
1645 |
static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, |
5424f32e4 [XFRM] netlink: U... |
1646 |
struct nlattr **attrs) |
d51d081d6 [IPSEC]: Sync ser... |
1647 |
{ |
fc34acd36 netns xfrm: xfrm_... |
1648 |
struct net *net = sock_net(skb->sk); |
d51d081d6 [IPSEC]: Sync ser... |
1649 1650 1651 |
struct xfrm_state *x; struct km_event c; int err = - EINVAL; |
6f26b61e1 xfrm: Allow user ... |
1652 1653 |
u32 mark = 0; struct xfrm_mark m; |
7b67c8575 [XFRM] netlink: U... |
1654 |
struct xfrm_aevent_id *p = nlmsg_data(nlh); |
5424f32e4 [XFRM] netlink: U... |
1655 |
struct nlattr *rp = attrs[XFRMA_REPLAY_VAL]; |
d8647b79c xfrm: Add user in... |
1656 |
struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL]; |
5424f32e4 [XFRM] netlink: U... |
1657 |
struct nlattr *lt = attrs[XFRMA_LTIME_VAL]; |
d51d081d6 [IPSEC]: Sync ser... |
1658 |
|
d8647b79c xfrm: Add user in... |
1659 |
if (!lt && !rp && !re) |
d51d081d6 [IPSEC]: Sync ser... |
1660 1661 1662 1663 1664 |
return err; /* pedantic mode - thou shalt sayeth replaceth */ if (!(nlh->nlmsg_flags&NLM_F_REPLACE)) return err; |
6f26b61e1 xfrm: Allow user ... |
1665 1666 1667 |
mark = xfrm_mark_get(attrs, &m); x = xfrm_state_lookup(net, mark, &p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family); |
d51d081d6 [IPSEC]: Sync ser... |
1668 1669 1670 1671 1672 |
if (x == NULL) return -ESRCH; if (x->km.state != XFRM_STATE_VALID) goto out; |
e2b19125e xfrm: Check for e... |
1673 1674 1675 |
err = xfrm_replay_verify_len(x->replay_esn, rp); if (err) goto out; |
d51d081d6 [IPSEC]: Sync ser... |
1676 |
spin_lock_bh(&x->lock); |
35a7aa08b [XFRM] netlink: R... |
1677 |
xfrm_update_ae_params(x, attrs); |
d51d081d6 [IPSEC]: Sync ser... |
1678 |
spin_unlock_bh(&x->lock); |
d51d081d6 [IPSEC]: Sync ser... |
1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 |
c.event = nlh->nlmsg_type; c.seq = nlh->nlmsg_seq; c.pid = nlh->nlmsg_pid; c.data.aevent = XFRM_AE_CU; km_state_notify(x, &c); err = 0; out: xfrm_state_put(x); return err; } |
22e700502 [XFRM_USER]: avoi... |
1690 |
static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, |
5424f32e4 [XFRM] netlink: U... |
1691 |
struct nlattr **attrs) |
1da177e4c Linux-2.6.12-rc2 |
1692 |
{ |
fc34acd36 netns xfrm: xfrm_... |
1693 |
struct net *net = sock_net(skb->sk); |
f7b6983f0 [XFRM] POLICY: Su... |
1694 |
struct km_event c; |
b798a9ede [XFRM]: Convert a... |
1695 |
u8 type = XFRM_POLICY_TYPE_MAIN; |
f7b6983f0 [XFRM] POLICY: Su... |
1696 |
int err; |
161a09e73 audit: Add auditi... |
1697 |
struct xfrm_audit audit_info; |
f7b6983f0 [XFRM] POLICY: Su... |
1698 |
|
35a7aa08b [XFRM] netlink: R... |
1699 |
err = copy_from_user_policy_type(&type, attrs); |
f7b6983f0 [XFRM] POLICY: Su... |
1700 1701 |
if (err) return err; |
26b15dad9 [IPSEC] Add compl... |
1702 |
|
c53fa1ed9 netlink: kill log... |
1703 1704 1705 |
audit_info.loginuid = audit_get_loginuid(current); audit_info.sessionid = audit_get_sessionid(current); security_task_getsecid(current, &audit_info.secid); |
fc34acd36 netns xfrm: xfrm_... |
1706 |
err = xfrm_policy_flush(net, type, &audit_info); |
2f1eb65f3 xfrm: Flushing em... |
1707 1708 1709 |
if (err) { if (err == -ESRCH) /* empty table */ return 0; |
069c474e8 xfrm: Revert fals... |
1710 |
return err; |
2f1eb65f3 xfrm: Flushing em... |
1711 |
} |
f7b6983f0 [XFRM] POLICY: Su... |
1712 |
c.data.type = type; |
f60f6b8f7 [IPSEC] Use XFRM_... |
1713 |
c.event = nlh->nlmsg_type; |
26b15dad9 [IPSEC] Add compl... |
1714 1715 |
c.seq = nlh->nlmsg_seq; c.pid = nlh->nlmsg_pid; |
7067802e2 netns xfrm: pass ... |
1716 |
c.net = net; |
26b15dad9 [IPSEC] Add compl... |
1717 |
km_policy_notify(NULL, 0, &c); |
1da177e4c Linux-2.6.12-rc2 |
1718 1719 |
return 0; } |
22e700502 [XFRM_USER]: avoi... |
1720 |
static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, |
5424f32e4 [XFRM] netlink: U... |
1721 |
struct nlattr **attrs) |
6c5c8ca7f [IPSEC]: Sync ser... |
1722 |
{ |
fc34acd36 netns xfrm: xfrm_... |
1723 |
struct net *net = sock_net(skb->sk); |
6c5c8ca7f [IPSEC]: Sync ser... |
1724 |
struct xfrm_policy *xp; |
7b67c8575 [XFRM] netlink: U... |
1725 |
struct xfrm_user_polexpire *up = nlmsg_data(nlh); |
6c5c8ca7f [IPSEC]: Sync ser... |
1726 |
struct xfrm_userpolicy_info *p = &up->pol; |
b798a9ede [XFRM]: Convert a... |
1727 |
u8 type = XFRM_POLICY_TYPE_MAIN; |
6c5c8ca7f [IPSEC]: Sync ser... |
1728 |
int err = -ENOENT; |
295fae568 xfrm: Allow user ... |
1729 1730 |
struct xfrm_mark m; u32 mark = xfrm_mark_get(attrs, &m); |
6c5c8ca7f [IPSEC]: Sync ser... |
1731 |
|
35a7aa08b [XFRM] netlink: R... |
1732 |
err = copy_from_user_policy_type(&type, attrs); |
f7b6983f0 [XFRM] POLICY: Su... |
1733 1734 |
if (err) return err; |
c8bf4d04f xfrm_user: verify... |
1735 1736 1737 |
err = verify_policy_dir(p->dir); if (err) return err; |
6c5c8ca7f [IPSEC]: Sync ser... |
1738 |
if (p->index) |
295fae568 xfrm: Allow user ... |
1739 |
xp = xfrm_policy_byid(net, mark, type, p->dir, p->index, 0, &err); |
6c5c8ca7f [IPSEC]: Sync ser... |
1740 |
else { |
5424f32e4 [XFRM] netlink: U... |
1741 |
struct nlattr *rt = attrs[XFRMA_SEC_CTX]; |
03e1ad7b5 LSM: Make the Lab... |
1742 |
struct xfrm_sec_ctx *ctx; |
6c5c8ca7f [IPSEC]: Sync ser... |
1743 |
|
35a7aa08b [XFRM] netlink: R... |
1744 |
err = verify_sec_ctx_len(attrs); |
6c5c8ca7f [IPSEC]: Sync ser... |
1745 1746 |
if (err) return err; |
2c8dd1163 [XFRM]: Compilati... |
1747 |
ctx = NULL; |
6c5c8ca7f [IPSEC]: Sync ser... |
1748 |
if (rt) { |
5424f32e4 [XFRM] netlink: U... |
1749 |
struct xfrm_user_sec_ctx *uctx = nla_data(rt); |
6c5c8ca7f [IPSEC]: Sync ser... |
1750 |
|
03e1ad7b5 LSM: Make the Lab... |
1751 1752 |
err = security_xfrm_policy_alloc(&ctx, uctx); if (err) |
6c5c8ca7f [IPSEC]: Sync ser... |
1753 |
return err; |
2c8dd1163 [XFRM]: Compilati... |
1754 |
} |
295fae568 xfrm: Allow user ... |
1755 |
xp = xfrm_policy_bysel_ctx(net, mark, type, p->dir, |
6f26b61e1 xfrm: Allow user ... |
1756 |
&p->sel, ctx, 0, &err); |
03e1ad7b5 LSM: Make the Lab... |
1757 |
security_xfrm_policy_free(ctx); |
6c5c8ca7f [IPSEC]: Sync ser... |
1758 |
} |
6c5c8ca7f [IPSEC]: Sync ser... |
1759 |
if (xp == NULL) |
ef41aaa0b [IPSEC]: xfrm_pol... |
1760 |
return -ENOENT; |
03e1ad7b5 LSM: Make the Lab... |
1761 |
|
ea2dea9da xfrm: remove poli... |
1762 |
if (unlikely(xp->walk.dead)) |
6c5c8ca7f [IPSEC]: Sync ser... |
1763 |
goto out; |
6c5c8ca7f [IPSEC]: Sync ser... |
1764 |
|
6c5c8ca7f [IPSEC]: Sync ser... |
1765 1766 |
err = 0; if (up->hard) { |
c53fa1ed9 netlink: kill log... |
1767 1768 1769 1770 1771 |
uid_t loginuid = audit_get_loginuid(current); u32 sessionid = audit_get_sessionid(current); u32 sid; security_task_getsecid(current, &sid); |
6c5c8ca7f [IPSEC]: Sync ser... |
1772 |
xfrm_policy_delete(xp, p->dir); |
2532386f4 Audit: collect se... |
1773 |
xfrm_audit_policy_delete(xp, 1, loginuid, sessionid, sid); |
161a09e73 audit: Add auditi... |
1774 |
|
6c5c8ca7f [IPSEC]: Sync ser... |
1775 1776 |
} else { // reset the timers here? |
62db5cfd7 xfrm: add severit... |
1777 1778 |
WARN(1, "Dont know what to do with soft policy expire "); |
6c5c8ca7f [IPSEC]: Sync ser... |
1779 1780 1781 1782 1783 1784 1785 |
} km_policy_expired(xp, p->dir, up->hard, current->pid); out: xfrm_pol_put(xp); return err; } |
22e700502 [XFRM_USER]: avoi... |
1786 |
static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, |
5424f32e4 [XFRM] netlink: U... |
1787 |
struct nlattr **attrs) |
53bc6b4d2 [IPSEC]: Sync ser... |
1788 |
{ |
fc34acd36 netns xfrm: xfrm_... |
1789 |
struct net *net = sock_net(skb->sk); |
53bc6b4d2 [IPSEC]: Sync ser... |
1790 1791 |
struct xfrm_state *x; int err; |
7b67c8575 [XFRM] netlink: U... |
1792 |
struct xfrm_user_expire *ue = nlmsg_data(nlh); |
53bc6b4d2 [IPSEC]: Sync ser... |
1793 |
struct xfrm_usersa_info *p = &ue->state; |
6f26b61e1 xfrm: Allow user ... |
1794 |
struct xfrm_mark m; |
928497f02 xfrm_user: avoid ... |
1795 |
u32 mark = xfrm_mark_get(attrs, &m); |
53bc6b4d2 [IPSEC]: Sync ser... |
1796 |
|
6f26b61e1 xfrm: Allow user ... |
1797 |
x = xfrm_state_lookup(net, mark, &p->id.daddr, p->id.spi, p->id.proto, p->family); |
53bc6b4d2 [IPSEC]: Sync ser... |
1798 |
|
3a765aa52 [XFRM] xfrm_user:... |
1799 |
err = -ENOENT; |
53bc6b4d2 [IPSEC]: Sync ser... |
1800 1801 |
if (x == NULL) return err; |
53bc6b4d2 [IPSEC]: Sync ser... |
1802 |
spin_lock_bh(&x->lock); |
3a765aa52 [XFRM] xfrm_user:... |
1803 |
err = -EINVAL; |
53bc6b4d2 [IPSEC]: Sync ser... |
1804 1805 1806 |
if (x->km.state != XFRM_STATE_VALID) goto out; km_state_expired(x, ue->hard, current->pid); |
161a09e73 audit: Add auditi... |
1807 |
if (ue->hard) { |
c53fa1ed9 netlink: kill log... |
1808 1809 1810 1811 1812 |
uid_t loginuid = audit_get_loginuid(current); u32 sessionid = audit_get_sessionid(current); u32 sid; security_task_getsecid(current, &sid); |
53bc6b4d2 [IPSEC]: Sync ser... |
1813 |
__xfrm_state_delete(x); |
2532386f4 Audit: collect se... |
1814 |
xfrm_audit_state_delete(x, 1, loginuid, sessionid, sid); |
161a09e73 audit: Add auditi... |
1815 |
} |
3a765aa52 [XFRM] xfrm_user:... |
1816 |
err = 0; |
53bc6b4d2 [IPSEC]: Sync ser... |
1817 1818 1819 1820 1821 |
out: spin_unlock_bh(&x->lock); xfrm_state_put(x); return err; } |
22e700502 [XFRM_USER]: avoi... |
1822 |
static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, |
5424f32e4 [XFRM] netlink: U... |
1823 |
struct nlattr **attrs) |
980ebd257 [IPSEC]: Sync ser... |
1824 |
{ |
fc34acd36 netns xfrm: xfrm_... |
1825 |
struct net *net = sock_net(skb->sk); |
980ebd257 [IPSEC]: Sync ser... |
1826 1827 1828 |
struct xfrm_policy *xp; struct xfrm_user_tmpl *ut; int i; |
5424f32e4 [XFRM] netlink: U... |
1829 |
struct nlattr *rt = attrs[XFRMA_TMPL]; |
6f26b61e1 xfrm: Allow user ... |
1830 |
struct xfrm_mark mark; |
980ebd257 [IPSEC]: Sync ser... |
1831 |
|
7b67c8575 [XFRM] netlink: U... |
1832 |
struct xfrm_user_acquire *ua = nlmsg_data(nlh); |
fc34acd36 netns xfrm: xfrm_... |
1833 |
struct xfrm_state *x = xfrm_state_alloc(net); |
980ebd257 [IPSEC]: Sync ser... |
1834 1835 1836 |
int err = -ENOMEM; if (!x) |
d8eb93078 xfrm: join error ... |
1837 |
goto nomem; |
980ebd257 [IPSEC]: Sync ser... |
1838 |
|
6f26b61e1 xfrm: Allow user ... |
1839 |
xfrm_mark_get(attrs, &mark); |
980ebd257 [IPSEC]: Sync ser... |
1840 |
err = verify_newpolicy_info(&ua->policy); |
d8eb93078 xfrm: join error ... |
1841 1842 |
if (err) goto bad_policy; |
980ebd257 [IPSEC]: Sync ser... |
1843 1844 |
/* build an XP */ |
fc34acd36 netns xfrm: xfrm_... |
1845 |
xp = xfrm_policy_construct(net, &ua->policy, attrs, &err); |
d8eb93078 xfrm: join error ... |
1846 1847 |
if (!xp) goto free_state; |
980ebd257 [IPSEC]: Sync ser... |
1848 1849 1850 1851 |
memcpy(&x->id, &ua->id, sizeof(ua->id)); memcpy(&x->props.saddr, &ua->saddr, sizeof(ua->saddr)); memcpy(&x->sel, &ua->sel, sizeof(ua->sel)); |
6f26b61e1 xfrm: Allow user ... |
1852 1853 |
xp->mark.m = x->mark.m = mark.m; xp->mark.v = x->mark.v = mark.v; |
5424f32e4 [XFRM] netlink: U... |
1854 |
ut = nla_data(rt); |
980ebd257 [IPSEC]: Sync ser... |
1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 |
/* extract the templates and for each call km_key */ for (i = 0; i < xp->xfrm_nr; i++, ut++) { struct xfrm_tmpl *t = &xp->xfrm_vec[i]; memcpy(&x->id, &t->id, sizeof(x->id)); x->props.mode = t->mode; x->props.reqid = t->reqid; x->props.family = ut->family; t->aalgos = ua->aalgos; t->ealgos = ua->ealgos; t->calgos = ua->calgos; err = km_query(x, t, xp); } kfree(x); kfree(xp); return 0; |
d8eb93078 xfrm: join error ... |
1873 1874 |
bad_policy: |
62db5cfd7 xfrm: add severit... |
1875 1876 |
WARN(1, "BAD policy passed "); |
d8eb93078 xfrm: join error ... |
1877 1878 1879 1880 |
free_state: kfree(x); nomem: return err; |
980ebd257 [IPSEC]: Sync ser... |
1881 |
} |
5c79de6e7 [XFRM]: User inte... |
1882 |
#ifdef CONFIG_XFRM_MIGRATE |
5c79de6e7 [XFRM]: User inte... |
1883 |
static int copy_from_user_migrate(struct xfrm_migrate *ma, |
13c1d1893 xfrm: MIGRATE enh... |
1884 |
struct xfrm_kmaddress *k, |
5424f32e4 [XFRM] netlink: U... |
1885 |
struct nlattr **attrs, int *num) |
5c79de6e7 [XFRM]: User inte... |
1886 |
{ |
5424f32e4 [XFRM] netlink: U... |
1887 |
struct nlattr *rt = attrs[XFRMA_MIGRATE]; |
5c79de6e7 [XFRM]: User inte... |
1888 1889 |
struct xfrm_user_migrate *um; int i, num_migrate; |
13c1d1893 xfrm: MIGRATE enh... |
1890 1891 1892 1893 1894 1895 1896 1897 1898 |
if (k != NULL) { struct xfrm_user_kmaddress *uk; uk = nla_data(attrs[XFRMA_KMADDRESS]); memcpy(&k->local, &uk->local, sizeof(k->local)); memcpy(&k->remote, &uk->remote, sizeof(k->remote)); k->family = uk->family; k->reserved = uk->reserved; } |
5424f32e4 [XFRM] netlink: U... |
1899 1900 |
um = nla_data(rt); num_migrate = nla_len(rt) / sizeof(*um); |
5c79de6e7 [XFRM]: User inte... |
1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 |
if (num_migrate <= 0 || num_migrate > XFRM_MAX_DEPTH) return -EINVAL; for (i = 0; i < num_migrate; i++, um++, ma++) { memcpy(&ma->old_daddr, &um->old_daddr, sizeof(ma->old_daddr)); memcpy(&ma->old_saddr, &um->old_saddr, sizeof(ma->old_saddr)); memcpy(&ma->new_daddr, &um->new_daddr, sizeof(ma->new_daddr)); memcpy(&ma->new_saddr, &um->new_saddr, sizeof(ma->new_saddr)); ma->proto = um->proto; ma->mode = um->mode; ma->reqid = um->reqid; ma->old_family = um->old_family; ma->new_family = um->new_family; } *num = i; return 0; } static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh, |
5424f32e4 [XFRM] netlink: U... |
1924 |
struct nlattr **attrs) |
5c79de6e7 [XFRM]: User inte... |
1925 |
{ |
7b67c8575 [XFRM] netlink: U... |
1926 |
struct xfrm_userpolicy_id *pi = nlmsg_data(nlh); |
5c79de6e7 [XFRM]: User inte... |
1927 |
struct xfrm_migrate m[XFRM_MAX_DEPTH]; |
13c1d1893 xfrm: MIGRATE enh... |
1928 |
struct xfrm_kmaddress km, *kmp; |
5c79de6e7 [XFRM]: User inte... |
1929 1930 1931 |
u8 type; int err; int n = 0; |
35a7aa08b [XFRM] netlink: R... |
1932 |
if (attrs[XFRMA_MIGRATE] == NULL) |
cf5cb79f6 [XFRM] netlink: E... |
1933 |
return -EINVAL; |
5c79de6e7 [XFRM]: User inte... |
1934 |
|
13c1d1893 xfrm: MIGRATE enh... |
1935 |
kmp = attrs[XFRMA_KMADDRESS] ? &km : NULL; |
5424f32e4 [XFRM] netlink: U... |
1936 |
err = copy_from_user_policy_type(&type, attrs); |
5c79de6e7 [XFRM]: User inte... |
1937 1938 |
if (err) return err; |
13c1d1893 xfrm: MIGRATE enh... |
1939 |
err = copy_from_user_migrate((struct xfrm_migrate *)m, kmp, attrs, &n); |
5c79de6e7 [XFRM]: User inte... |
1940 1941 1942 1943 1944 |
if (err) return err; if (!n) return 0; |
13c1d1893 xfrm: MIGRATE enh... |
1945 |
xfrm_migrate(&pi->sel, pi->dir, type, m, n, kmp); |
5c79de6e7 [XFRM]: User inte... |
1946 1947 1948 1949 1950 |
return 0; } #else static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh, |
5424f32e4 [XFRM] netlink: U... |
1951 |
struct nlattr **attrs) |
5c79de6e7 [XFRM]: User inte... |
1952 1953 1954 1955 1956 1957 |
{ return -ENOPROTOOPT; } #endif #ifdef CONFIG_XFRM_MIGRATE |
183cad127 xfrm: Const'ify p... |
1958 |
static int copy_to_user_migrate(const struct xfrm_migrate *m, struct sk_buff *skb) |
5c79de6e7 [XFRM]: User inte... |
1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 |
{ struct xfrm_user_migrate um; memset(&um, 0, sizeof(um)); um.proto = m->proto; um.mode = m->mode; um.reqid = m->reqid; um.old_family = m->old_family; memcpy(&um.old_daddr, &m->old_daddr, sizeof(um.old_daddr)); memcpy(&um.old_saddr, &m->old_saddr, sizeof(um.old_saddr)); um.new_family = m->new_family; memcpy(&um.new_daddr, &m->new_daddr, sizeof(um.new_daddr)); memcpy(&um.new_saddr, &m->new_saddr, sizeof(um.new_saddr)); |
c0144beae [XFRM] netlink: U... |
1972 |
return nla_put(skb, XFRMA_MIGRATE, sizeof(um), &um); |
5c79de6e7 [XFRM]: User inte... |
1973 |
} |
183cad127 xfrm: Const'ify p... |
1974 |
static int copy_to_user_kmaddress(const struct xfrm_kmaddress *k, struct sk_buff *skb) |
13c1d1893 xfrm: MIGRATE enh... |
1975 1976 1977 1978 1979 1980 1981 |
{ struct xfrm_user_kmaddress uk; memset(&uk, 0, sizeof(uk)); uk.family = k->family; uk.reserved = k->reserved; memcpy(&uk.local, &k->local, sizeof(uk.local)); |
a1caa3229 XFRM: copy_to_use... |
1982 |
memcpy(&uk.remote, &k->remote, sizeof(uk.remote)); |
13c1d1893 xfrm: MIGRATE enh... |
1983 1984 1985 1986 1987 |
return nla_put(skb, XFRMA_KMADDRESS, sizeof(uk), &uk); } static inline size_t xfrm_migrate_msgsize(int num_migrate, int with_kma) |
7deb22649 [XFRM] netlink: U... |
1988 1989 |
{ return NLMSG_ALIGN(sizeof(struct xfrm_userpolicy_id)) |
13c1d1893 xfrm: MIGRATE enh... |
1990 1991 1992 |
+ (with_kma ? nla_total_size(sizeof(struct xfrm_kmaddress)) : 0) + nla_total_size(sizeof(struct xfrm_user_migrate) * num_migrate) + userpolicy_type_attrsize(); |
7deb22649 [XFRM] netlink: U... |
1993 |
} |
183cad127 xfrm: Const'ify p... |
1994 1995 1996 |
static int build_migrate(struct sk_buff *skb, const struct xfrm_migrate *m, int num_migrate, const struct xfrm_kmaddress *k, const struct xfrm_selector *sel, u8 dir, u8 type) |
5c79de6e7 [XFRM]: User inte... |
1997 |
{ |
183cad127 xfrm: Const'ify p... |
1998 |
const struct xfrm_migrate *mp; |
5c79de6e7 [XFRM]: User inte... |
1999 2000 |
struct xfrm_userpolicy_id *pol_id; struct nlmsghdr *nlh; |
5c79de6e7 [XFRM]: User inte... |
2001 |
int i; |
79b8b7f4a [XFRM] netlink: U... |
2002 2003 2004 |
nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_MIGRATE, sizeof(*pol_id), 0); if (nlh == NULL) return -EMSGSIZE; |
5c79de6e7 [XFRM]: User inte... |
2005 |
|
7b67c8575 [XFRM] netlink: U... |
2006 |
pol_id = nlmsg_data(nlh); |
5c79de6e7 [XFRM]: User inte... |
2007 2008 2009 2010 |
/* copy data from selector, dir, and type to the pol_id */ memset(pol_id, 0, sizeof(*pol_id)); memcpy(&pol_id->sel, sel, sizeof(pol_id->sel)); pol_id->dir = dir; |
13c1d1893 xfrm: MIGRATE enh... |
2011 2012 |
if (k != NULL && (copy_to_user_kmaddress(k, skb) < 0)) goto nlmsg_failure; |
5c79de6e7 [XFRM]: User inte... |
2013 2014 2015 2016 2017 2018 2019 |
if (copy_to_user_policy_type(type, skb) < 0) goto nlmsg_failure; for (i = 0, mp = m ; i < num_migrate; i++, mp++) { if (copy_to_user_migrate(mp, skb) < 0) goto nlmsg_failure; } |
9825069d0 [XFRM] netlink: U... |
2020 |
return nlmsg_end(skb, nlh); |
5c79de6e7 [XFRM]: User inte... |
2021 |
nlmsg_failure: |
9825069d0 [XFRM] netlink: U... |
2022 2023 |
nlmsg_cancel(skb, nlh); return -EMSGSIZE; |
5c79de6e7 [XFRM]: User inte... |
2024 |
} |
183cad127 xfrm: Const'ify p... |
2025 2026 2027 |
static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, const struct xfrm_migrate *m, int num_migrate, const struct xfrm_kmaddress *k) |
5c79de6e7 [XFRM]: User inte... |
2028 |
{ |
a6483b790 netns xfrm: per-n... |
2029 |
struct net *net = &init_net; |
5c79de6e7 [XFRM]: User inte... |
2030 |
struct sk_buff *skb; |
5c79de6e7 [XFRM]: User inte... |
2031 |
|
13c1d1893 xfrm: MIGRATE enh... |
2032 |
skb = nlmsg_new(xfrm_migrate_msgsize(num_migrate, !!k), GFP_ATOMIC); |
5c79de6e7 [XFRM]: User inte... |
2033 2034 2035 2036 |
if (skb == NULL) return -ENOMEM; /* build migrate */ |
13c1d1893 xfrm: MIGRATE enh... |
2037 |
if (build_migrate(skb, m, num_migrate, k, sel, dir, type) < 0) |
5c79de6e7 [XFRM]: User inte... |
2038 |
BUG(); |
a6483b790 netns xfrm: per-n... |
2039 |
return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_MIGRATE, GFP_ATOMIC); |
5c79de6e7 [XFRM]: User inte... |
2040 2041 |
} #else |
183cad127 xfrm: Const'ify p... |
2042 2043 2044 |
static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, const struct xfrm_migrate *m, int num_migrate, const struct xfrm_kmaddress *k) |
5c79de6e7 [XFRM]: User inte... |
2045 2046 2047 2048 |
{ return -ENOPROTOOPT; } #endif |
d51d081d6 [IPSEC]: Sync ser... |
2049 |
|
a7bd9a45c [XFRM] netlink: U... |
2050 |
#define XMSGSIZE(type) sizeof(struct type) |
492b558b3 [XFRM]: Cleanup x... |
2051 2052 |
static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = { |
66f9a2590 Revert "xfrm: For... |
2053 |
[XFRM_MSG_NEWSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_info), |
492b558b3 [XFRM]: Cleanup x... |
2054 2055 2056 2057 2058 2059 |
[XFRM_MSG_DELSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_id), [XFRM_MSG_GETSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_id), [XFRM_MSG_NEWPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_info), [XFRM_MSG_DELPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id), [XFRM_MSG_GETPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id), [XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userspi_info), |
980ebd257 [IPSEC]: Sync ser... |
2060 |
[XFRM_MSG_ACQUIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_acquire), |
53bc6b4d2 [IPSEC]: Sync ser... |
2061 |
[XFRM_MSG_EXPIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_expire), |
492b558b3 [XFRM]: Cleanup x... |
2062 |
[XFRM_MSG_UPDPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_info), |
66f9a2590 Revert "xfrm: For... |
2063 |
[XFRM_MSG_UPDSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_info), |
6c5c8ca7f [IPSEC]: Sync ser... |
2064 |
[XFRM_MSG_POLEXPIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_polexpire), |
492b558b3 [XFRM]: Cleanup x... |
2065 |
[XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_flush), |
a7bd9a45c [XFRM] netlink: U... |
2066 |
[XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = 0, |
d51d081d6 [IPSEC]: Sync ser... |
2067 2068 |
[XFRM_MSG_NEWAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id), [XFRM_MSG_GETAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id), |
97a64b457 [XFRM]: Introduce... |
2069 |
[XFRM_MSG_REPORT - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_report), |
5c79de6e7 [XFRM]: User inte... |
2070 |
[XFRM_MSG_MIGRATE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id), |
a7bd9a45c [XFRM] netlink: U... |
2071 2072 |
[XFRM_MSG_GETSADINFO - XFRM_MSG_BASE] = sizeof(u32), [XFRM_MSG_GETSPDINFO - XFRM_MSG_BASE] = sizeof(u32), |
1da177e4c Linux-2.6.12-rc2 |
2073 |
}; |
492b558b3 [XFRM]: Cleanup x... |
2074 |
#undef XMSGSIZE |
cf5cb79f6 [XFRM] netlink: E... |
2075 |
static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { |
c28e93040 xfrm: validate at... |
2076 2077 2078 2079 |
[XFRMA_SA] = { .len = sizeof(struct xfrm_usersa_info)}, [XFRMA_POLICY] = { .len = sizeof(struct xfrm_userpolicy_info)}, [XFRMA_LASTUSED] = { .type = NLA_U64}, [XFRMA_ALG_AUTH_TRUNC] = { .len = sizeof(struct xfrm_algo_auth)}, |
1a6509d99 [IPSEC]: Add supp... |
2080 |
[XFRMA_ALG_AEAD] = { .len = sizeof(struct xfrm_algo_aead) }, |
cf5cb79f6 [XFRM] netlink: E... |
2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 |
[XFRMA_ALG_AUTH] = { .len = sizeof(struct xfrm_algo) }, [XFRMA_ALG_CRYPT] = { .len = sizeof(struct xfrm_algo) }, [XFRMA_ALG_COMP] = { .len = sizeof(struct xfrm_algo) }, [XFRMA_ENCAP] = { .len = sizeof(struct xfrm_encap_tmpl) }, [XFRMA_TMPL] = { .len = sizeof(struct xfrm_user_tmpl) }, [XFRMA_SEC_CTX] = { .len = sizeof(struct xfrm_sec_ctx) }, [XFRMA_LTIME_VAL] = { .len = sizeof(struct xfrm_lifetime_cur) }, [XFRMA_REPLAY_VAL] = { .len = sizeof(struct xfrm_replay_state) }, [XFRMA_REPLAY_THRESH] = { .type = NLA_U32 }, [XFRMA_ETIMER_THRESH] = { .type = NLA_U32 }, [XFRMA_SRCADDR] = { .len = sizeof(xfrm_address_t) }, [XFRMA_COADDR] = { .len = sizeof(xfrm_address_t) }, [XFRMA_POLICY_TYPE] = { .len = sizeof(struct xfrm_userpolicy_type)}, [XFRMA_MIGRATE] = { .len = sizeof(struct xfrm_user_migrate) }, |
13c1d1893 xfrm: MIGRATE enh... |
2095 |
[XFRMA_KMADDRESS] = { .len = sizeof(struct xfrm_user_kmaddress) }, |
6f26b61e1 xfrm: Allow user ... |
2096 |
[XFRMA_MARK] = { .len = sizeof(struct xfrm_mark) }, |
35d2856b4 xfrm: Add Traffic... |
2097 |
[XFRMA_TFCPAD] = { .type = NLA_U32 }, |
d8647b79c xfrm: Add user in... |
2098 |
[XFRMA_REPLAY_ESN_VAL] = { .len = sizeof(struct xfrm_replay_state_esn) }, |
cf5cb79f6 [XFRM] netlink: E... |
2099 |
}; |
1da177e4c Linux-2.6.12-rc2 |
2100 |
static struct xfrm_link { |
5424f32e4 [XFRM] netlink: U... |
2101 |
int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **); |
1da177e4c Linux-2.6.12-rc2 |
2102 |
int (*dump)(struct sk_buff *, struct netlink_callback *); |
4c563f766 [XFRM]: Speed up ... |
2103 |
int (*done)(struct netlink_callback *); |
492b558b3 [XFRM]: Cleanup x... |
2104 2105 2106 2107 |
} xfrm_dispatch[XFRM_NR_MSGTYPES] = { [XFRM_MSG_NEWSA - XFRM_MSG_BASE] = { .doit = xfrm_add_sa }, [XFRM_MSG_DELSA - XFRM_MSG_BASE] = { .doit = xfrm_del_sa }, [XFRM_MSG_GETSA - XFRM_MSG_BASE] = { .doit = xfrm_get_sa, |
4c563f766 [XFRM]: Speed up ... |
2108 2109 |
.dump = xfrm_dump_sa, .done = xfrm_dump_sa_done }, |
492b558b3 [XFRM]: Cleanup x... |
2110 2111 2112 |
[XFRM_MSG_NEWPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_add_policy }, [XFRM_MSG_DELPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_get_policy }, [XFRM_MSG_GETPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_get_policy, |
4c563f766 [XFRM]: Speed up ... |
2113 2114 |
.dump = xfrm_dump_policy, .done = xfrm_dump_policy_done }, |
492b558b3 [XFRM]: Cleanup x... |
2115 |
[XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = { .doit = xfrm_alloc_userspi }, |
980ebd257 [IPSEC]: Sync ser... |
2116 |
[XFRM_MSG_ACQUIRE - XFRM_MSG_BASE] = { .doit = xfrm_add_acquire }, |
53bc6b4d2 [IPSEC]: Sync ser... |
2117 |
[XFRM_MSG_EXPIRE - XFRM_MSG_BASE] = { .doit = xfrm_add_sa_expire }, |
492b558b3 [XFRM]: Cleanup x... |
2118 2119 |
[XFRM_MSG_UPDPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_add_policy }, [XFRM_MSG_UPDSA - XFRM_MSG_BASE] = { .doit = xfrm_add_sa }, |
6c5c8ca7f [IPSEC]: Sync ser... |
2120 |
[XFRM_MSG_POLEXPIRE - XFRM_MSG_BASE] = { .doit = xfrm_add_pol_expire}, |
492b558b3 [XFRM]: Cleanup x... |
2121 2122 |
[XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = { .doit = xfrm_flush_sa }, [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_flush_policy }, |
d51d081d6 [IPSEC]: Sync ser... |
2123 2124 |
[XFRM_MSG_NEWAE - XFRM_MSG_BASE] = { .doit = xfrm_new_ae }, [XFRM_MSG_GETAE - XFRM_MSG_BASE] = { .doit = xfrm_get_ae }, |
5c79de6e7 [XFRM]: User inte... |
2125 |
[XFRM_MSG_MIGRATE - XFRM_MSG_BASE] = { .doit = xfrm_do_migrate }, |
566ec0344 [XFRM]: Missing b... |
2126 |
[XFRM_MSG_GETSADINFO - XFRM_MSG_BASE] = { .doit = xfrm_get_sadinfo }, |
ecfd6b183 [XFRM]: Export SP... |
2127 |
[XFRM_MSG_GETSPDINFO - XFRM_MSG_BASE] = { .doit = xfrm_get_spdinfo }, |
1da177e4c Linux-2.6.12-rc2 |
2128 |
}; |
1d00a4eb4 [NETLINK]: Remove... |
2129 |
static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) |
1da177e4c Linux-2.6.12-rc2 |
2130 |
{ |
a6483b790 netns xfrm: per-n... |
2131 |
struct net *net = sock_net(skb->sk); |
35a7aa08b [XFRM] netlink: R... |
2132 |
struct nlattr *attrs[XFRMA_MAX+1]; |
1da177e4c Linux-2.6.12-rc2 |
2133 |
struct xfrm_link *link; |
a7bd9a45c [XFRM] netlink: U... |
2134 |
int type, err; |
1da177e4c Linux-2.6.12-rc2 |
2135 |
|
1da177e4c Linux-2.6.12-rc2 |
2136 |
type = nlh->nlmsg_type; |
1da177e4c Linux-2.6.12-rc2 |
2137 |
if (type > XFRM_MSG_MAX) |
1d00a4eb4 [NETLINK]: Remove... |
2138 |
return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
2139 2140 2141 2142 2143 |
type -= XFRM_MSG_BASE; link = &xfrm_dispatch[type]; /* All operations require privileges, even GET */ |
fd7784615 security: remove ... |
2144 |
if (!capable(CAP_NET_ADMIN)) |
1d00a4eb4 [NETLINK]: Remove... |
2145 |
return -EPERM; |
1da177e4c Linux-2.6.12-rc2 |
2146 |
|
492b558b3 [XFRM]: Cleanup x... |
2147 2148 |
if ((type == (XFRM_MSG_GETSA - XFRM_MSG_BASE) || type == (XFRM_MSG_GETPOLICY - XFRM_MSG_BASE)) && |
b8f3ab429 Revert "netlink: ... |
2149 |
(nlh->nlmsg_flags & NLM_F_DUMP)) { |
1da177e4c Linux-2.6.12-rc2 |
2150 |
if (link->dump == NULL) |
1d00a4eb4 [NETLINK]: Remove... |
2151 |
return -EINVAL; |
88fc2c843 [XFRM]: Use gener... |
2152 |
|
c7ac8679b rtnetlink: Comput... |
2153 2154 |
return netlink_dump_start(net->xfrm.nlsk, skb, nlh, link->dump, link->done, 0); |
1da177e4c Linux-2.6.12-rc2 |
2155 |
} |
35a7aa08b [XFRM] netlink: R... |
2156 |
err = nlmsg_parse(nlh, xfrm_msg_min[type], attrs, XFRMA_MAX, |
cf5cb79f6 [XFRM] netlink: E... |
2157 |
xfrma_policy); |
a7bd9a45c [XFRM] netlink: U... |
2158 2159 |
if (err < 0) return err; |
1da177e4c Linux-2.6.12-rc2 |
2160 2161 |
if (link->doit == NULL) |
1d00a4eb4 [NETLINK]: Remove... |
2162 |
return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
2163 |
|
5424f32e4 [XFRM] netlink: U... |
2164 |
return link->doit(skb, nlh, attrs); |
1da177e4c Linux-2.6.12-rc2 |
2165 |
} |
cd40b7d39 [NET]: make netli... |
2166 |
static void xfrm_netlink_rcv(struct sk_buff *skb) |
1da177e4c Linux-2.6.12-rc2 |
2167 |
{ |
cd40b7d39 [NET]: make netli... |
2168 2169 2170 |
mutex_lock(&xfrm_cfg_mutex); netlink_rcv_skb(skb, &xfrm_user_rcv_msg); mutex_unlock(&xfrm_cfg_mutex); |
1da177e4c Linux-2.6.12-rc2 |
2171 |
} |
7deb22649 [XFRM] netlink: U... |
2172 2173 |
static inline size_t xfrm_expire_msgsize(void) { |
6f26b61e1 xfrm: Allow user ... |
2174 2175 |
return NLMSG_ALIGN(sizeof(struct xfrm_user_expire)) + nla_total_size(sizeof(struct xfrm_mark)); |
7deb22649 [XFRM] netlink: U... |
2176 |
} |
214e005bc xfrm: Pass km_eve... |
2177 |
static int build_expire(struct sk_buff *skb, struct xfrm_state *x, const struct km_event *c) |
1da177e4c Linux-2.6.12-rc2 |
2178 2179 2180 |
{ struct xfrm_user_expire *ue; struct nlmsghdr *nlh; |
1da177e4c Linux-2.6.12-rc2 |
2181 |
|
79b8b7f4a [XFRM] netlink: U... |
2182 2183 2184 |
nlh = nlmsg_put(skb, c->pid, 0, XFRM_MSG_EXPIRE, sizeof(*ue), 0); if (nlh == NULL) return -EMSGSIZE; |
1da177e4c Linux-2.6.12-rc2 |
2185 |
|
7b67c8575 [XFRM] netlink: U... |
2186 |
ue = nlmsg_data(nlh); |
1da177e4c Linux-2.6.12-rc2 |
2187 |
copy_to_user_state(x, &ue->state); |
d51d081d6 [IPSEC]: Sync ser... |
2188 |
ue->hard = (c->data.hard != 0) ? 1 : 0; |
1da177e4c Linux-2.6.12-rc2 |
2189 |
|
6f26b61e1 xfrm: Allow user ... |
2190 2191 |
if (xfrm_mark_put(skb, &x->mark)) goto nla_put_failure; |
9825069d0 [XFRM] netlink: U... |
2192 |
return nlmsg_end(skb, nlh); |
6f26b61e1 xfrm: Allow user ... |
2193 2194 2195 |
nla_put_failure: return -EMSGSIZE; |
1da177e4c Linux-2.6.12-rc2 |
2196 |
} |
214e005bc xfrm: Pass km_eve... |
2197 |
static int xfrm_exp_state_notify(struct xfrm_state *x, const struct km_event *c) |
1da177e4c Linux-2.6.12-rc2 |
2198 |
{ |
fc34acd36 netns xfrm: xfrm_... |
2199 |
struct net *net = xs_net(x); |
1da177e4c Linux-2.6.12-rc2 |
2200 |
struct sk_buff *skb; |
7deb22649 [XFRM] netlink: U... |
2201 |
skb = nlmsg_new(xfrm_expire_msgsize(), GFP_ATOMIC); |
1da177e4c Linux-2.6.12-rc2 |
2202 2203 |
if (skb == NULL) return -ENOMEM; |
6f26b61e1 xfrm: Allow user ... |
2204 2205 2206 2207 |
if (build_expire(skb, x, c) < 0) { kfree_skb(skb); return -EMSGSIZE; } |
1da177e4c Linux-2.6.12-rc2 |
2208 |
|
a6483b790 netns xfrm: per-n... |
2209 |
return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); |
1da177e4c Linux-2.6.12-rc2 |
2210 |
} |
214e005bc xfrm: Pass km_eve... |
2211 |
static int xfrm_aevent_state_notify(struct xfrm_state *x, const struct km_event *c) |
d51d081d6 [IPSEC]: Sync ser... |
2212 |
{ |
fc34acd36 netns xfrm: xfrm_... |
2213 |
struct net *net = xs_net(x); |
d51d081d6 [IPSEC]: Sync ser... |
2214 |
struct sk_buff *skb; |
d51d081d6 [IPSEC]: Sync ser... |
2215 |
|
d8647b79c xfrm: Add user in... |
2216 |
skb = nlmsg_new(xfrm_aevent_msgsize(x), GFP_ATOMIC); |
d51d081d6 [IPSEC]: Sync ser... |
2217 2218 2219 2220 2221 |
if (skb == NULL) return -ENOMEM; if (build_aevent(skb, x, c) < 0) BUG(); |
a6483b790 netns xfrm: per-n... |
2222 |
return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_AEVENTS, GFP_ATOMIC); |
d51d081d6 [IPSEC]: Sync ser... |
2223 |
} |
214e005bc xfrm: Pass km_eve... |
2224 |
static int xfrm_notify_sa_flush(const struct km_event *c) |
26b15dad9 [IPSEC] Add compl... |
2225 |
{ |
7067802e2 netns xfrm: pass ... |
2226 |
struct net *net = c->net; |
26b15dad9 [IPSEC] Add compl... |
2227 2228 2229 |
struct xfrm_usersa_flush *p; struct nlmsghdr *nlh; struct sk_buff *skb; |
7deb22649 [XFRM] netlink: U... |
2230 |
int len = NLMSG_ALIGN(sizeof(struct xfrm_usersa_flush)); |
26b15dad9 [IPSEC] Add compl... |
2231 |
|
7deb22649 [XFRM] netlink: U... |
2232 |
skb = nlmsg_new(len, GFP_ATOMIC); |
26b15dad9 [IPSEC] Add compl... |
2233 2234 |
if (skb == NULL) return -ENOMEM; |
26b15dad9 [IPSEC] Add compl... |
2235 |
|
79b8b7f4a [XFRM] netlink: U... |
2236 2237 2238 2239 2240 |
nlh = nlmsg_put(skb, c->pid, c->seq, XFRM_MSG_FLUSHSA, sizeof(*p), 0); if (nlh == NULL) { kfree_skb(skb); return -EMSGSIZE; } |
26b15dad9 [IPSEC] Add compl... |
2241 |
|
7b67c8575 [XFRM] netlink: U... |
2242 |
p = nlmsg_data(nlh); |
bf08867f9 [IPSEC] Turn km_e... |
2243 |
p->proto = c->data.proto; |
26b15dad9 [IPSEC] Add compl... |
2244 |
|
9825069d0 [XFRM] netlink: U... |
2245 |
nlmsg_end(skb, nlh); |
26b15dad9 [IPSEC] Add compl... |
2246 |
|
a6483b790 netns xfrm: per-n... |
2247 |
return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC); |
26b15dad9 [IPSEC] Add compl... |
2248 |
} |
7deb22649 [XFRM] netlink: U... |
2249 |
static inline size_t xfrm_sa_len(struct xfrm_state *x) |
26b15dad9 [IPSEC] Add compl... |
2250 |
{ |
7deb22649 [XFRM] netlink: U... |
2251 |
size_t l = 0; |
1a6509d99 [IPSEC]: Add supp... |
2252 2253 |
if (x->aead) l += nla_total_size(aead_len(x->aead)); |
4447bb33f xfrm: Store aalg ... |
2254 2255 2256 2257 2258 |
if (x->aalg) { l += nla_total_size(sizeof(struct xfrm_algo) + (x->aalg->alg_key_len + 7) / 8); l += nla_total_size(xfrm_alg_auth_len(x->aalg)); } |
26b15dad9 [IPSEC] Add compl... |
2259 |
if (x->ealg) |
0f99be0d1 [XFRM]: xfrm_algo... |
2260 |
l += nla_total_size(xfrm_alg_len(x->ealg)); |
26b15dad9 [IPSEC] Add compl... |
2261 |
if (x->calg) |
7deb22649 [XFRM] netlink: U... |
2262 |
l += nla_total_size(sizeof(*x->calg)); |
26b15dad9 [IPSEC] Add compl... |
2263 |
if (x->encap) |
7deb22649 [XFRM] netlink: U... |
2264 |
l += nla_total_size(sizeof(*x->encap)); |
35d2856b4 xfrm: Add Traffic... |
2265 2266 |
if (x->tfcpad) l += nla_total_size(sizeof(x->tfcpad)); |
d8647b79c xfrm: Add user in... |
2267 2268 |
if (x->replay_esn) l += nla_total_size(xfrm_replay_state_esn_len(x->replay_esn)); |
68325d3b1 [XFRM] user: Move... |
2269 2270 2271 2272 2273 |
if (x->security) l += nla_total_size(sizeof(struct xfrm_user_sec_ctx) + x->security->ctx_len); if (x->coaddr) l += nla_total_size(sizeof(*x->coaddr)); |
d26f39840 [IPSEC]: Make x->... |
2274 2275 |
/* Must count x->lastused as it may become non-zero behind our back. */ l += nla_total_size(sizeof(u64)); |
26b15dad9 [IPSEC] Add compl... |
2276 2277 2278 |
return l; } |
214e005bc xfrm: Pass km_eve... |
2279 |
static int xfrm_notify_sa(struct xfrm_state *x, const struct km_event *c) |
26b15dad9 [IPSEC] Add compl... |
2280 |
{ |
fc34acd36 netns xfrm: xfrm_... |
2281 |
struct net *net = xs_net(x); |
26b15dad9 [IPSEC] Add compl... |
2282 |
struct xfrm_usersa_info *p; |
0603eac0d [IPSEC]: Add XFRM... |
2283 |
struct xfrm_usersa_id *id; |
26b15dad9 [IPSEC] Add compl... |
2284 2285 |
struct nlmsghdr *nlh; struct sk_buff *skb; |
26b15dad9 [IPSEC] Add compl... |
2286 |
int len = xfrm_sa_len(x); |
0603eac0d [IPSEC]: Add XFRM... |
2287 2288 2289 2290 |
int headlen; headlen = sizeof(*p); if (c->event == XFRM_MSG_DELSA) { |
7deb22649 [XFRM] netlink: U... |
2291 |
len += nla_total_size(headlen); |
0603eac0d [IPSEC]: Add XFRM... |
2292 |
headlen = sizeof(*id); |
6f26b61e1 xfrm: Allow user ... |
2293 |
len += nla_total_size(sizeof(struct xfrm_mark)); |
0603eac0d [IPSEC]: Add XFRM... |
2294 |
} |
7deb22649 [XFRM] netlink: U... |
2295 |
len += NLMSG_ALIGN(headlen); |
26b15dad9 [IPSEC] Add compl... |
2296 |
|
7deb22649 [XFRM] netlink: U... |
2297 |
skb = nlmsg_new(len, GFP_ATOMIC); |
26b15dad9 [IPSEC] Add compl... |
2298 2299 |
if (skb == NULL) return -ENOMEM; |
26b15dad9 [IPSEC] Add compl... |
2300 |
|
79b8b7f4a [XFRM] netlink: U... |
2301 2302 |
nlh = nlmsg_put(skb, c->pid, c->seq, c->event, headlen, 0); if (nlh == NULL) |
c0144beae [XFRM] netlink: U... |
2303 |
goto nla_put_failure; |
26b15dad9 [IPSEC] Add compl... |
2304 |
|
7b67c8575 [XFRM] netlink: U... |
2305 |
p = nlmsg_data(nlh); |
0603eac0d [IPSEC]: Add XFRM... |
2306 |
if (c->event == XFRM_MSG_DELSA) { |
c0144beae [XFRM] netlink: U... |
2307 |
struct nlattr *attr; |
7b67c8575 [XFRM] netlink: U... |
2308 |
id = nlmsg_data(nlh); |
0603eac0d [IPSEC]: Add XFRM... |
2309 2310 2311 2312 |
memcpy(&id->daddr, &x->id.daddr, sizeof(id->daddr)); id->spi = x->id.spi; id->family = x->props.family; id->proto = x->id.proto; |
c0144beae [XFRM] netlink: U... |
2313 2314 2315 2316 2317 |
attr = nla_reserve(skb, XFRMA_SA, sizeof(*p)); if (attr == NULL) goto nla_put_failure; p = nla_data(attr); |
0603eac0d [IPSEC]: Add XFRM... |
2318 |
} |
68325d3b1 [XFRM] user: Move... |
2319 2320 |
if (copy_to_user_state_extra(x, p, skb)) goto nla_put_failure; |
26b15dad9 [IPSEC] Add compl... |
2321 |
|
9825069d0 [XFRM] netlink: U... |
2322 |
nlmsg_end(skb, nlh); |
26b15dad9 [IPSEC] Add compl... |
2323 |
|
a6483b790 netns xfrm: per-n... |
2324 |
return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_SA, GFP_ATOMIC); |
26b15dad9 [IPSEC] Add compl... |
2325 |
|
c0144beae [XFRM] netlink: U... |
2326 |
nla_put_failure: |
68325d3b1 [XFRM] user: Move... |
2327 2328 |
/* Somebody screwed up with xfrm_sa_len! */ WARN_ON(1); |
26b15dad9 [IPSEC] Add compl... |
2329 2330 2331 |
kfree_skb(skb); return -1; } |
214e005bc xfrm: Pass km_eve... |
2332 |
static int xfrm_send_state_notify(struct xfrm_state *x, const struct km_event *c) |
26b15dad9 [IPSEC] Add compl... |
2333 2334 2335 |
{ switch (c->event) { |
f60f6b8f7 [IPSEC] Use XFRM_... |
2336 |
case XFRM_MSG_EXPIRE: |
26b15dad9 [IPSEC] Add compl... |
2337 |
return xfrm_exp_state_notify(x, c); |
d51d081d6 [IPSEC]: Sync ser... |
2338 2339 |
case XFRM_MSG_NEWAE: return xfrm_aevent_state_notify(x, c); |
f60f6b8f7 [IPSEC] Use XFRM_... |
2340 2341 2342 |
case XFRM_MSG_DELSA: case XFRM_MSG_UPDSA: case XFRM_MSG_NEWSA: |
26b15dad9 [IPSEC] Add compl... |
2343 |
return xfrm_notify_sa(x, c); |
f60f6b8f7 [IPSEC] Use XFRM_... |
2344 |
case XFRM_MSG_FLUSHSA: |
26b15dad9 [IPSEC] Add compl... |
2345 2346 |
return xfrm_notify_sa_flush(c); default: |
62db5cfd7 xfrm: add severit... |
2347 2348 2349 2350 |
printk(KERN_NOTICE "xfrm_user: Unknown SA event %d ", c->event); break; |
26b15dad9 [IPSEC] Add compl... |
2351 2352 2353 2354 2355 |
} return 0; } |
7deb22649 [XFRM] netlink: U... |
2356 2357 2358 2359 2360 |
static inline size_t xfrm_acquire_msgsize(struct xfrm_state *x, struct xfrm_policy *xp) { return NLMSG_ALIGN(sizeof(struct xfrm_user_acquire)) + nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr) |
6f26b61e1 xfrm: Allow user ... |
2361 |
+ nla_total_size(sizeof(struct xfrm_mark)) |
7deb22649 [XFRM] netlink: U... |
2362 2363 2364 |
+ nla_total_size(xfrm_user_sec_ctx_size(x->security)) + userpolicy_type_attrsize(); } |
1da177e4c Linux-2.6.12-rc2 |
2365 2366 2367 2368 2369 2370 |
static int build_acquire(struct sk_buff *skb, struct xfrm_state *x, struct xfrm_tmpl *xt, struct xfrm_policy *xp, int dir) { struct xfrm_user_acquire *ua; struct nlmsghdr *nlh; |
1da177e4c Linux-2.6.12-rc2 |
2371 |
__u32 seq = xfrm_get_acqseq(); |
79b8b7f4a [XFRM] netlink: U... |
2372 2373 2374 |
nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_ACQUIRE, sizeof(*ua), 0); if (nlh == NULL) return -EMSGSIZE; |
1da177e4c Linux-2.6.12-rc2 |
2375 |
|
7b67c8575 [XFRM] netlink: U... |
2376 |
ua = nlmsg_data(nlh); |
1da177e4c Linux-2.6.12-rc2 |
2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 |
memcpy(&ua->id, &x->id, sizeof(ua->id)); memcpy(&ua->saddr, &x->props.saddr, sizeof(ua->saddr)); memcpy(&ua->sel, &x->sel, sizeof(ua->sel)); copy_to_user_policy(xp, &ua->policy, dir); ua->aalgos = xt->aalgos; ua->ealgos = xt->ealgos; ua->calgos = xt->calgos; ua->seq = x->km.seq = seq; if (copy_to_user_tmpl(xp, skb) < 0) goto nlmsg_failure; |
0d681623d [MLSXFRM]: Add se... |
2388 |
if (copy_to_user_state_sec_ctx(x, skb)) |
df71837d5 [LSM-IPSec]: Secu... |
2389 |
goto nlmsg_failure; |
1459bb36b [XFRM]: Make copy... |
2390 |
if (copy_to_user_policy_type(xp->type, skb) < 0) |
f7b6983f0 [XFRM] POLICY: Su... |
2391 |
goto nlmsg_failure; |
295fae568 xfrm: Allow user ... |
2392 2393 |
if (xfrm_mark_put(skb, &xp->mark)) goto nla_put_failure; |
1da177e4c Linux-2.6.12-rc2 |
2394 |
|
9825069d0 [XFRM] netlink: U... |
2395 |
return nlmsg_end(skb, nlh); |
1da177e4c Linux-2.6.12-rc2 |
2396 |
|
295fae568 xfrm: Allow user ... |
2397 |
nla_put_failure: |
1da177e4c Linux-2.6.12-rc2 |
2398 |
nlmsg_failure: |
9825069d0 [XFRM] netlink: U... |
2399 2400 |
nlmsg_cancel(skb, nlh); return -EMSGSIZE; |
1da177e4c Linux-2.6.12-rc2 |
2401 2402 2403 2404 2405 |
} static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt, struct xfrm_policy *xp, int dir) { |
a6483b790 netns xfrm: per-n... |
2406 |
struct net *net = xs_net(x); |
1da177e4c Linux-2.6.12-rc2 |
2407 |
struct sk_buff *skb; |
1da177e4c Linux-2.6.12-rc2 |
2408 |
|
7deb22649 [XFRM] netlink: U... |
2409 |
skb = nlmsg_new(xfrm_acquire_msgsize(x, xp), GFP_ATOMIC); |
1da177e4c Linux-2.6.12-rc2 |
2410 2411 2412 2413 2414 |
if (skb == NULL) return -ENOMEM; if (build_acquire(skb, x, xt, xp, dir) < 0) BUG(); |
a6483b790 netns xfrm: per-n... |
2415 |
return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_ACQUIRE, GFP_ATOMIC); |
1da177e4c Linux-2.6.12-rc2 |
2416 2417 2418 2419 2420 |
} /* User gives us xfrm_user_policy_info followed by an array of 0 * or more templates. */ |
cb969f072 [MLSXFRM]: Defaul... |
2421 |
static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt, |
1da177e4c Linux-2.6.12-rc2 |
2422 2423 |
u8 *data, int len, int *dir) { |
fc34acd36 netns xfrm: xfrm_... |
2424 |
struct net *net = sock_net(sk); |
1da177e4c Linux-2.6.12-rc2 |
2425 2426 2427 2428 |
struct xfrm_userpolicy_info *p = (struct xfrm_userpolicy_info *)data; struct xfrm_user_tmpl *ut = (struct xfrm_user_tmpl *) (p + 1); struct xfrm_policy *xp; int nr; |
cb969f072 [MLSXFRM]: Defaul... |
2429 |
switch (sk->sk_family) { |
1da177e4c Linux-2.6.12-rc2 |
2430 2431 2432 2433 2434 2435 |
case AF_INET: if (opt != IP_XFRM_POLICY) { *dir = -EOPNOTSUPP; return NULL; } break; |
dfd56b8b3 net: use IS_ENABL... |
2436 |
#if IS_ENABLED(CONFIG_IPV6) |
1da177e4c Linux-2.6.12-rc2 |
2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 |
case AF_INET6: if (opt != IPV6_XFRM_POLICY) { *dir = -EOPNOTSUPP; return NULL; } break; #endif default: *dir = -EINVAL; return NULL; } *dir = -EINVAL; if (len < sizeof(*p) || verify_newpolicy_info(p)) return NULL; nr = ((len - sizeof(*p)) / sizeof(*ut)); |
b4ad86bf5 [XFRM] xfrm_user:... |
2456 |
if (validate_tmpl(nr, ut, p->sel.family)) |
1da177e4c Linux-2.6.12-rc2 |
2457 |
return NULL; |
a4f1bac62 [XFRM]: Fix possi... |
2458 2459 |
if (p->dir > XFRM_POLICY_OUT) return NULL; |
2f09a4d5d xfrm: Use GFP_ATO... |
2460 |
xp = xfrm_policy_alloc(net, GFP_ATOMIC); |
1da177e4c Linux-2.6.12-rc2 |
2461 2462 2463 2464 2465 2466 |
if (xp == NULL) { *dir = -ENOBUFS; return NULL; } copy_from_user_policy(xp, p); |
f7b6983f0 [XFRM] POLICY: Su... |
2467 |
xp->type = XFRM_POLICY_TYPE_MAIN; |
1da177e4c Linux-2.6.12-rc2 |
2468 2469 2470 2471 2472 2473 |
copy_templates(xp, ut, nr); *dir = p->dir; return xp; } |
7deb22649 [XFRM] netlink: U... |
2474 2475 2476 2477 2478 |
static inline size_t xfrm_polexpire_msgsize(struct xfrm_policy *xp) { return NLMSG_ALIGN(sizeof(struct xfrm_user_polexpire)) + nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr) + nla_total_size(xfrm_user_sec_ctx_size(xp->security)) |
295fae568 xfrm: Allow user ... |
2479 |
+ nla_total_size(sizeof(struct xfrm_mark)) |
7deb22649 [XFRM] netlink: U... |
2480 2481 |
+ userpolicy_type_attrsize(); } |
1da177e4c Linux-2.6.12-rc2 |
2482 |
static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp, |
214e005bc xfrm: Pass km_eve... |
2483 |
int dir, const struct km_event *c) |
1da177e4c Linux-2.6.12-rc2 |
2484 2485 2486 |
{ struct xfrm_user_polexpire *upe; struct nlmsghdr *nlh; |
d51d081d6 [IPSEC]: Sync ser... |
2487 |
int hard = c->data.hard; |
1da177e4c Linux-2.6.12-rc2 |
2488 |
|
79b8b7f4a [XFRM] netlink: U... |
2489 2490 2491 |
nlh = nlmsg_put(skb, c->pid, 0, XFRM_MSG_POLEXPIRE, sizeof(*upe), 0); if (nlh == NULL) return -EMSGSIZE; |
1da177e4c Linux-2.6.12-rc2 |
2492 |
|
7b67c8575 [XFRM] netlink: U... |
2493 |
upe = nlmsg_data(nlh); |
1da177e4c Linux-2.6.12-rc2 |
2494 2495 2496 |
copy_to_user_policy(xp, &upe->pol, dir); if (copy_to_user_tmpl(xp, skb) < 0) goto nlmsg_failure; |
df71837d5 [LSM-IPSec]: Secu... |
2497 2498 |
if (copy_to_user_sec_ctx(xp, skb)) goto nlmsg_failure; |
1459bb36b [XFRM]: Make copy... |
2499 |
if (copy_to_user_policy_type(xp->type, skb) < 0) |
f7b6983f0 [XFRM] POLICY: Su... |
2500 |
goto nlmsg_failure; |
295fae568 xfrm: Allow user ... |
2501 2502 |
if (xfrm_mark_put(skb, &xp->mark)) goto nla_put_failure; |
1da177e4c Linux-2.6.12-rc2 |
2503 |
upe->hard = !!hard; |
9825069d0 [XFRM] netlink: U... |
2504 |
return nlmsg_end(skb, nlh); |
1da177e4c Linux-2.6.12-rc2 |
2505 |
|
295fae568 xfrm: Allow user ... |
2506 |
nla_put_failure: |
1da177e4c Linux-2.6.12-rc2 |
2507 |
nlmsg_failure: |
9825069d0 [XFRM] netlink: U... |
2508 2509 |
nlmsg_cancel(skb, nlh); return -EMSGSIZE; |
1da177e4c Linux-2.6.12-rc2 |
2510 |
} |
214e005bc xfrm: Pass km_eve... |
2511 |
static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c) |
1da177e4c Linux-2.6.12-rc2 |
2512 |
{ |
fc34acd36 netns xfrm: xfrm_... |
2513 |
struct net *net = xp_net(xp); |
1da177e4c Linux-2.6.12-rc2 |
2514 |
struct sk_buff *skb; |
1da177e4c Linux-2.6.12-rc2 |
2515 |
|
7deb22649 [XFRM] netlink: U... |
2516 |
skb = nlmsg_new(xfrm_polexpire_msgsize(xp), GFP_ATOMIC); |
1da177e4c Linux-2.6.12-rc2 |
2517 2518 |
if (skb == NULL) return -ENOMEM; |
d51d081d6 [IPSEC]: Sync ser... |
2519 |
if (build_polexpire(skb, xp, dir, c) < 0) |
1da177e4c Linux-2.6.12-rc2 |
2520 |
BUG(); |
a6483b790 netns xfrm: per-n... |
2521 |
return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); |
1da177e4c Linux-2.6.12-rc2 |
2522 |
} |
214e005bc xfrm: Pass km_eve... |
2523 |
static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, const struct km_event *c) |
26b15dad9 [IPSEC] Add compl... |
2524 |
{ |
fc34acd36 netns xfrm: xfrm_... |
2525 |
struct net *net = xp_net(xp); |
26b15dad9 [IPSEC] Add compl... |
2526 |
struct xfrm_userpolicy_info *p; |
0603eac0d [IPSEC]: Add XFRM... |
2527 |
struct xfrm_userpolicy_id *id; |
26b15dad9 [IPSEC] Add compl... |
2528 2529 |
struct nlmsghdr *nlh; struct sk_buff *skb; |
7deb22649 [XFRM] netlink: U... |
2530 |
int len = nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr); |
0603eac0d [IPSEC]: Add XFRM... |
2531 2532 2533 2534 |
int headlen; headlen = sizeof(*p); if (c->event == XFRM_MSG_DELPOLICY) { |
7deb22649 [XFRM] netlink: U... |
2535 |
len += nla_total_size(headlen); |
0603eac0d [IPSEC]: Add XFRM... |
2536 2537 |
headlen = sizeof(*id); } |
cfbfd45a8 [XFRM] netlink: C... |
2538 |
len += userpolicy_type_attrsize(); |
295fae568 xfrm: Allow user ... |
2539 |
len += nla_total_size(sizeof(struct xfrm_mark)); |
7deb22649 [XFRM] netlink: U... |
2540 |
len += NLMSG_ALIGN(headlen); |
26b15dad9 [IPSEC] Add compl... |
2541 |
|
7deb22649 [XFRM] netlink: U... |
2542 |
skb = nlmsg_new(len, GFP_ATOMIC); |
26b15dad9 [IPSEC] Add compl... |
2543 2544 |
if (skb == NULL) return -ENOMEM; |
26b15dad9 [IPSEC] Add compl... |
2545 |
|
79b8b7f4a [XFRM] netlink: U... |
2546 2547 2548 |
nlh = nlmsg_put(skb, c->pid, c->seq, c->event, headlen, 0); if (nlh == NULL) goto nlmsg_failure; |
26b15dad9 [IPSEC] Add compl... |
2549 |
|
7b67c8575 [XFRM] netlink: U... |
2550 |
p = nlmsg_data(nlh); |
0603eac0d [IPSEC]: Add XFRM... |
2551 |
if (c->event == XFRM_MSG_DELPOLICY) { |
c0144beae [XFRM] netlink: U... |
2552 |
struct nlattr *attr; |
7b67c8575 [XFRM] netlink: U... |
2553 |
id = nlmsg_data(nlh); |
0603eac0d [IPSEC]: Add XFRM... |
2554 2555 2556 2557 2558 2559 |
memset(id, 0, sizeof(*id)); id->dir = dir; if (c->data.byid) id->index = xp->index; else memcpy(&id->sel, &xp->selector, sizeof(id->sel)); |
c0144beae [XFRM] netlink: U... |
2560 2561 2562 2563 2564 |
attr = nla_reserve(skb, XFRMA_POLICY, sizeof(*p)); if (attr == NULL) goto nlmsg_failure; p = nla_data(attr); |
0603eac0d [IPSEC]: Add XFRM... |
2565 |
} |
26b15dad9 [IPSEC] Add compl... |
2566 |
|
26b15dad9 [IPSEC] Add compl... |
2567 2568 2569 |
copy_to_user_policy(xp, p, dir); if (copy_to_user_tmpl(xp, skb) < 0) goto nlmsg_failure; |
1459bb36b [XFRM]: Make copy... |
2570 |
if (copy_to_user_policy_type(xp->type, skb) < 0) |
f7b6983f0 [XFRM] POLICY: Su... |
2571 |
goto nlmsg_failure; |
26b15dad9 [IPSEC] Add compl... |
2572 |
|
295fae568 xfrm: Allow user ... |
2573 2574 |
if (xfrm_mark_put(skb, &xp->mark)) goto nla_put_failure; |
9825069d0 [XFRM] netlink: U... |
2575 |
nlmsg_end(skb, nlh); |
26b15dad9 [IPSEC] Add compl... |
2576 |
|
a6483b790 netns xfrm: per-n... |
2577 |
return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC); |
26b15dad9 [IPSEC] Add compl... |
2578 |
|
295fae568 xfrm: Allow user ... |
2579 |
nla_put_failure: |
26b15dad9 [IPSEC] Add compl... |
2580 2581 2582 2583 |
nlmsg_failure: kfree_skb(skb); return -1; } |
214e005bc xfrm: Pass km_eve... |
2584 |
static int xfrm_notify_policy_flush(const struct km_event *c) |
26b15dad9 [IPSEC] Add compl... |
2585 |
{ |
7067802e2 netns xfrm: pass ... |
2586 |
struct net *net = c->net; |
26b15dad9 [IPSEC] Add compl... |
2587 2588 |
struct nlmsghdr *nlh; struct sk_buff *skb; |
26b15dad9 [IPSEC] Add compl... |
2589 |
|
7deb22649 [XFRM] netlink: U... |
2590 |
skb = nlmsg_new(userpolicy_type_attrsize(), GFP_ATOMIC); |
26b15dad9 [IPSEC] Add compl... |
2591 2592 |
if (skb == NULL) return -ENOMEM; |
26b15dad9 [IPSEC] Add compl... |
2593 |
|
79b8b7f4a [XFRM] netlink: U... |
2594 2595 2596 |
nlh = nlmsg_put(skb, c->pid, c->seq, XFRM_MSG_FLUSHPOLICY, 0, 0); if (nlh == NULL) goto nlmsg_failure; |
0c51f53c5 [XFRM]: Make flus... |
2597 2598 |
if (copy_to_user_policy_type(c->data.type, skb) < 0) goto nlmsg_failure; |
26b15dad9 [IPSEC] Add compl... |
2599 |
|
9825069d0 [XFRM] netlink: U... |
2600 |
nlmsg_end(skb, nlh); |
26b15dad9 [IPSEC] Add compl... |
2601 |
|
a6483b790 netns xfrm: per-n... |
2602 |
return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC); |
26b15dad9 [IPSEC] Add compl... |
2603 2604 2605 2606 2607 |
nlmsg_failure: kfree_skb(skb); return -1; } |
214e005bc xfrm: Pass km_eve... |
2608 |
static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c) |
26b15dad9 [IPSEC] Add compl... |
2609 2610 2611 |
{ switch (c->event) { |
f60f6b8f7 [IPSEC] Use XFRM_... |
2612 2613 2614 |
case XFRM_MSG_NEWPOLICY: case XFRM_MSG_UPDPOLICY: case XFRM_MSG_DELPOLICY: |
26b15dad9 [IPSEC] Add compl... |
2615 |
return xfrm_notify_policy(xp, dir, c); |
f60f6b8f7 [IPSEC] Use XFRM_... |
2616 |
case XFRM_MSG_FLUSHPOLICY: |
26b15dad9 [IPSEC] Add compl... |
2617 |
return xfrm_notify_policy_flush(c); |
f60f6b8f7 [IPSEC] Use XFRM_... |
2618 |
case XFRM_MSG_POLEXPIRE: |
26b15dad9 [IPSEC] Add compl... |
2619 2620 |
return xfrm_exp_policy_notify(xp, dir, c); default: |
62db5cfd7 xfrm: add severit... |
2621 2622 2623 |
printk(KERN_NOTICE "xfrm_user: Unknown Policy event %d ", c->event); |
26b15dad9 [IPSEC] Add compl... |
2624 2625 2626 2627 2628 |
} return 0; } |
7deb22649 [XFRM] netlink: U... |
2629 2630 2631 2632 |
static inline size_t xfrm_report_msgsize(void) { return NLMSG_ALIGN(sizeof(struct xfrm_user_report)); } |
97a64b457 [XFRM]: Introduce... |
2633 2634 2635 2636 2637 |
static int build_report(struct sk_buff *skb, u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr) { struct xfrm_user_report *ur; struct nlmsghdr *nlh; |
97a64b457 [XFRM]: Introduce... |
2638 |
|
79b8b7f4a [XFRM] netlink: U... |
2639 2640 2641 |
nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_REPORT, sizeof(*ur), 0); if (nlh == NULL) return -EMSGSIZE; |
97a64b457 [XFRM]: Introduce... |
2642 |
|
7b67c8575 [XFRM] netlink: U... |
2643 |
ur = nlmsg_data(nlh); |
97a64b457 [XFRM]: Introduce... |
2644 2645 2646 2647 |
ur->proto = proto; memcpy(&ur->sel, sel, sizeof(ur->sel)); if (addr) |
c0144beae [XFRM] netlink: U... |
2648 |
NLA_PUT(skb, XFRMA_COADDR, sizeof(*addr), addr); |
97a64b457 [XFRM]: Introduce... |
2649 |
|
9825069d0 [XFRM] netlink: U... |
2650 |
return nlmsg_end(skb, nlh); |
97a64b457 [XFRM]: Introduce... |
2651 |
|
c0144beae [XFRM] netlink: U... |
2652 |
nla_put_failure: |
9825069d0 [XFRM] netlink: U... |
2653 2654 |
nlmsg_cancel(skb, nlh); return -EMSGSIZE; |
97a64b457 [XFRM]: Introduce... |
2655 |
} |
db983c114 netns xfrm: KM re... |
2656 2657 |
static int xfrm_send_report(struct net *net, u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr) |
97a64b457 [XFRM]: Introduce... |
2658 2659 |
{ struct sk_buff *skb; |
97a64b457 [XFRM]: Introduce... |
2660 |
|
7deb22649 [XFRM] netlink: U... |
2661 |
skb = nlmsg_new(xfrm_report_msgsize(), GFP_ATOMIC); |
97a64b457 [XFRM]: Introduce... |
2662 2663 2664 2665 2666 |
if (skb == NULL) return -ENOMEM; if (build_report(skb, proto, sel, addr) < 0) BUG(); |
a6483b790 netns xfrm: per-n... |
2667 |
return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_REPORT, GFP_ATOMIC); |
97a64b457 [XFRM]: Introduce... |
2668 |
} |
3a2dfbe8a xfrm: Notify chan... |
2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 |
static inline size_t xfrm_mapping_msgsize(void) { return NLMSG_ALIGN(sizeof(struct xfrm_user_mapping)); } static int build_mapping(struct sk_buff *skb, struct xfrm_state *x, xfrm_address_t *new_saddr, __be16 new_sport) { struct xfrm_user_mapping *um; struct nlmsghdr *nlh; nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_MAPPING, sizeof(*um), 0); if (nlh == NULL) return -EMSGSIZE; um = nlmsg_data(nlh); memcpy(&um->id.daddr, &x->id.daddr, sizeof(um->id.daddr)); um->id.spi = x->id.spi; um->id.family = x->props.family; um->id.proto = x->id.proto; memcpy(&um->new_saddr, new_saddr, sizeof(um->new_saddr)); memcpy(&um->old_saddr, &x->props.saddr, sizeof(um->old_saddr)); um->new_sport = new_sport; um->old_sport = x->encap->encap_sport; um->reqid = x->props.reqid; return nlmsg_end(skb, nlh); } static int xfrm_send_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport) { |
a6483b790 netns xfrm: per-n... |
2702 |
struct net *net = xs_net(x); |
3a2dfbe8a xfrm: Notify chan... |
2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 |
struct sk_buff *skb; if (x->id.proto != IPPROTO_ESP) return -EINVAL; if (!x->encap) return -EINVAL; skb = nlmsg_new(xfrm_mapping_msgsize(), GFP_ATOMIC); if (skb == NULL) return -ENOMEM; if (build_mapping(skb, x, ipaddr, sport) < 0) BUG(); |
a6483b790 netns xfrm: per-n... |
2717 |
return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_MAPPING, GFP_ATOMIC); |
3a2dfbe8a xfrm: Notify chan... |
2718 |
} |
1da177e4c Linux-2.6.12-rc2 |
2719 2720 2721 2722 2723 2724 |
static struct xfrm_mgr netlink_mgr = { .id = "netlink", .notify = xfrm_send_state_notify, .acquire = xfrm_send_acquire, .compile_policy = xfrm_compile_policy, .notify_policy = xfrm_send_policy_notify, |
97a64b457 [XFRM]: Introduce... |
2725 |
.report = xfrm_send_report, |
5c79de6e7 [XFRM]: User inte... |
2726 |
.migrate = xfrm_send_migrate, |
3a2dfbe8a xfrm: Notify chan... |
2727 |
.new_mapping = xfrm_send_mapping, |
1da177e4c Linux-2.6.12-rc2 |
2728 |
}; |
a6483b790 netns xfrm: per-n... |
2729 |
static int __net_init xfrm_user_net_init(struct net *net) |
1da177e4c Linux-2.6.12-rc2 |
2730 |
{ |
be33690d8 [XFRM]: Fix aeven... |
2731 |
struct sock *nlsk; |
a6483b790 netns xfrm: per-n... |
2732 |
nlsk = netlink_kernel_create(net, NETLINK_XFRM, XFRMNLGRP_MAX, |
af65bdfce [NETLINK]: Switch... |
2733 |
xfrm_netlink_rcv, NULL, THIS_MODULE); |
be33690d8 [XFRM]: Fix aeven... |
2734 |
if (nlsk == NULL) |
1da177e4c Linux-2.6.12-rc2 |
2735 |
return -ENOMEM; |
d79d792ef net: Allow xfrm_u... |
2736 |
net->xfrm.nlsk_stash = nlsk; /* Don't set to NULL */ |
cf778b00e net: reintroduce ... |
2737 |
rcu_assign_pointer(net->xfrm.nlsk, nlsk); |
1da177e4c Linux-2.6.12-rc2 |
2738 2739 |
return 0; } |
d79d792ef net: Allow xfrm_u... |
2740 |
static void __net_exit xfrm_user_net_exit(struct list_head *net_exit_list) |
1da177e4c Linux-2.6.12-rc2 |
2741 |
{ |
d79d792ef net: Allow xfrm_u... |
2742 2743 |
struct net *net; list_for_each_entry(net, net_exit_list, exit_list) |
a9b3cd7f3 rcu: convert uses... |
2744 |
RCU_INIT_POINTER(net->xfrm.nlsk, NULL); |
d79d792ef net: Allow xfrm_u... |
2745 2746 2747 |
synchronize_net(); list_for_each_entry(net, net_exit_list, exit_list) netlink_kernel_release(net->xfrm.nlsk_stash); |
1da177e4c Linux-2.6.12-rc2 |
2748 |
} |
a6483b790 netns xfrm: per-n... |
2749 |
static struct pernet_operations xfrm_user_net_ops = { |
d79d792ef net: Allow xfrm_u... |
2750 2751 |
.init = xfrm_user_net_init, .exit_batch = xfrm_user_net_exit, |
a6483b790 netns xfrm: per-n... |
2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 |
}; static int __init xfrm_user_init(void) { int rv; printk(KERN_INFO "Initializing XFRM netlink socket "); rv = register_pernet_subsys(&xfrm_user_net_ops); if (rv < 0) return rv; rv = xfrm_register_km(&netlink_mgr); if (rv < 0) unregister_pernet_subsys(&xfrm_user_net_ops); return rv; } static void __exit xfrm_user_exit(void) { xfrm_unregister_km(&netlink_mgr); unregister_pernet_subsys(&xfrm_user_net_ops); } |
1da177e4c Linux-2.6.12-rc2 |
2775 2776 2777 |
module_init(xfrm_user_init); module_exit(xfrm_user_exit); MODULE_LICENSE("GPL"); |
4fdb3bb72 [NETLINK]: Add pr... |
2778 |
MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_XFRM); |
f8cd54884 [IPSEC]: Sync ser... |
2779 |