diff options
author | Anton Altaparmakov <aia21@cantab.net> | 2005-06-23 06:26:22 -0400 |
---|---|---|
committer | Anton Altaparmakov <aia21@cantab.net> | 2005-06-23 06:26:22 -0400 |
commit | 3357d4c75f1fb67e7304998c4ad4e9a9fed66fa4 (patch) | |
tree | ceba46966a5a1112a05d257d8ecb25ae5eee95e0 /net/key | |
parent | 364f6c717deef4a3ac4982e670fa9846b43cd060 (diff) | |
parent | ee98689be1b054897ff17655008c3048fe88be94 (diff) |
Automatic merge with /usr/src/ntfs-2.6.git.
Diffstat (limited to 'net/key')
-rw-r--r-- | net/key/af_key.c | 385 |
1 files changed, 279 insertions, 106 deletions
diff --git a/net/key/af_key.c b/net/key/af_key.c index ce980aa94ed8..4879743b945a 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -656,13 +656,18 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, | |||
656 | sa->sadb_sa_exttype = SADB_EXT_SA; | 656 | sa->sadb_sa_exttype = SADB_EXT_SA; |
657 | sa->sadb_sa_spi = x->id.spi; | 657 | sa->sadb_sa_spi = x->id.spi; |
658 | sa->sadb_sa_replay = x->props.replay_window; | 658 | sa->sadb_sa_replay = x->props.replay_window; |
659 | sa->sadb_sa_state = SADB_SASTATE_DYING; | 659 | switch (x->km.state) { |
660 | if (x->km.state == XFRM_STATE_VALID && !x->km.dying) | 660 | case XFRM_STATE_VALID: |
661 | sa->sadb_sa_state = SADB_SASTATE_MATURE; | 661 | sa->sadb_sa_state = x->km.dying ? |
662 | else if (x->km.state == XFRM_STATE_ACQ) | 662 | SADB_SASTATE_DYING : SADB_SASTATE_MATURE; |
663 | break; | ||
664 | case XFRM_STATE_ACQ: | ||
663 | sa->sadb_sa_state = SADB_SASTATE_LARVAL; | 665 | sa->sadb_sa_state = SADB_SASTATE_LARVAL; |
664 | else if (x->km.state == XFRM_STATE_EXPIRED) | 666 | break; |
667 | default: | ||
665 | sa->sadb_sa_state = SADB_SASTATE_DEAD; | 668 | sa->sadb_sa_state = SADB_SASTATE_DEAD; |
669 | break; | ||
670 | } | ||
666 | sa->sadb_sa_auth = 0; | 671 | sa->sadb_sa_auth = 0; |
667 | if (x->aalg) { | 672 | if (x->aalg) { |
668 | struct xfrm_algo_desc *a = xfrm_aalg_get_byname(x->aalg->alg_name, 0); | 673 | struct xfrm_algo_desc *a = xfrm_aalg_get_byname(x->aalg->alg_name, 0); |
@@ -685,6 +690,8 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys, | |||
685 | sa->sadb_sa_flags |= SADB_SAFLAGS_NOECN; | 690 | sa->sadb_sa_flags |= SADB_SAFLAGS_NOECN; |
686 | if (x->props.flags & XFRM_STATE_DECAP_DSCP) | 691 | if (x->props.flags & XFRM_STATE_DECAP_DSCP) |
687 | sa->sadb_sa_flags |= SADB_SAFLAGS_DECAP_DSCP; | 692 | sa->sadb_sa_flags |= SADB_SAFLAGS_DECAP_DSCP; |
693 | if (x->props.flags & XFRM_STATE_NOPMTUDISC) | ||
694 | sa->sadb_sa_flags |= SADB_SAFLAGS_NOPMTUDISC; | ||
688 | 695 | ||
689 | /* hard time */ | 696 | /* hard time */ |
690 | if (hsc & 2) { | 697 | if (hsc & 2) { |
@@ -969,6 +976,8 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, | |||
969 | x->props.flags |= XFRM_STATE_NOECN; | 976 | x->props.flags |= XFRM_STATE_NOECN; |
970 | if (sa->sadb_sa_flags & SADB_SAFLAGS_DECAP_DSCP) | 977 | if (sa->sadb_sa_flags & SADB_SAFLAGS_DECAP_DSCP) |
971 | x->props.flags |= XFRM_STATE_DECAP_DSCP; | 978 | x->props.flags |= XFRM_STATE_DECAP_DSCP; |
979 | if (sa->sadb_sa_flags & SADB_SAFLAGS_NOPMTUDISC) | ||
980 | x->props.flags |= XFRM_STATE_NOPMTUDISC; | ||
972 | 981 | ||
973 | lifetime = (struct sadb_lifetime*) ext_hdrs[SADB_EXT_LIFETIME_HARD-1]; | 982 | lifetime = (struct sadb_lifetime*) ext_hdrs[SADB_EXT_LIFETIME_HARD-1]; |
974 | if (lifetime != NULL) { | 983 | if (lifetime != NULL) { |
@@ -1091,17 +1100,11 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, | |||
1091 | } | 1100 | } |
1092 | } | 1101 | } |
1093 | 1102 | ||
1094 | x->type = xfrm_get_type(proto, x->props.family); | 1103 | err = xfrm_init_state(x); |
1095 | if (x->type == NULL) { | 1104 | if (err) |
1096 | err = -ENOPROTOOPT; | ||
1097 | goto out; | ||
1098 | } | ||
1099 | if (x->type->init_state(x, NULL)) { | ||
1100 | err = -EINVAL; | ||
1101 | goto out; | 1105 | goto out; |
1102 | } | 1106 | |
1103 | x->km.seq = hdr->sadb_msg_seq; | 1107 | x->km.seq = hdr->sadb_msg_seq; |
1104 | x->km.state = XFRM_STATE_VALID; | ||
1105 | return x; | 1108 | return x; |
1106 | 1109 | ||
1107 | out: | 1110 | out: |
@@ -1240,13 +1243,78 @@ static int pfkey_acquire(struct sock *sk, struct sk_buff *skb, struct sadb_msg * | |||
1240 | return 0; | 1243 | return 0; |
1241 | } | 1244 | } |
1242 | 1245 | ||
1246 | static inline int event2poltype(int event) | ||
1247 | { | ||
1248 | switch (event) { | ||
1249 | case XFRM_MSG_DELPOLICY: | ||
1250 | return SADB_X_SPDDELETE; | ||
1251 | case XFRM_MSG_NEWPOLICY: | ||
1252 | return SADB_X_SPDADD; | ||
1253 | case XFRM_MSG_UPDPOLICY: | ||
1254 | return SADB_X_SPDUPDATE; | ||
1255 | case XFRM_MSG_POLEXPIRE: | ||
1256 | // return SADB_X_SPDEXPIRE; | ||
1257 | default: | ||
1258 | printk("pfkey: Unknown policy event %d\n", event); | ||
1259 | break; | ||
1260 | } | ||
1261 | |||
1262 | return 0; | ||
1263 | } | ||
1264 | |||
1265 | static inline int event2keytype(int event) | ||
1266 | { | ||
1267 | switch (event) { | ||
1268 | case XFRM_MSG_DELSA: | ||
1269 | return SADB_DELETE; | ||
1270 | case XFRM_MSG_NEWSA: | ||
1271 | return SADB_ADD; | ||
1272 | case XFRM_MSG_UPDSA: | ||
1273 | return SADB_UPDATE; | ||
1274 | case XFRM_MSG_EXPIRE: | ||
1275 | return SADB_EXPIRE; | ||
1276 | default: | ||
1277 | printk("pfkey: Unknown SA event %d\n", event); | ||
1278 | break; | ||
1279 | } | ||
1280 | |||
1281 | return 0; | ||
1282 | } | ||
1283 | |||
1284 | /* ADD/UPD/DEL */ | ||
1285 | static int key_notify_sa(struct xfrm_state *x, struct km_event *c) | ||
1286 | { | ||
1287 | struct sk_buff *skb; | ||
1288 | struct sadb_msg *hdr; | ||
1289 | int hsc = 3; | ||
1290 | |||
1291 | if (c->event == XFRM_MSG_DELSA) | ||
1292 | hsc = 0; | ||
1293 | |||
1294 | skb = pfkey_xfrm_state2msg(x, 0, hsc); | ||
1295 | |||
1296 | if (IS_ERR(skb)) | ||
1297 | return PTR_ERR(skb); | ||
1298 | |||
1299 | hdr = (struct sadb_msg *) skb->data; | ||
1300 | hdr->sadb_msg_version = PF_KEY_V2; | ||
1301 | hdr->sadb_msg_type = event2keytype(c->event); | ||
1302 | hdr->sadb_msg_satype = pfkey_proto2satype(x->id.proto); | ||
1303 | hdr->sadb_msg_errno = 0; | ||
1304 | hdr->sadb_msg_reserved = 0; | ||
1305 | hdr->sadb_msg_seq = c->seq; | ||
1306 | hdr->sadb_msg_pid = c->pid; | ||
1307 | |||
1308 | pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL); | ||
1309 | |||
1310 | return 0; | ||
1311 | } | ||
1243 | 1312 | ||
1244 | static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) | 1313 | static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) |
1245 | { | 1314 | { |
1246 | struct sk_buff *out_skb; | ||
1247 | struct sadb_msg *out_hdr; | ||
1248 | struct xfrm_state *x; | 1315 | struct xfrm_state *x; |
1249 | int err; | 1316 | int err; |
1317 | struct km_event c; | ||
1250 | 1318 | ||
1251 | xfrm_probe_algs(); | 1319 | xfrm_probe_algs(); |
1252 | 1320 | ||
@@ -1254,6 +1322,7 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, | |||
1254 | if (IS_ERR(x)) | 1322 | if (IS_ERR(x)) |
1255 | return PTR_ERR(x); | 1323 | return PTR_ERR(x); |
1256 | 1324 | ||
1325 | xfrm_state_hold(x); | ||
1257 | if (hdr->sadb_msg_type == SADB_ADD) | 1326 | if (hdr->sadb_msg_type == SADB_ADD) |
1258 | err = xfrm_state_add(x); | 1327 | err = xfrm_state_add(x); |
1259 | else | 1328 | else |
@@ -1262,30 +1331,26 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, | |||
1262 | if (err < 0) { | 1331 | if (err < 0) { |
1263 | x->km.state = XFRM_STATE_DEAD; | 1332 | x->km.state = XFRM_STATE_DEAD; |
1264 | xfrm_state_put(x); | 1333 | xfrm_state_put(x); |
1265 | return err; | 1334 | goto out; |
1266 | } | 1335 | } |
1267 | 1336 | ||
1268 | out_skb = pfkey_xfrm_state2msg(x, 0, 3); | 1337 | if (hdr->sadb_msg_type == SADB_ADD) |
1269 | if (IS_ERR(out_skb)) | 1338 | c.event = XFRM_MSG_NEWSA; |
1270 | return PTR_ERR(out_skb); /* XXX Should we return 0 here ? */ | 1339 | else |
1271 | 1340 | c.event = XFRM_MSG_UPDSA; | |
1272 | out_hdr = (struct sadb_msg *) out_skb->data; | 1341 | c.seq = hdr->sadb_msg_seq; |
1273 | out_hdr->sadb_msg_version = hdr->sadb_msg_version; | 1342 | c.pid = hdr->sadb_msg_pid; |
1274 | out_hdr->sadb_msg_type = hdr->sadb_msg_type; | 1343 | km_state_notify(x, &c); |
1275 | out_hdr->sadb_msg_satype = pfkey_proto2satype(x->id.proto); | 1344 | out: |
1276 | out_hdr->sadb_msg_errno = 0; | 1345 | xfrm_state_put(x); |
1277 | out_hdr->sadb_msg_reserved = 0; | 1346 | return err; |
1278 | out_hdr->sadb_msg_seq = hdr->sadb_msg_seq; | ||
1279 | out_hdr->sadb_msg_pid = hdr->sadb_msg_pid; | ||
1280 | |||
1281 | pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, sk); | ||
1282 | |||
1283 | return 0; | ||
1284 | } | 1347 | } |
1285 | 1348 | ||
1286 | static int pfkey_delete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) | 1349 | static int pfkey_delete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) |
1287 | { | 1350 | { |
1288 | struct xfrm_state *x; | 1351 | struct xfrm_state *x; |
1352 | struct km_event c; | ||
1353 | int err; | ||
1289 | 1354 | ||
1290 | if (!ext_hdrs[SADB_EXT_SA-1] || | 1355 | if (!ext_hdrs[SADB_EXT_SA-1] || |
1291 | !present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1], | 1356 | !present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1], |
@@ -1301,13 +1366,19 @@ static int pfkey_delete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h | |||
1301 | return -EPERM; | 1366 | return -EPERM; |
1302 | } | 1367 | } |
1303 | 1368 | ||
1304 | xfrm_state_delete(x); | 1369 | err = xfrm_state_delete(x); |
1305 | xfrm_state_put(x); | 1370 | if (err < 0) { |
1371 | xfrm_state_put(x); | ||
1372 | return err; | ||
1373 | } | ||
1306 | 1374 | ||
1307 | pfkey_broadcast(skb_clone(skb, GFP_KERNEL), GFP_KERNEL, | 1375 | c.seq = hdr->sadb_msg_seq; |
1308 | BROADCAST_ALL, sk); | 1376 | c.pid = hdr->sadb_msg_pid; |
1377 | c.event = XFRM_MSG_DELSA; | ||
1378 | km_state_notify(x, &c); | ||
1379 | xfrm_state_put(x); | ||
1309 | 1380 | ||
1310 | return 0; | 1381 | return err; |
1311 | } | 1382 | } |
1312 | 1383 | ||
1313 | static int pfkey_get(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) | 1384 | static int pfkey_get(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) |
@@ -1445,28 +1516,42 @@ static int pfkey_register(struct sock *sk, struct sk_buff *skb, struct sadb_msg | |||
1445 | return 0; | 1516 | return 0; |
1446 | } | 1517 | } |
1447 | 1518 | ||
1519 | static int key_notify_sa_flush(struct km_event *c) | ||
1520 | { | ||
1521 | struct sk_buff *skb; | ||
1522 | struct sadb_msg *hdr; | ||
1523 | |||
1524 | skb = alloc_skb(sizeof(struct sadb_msg) + 16, GFP_ATOMIC); | ||
1525 | if (!skb) | ||
1526 | return -ENOBUFS; | ||
1527 | hdr = (struct sadb_msg *) skb_put(skb, sizeof(struct sadb_msg)); | ||
1528 | hdr->sadb_msg_satype = pfkey_proto2satype(c->data.proto); | ||
1529 | hdr->sadb_msg_seq = c->seq; | ||
1530 | hdr->sadb_msg_pid = c->pid; | ||
1531 | hdr->sadb_msg_version = PF_KEY_V2; | ||
1532 | hdr->sadb_msg_errno = (uint8_t) 0; | ||
1533 | hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); | ||
1534 | |||
1535 | pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL); | ||
1536 | |||
1537 | return 0; | ||
1538 | } | ||
1539 | |||
1448 | static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) | 1540 | static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) |
1449 | { | 1541 | { |
1450 | unsigned proto; | 1542 | unsigned proto; |
1451 | struct sk_buff *skb_out; | 1543 | struct km_event c; |
1452 | struct sadb_msg *hdr_out; | ||
1453 | 1544 | ||
1454 | proto = pfkey_satype2proto(hdr->sadb_msg_satype); | 1545 | proto = pfkey_satype2proto(hdr->sadb_msg_satype); |
1455 | if (proto == 0) | 1546 | if (proto == 0) |
1456 | return -EINVAL; | 1547 | return -EINVAL; |
1457 | 1548 | ||
1458 | skb_out = alloc_skb(sizeof(struct sadb_msg) + 16, GFP_KERNEL); | ||
1459 | if (!skb_out) | ||
1460 | return -ENOBUFS; | ||
1461 | |||
1462 | xfrm_state_flush(proto); | 1549 | xfrm_state_flush(proto); |
1463 | 1550 | c.data.proto = proto; | |
1464 | hdr_out = (struct sadb_msg *) skb_put(skb_out, sizeof(struct sadb_msg)); | 1551 | c.seq = hdr->sadb_msg_seq; |
1465 | pfkey_hdr_dup(hdr_out, hdr); | 1552 | c.pid = hdr->sadb_msg_pid; |
1466 | hdr_out->sadb_msg_errno = (uint8_t) 0; | 1553 | c.event = XFRM_MSG_FLUSHSA; |
1467 | hdr_out->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); | 1554 | km_state_notify(NULL, &c); |
1468 | |||
1469 | pfkey_broadcast(skb_out, GFP_KERNEL, BROADCAST_ALL, NULL); | ||
1470 | 1555 | ||
1471 | return 0; | 1556 | return 0; |
1472 | } | 1557 | } |
@@ -1859,6 +1944,35 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i | |||
1859 | hdr->sadb_msg_reserved = atomic_read(&xp->refcnt); | 1944 | hdr->sadb_msg_reserved = atomic_read(&xp->refcnt); |
1860 | } | 1945 | } |
1861 | 1946 | ||
1947 | static int key_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c) | ||
1948 | { | ||
1949 | struct sk_buff *out_skb; | ||
1950 | struct sadb_msg *out_hdr; | ||
1951 | int err; | ||
1952 | |||
1953 | out_skb = pfkey_xfrm_policy2msg_prep(xp); | ||
1954 | if (IS_ERR(out_skb)) { | ||
1955 | err = PTR_ERR(out_skb); | ||
1956 | goto out; | ||
1957 | } | ||
1958 | pfkey_xfrm_policy2msg(out_skb, xp, dir); | ||
1959 | |||
1960 | out_hdr = (struct sadb_msg *) out_skb->data; | ||
1961 | out_hdr->sadb_msg_version = PF_KEY_V2; | ||
1962 | |||
1963 | if (c->data.byid && c->event == XFRM_MSG_DELPOLICY) | ||
1964 | out_hdr->sadb_msg_type = SADB_X_SPDDELETE2; | ||
1965 | else | ||
1966 | out_hdr->sadb_msg_type = event2poltype(c->event); | ||
1967 | out_hdr->sadb_msg_errno = 0; | ||
1968 | out_hdr->sadb_msg_seq = c->seq; | ||
1969 | out_hdr->sadb_msg_pid = c->pid; | ||
1970 | pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, NULL); | ||
1971 | out: | ||
1972 | return 0; | ||
1973 | |||
1974 | } | ||
1975 | |||
1862 | static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) | 1976 | static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) |
1863 | { | 1977 | { |
1864 | int err; | 1978 | int err; |
@@ -1866,8 +1980,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h | |||
1866 | struct sadb_address *sa; | 1980 | struct sadb_address *sa; |
1867 | struct sadb_x_policy *pol; | 1981 | struct sadb_x_policy *pol; |
1868 | struct xfrm_policy *xp; | 1982 | struct xfrm_policy *xp; |
1869 | struct sk_buff *out_skb; | 1983 | struct km_event c; |
1870 | struct sadb_msg *out_hdr; | ||
1871 | 1984 | ||
1872 | if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1], | 1985 | if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1], |
1873 | ext_hdrs[SADB_EXT_ADDRESS_DST-1]) || | 1986 | ext_hdrs[SADB_EXT_ADDRESS_DST-1]) || |
@@ -1935,31 +2048,23 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h | |||
1935 | (err = parse_ipsecrequests(xp, pol)) < 0) | 2048 | (err = parse_ipsecrequests(xp, pol)) < 0) |
1936 | goto out; | 2049 | goto out; |
1937 | 2050 | ||
1938 | out_skb = pfkey_xfrm_policy2msg_prep(xp); | ||
1939 | if (IS_ERR(out_skb)) { | ||
1940 | err = PTR_ERR(out_skb); | ||
1941 | goto out; | ||
1942 | } | ||
1943 | |||
1944 | err = xfrm_policy_insert(pol->sadb_x_policy_dir-1, xp, | 2051 | err = xfrm_policy_insert(pol->sadb_x_policy_dir-1, xp, |
1945 | hdr->sadb_msg_type != SADB_X_SPDUPDATE); | 2052 | hdr->sadb_msg_type != SADB_X_SPDUPDATE); |
1946 | if (err) { | 2053 | if (err) { |
1947 | kfree_skb(out_skb); | 2054 | kfree(xp); |
1948 | goto out; | 2055 | return err; |
1949 | } | 2056 | } |
1950 | 2057 | ||
1951 | pfkey_xfrm_policy2msg(out_skb, xp, pol->sadb_x_policy_dir-1); | 2058 | if (hdr->sadb_msg_type == SADB_X_SPDUPDATE) |
2059 | c.event = XFRM_MSG_UPDPOLICY; | ||
2060 | else | ||
2061 | c.event = XFRM_MSG_NEWPOLICY; | ||
1952 | 2062 | ||
1953 | xfrm_pol_put(xp); | 2063 | c.seq = hdr->sadb_msg_seq; |
2064 | c.pid = hdr->sadb_msg_pid; | ||
1954 | 2065 | ||
1955 | out_hdr = (struct sadb_msg *) out_skb->data; | 2066 | km_policy_notify(xp, pol->sadb_x_policy_dir-1, &c); |
1956 | out_hdr->sadb_msg_version = hdr->sadb_msg_version; | 2067 | xfrm_pol_put(xp); |
1957 | out_hdr->sadb_msg_type = hdr->sadb_msg_type; | ||
1958 | out_hdr->sadb_msg_satype = 0; | ||
1959 | out_hdr->sadb_msg_errno = 0; | ||
1960 | out_hdr->sadb_msg_seq = hdr->sadb_msg_seq; | ||
1961 | out_hdr->sadb_msg_pid = hdr->sadb_msg_pid; | ||
1962 | pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, sk); | ||
1963 | return 0; | 2068 | return 0; |
1964 | 2069 | ||
1965 | out: | 2070 | out: |
@@ -1973,9 +2078,8 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg | |||
1973 | struct sadb_address *sa; | 2078 | struct sadb_address *sa; |
1974 | struct sadb_x_policy *pol; | 2079 | struct sadb_x_policy *pol; |
1975 | struct xfrm_policy *xp; | 2080 | struct xfrm_policy *xp; |
1976 | struct sk_buff *out_skb; | ||
1977 | struct sadb_msg *out_hdr; | ||
1978 | struct xfrm_selector sel; | 2081 | struct xfrm_selector sel; |
2082 | struct km_event c; | ||
1979 | 2083 | ||
1980 | if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1], | 2084 | if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1], |
1981 | ext_hdrs[SADB_EXT_ADDRESS_DST-1]) || | 2085 | ext_hdrs[SADB_EXT_ADDRESS_DST-1]) || |
@@ -2010,25 +2114,40 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg | |||
2010 | 2114 | ||
2011 | err = 0; | 2115 | err = 0; |
2012 | 2116 | ||
2117 | c.seq = hdr->sadb_msg_seq; | ||
2118 | c.pid = hdr->sadb_msg_pid; | ||
2119 | c.event = XFRM_MSG_DELPOLICY; | ||
2120 | km_policy_notify(xp, pol->sadb_x_policy_dir-1, &c); | ||
2121 | |||
2122 | xfrm_pol_put(xp); | ||
2123 | return err; | ||
2124 | } | ||
2125 | |||
2126 | static int key_pol_get_resp(struct sock *sk, struct xfrm_policy *xp, struct sadb_msg *hdr, int dir) | ||
2127 | { | ||
2128 | int err; | ||
2129 | struct sk_buff *out_skb; | ||
2130 | struct sadb_msg *out_hdr; | ||
2131 | err = 0; | ||
2132 | |||
2013 | out_skb = pfkey_xfrm_policy2msg_prep(xp); | 2133 | out_skb = pfkey_xfrm_policy2msg_prep(xp); |
2014 | if (IS_ERR(out_skb)) { | 2134 | if (IS_ERR(out_skb)) { |
2015 | err = PTR_ERR(out_skb); | 2135 | err = PTR_ERR(out_skb); |
2016 | goto out; | 2136 | goto out; |
2017 | } | 2137 | } |
2018 | pfkey_xfrm_policy2msg(out_skb, xp, pol->sadb_x_policy_dir-1); | 2138 | pfkey_xfrm_policy2msg(out_skb, xp, dir); |
2019 | 2139 | ||
2020 | out_hdr = (struct sadb_msg *) out_skb->data; | 2140 | out_hdr = (struct sadb_msg *) out_skb->data; |
2021 | out_hdr->sadb_msg_version = hdr->sadb_msg_version; | 2141 | out_hdr->sadb_msg_version = hdr->sadb_msg_version; |
2022 | out_hdr->sadb_msg_type = SADB_X_SPDDELETE; | 2142 | out_hdr->sadb_msg_type = hdr->sadb_msg_type; |
2023 | out_hdr->sadb_msg_satype = 0; | 2143 | out_hdr->sadb_msg_satype = 0; |
2024 | out_hdr->sadb_msg_errno = 0; | 2144 | out_hdr->sadb_msg_errno = 0; |
2025 | out_hdr->sadb_msg_seq = hdr->sadb_msg_seq; | 2145 | out_hdr->sadb_msg_seq = hdr->sadb_msg_seq; |
2026 | out_hdr->sadb_msg_pid = hdr->sadb_msg_pid; | 2146 | out_hdr->sadb_msg_pid = hdr->sadb_msg_pid; |
2027 | pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, sk); | 2147 | pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, sk); |
2028 | err = 0; | 2148 | err = 0; |
2029 | 2149 | ||
2030 | out: | 2150 | out: |
2031 | xfrm_pol_put(xp); | ||
2032 | return err; | 2151 | return err; |
2033 | } | 2152 | } |
2034 | 2153 | ||
@@ -2037,8 +2156,7 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h | |||
2037 | int err; | 2156 | int err; |
2038 | struct sadb_x_policy *pol; | 2157 | struct sadb_x_policy *pol; |
2039 | struct xfrm_policy *xp; | 2158 | struct xfrm_policy *xp; |
2040 | struct sk_buff *out_skb; | 2159 | struct km_event c; |
2041 | struct sadb_msg *out_hdr; | ||
2042 | 2160 | ||
2043 | if ((pol = ext_hdrs[SADB_X_EXT_POLICY-1]) == NULL) | 2161 | if ((pol = ext_hdrs[SADB_X_EXT_POLICY-1]) == NULL) |
2044 | return -EINVAL; | 2162 | return -EINVAL; |
@@ -2050,24 +2168,16 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h | |||
2050 | 2168 | ||
2051 | err = 0; | 2169 | err = 0; |
2052 | 2170 | ||
2053 | out_skb = pfkey_xfrm_policy2msg_prep(xp); | 2171 | c.seq = hdr->sadb_msg_seq; |
2054 | if (IS_ERR(out_skb)) { | 2172 | c.pid = hdr->sadb_msg_pid; |
2055 | err = PTR_ERR(out_skb); | 2173 | if (hdr->sadb_msg_type == SADB_X_SPDDELETE2) { |
2056 | goto out; | 2174 | c.data.byid = 1; |
2175 | c.event = XFRM_MSG_DELPOLICY; | ||
2176 | km_policy_notify(xp, pol->sadb_x_policy_dir-1, &c); | ||
2177 | } else { | ||
2178 | err = key_pol_get_resp(sk, xp, hdr, pol->sadb_x_policy_dir-1); | ||
2057 | } | 2179 | } |
2058 | pfkey_xfrm_policy2msg(out_skb, xp, pol->sadb_x_policy_dir-1); | ||
2059 | 2180 | ||
2060 | out_hdr = (struct sadb_msg *) out_skb->data; | ||
2061 | out_hdr->sadb_msg_version = hdr->sadb_msg_version; | ||
2062 | out_hdr->sadb_msg_type = hdr->sadb_msg_type; | ||
2063 | out_hdr->sadb_msg_satype = 0; | ||
2064 | out_hdr->sadb_msg_errno = 0; | ||
2065 | out_hdr->sadb_msg_seq = hdr->sadb_msg_seq; | ||
2066 | out_hdr->sadb_msg_pid = hdr->sadb_msg_pid; | ||
2067 | pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, sk); | ||
2068 | err = 0; | ||
2069 | |||
2070 | out: | ||
2071 | xfrm_pol_put(xp); | 2181 | xfrm_pol_put(xp); |
2072 | return err; | 2182 | return err; |
2073 | } | 2183 | } |
@@ -2102,22 +2212,34 @@ static int pfkey_spddump(struct sock *sk, struct sk_buff *skb, struct sadb_msg * | |||
2102 | return xfrm_policy_walk(dump_sp, &data); | 2212 | return xfrm_policy_walk(dump_sp, &data); |
2103 | } | 2213 | } |
2104 | 2214 | ||
2105 | static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) | 2215 | static int key_notify_policy_flush(struct km_event *c) |
2106 | { | 2216 | { |
2107 | struct sk_buff *skb_out; | 2217 | struct sk_buff *skb_out; |
2108 | struct sadb_msg *hdr_out; | 2218 | struct sadb_msg *hdr; |
2109 | 2219 | ||
2110 | skb_out = alloc_skb(sizeof(struct sadb_msg) + 16, GFP_KERNEL); | 2220 | skb_out = alloc_skb(sizeof(struct sadb_msg) + 16, GFP_ATOMIC); |
2111 | if (!skb_out) | 2221 | if (!skb_out) |
2112 | return -ENOBUFS; | 2222 | return -ENOBUFS; |
2223 | hdr = (struct sadb_msg *) skb_put(skb_out, sizeof(struct sadb_msg)); | ||
2224 | hdr->sadb_msg_seq = c->seq; | ||
2225 | hdr->sadb_msg_pid = c->pid; | ||
2226 | hdr->sadb_msg_version = PF_KEY_V2; | ||
2227 | hdr->sadb_msg_errno = (uint8_t) 0; | ||
2228 | hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); | ||
2229 | pfkey_broadcast(skb_out, GFP_ATOMIC, BROADCAST_ALL, NULL); | ||
2230 | return 0; | ||
2113 | 2231 | ||
2114 | xfrm_policy_flush(); | 2232 | } |
2115 | 2233 | ||
2116 | hdr_out = (struct sadb_msg *) skb_put(skb_out, sizeof(struct sadb_msg)); | 2234 | static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) |
2117 | pfkey_hdr_dup(hdr_out, hdr); | 2235 | { |
2118 | hdr_out->sadb_msg_errno = (uint8_t) 0; | 2236 | struct km_event c; |
2119 | hdr_out->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); | 2237 | |
2120 | pfkey_broadcast(skb_out, GFP_KERNEL, BROADCAST_ALL, NULL); | 2238 | xfrm_policy_flush(); |
2239 | c.event = XFRM_MSG_FLUSHPOLICY; | ||
2240 | c.pid = hdr->sadb_msg_pid; | ||
2241 | c.seq = hdr->sadb_msg_seq; | ||
2242 | km_policy_notify(NULL, 0, &c); | ||
2121 | 2243 | ||
2122 | return 0; | 2244 | return 0; |
2123 | } | 2245 | } |
@@ -2317,11 +2439,23 @@ static void dump_esp_combs(struct sk_buff *skb, struct xfrm_tmpl *t) | |||
2317 | } | 2439 | } |
2318 | } | 2440 | } |
2319 | 2441 | ||
2320 | static int pfkey_send_notify(struct xfrm_state *x, int hard) | 2442 | static int key_notify_policy_expire(struct xfrm_policy *xp, struct km_event *c) |
2443 | { | ||
2444 | return 0; | ||
2445 | } | ||
2446 | |||
2447 | static int key_notify_sa_expire(struct xfrm_state *x, struct km_event *c) | ||
2321 | { | 2448 | { |
2322 | struct sk_buff *out_skb; | 2449 | struct sk_buff *out_skb; |
2323 | struct sadb_msg *out_hdr; | 2450 | struct sadb_msg *out_hdr; |
2324 | int hsc = (hard ? 2 : 1); | 2451 | int hard; |
2452 | int hsc; | ||
2453 | |||
2454 | hard = c->data.hard; | ||
2455 | if (hard) | ||
2456 | hsc = 2; | ||
2457 | else | ||
2458 | hsc = 1; | ||
2325 | 2459 | ||
2326 | out_skb = pfkey_xfrm_state2msg(x, 0, hsc); | 2460 | out_skb = pfkey_xfrm_state2msg(x, 0, hsc); |
2327 | if (IS_ERR(out_skb)) | 2461 | if (IS_ERR(out_skb)) |
@@ -2340,6 +2474,44 @@ static int pfkey_send_notify(struct xfrm_state *x, int hard) | |||
2340 | return 0; | 2474 | return 0; |
2341 | } | 2475 | } |
2342 | 2476 | ||
2477 | static int pfkey_send_notify(struct xfrm_state *x, struct km_event *c) | ||
2478 | { | ||
2479 | switch (c->event) { | ||
2480 | case XFRM_MSG_EXPIRE: | ||
2481 | return key_notify_sa_expire(x, c); | ||
2482 | case XFRM_MSG_DELSA: | ||
2483 | case XFRM_MSG_NEWSA: | ||
2484 | case XFRM_MSG_UPDSA: | ||
2485 | return key_notify_sa(x, c); | ||
2486 | case XFRM_MSG_FLUSHSA: | ||
2487 | return key_notify_sa_flush(c); | ||
2488 | default: | ||
2489 | printk("pfkey: Unknown SA event %d\n", c->event); | ||
2490 | break; | ||
2491 | } | ||
2492 | |||
2493 | return 0; | ||
2494 | } | ||
2495 | |||
2496 | static int pfkey_send_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c) | ||
2497 | { | ||
2498 | switch (c->event) { | ||
2499 | case XFRM_MSG_POLEXPIRE: | ||
2500 | return key_notify_policy_expire(xp, c); | ||
2501 | case XFRM_MSG_DELPOLICY: | ||
2502 | case XFRM_MSG_NEWPOLICY: | ||
2503 | case XFRM_MSG_UPDPOLICY: | ||
2504 | return key_notify_policy(xp, dir, c); | ||
2505 | case XFRM_MSG_FLUSHPOLICY: | ||
2506 | return key_notify_policy_flush(c); | ||
2507 | default: | ||
2508 | printk("pfkey: Unknown policy event %d\n", c->event); | ||
2509 | break; | ||
2510 | } | ||
2511 | |||
2512 | return 0; | ||
2513 | } | ||
2514 | |||
2343 | static u32 get_acqseq(void) | 2515 | static u32 get_acqseq(void) |
2344 | { | 2516 | { |
2345 | u32 res; | 2517 | u32 res; |
@@ -2856,6 +3028,7 @@ static struct xfrm_mgr pfkeyv2_mgr = | |||
2856 | .acquire = pfkey_send_acquire, | 3028 | .acquire = pfkey_send_acquire, |
2857 | .compile_policy = pfkey_compile_policy, | 3029 | .compile_policy = pfkey_compile_policy, |
2858 | .new_mapping = pfkey_send_new_mapping, | 3030 | .new_mapping = pfkey_send_new_mapping, |
3031 | .notify_policy = pfkey_send_policy_notify, | ||
2859 | }; | 3032 | }; |
2860 | 3033 | ||
2861 | static void __exit ipsec_pfkey_exit(void) | 3034 | static void __exit ipsec_pfkey_exit(void) |