diff options
Diffstat (limited to 'net/key/af_key.c')
| -rw-r--r-- | net/key/af_key.c | 369 |
1 files changed, 272 insertions, 97 deletions
diff --git a/net/key/af_key.c b/net/key/af_key.c index ce980aa94ed8..98b72f2024ff 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); |
| @@ -1240,13 +1245,78 @@ static int pfkey_acquire(struct sock *sk, struct sk_buff *skb, struct sadb_msg * | |||
| 1240 | return 0; | 1245 | return 0; |
| 1241 | } | 1246 | } |
| 1242 | 1247 | ||
| 1248 | static inline int event2poltype(int event) | ||
| 1249 | { | ||
| 1250 | switch (event) { | ||
| 1251 | case XFRM_MSG_DELPOLICY: | ||
| 1252 | return SADB_X_SPDDELETE; | ||
| 1253 | case XFRM_MSG_NEWPOLICY: | ||
| 1254 | return SADB_X_SPDADD; | ||
| 1255 | case XFRM_MSG_UPDPOLICY: | ||
| 1256 | return SADB_X_SPDUPDATE; | ||
| 1257 | case XFRM_MSG_POLEXPIRE: | ||
| 1258 | // return SADB_X_SPDEXPIRE; | ||
| 1259 | default: | ||
| 1260 | printk("pfkey: Unknown policy event %d\n", event); | ||
| 1261 | break; | ||
| 1262 | } | ||
| 1263 | |||
| 1264 | return 0; | ||
| 1265 | } | ||
| 1266 | |||
| 1267 | static inline int event2keytype(int event) | ||
| 1268 | { | ||
| 1269 | switch (event) { | ||
| 1270 | case XFRM_MSG_DELSA: | ||
| 1271 | return SADB_DELETE; | ||
| 1272 | case XFRM_MSG_NEWSA: | ||
| 1273 | return SADB_ADD; | ||
| 1274 | case XFRM_MSG_UPDSA: | ||
| 1275 | return SADB_UPDATE; | ||
| 1276 | case XFRM_MSG_EXPIRE: | ||
| 1277 | return SADB_EXPIRE; | ||
| 1278 | default: | ||
| 1279 | printk("pfkey: Unknown SA event %d\n", event); | ||
| 1280 | break; | ||
| 1281 | } | ||
| 1282 | |||
| 1283 | return 0; | ||
| 1284 | } | ||
| 1285 | |||
| 1286 | /* ADD/UPD/DEL */ | ||
| 1287 | static int key_notify_sa(struct xfrm_state *x, struct km_event *c) | ||
| 1288 | { | ||
| 1289 | struct sk_buff *skb; | ||
| 1290 | struct sadb_msg *hdr; | ||
| 1291 | int hsc = 3; | ||
| 1292 | |||
| 1293 | if (c->event == XFRM_MSG_DELSA) | ||
| 1294 | hsc = 0; | ||
| 1295 | |||
| 1296 | skb = pfkey_xfrm_state2msg(x, 0, hsc); | ||
| 1297 | |||
| 1298 | if (IS_ERR(skb)) | ||
| 1299 | return PTR_ERR(skb); | ||
| 1300 | |||
| 1301 | hdr = (struct sadb_msg *) skb->data; | ||
| 1302 | hdr->sadb_msg_version = PF_KEY_V2; | ||
| 1303 | hdr->sadb_msg_type = event2keytype(c->event); | ||
| 1304 | hdr->sadb_msg_satype = pfkey_proto2satype(x->id.proto); | ||
| 1305 | hdr->sadb_msg_errno = 0; | ||
| 1306 | hdr->sadb_msg_reserved = 0; | ||
| 1307 | hdr->sadb_msg_seq = c->seq; | ||
| 1308 | hdr->sadb_msg_pid = c->pid; | ||
| 1309 | |||
| 1310 | pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL); | ||
| 1311 | |||
| 1312 | return 0; | ||
| 1313 | } | ||
| 1243 | 1314 | ||
| 1244 | static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) | 1315 | static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) |
| 1245 | { | 1316 | { |
| 1246 | struct sk_buff *out_skb; | ||
| 1247 | struct sadb_msg *out_hdr; | ||
| 1248 | struct xfrm_state *x; | 1317 | struct xfrm_state *x; |
| 1249 | int err; | 1318 | int err; |
| 1319 | struct km_event c; | ||
| 1250 | 1320 | ||
| 1251 | xfrm_probe_algs(); | 1321 | xfrm_probe_algs(); |
| 1252 | 1322 | ||
| @@ -1254,6 +1324,7 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, | |||
| 1254 | if (IS_ERR(x)) | 1324 | if (IS_ERR(x)) |
| 1255 | return PTR_ERR(x); | 1325 | return PTR_ERR(x); |
| 1256 | 1326 | ||
| 1327 | xfrm_state_hold(x); | ||
| 1257 | if (hdr->sadb_msg_type == SADB_ADD) | 1328 | if (hdr->sadb_msg_type == SADB_ADD) |
| 1258 | err = xfrm_state_add(x); | 1329 | err = xfrm_state_add(x); |
| 1259 | else | 1330 | else |
| @@ -1262,30 +1333,26 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, | |||
| 1262 | if (err < 0) { | 1333 | if (err < 0) { |
| 1263 | x->km.state = XFRM_STATE_DEAD; | 1334 | x->km.state = XFRM_STATE_DEAD; |
| 1264 | xfrm_state_put(x); | 1335 | xfrm_state_put(x); |
| 1265 | return err; | 1336 | goto out; |
| 1266 | } | 1337 | } |
| 1267 | 1338 | ||
| 1268 | out_skb = pfkey_xfrm_state2msg(x, 0, 3); | 1339 | if (hdr->sadb_msg_type == SADB_ADD) |
| 1269 | if (IS_ERR(out_skb)) | 1340 | c.event = XFRM_MSG_NEWSA; |
| 1270 | return PTR_ERR(out_skb); /* XXX Should we return 0 here ? */ | 1341 | else |
| 1271 | 1342 | c.event = XFRM_MSG_UPDSA; | |
| 1272 | out_hdr = (struct sadb_msg *) out_skb->data; | 1343 | c.seq = hdr->sadb_msg_seq; |
| 1273 | out_hdr->sadb_msg_version = hdr->sadb_msg_version; | 1344 | c.pid = hdr->sadb_msg_pid; |
| 1274 | out_hdr->sadb_msg_type = hdr->sadb_msg_type; | 1345 | km_state_notify(x, &c); |
| 1275 | out_hdr->sadb_msg_satype = pfkey_proto2satype(x->id.proto); | 1346 | out: |
| 1276 | out_hdr->sadb_msg_errno = 0; | 1347 | xfrm_state_put(x); |
| 1277 | out_hdr->sadb_msg_reserved = 0; | 1348 | 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 | } | 1349 | } |
| 1285 | 1350 | ||
| 1286 | static int pfkey_delete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) | 1351 | static int pfkey_delete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) |
| 1287 | { | 1352 | { |
| 1288 | struct xfrm_state *x; | 1353 | struct xfrm_state *x; |
| 1354 | struct km_event c; | ||
| 1355 | int err; | ||
| 1289 | 1356 | ||
| 1290 | if (!ext_hdrs[SADB_EXT_SA-1] || | 1357 | if (!ext_hdrs[SADB_EXT_SA-1] || |
| 1291 | !present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1], | 1358 | !present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1], |
| @@ -1301,13 +1368,19 @@ static int pfkey_delete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h | |||
| 1301 | return -EPERM; | 1368 | return -EPERM; |
| 1302 | } | 1369 | } |
| 1303 | 1370 | ||
| 1304 | xfrm_state_delete(x); | 1371 | err = xfrm_state_delete(x); |
| 1305 | xfrm_state_put(x); | 1372 | if (err < 0) { |
| 1373 | xfrm_state_put(x); | ||
| 1374 | return err; | ||
| 1375 | } | ||
| 1306 | 1376 | ||
| 1307 | pfkey_broadcast(skb_clone(skb, GFP_KERNEL), GFP_KERNEL, | 1377 | c.seq = hdr->sadb_msg_seq; |
| 1308 | BROADCAST_ALL, sk); | 1378 | c.pid = hdr->sadb_msg_pid; |
| 1379 | c.event = XFRM_MSG_DELSA; | ||
| 1380 | km_state_notify(x, &c); | ||
| 1381 | xfrm_state_put(x); | ||
| 1309 | 1382 | ||
| 1310 | return 0; | 1383 | return err; |
| 1311 | } | 1384 | } |
| 1312 | 1385 | ||
| 1313 | static int pfkey_get(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) | 1386 | static int pfkey_get(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) |
| @@ -1445,28 +1518,42 @@ static int pfkey_register(struct sock *sk, struct sk_buff *skb, struct sadb_msg | |||
| 1445 | return 0; | 1518 | return 0; |
| 1446 | } | 1519 | } |
| 1447 | 1520 | ||
| 1521 | static int key_notify_sa_flush(struct km_event *c) | ||
| 1522 | { | ||
| 1523 | struct sk_buff *skb; | ||
| 1524 | struct sadb_msg *hdr; | ||
| 1525 | |||
| 1526 | skb = alloc_skb(sizeof(struct sadb_msg) + 16, GFP_ATOMIC); | ||
| 1527 | if (!skb) | ||
| 1528 | return -ENOBUFS; | ||
| 1529 | hdr = (struct sadb_msg *) skb_put(skb, sizeof(struct sadb_msg)); | ||
| 1530 | hdr->sadb_msg_satype = pfkey_proto2satype(c->data.proto); | ||
| 1531 | hdr->sadb_msg_seq = c->seq; | ||
| 1532 | hdr->sadb_msg_pid = c->pid; | ||
| 1533 | hdr->sadb_msg_version = PF_KEY_V2; | ||
| 1534 | hdr->sadb_msg_errno = (uint8_t) 0; | ||
| 1535 | hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); | ||
| 1536 | |||
| 1537 | pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL); | ||
| 1538 | |||
| 1539 | return 0; | ||
| 1540 | } | ||
| 1541 | |||
| 1448 | static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) | 1542 | static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) |
| 1449 | { | 1543 | { |
| 1450 | unsigned proto; | 1544 | unsigned proto; |
| 1451 | struct sk_buff *skb_out; | 1545 | struct km_event c; |
| 1452 | struct sadb_msg *hdr_out; | ||
| 1453 | 1546 | ||
| 1454 | proto = pfkey_satype2proto(hdr->sadb_msg_satype); | 1547 | proto = pfkey_satype2proto(hdr->sadb_msg_satype); |
| 1455 | if (proto == 0) | 1548 | if (proto == 0) |
| 1456 | return -EINVAL; | 1549 | return -EINVAL; |
| 1457 | 1550 | ||
| 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); | 1551 | xfrm_state_flush(proto); |
| 1463 | 1552 | c.data.proto = proto; | |
| 1464 | hdr_out = (struct sadb_msg *) skb_put(skb_out, sizeof(struct sadb_msg)); | 1553 | c.seq = hdr->sadb_msg_seq; |
| 1465 | pfkey_hdr_dup(hdr_out, hdr); | 1554 | c.pid = hdr->sadb_msg_pid; |
| 1466 | hdr_out->sadb_msg_errno = (uint8_t) 0; | 1555 | c.event = XFRM_MSG_FLUSHSA; |
| 1467 | hdr_out->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); | 1556 | km_state_notify(NULL, &c); |
| 1468 | |||
| 1469 | pfkey_broadcast(skb_out, GFP_KERNEL, BROADCAST_ALL, NULL); | ||
| 1470 | 1557 | ||
| 1471 | return 0; | 1558 | return 0; |
| 1472 | } | 1559 | } |
| @@ -1859,6 +1946,35 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i | |||
| 1859 | hdr->sadb_msg_reserved = atomic_read(&xp->refcnt); | 1946 | hdr->sadb_msg_reserved = atomic_read(&xp->refcnt); |
| 1860 | } | 1947 | } |
| 1861 | 1948 | ||
| 1949 | static int key_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c) | ||
| 1950 | { | ||
| 1951 | struct sk_buff *out_skb; | ||
| 1952 | struct sadb_msg *out_hdr; | ||
| 1953 | int err; | ||
| 1954 | |||
| 1955 | out_skb = pfkey_xfrm_policy2msg_prep(xp); | ||
| 1956 | if (IS_ERR(out_skb)) { | ||
| 1957 | err = PTR_ERR(out_skb); | ||
| 1958 | goto out; | ||
| 1959 | } | ||
| 1960 | pfkey_xfrm_policy2msg(out_skb, xp, dir); | ||
| 1961 | |||
| 1962 | out_hdr = (struct sadb_msg *) out_skb->data; | ||
| 1963 | out_hdr->sadb_msg_version = PF_KEY_V2; | ||
| 1964 | |||
| 1965 | if (c->data.byid && c->event == XFRM_MSG_DELPOLICY) | ||
| 1966 | out_hdr->sadb_msg_type = SADB_X_SPDDELETE2; | ||
| 1967 | else | ||
| 1968 | out_hdr->sadb_msg_type = event2poltype(c->event); | ||
| 1969 | out_hdr->sadb_msg_errno = 0; | ||
| 1970 | out_hdr->sadb_msg_seq = c->seq; | ||
| 1971 | out_hdr->sadb_msg_pid = c->pid; | ||
| 1972 | pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, NULL); | ||
| 1973 | out: | ||
| 1974 | return 0; | ||
| 1975 | |||
| 1976 | } | ||
| 1977 | |||
| 1862 | static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) | 1978 | static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) |
| 1863 | { | 1979 | { |
| 1864 | int err; | 1980 | int err; |
| @@ -1866,8 +1982,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h | |||
| 1866 | struct sadb_address *sa; | 1982 | struct sadb_address *sa; |
| 1867 | struct sadb_x_policy *pol; | 1983 | struct sadb_x_policy *pol; |
| 1868 | struct xfrm_policy *xp; | 1984 | struct xfrm_policy *xp; |
| 1869 | struct sk_buff *out_skb; | 1985 | struct km_event c; |
| 1870 | struct sadb_msg *out_hdr; | ||
| 1871 | 1986 | ||
| 1872 | if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1], | 1987 | if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1], |
| 1873 | ext_hdrs[SADB_EXT_ADDRESS_DST-1]) || | 1988 | ext_hdrs[SADB_EXT_ADDRESS_DST-1]) || |
| @@ -1935,31 +2050,23 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h | |||
| 1935 | (err = parse_ipsecrequests(xp, pol)) < 0) | 2050 | (err = parse_ipsecrequests(xp, pol)) < 0) |
| 1936 | goto out; | 2051 | goto out; |
| 1937 | 2052 | ||
| 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, | 2053 | err = xfrm_policy_insert(pol->sadb_x_policy_dir-1, xp, |
| 1945 | hdr->sadb_msg_type != SADB_X_SPDUPDATE); | 2054 | hdr->sadb_msg_type != SADB_X_SPDUPDATE); |
| 1946 | if (err) { | 2055 | if (err) { |
| 1947 | kfree_skb(out_skb); | 2056 | kfree(xp); |
| 1948 | goto out; | 2057 | return err; |
| 1949 | } | 2058 | } |
| 1950 | 2059 | ||
| 1951 | pfkey_xfrm_policy2msg(out_skb, xp, pol->sadb_x_policy_dir-1); | 2060 | if (hdr->sadb_msg_type == SADB_X_SPDUPDATE) |
| 2061 | c.event = XFRM_MSG_UPDPOLICY; | ||
| 2062 | else | ||
| 2063 | c.event = XFRM_MSG_NEWPOLICY; | ||
| 1952 | 2064 | ||
| 1953 | xfrm_pol_put(xp); | 2065 | c.seq = hdr->sadb_msg_seq; |
| 2066 | c.pid = hdr->sadb_msg_pid; | ||
| 1954 | 2067 | ||
| 1955 | out_hdr = (struct sadb_msg *) out_skb->data; | 2068 | km_policy_notify(xp, pol->sadb_x_policy_dir-1, &c); |
| 1956 | out_hdr->sadb_msg_version = hdr->sadb_msg_version; | 2069 | 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; | 2070 | return 0; |
| 1964 | 2071 | ||
| 1965 | out: | 2072 | out: |
| @@ -1973,9 +2080,8 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg | |||
| 1973 | struct sadb_address *sa; | 2080 | struct sadb_address *sa; |
| 1974 | struct sadb_x_policy *pol; | 2081 | struct sadb_x_policy *pol; |
| 1975 | struct xfrm_policy *xp; | 2082 | struct xfrm_policy *xp; |
| 1976 | struct sk_buff *out_skb; | ||
| 1977 | struct sadb_msg *out_hdr; | ||
| 1978 | struct xfrm_selector sel; | 2083 | struct xfrm_selector sel; |
| 2084 | struct km_event c; | ||
| 1979 | 2085 | ||
| 1980 | if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1], | 2086 | if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1], |
| 1981 | ext_hdrs[SADB_EXT_ADDRESS_DST-1]) || | 2087 | ext_hdrs[SADB_EXT_ADDRESS_DST-1]) || |
| @@ -2010,25 +2116,40 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg | |||
| 2010 | 2116 | ||
| 2011 | err = 0; | 2117 | err = 0; |
| 2012 | 2118 | ||
| 2119 | c.seq = hdr->sadb_msg_seq; | ||
| 2120 | c.pid = hdr->sadb_msg_pid; | ||
| 2121 | c.event = XFRM_MSG_DELPOLICY; | ||
| 2122 | km_policy_notify(xp, pol->sadb_x_policy_dir-1, &c); | ||
| 2123 | |||
| 2124 | xfrm_pol_put(xp); | ||
| 2125 | return err; | ||
| 2126 | } | ||
| 2127 | |||
| 2128 | static int key_pol_get_resp(struct sock *sk, struct xfrm_policy *xp, struct sadb_msg *hdr, int dir) | ||
| 2129 | { | ||
| 2130 | int err; | ||
| 2131 | struct sk_buff *out_skb; | ||
| 2132 | struct sadb_msg *out_hdr; | ||
| 2133 | err = 0; | ||
| 2134 | |||
| 2013 | out_skb = pfkey_xfrm_policy2msg_prep(xp); | 2135 | out_skb = pfkey_xfrm_policy2msg_prep(xp); |
| 2014 | if (IS_ERR(out_skb)) { | 2136 | if (IS_ERR(out_skb)) { |
| 2015 | err = PTR_ERR(out_skb); | 2137 | err = PTR_ERR(out_skb); |
| 2016 | goto out; | 2138 | goto out; |
| 2017 | } | 2139 | } |
| 2018 | pfkey_xfrm_policy2msg(out_skb, xp, pol->sadb_x_policy_dir-1); | 2140 | pfkey_xfrm_policy2msg(out_skb, xp, dir); |
| 2019 | 2141 | ||
| 2020 | out_hdr = (struct sadb_msg *) out_skb->data; | 2142 | out_hdr = (struct sadb_msg *) out_skb->data; |
| 2021 | out_hdr->sadb_msg_version = hdr->sadb_msg_version; | 2143 | out_hdr->sadb_msg_version = hdr->sadb_msg_version; |
| 2022 | out_hdr->sadb_msg_type = SADB_X_SPDDELETE; | 2144 | out_hdr->sadb_msg_type = hdr->sadb_msg_type; |
| 2023 | out_hdr->sadb_msg_satype = 0; | 2145 | out_hdr->sadb_msg_satype = 0; |
| 2024 | out_hdr->sadb_msg_errno = 0; | 2146 | out_hdr->sadb_msg_errno = 0; |
| 2025 | out_hdr->sadb_msg_seq = hdr->sadb_msg_seq; | 2147 | out_hdr->sadb_msg_seq = hdr->sadb_msg_seq; |
| 2026 | out_hdr->sadb_msg_pid = hdr->sadb_msg_pid; | 2148 | out_hdr->sadb_msg_pid = hdr->sadb_msg_pid; |
| 2027 | pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, sk); | 2149 | pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, sk); |
| 2028 | err = 0; | 2150 | err = 0; |
| 2029 | 2151 | ||
| 2030 | out: | 2152 | out: |
| 2031 | xfrm_pol_put(xp); | ||
| 2032 | return err; | 2153 | return err; |
| 2033 | } | 2154 | } |
| 2034 | 2155 | ||
| @@ -2037,8 +2158,7 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h | |||
| 2037 | int err; | 2158 | int err; |
| 2038 | struct sadb_x_policy *pol; | 2159 | struct sadb_x_policy *pol; |
| 2039 | struct xfrm_policy *xp; | 2160 | struct xfrm_policy *xp; |
| 2040 | struct sk_buff *out_skb; | 2161 | struct km_event c; |
| 2041 | struct sadb_msg *out_hdr; | ||
| 2042 | 2162 | ||
| 2043 | if ((pol = ext_hdrs[SADB_X_EXT_POLICY-1]) == NULL) | 2163 | if ((pol = ext_hdrs[SADB_X_EXT_POLICY-1]) == NULL) |
| 2044 | return -EINVAL; | 2164 | return -EINVAL; |
| @@ -2050,24 +2170,16 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h | |||
| 2050 | 2170 | ||
| 2051 | err = 0; | 2171 | err = 0; |
| 2052 | 2172 | ||
| 2053 | out_skb = pfkey_xfrm_policy2msg_prep(xp); | 2173 | c.seq = hdr->sadb_msg_seq; |
| 2054 | if (IS_ERR(out_skb)) { | 2174 | c.pid = hdr->sadb_msg_pid; |
| 2055 | err = PTR_ERR(out_skb); | 2175 | if (hdr->sadb_msg_type == SADB_X_SPDDELETE2) { |
| 2056 | goto out; | 2176 | c.data.byid = 1; |
| 2177 | c.event = XFRM_MSG_DELPOLICY; | ||
| 2178 | km_policy_notify(xp, pol->sadb_x_policy_dir-1, &c); | ||
| 2179 | } else { | ||
| 2180 | err = key_pol_get_resp(sk, xp, hdr, pol->sadb_x_policy_dir-1); | ||
| 2057 | } | 2181 | } |
| 2058 | pfkey_xfrm_policy2msg(out_skb, xp, pol->sadb_x_policy_dir-1); | ||
| 2059 | |||
| 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 | 2182 | ||
| 2070 | out: | ||
| 2071 | xfrm_pol_put(xp); | 2183 | xfrm_pol_put(xp); |
| 2072 | return err; | 2184 | return err; |
| 2073 | } | 2185 | } |
| @@ -2102,22 +2214,34 @@ static int pfkey_spddump(struct sock *sk, struct sk_buff *skb, struct sadb_msg * | |||
| 2102 | return xfrm_policy_walk(dump_sp, &data); | 2214 | return xfrm_policy_walk(dump_sp, &data); |
| 2103 | } | 2215 | } |
| 2104 | 2216 | ||
| 2105 | static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) | 2217 | static int key_notify_policy_flush(struct km_event *c) |
| 2106 | { | 2218 | { |
| 2107 | struct sk_buff *skb_out; | 2219 | struct sk_buff *skb_out; |
| 2108 | struct sadb_msg *hdr_out; | 2220 | struct sadb_msg *hdr; |
| 2109 | 2221 | ||
| 2110 | skb_out = alloc_skb(sizeof(struct sadb_msg) + 16, GFP_KERNEL); | 2222 | skb_out = alloc_skb(sizeof(struct sadb_msg) + 16, GFP_ATOMIC); |
| 2111 | if (!skb_out) | 2223 | if (!skb_out) |
| 2112 | return -ENOBUFS; | 2224 | return -ENOBUFS; |
| 2225 | hdr = (struct sadb_msg *) skb_put(skb_out, sizeof(struct sadb_msg)); | ||
| 2226 | hdr->sadb_msg_seq = c->seq; | ||
| 2227 | hdr->sadb_msg_pid = c->pid; | ||
| 2228 | hdr->sadb_msg_version = PF_KEY_V2; | ||
| 2229 | hdr->sadb_msg_errno = (uint8_t) 0; | ||
| 2230 | hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); | ||
| 2231 | pfkey_broadcast(skb_out, GFP_ATOMIC, BROADCAST_ALL, NULL); | ||
| 2232 | return 0; | ||
| 2113 | 2233 | ||
| 2114 | xfrm_policy_flush(); | 2234 | } |
| 2235 | |||
| 2236 | static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) | ||
| 2237 | { | ||
| 2238 | struct km_event c; | ||
| 2115 | 2239 | ||
| 2116 | hdr_out = (struct sadb_msg *) skb_put(skb_out, sizeof(struct sadb_msg)); | 2240 | xfrm_policy_flush(); |
| 2117 | pfkey_hdr_dup(hdr_out, hdr); | 2241 | c.event = XFRM_MSG_FLUSHPOLICY; |
| 2118 | hdr_out->sadb_msg_errno = (uint8_t) 0; | 2242 | c.pid = hdr->sadb_msg_pid; |
| 2119 | hdr_out->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); | 2243 | c.seq = hdr->sadb_msg_seq; |
| 2120 | pfkey_broadcast(skb_out, GFP_KERNEL, BROADCAST_ALL, NULL); | 2244 | km_policy_notify(NULL, 0, &c); |
| 2121 | 2245 | ||
| 2122 | return 0; | 2246 | return 0; |
| 2123 | } | 2247 | } |
| @@ -2317,11 +2441,23 @@ static void dump_esp_combs(struct sk_buff *skb, struct xfrm_tmpl *t) | |||
| 2317 | } | 2441 | } |
| 2318 | } | 2442 | } |
| 2319 | 2443 | ||
| 2320 | static int pfkey_send_notify(struct xfrm_state *x, int hard) | 2444 | static int key_notify_policy_expire(struct xfrm_policy *xp, struct km_event *c) |
| 2445 | { | ||
| 2446 | return 0; | ||
| 2447 | } | ||
| 2448 | |||
| 2449 | static int key_notify_sa_expire(struct xfrm_state *x, struct km_event *c) | ||
| 2321 | { | 2450 | { |
| 2322 | struct sk_buff *out_skb; | 2451 | struct sk_buff *out_skb; |
| 2323 | struct sadb_msg *out_hdr; | 2452 | struct sadb_msg *out_hdr; |
| 2324 | int hsc = (hard ? 2 : 1); | 2453 | int hard; |
| 2454 | int hsc; | ||
| 2455 | |||
| 2456 | hard = c->data.hard; | ||
| 2457 | if (hard) | ||
| 2458 | hsc = 2; | ||
| 2459 | else | ||
| 2460 | hsc = 1; | ||
| 2325 | 2461 | ||
| 2326 | out_skb = pfkey_xfrm_state2msg(x, 0, hsc); | 2462 | out_skb = pfkey_xfrm_state2msg(x, 0, hsc); |
| 2327 | if (IS_ERR(out_skb)) | 2463 | if (IS_ERR(out_skb)) |
| @@ -2340,6 +2476,44 @@ static int pfkey_send_notify(struct xfrm_state *x, int hard) | |||
| 2340 | return 0; | 2476 | return 0; |
| 2341 | } | 2477 | } |
| 2342 | 2478 | ||
| 2479 | static int pfkey_send_notify(struct xfrm_state *x, struct km_event *c) | ||
| 2480 | { | ||
| 2481 | switch (c->event) { | ||
| 2482 | case XFRM_MSG_EXPIRE: | ||
| 2483 | return key_notify_sa_expire(x, c); | ||
| 2484 | case XFRM_MSG_DELSA: | ||
| 2485 | case XFRM_MSG_NEWSA: | ||
| 2486 | case XFRM_MSG_UPDSA: | ||
| 2487 | return key_notify_sa(x, c); | ||
| 2488 | case XFRM_MSG_FLUSHSA: | ||
| 2489 | return key_notify_sa_flush(c); | ||
| 2490 | default: | ||
| 2491 | printk("pfkey: Unknown SA event %d\n", c->event); | ||
| 2492 | break; | ||
| 2493 | } | ||
| 2494 | |||
| 2495 | return 0; | ||
| 2496 | } | ||
| 2497 | |||
| 2498 | static int pfkey_send_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c) | ||
| 2499 | { | ||
| 2500 | switch (c->event) { | ||
| 2501 | case XFRM_MSG_POLEXPIRE: | ||
| 2502 | return key_notify_policy_expire(xp, c); | ||
| 2503 | case XFRM_MSG_DELPOLICY: | ||
| 2504 | case XFRM_MSG_NEWPOLICY: | ||
| 2505 | case XFRM_MSG_UPDPOLICY: | ||
| 2506 | return key_notify_policy(xp, dir, c); | ||
| 2507 | case XFRM_MSG_FLUSHPOLICY: | ||
| 2508 | return key_notify_policy_flush(c); | ||
| 2509 | default: | ||
| 2510 | printk("pfkey: Unknown policy event %d\n", c->event); | ||
| 2511 | break; | ||
| 2512 | } | ||
| 2513 | |||
| 2514 | return 0; | ||
| 2515 | } | ||
| 2516 | |||
| 2343 | static u32 get_acqseq(void) | 2517 | static u32 get_acqseq(void) |
| 2344 | { | 2518 | { |
| 2345 | u32 res; | 2519 | u32 res; |
| @@ -2856,6 +3030,7 @@ static struct xfrm_mgr pfkeyv2_mgr = | |||
| 2856 | .acquire = pfkey_send_acquire, | 3030 | .acquire = pfkey_send_acquire, |
| 2857 | .compile_policy = pfkey_compile_policy, | 3031 | .compile_policy = pfkey_compile_policy, |
| 2858 | .new_mapping = pfkey_send_new_mapping, | 3032 | .new_mapping = pfkey_send_new_mapping, |
| 3033 | .notify_policy = pfkey_send_policy_notify, | ||
| 2859 | }; | 3034 | }; |
| 2860 | 3035 | ||
| 2861 | static void __exit ipsec_pfkey_exit(void) | 3036 | static void __exit ipsec_pfkey_exit(void) |
