aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJamal Hadi Salim <hadi@cyberus.ca>2005-06-19 01:42:13 -0400
committerDavid S. Miller <davem@davemloft.net>2005-06-19 01:42:13 -0400
commit26b15dad9f1c19d6d4f7b999b07eaa6d98e4b375 (patch)
tree2ca3039488d9df023fb84eaa7c1f52aa8d1ce69c
parent3aa3dfb372576f30835a94409556e3c8681b5756 (diff)
[IPSEC] Add complete xfrm event notification
Heres the final patch. What this patch provides - netlink xfrm events - ability to have events generated by netlink propagated to pfkey and vice versa. - fixes the acquire lets-be-happy-with-one-success issue Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--include/linux/xfrm.h2
-rw-r--r--include/net/xfrm.h29
-rw-r--r--net/key/af_key.c357
-rw-r--r--net/xfrm/xfrm_state.c74
-rw-r--r--net/xfrm/xfrm_user.c272
5 files changed, 616 insertions, 118 deletions
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index fd2ef742a9fd..03bc600516ea 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -257,5 +257,7 @@ struct xfrm_usersa_flush {
257 257
258#define XFRMGRP_ACQUIRE 1 258#define XFRMGRP_ACQUIRE 1
259#define XFRMGRP_EXPIRE 2 259#define XFRMGRP_EXPIRE 2
260#define XFRMGRP_SA 4
261#define XFRMGRP_POLICY 8
260 262
261#endif /* _LINUX_XFRM_H */ 263#endif /* _LINUX_XFRM_H */
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index d675836ba6c3..a159655ebede 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -158,6 +158,27 @@ enum {
158 XFRM_STATE_DEAD 158 XFRM_STATE_DEAD
159}; 159};
160 160
161/* events that could be sent by kernel */
162enum {
163 XFRM_SAP_INVALID,
164 XFRM_SAP_EXPIRED,
165 XFRM_SAP_ADDED,
166 XFRM_SAP_UPDATED,
167 XFRM_SAP_DELETED,
168 XFRM_SAP_FLUSHED,
169 __XFRM_SAP_MAX
170};
171#define XFRM_SAP_MAX (__XFRM_SAP_MAX - 1)
172
173/* callback structure passed from either netlink or pfkey */
174struct km_event
175{
176 u32 data;
177 u32 seq;
178 u32 pid;
179 u32 event;
180};
181
161struct xfrm_type; 182struct xfrm_type;
162struct xfrm_dst; 183struct xfrm_dst;
163struct xfrm_policy_afinfo { 184struct xfrm_policy_afinfo {
@@ -179,6 +200,8 @@ struct xfrm_policy_afinfo {
179 200
180extern int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo); 201extern int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo);
181extern int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo); 202extern int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo);
203extern void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c);
204extern void km_state_notify(struct xfrm_state *x, struct km_event *c);
182 205
183#define XFRM_ACQ_EXPIRES 30 206#define XFRM_ACQ_EXPIRES 30
184 207
@@ -290,11 +313,11 @@ struct xfrm_mgr
290{ 313{
291 struct list_head list; 314 struct list_head list;
292 char *id; 315 char *id;
293 int (*notify)(struct xfrm_state *x, int event); 316 int (*notify)(struct xfrm_state *x, struct km_event *c);
294 int (*acquire)(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *xp, int dir); 317 int (*acquire)(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *xp, int dir);
295 struct xfrm_policy *(*compile_policy)(u16 family, int opt, u8 *data, int len, int *dir); 318 struct xfrm_policy *(*compile_policy)(u16 family, int opt, u8 *data, int len, int *dir);
296 int (*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport); 319 int (*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport);
297 int (*notify_policy)(struct xfrm_policy *x, int dir, int event); 320 int (*notify_policy)(struct xfrm_policy *x, int dir, struct km_event *c);
298}; 321};
299 322
300extern int xfrm_register_km(struct xfrm_mgr *km); 323extern int xfrm_register_km(struct xfrm_mgr *km);
@@ -817,7 +840,7 @@ extern int xfrm_state_add(struct xfrm_state *x);
817extern int xfrm_state_update(struct xfrm_state *x); 840extern int xfrm_state_update(struct xfrm_state *x);
818extern struct xfrm_state *xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family); 841extern struct xfrm_state *xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family);
819extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq); 842extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
820extern void xfrm_state_delete(struct xfrm_state *x); 843extern int xfrm_state_delete(struct xfrm_state *x);
821extern void xfrm_state_flush(u8 proto); 844extern void xfrm_state_flush(u8 proto);
822extern int xfrm_replay_check(struct xfrm_state *x, u32 seq); 845extern int xfrm_replay_check(struct xfrm_state *x, u32 seq);
823extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq); 846extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq);
diff --git a/net/key/af_key.c b/net/key/af_key.c
index ce980aa94ed8..d086c117f5f0 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -1240,13 +1240,85 @@ static int pfkey_acquire(struct sock *sk, struct sk_buff *skb, struct sadb_msg *
1240 return 0; 1240 return 0;
1241} 1241}
1242 1242
1243static inline int event2poltype(int event)
1244{
1245 switch (event) {
1246 case XFRM_SAP_DELETED:
1247 return SADB_X_SPDDELETE;
1248 case XFRM_SAP_ADDED:
1249 return SADB_X_SPDADD;
1250 case XFRM_SAP_UPDATED:
1251 return SADB_X_SPDUPDATE;
1252 case XFRM_SAP_EXPIRED:
1253 // return SADB_X_SPDEXPIRE;
1254 default:
1255 printk("pfkey: Unknown policy event %d\n", event);
1256 break;
1257 }
1258
1259 return 0;
1260}
1261
1262static inline int event2keytype(int event)
1263{
1264 switch (event) {
1265 case XFRM_SAP_DELETED:
1266 return SADB_DELETE;
1267 case XFRM_SAP_ADDED:
1268 return SADB_ADD;
1269 case XFRM_SAP_UPDATED:
1270 return SADB_UPDATE;
1271 case XFRM_SAP_EXPIRED:
1272 return SADB_EXPIRE;
1273 default:
1274 printk("pfkey: Unknown SA event %d\n", event);
1275 break;
1276 }
1277
1278 return 0;
1279}
1280
1281/* ADD/UPD/DEL */
1282static int key_notify_sa(struct xfrm_state *x, struct km_event *c)
1283{
1284 struct sk_buff *skb;
1285 struct sadb_msg *hdr;
1286 int hsc = 3;
1287
1288 if (c->event == XFRM_SAP_DELETED)
1289 hsc = 0;
1290
1291 if (c->event == XFRM_SAP_EXPIRED) {
1292 if (c->data)
1293 hsc = 2;
1294 else
1295 hsc = 1;
1296 }
1297
1298 skb = pfkey_xfrm_state2msg(x, 0, hsc);
1299
1300 if (IS_ERR(skb))
1301 return PTR_ERR(skb);
1302
1303 hdr = (struct sadb_msg *) skb->data;
1304 hdr->sadb_msg_version = PF_KEY_V2;
1305 hdr->sadb_msg_type = event2keytype(c->event);
1306 hdr->sadb_msg_satype = pfkey_proto2satype(x->id.proto);
1307 hdr->sadb_msg_errno = 0;
1308 hdr->sadb_msg_reserved = 0;
1309 hdr->sadb_msg_seq = c->seq;
1310 hdr->sadb_msg_pid = c->pid;
1311
1312 pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL);
1313
1314 return 0;
1315}
1243 1316
1244static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) 1317static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
1245{ 1318{
1246 struct sk_buff *out_skb;
1247 struct sadb_msg *out_hdr;
1248 struct xfrm_state *x; 1319 struct xfrm_state *x;
1249 int err; 1320 int err;
1321 struct km_event c;
1250 1322
1251 xfrm_probe_algs(); 1323 xfrm_probe_algs();
1252 1324
@@ -1254,6 +1326,7 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr,
1254 if (IS_ERR(x)) 1326 if (IS_ERR(x))
1255 return PTR_ERR(x); 1327 return PTR_ERR(x);
1256 1328
1329 xfrm_state_hold(x);
1257 if (hdr->sadb_msg_type == SADB_ADD) 1330 if (hdr->sadb_msg_type == SADB_ADD)
1258 err = xfrm_state_add(x); 1331 err = xfrm_state_add(x);
1259 else 1332 else
@@ -1265,27 +1338,23 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr,
1265 return err; 1338 return err;
1266 } 1339 }
1267 1340
1268 out_skb = pfkey_xfrm_state2msg(x, 0, 3); 1341 if (hdr->sadb_msg_type == SADB_ADD)
1269 if (IS_ERR(out_skb)) 1342 c.event = XFRM_SAP_ADDED;
1270 return PTR_ERR(out_skb); /* XXX Should we return 0 here ? */ 1343 else
1271 1344 c.event = XFRM_SAP_UPDATED;
1272 out_hdr = (struct sadb_msg *) out_skb->data; 1345 c.seq = hdr->sadb_msg_seq;
1273 out_hdr->sadb_msg_version = hdr->sadb_msg_version; 1346 c.pid = hdr->sadb_msg_pid;
1274 out_hdr->sadb_msg_type = hdr->sadb_msg_type; 1347 km_state_notify(x, &c);
1275 out_hdr->sadb_msg_satype = pfkey_proto2satype(x->id.proto); 1348 xfrm_state_put(x);
1276 out_hdr->sadb_msg_errno = 0;
1277 out_hdr->sadb_msg_reserved = 0;
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 1349
1283 return 0; 1350 return err;
1284} 1351}
1285 1352
1286static int pfkey_delete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) 1353static int pfkey_delete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
1287{ 1354{
1288 struct xfrm_state *x; 1355 struct xfrm_state *x;
1356 struct km_event c;
1357 int err;
1289 1358
1290 if (!ext_hdrs[SADB_EXT_SA-1] || 1359 if (!ext_hdrs[SADB_EXT_SA-1] ||
1291 !present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1], 1360 !present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
@@ -1301,13 +1370,19 @@ static int pfkey_delete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
1301 return -EPERM; 1370 return -EPERM;
1302 } 1371 }
1303 1372
1304 xfrm_state_delete(x); 1373 err = xfrm_state_delete(x);
1305 xfrm_state_put(x); 1374 if (err < 0) {
1375 xfrm_state_put(x);
1376 return err;
1377 }
1306 1378
1307 pfkey_broadcast(skb_clone(skb, GFP_KERNEL), GFP_KERNEL, 1379 c.seq = hdr->sadb_msg_seq;
1308 BROADCAST_ALL, sk); 1380 c.pid = hdr->sadb_msg_pid;
1381 c.event = XFRM_SAP_DELETED;
1382 km_state_notify(x, &c);
1383 xfrm_state_put(x);
1309 1384
1310 return 0; 1385 return err;
1311} 1386}
1312 1387
1313static int pfkey_get(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) 1388static int pfkey_get(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
@@ -1445,28 +1520,42 @@ static int pfkey_register(struct sock *sk, struct sk_buff *skb, struct sadb_msg
1445 return 0; 1520 return 0;
1446} 1521}
1447 1522
1523static int key_notify_sa_flush(struct km_event *c)
1524{
1525 struct sk_buff *skb;
1526 struct sadb_msg *hdr;
1527
1528 skb = alloc_skb(sizeof(struct sadb_msg) + 16, GFP_ATOMIC);
1529 if (!skb)
1530 return -ENOBUFS;
1531 hdr = (struct sadb_msg *) skb_put(skb, sizeof(struct sadb_msg));
1532 hdr->sadb_msg_satype = pfkey_proto2satype(c->data);
1533 hdr->sadb_msg_seq = c->seq;
1534 hdr->sadb_msg_pid = c->pid;
1535 hdr->sadb_msg_version = PF_KEY_V2;
1536 hdr->sadb_msg_errno = (uint8_t) 0;
1537 hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
1538
1539 pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL);
1540
1541 return 0;
1542}
1543
1448static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) 1544static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
1449{ 1545{
1450 unsigned proto; 1546 unsigned proto;
1451 struct sk_buff *skb_out; 1547 struct km_event c;
1452 struct sadb_msg *hdr_out;
1453 1548
1454 proto = pfkey_satype2proto(hdr->sadb_msg_satype); 1549 proto = pfkey_satype2proto(hdr->sadb_msg_satype);
1455 if (proto == 0) 1550 if (proto == 0)
1456 return -EINVAL; 1551 return -EINVAL;
1457 1552
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); 1553 xfrm_state_flush(proto);
1463 1554 c.data = proto;
1464 hdr_out = (struct sadb_msg *) skb_put(skb_out, sizeof(struct sadb_msg)); 1555 c.seq = hdr->sadb_msg_seq;
1465 pfkey_hdr_dup(hdr_out, hdr); 1556 c.pid = hdr->sadb_msg_pid;
1466 hdr_out->sadb_msg_errno = (uint8_t) 0; 1557 c.event = XFRM_SAP_FLUSHED;
1467 hdr_out->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); 1558 km_state_notify(NULL, &c);
1468
1469 pfkey_broadcast(skb_out, GFP_KERNEL, BROADCAST_ALL, NULL);
1470 1559
1471 return 0; 1560 return 0;
1472} 1561}
@@ -1859,6 +1948,35 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i
1859 hdr->sadb_msg_reserved = atomic_read(&xp->refcnt); 1948 hdr->sadb_msg_reserved = atomic_read(&xp->refcnt);
1860} 1949}
1861 1950
1951static int key_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c)
1952{
1953 struct sk_buff *out_skb;
1954 struct sadb_msg *out_hdr;
1955 int err;
1956
1957 out_skb = pfkey_xfrm_policy2msg_prep(xp);
1958 if (IS_ERR(out_skb)) {
1959 err = PTR_ERR(out_skb);
1960 goto out;
1961 }
1962 pfkey_xfrm_policy2msg(out_skb, xp, dir);
1963
1964 out_hdr = (struct sadb_msg *) out_skb->data;
1965 out_hdr->sadb_msg_version = PF_KEY_V2;
1966
1967 if (c->data && c->event == XFRM_SAP_DELETED)
1968 out_hdr->sadb_msg_type = SADB_X_SPDDELETE2;
1969 else
1970 out_hdr->sadb_msg_type = event2poltype(c->event);
1971 out_hdr->sadb_msg_errno = 0;
1972 out_hdr->sadb_msg_seq = c->seq;
1973 out_hdr->sadb_msg_pid = c->pid;
1974 pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, NULL);
1975out:
1976 return 0;
1977
1978}
1979
1862static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) 1980static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
1863{ 1981{
1864 int err; 1982 int err;
@@ -1866,8 +1984,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
1866 struct sadb_address *sa; 1984 struct sadb_address *sa;
1867 struct sadb_x_policy *pol; 1985 struct sadb_x_policy *pol;
1868 struct xfrm_policy *xp; 1986 struct xfrm_policy *xp;
1869 struct sk_buff *out_skb; 1987 struct km_event c;
1870 struct sadb_msg *out_hdr;
1871 1988
1872 if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1], 1989 if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
1873 ext_hdrs[SADB_EXT_ADDRESS_DST-1]) || 1990 ext_hdrs[SADB_EXT_ADDRESS_DST-1]) ||
@@ -1935,31 +2052,23 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
1935 (err = parse_ipsecrequests(xp, pol)) < 0) 2052 (err = parse_ipsecrequests(xp, pol)) < 0)
1936 goto out; 2053 goto out;
1937 2054
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, 2055 err = xfrm_policy_insert(pol->sadb_x_policy_dir-1, xp,
1945 hdr->sadb_msg_type != SADB_X_SPDUPDATE); 2056 hdr->sadb_msg_type != SADB_X_SPDUPDATE);
1946 if (err) { 2057 if (err) {
1947 kfree_skb(out_skb); 2058 kfree(xp);
1948 goto out; 2059 return err;
1949 } 2060 }
1950 2061
1951 pfkey_xfrm_policy2msg(out_skb, xp, pol->sadb_x_policy_dir-1); 2062 if (hdr->sadb_msg_type == SADB_X_SPDUPDATE)
2063 c.event = XFRM_SAP_UPDATED;
2064 else
2065 c.event = XFRM_SAP_ADDED;
1952 2066
1953 xfrm_pol_put(xp); 2067 c.seq = hdr->sadb_msg_seq;
2068 c.pid = hdr->sadb_msg_pid;
1954 2069
1955 out_hdr = (struct sadb_msg *) out_skb->data; 2070 km_policy_notify(xp, pol->sadb_x_policy_dir-1, &c);
1956 out_hdr->sadb_msg_version = hdr->sadb_msg_version; 2071 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; 2072 return 0;
1964 2073
1965out: 2074out:
@@ -1973,9 +2082,8 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
1973 struct sadb_address *sa; 2082 struct sadb_address *sa;
1974 struct sadb_x_policy *pol; 2083 struct sadb_x_policy *pol;
1975 struct xfrm_policy *xp; 2084 struct xfrm_policy *xp;
1976 struct sk_buff *out_skb;
1977 struct sadb_msg *out_hdr;
1978 struct xfrm_selector sel; 2085 struct xfrm_selector sel;
2086 struct km_event c;
1979 2087
1980 if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1], 2088 if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
1981 ext_hdrs[SADB_EXT_ADDRESS_DST-1]) || 2089 ext_hdrs[SADB_EXT_ADDRESS_DST-1]) ||
@@ -2010,25 +2118,40 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
2010 2118
2011 err = 0; 2119 err = 0;
2012 2120
2121 c.seq = hdr->sadb_msg_seq;
2122 c.pid = hdr->sadb_msg_pid;
2123 c.event = XFRM_SAP_DELETED;
2124 km_policy_notify(xp, pol->sadb_x_policy_dir-1, &c);
2125
2126 xfrm_pol_put(xp);
2127 return err;
2128}
2129
2130static int key_pol_get_resp(struct sock *sk, struct xfrm_policy *xp, struct sadb_msg *hdr, int dir)
2131{
2132 int err;
2133 struct sk_buff *out_skb;
2134 struct sadb_msg *out_hdr;
2135 err = 0;
2136
2013 out_skb = pfkey_xfrm_policy2msg_prep(xp); 2137 out_skb = pfkey_xfrm_policy2msg_prep(xp);
2014 if (IS_ERR(out_skb)) { 2138 if (IS_ERR(out_skb)) {
2015 err = PTR_ERR(out_skb); 2139 err = PTR_ERR(out_skb);
2016 goto out; 2140 goto out;
2017 } 2141 }
2018 pfkey_xfrm_policy2msg(out_skb, xp, pol->sadb_x_policy_dir-1); 2142 pfkey_xfrm_policy2msg(out_skb, xp, dir);
2019 2143
2020 out_hdr = (struct sadb_msg *) out_skb->data; 2144 out_hdr = (struct sadb_msg *) out_skb->data;
2021 out_hdr->sadb_msg_version = hdr->sadb_msg_version; 2145 out_hdr->sadb_msg_version = hdr->sadb_msg_version;
2022 out_hdr->sadb_msg_type = SADB_X_SPDDELETE; 2146 out_hdr->sadb_msg_type = hdr->sadb_msg_type;
2023 out_hdr->sadb_msg_satype = 0; 2147 out_hdr->sadb_msg_satype = 0;
2024 out_hdr->sadb_msg_errno = 0; 2148 out_hdr->sadb_msg_errno = 0;
2025 out_hdr->sadb_msg_seq = hdr->sadb_msg_seq; 2149 out_hdr->sadb_msg_seq = hdr->sadb_msg_seq;
2026 out_hdr->sadb_msg_pid = hdr->sadb_msg_pid; 2150 out_hdr->sadb_msg_pid = hdr->sadb_msg_pid;
2027 pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, sk); 2151 pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, sk);
2028 err = 0; 2152 err = 0;
2029 2153
2030out: 2154out:
2031 xfrm_pol_put(xp);
2032 return err; 2155 return err;
2033} 2156}
2034 2157
@@ -2037,8 +2160,7 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
2037 int err; 2160 int err;
2038 struct sadb_x_policy *pol; 2161 struct sadb_x_policy *pol;
2039 struct xfrm_policy *xp; 2162 struct xfrm_policy *xp;
2040 struct sk_buff *out_skb; 2163 struct km_event c;
2041 struct sadb_msg *out_hdr;
2042 2164
2043 if ((pol = ext_hdrs[SADB_X_EXT_POLICY-1]) == NULL) 2165 if ((pol = ext_hdrs[SADB_X_EXT_POLICY-1]) == NULL)
2044 return -EINVAL; 2166 return -EINVAL;
@@ -2050,24 +2172,16 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
2050 2172
2051 err = 0; 2173 err = 0;
2052 2174
2053 out_skb = pfkey_xfrm_policy2msg_prep(xp); 2175 c.seq = hdr->sadb_msg_seq;
2054 if (IS_ERR(out_skb)) { 2176 c.pid = hdr->sadb_msg_pid;
2055 err = PTR_ERR(out_skb); 2177 if (hdr->sadb_msg_type == SADB_X_SPDDELETE2) {
2056 goto out; 2178 c.data = 1; // to signal pfkey of SADB_X_SPDDELETE2
2179 c.event = XFRM_SAP_DELETED;
2180 km_policy_notify(xp, pol->sadb_x_policy_dir-1, &c);
2181 } else {
2182 err = key_pol_get_resp(sk, xp, hdr, pol->sadb_x_policy_dir-1);
2057 } 2183 }
2058 pfkey_xfrm_policy2msg(out_skb, xp, pol->sadb_x_policy_dir-1);
2059 2184
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
2070out:
2071 xfrm_pol_put(xp); 2185 xfrm_pol_put(xp);
2072 return err; 2186 return err;
2073} 2187}
@@ -2102,22 +2216,34 @@ static int pfkey_spddump(struct sock *sk, struct sk_buff *skb, struct sadb_msg *
2102 return xfrm_policy_walk(dump_sp, &data); 2216 return xfrm_policy_walk(dump_sp, &data);
2103} 2217}
2104 2218
2105static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs) 2219static int key_notify_policy_flush(struct km_event *c)
2106{ 2220{
2107 struct sk_buff *skb_out; 2221 struct sk_buff *skb_out;
2108 struct sadb_msg *hdr_out; 2222 struct sadb_msg *hdr;
2109 2223
2110 skb_out = alloc_skb(sizeof(struct sadb_msg) + 16, GFP_KERNEL); 2224 skb_out = alloc_skb(sizeof(struct sadb_msg) + 16, GFP_ATOMIC);
2111 if (!skb_out) 2225 if (!skb_out)
2112 return -ENOBUFS; 2226 return -ENOBUFS;
2227 hdr = (struct sadb_msg *) skb_put(skb_out, sizeof(struct sadb_msg));
2228 hdr->sadb_msg_seq = c->seq;
2229 hdr->sadb_msg_pid = c->pid;
2230 hdr->sadb_msg_version = PF_KEY_V2;
2231 hdr->sadb_msg_errno = (uint8_t) 0;
2232 hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
2233 pfkey_broadcast(skb_out, GFP_ATOMIC, BROADCAST_ALL, NULL);
2234 return 0;
2113 2235
2114 xfrm_policy_flush(); 2236}
2237
2238static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
2239{
2240 struct km_event c;
2115 2241
2116 hdr_out = (struct sadb_msg *) skb_put(skb_out, sizeof(struct sadb_msg)); 2242 xfrm_policy_flush();
2117 pfkey_hdr_dup(hdr_out, hdr); 2243 c.event = XFRM_SAP_FLUSHED;
2118 hdr_out->sadb_msg_errno = (uint8_t) 0; 2244 c.pid = hdr->sadb_msg_pid;
2119 hdr_out->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); 2245 c.seq = hdr->sadb_msg_seq;
2120 pfkey_broadcast(skb_out, GFP_KERNEL, BROADCAST_ALL, NULL); 2246 km_policy_notify(NULL, 0, &c);
2121 2247
2122 return 0; 2248 return 0;
2123} 2249}
@@ -2317,11 +2443,23 @@ static void dump_esp_combs(struct sk_buff *skb, struct xfrm_tmpl *t)
2317 } 2443 }
2318} 2444}
2319 2445
2320static int pfkey_send_notify(struct xfrm_state *x, int hard) 2446static int key_notify_policy_expire(struct xfrm_policy *xp, struct km_event *c)
2447{
2448 return 0;
2449}
2450
2451static int key_notify_sa_expire(struct xfrm_state *x, struct km_event *c)
2321{ 2452{
2322 struct sk_buff *out_skb; 2453 struct sk_buff *out_skb;
2323 struct sadb_msg *out_hdr; 2454 struct sadb_msg *out_hdr;
2324 int hsc = (hard ? 2 : 1); 2455 int hard;
2456 int hsc;
2457
2458 hard = c->data;
2459 if (hard)
2460 hsc = 2;
2461 else
2462 hsc = 1;
2325 2463
2326 out_skb = pfkey_xfrm_state2msg(x, 0, hsc); 2464 out_skb = pfkey_xfrm_state2msg(x, 0, hsc);
2327 if (IS_ERR(out_skb)) 2465 if (IS_ERR(out_skb))
@@ -2340,6 +2478,44 @@ static int pfkey_send_notify(struct xfrm_state *x, int hard)
2340 return 0; 2478 return 0;
2341} 2479}
2342 2480
2481static int pfkey_send_notify(struct xfrm_state *x, struct km_event *c)
2482{
2483 switch (c->event) {
2484 case XFRM_SAP_EXPIRED:
2485 return key_notify_sa_expire(x, c);
2486 case XFRM_SAP_DELETED:
2487 case XFRM_SAP_ADDED:
2488 case XFRM_SAP_UPDATED:
2489 return key_notify_sa(x, c);
2490 case XFRM_SAP_FLUSHED:
2491 return key_notify_sa_flush(c);
2492 default:
2493 printk("pfkey: Unknown SA event %d\n", c->event);
2494 break;
2495 }
2496
2497 return 0;
2498}
2499
2500static int pfkey_send_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)
2501{
2502 switch (c->event) {
2503 case XFRM_SAP_EXPIRED:
2504 return key_notify_policy_expire(xp, c);
2505 case XFRM_SAP_DELETED:
2506 case XFRM_SAP_ADDED:
2507 case XFRM_SAP_UPDATED:
2508 return key_notify_policy(xp, dir, c);
2509 case XFRM_SAP_FLUSHED:
2510 return key_notify_policy_flush(c);
2511 default:
2512 printk("pfkey: Unknown policy event %d\n", c->event);
2513 break;
2514 }
2515
2516 return 0;
2517}
2518
2343static u32 get_acqseq(void) 2519static u32 get_acqseq(void)
2344{ 2520{
2345 u32 res; 2521 u32 res;
@@ -2856,6 +3032,7 @@ static struct xfrm_mgr pfkeyv2_mgr =
2856 .acquire = pfkey_send_acquire, 3032 .acquire = pfkey_send_acquire,
2857 .compile_policy = pfkey_compile_policy, 3033 .compile_policy = pfkey_compile_policy,
2858 .new_mapping = pfkey_send_new_mapping, 3034 .new_mapping = pfkey_send_new_mapping,
3035 .notify_policy = pfkey_send_policy_notify,
2859}; 3036};
2860 3037
2861static void __exit ipsec_pfkey_exit(void) 3038static void __exit ipsec_pfkey_exit(void)
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index d11747c2a763..918a94c552a5 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -50,7 +50,7 @@ static DEFINE_SPINLOCK(xfrm_state_gc_lock);
50 50
51static int xfrm_state_gc_flush_bundles; 51static int xfrm_state_gc_flush_bundles;
52 52
53static void __xfrm_state_delete(struct xfrm_state *x); 53static int __xfrm_state_delete(struct xfrm_state *x);
54 54
55static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family); 55static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family);
56static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo); 56static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
@@ -215,8 +215,10 @@ void __xfrm_state_destroy(struct xfrm_state *x)
215} 215}
216EXPORT_SYMBOL(__xfrm_state_destroy); 216EXPORT_SYMBOL(__xfrm_state_destroy);
217 217
218static void __xfrm_state_delete(struct xfrm_state *x) 218static int __xfrm_state_delete(struct xfrm_state *x)
219{ 219{
220 int err = -ESRCH;
221
220 if (x->km.state != XFRM_STATE_DEAD) { 222 if (x->km.state != XFRM_STATE_DEAD) {
221 x->km.state = XFRM_STATE_DEAD; 223 x->km.state = XFRM_STATE_DEAD;
222 spin_lock(&xfrm_state_lock); 224 spin_lock(&xfrm_state_lock);
@@ -245,14 +247,21 @@ static void __xfrm_state_delete(struct xfrm_state *x)
245 * is what we are dropping here. 247 * is what we are dropping here.
246 */ 248 */
247 atomic_dec(&x->refcnt); 249 atomic_dec(&x->refcnt);
250 err = 0;
248 } 251 }
252
253 return err;
249} 254}
250 255
251void xfrm_state_delete(struct xfrm_state *x) 256int xfrm_state_delete(struct xfrm_state *x)
252{ 257{
258 int err;
259
253 spin_lock_bh(&x->lock); 260 spin_lock_bh(&x->lock);
254 __xfrm_state_delete(x); 261 err = __xfrm_state_delete(x);
255 spin_unlock_bh(&x->lock); 262 spin_unlock_bh(&x->lock);
263
264 return err;
256} 265}
257EXPORT_SYMBOL(xfrm_state_delete); 266EXPORT_SYMBOL(xfrm_state_delete);
258 267
@@ -796,34 +805,60 @@ EXPORT_SYMBOL(xfrm_replay_advance);
796static struct list_head xfrm_km_list = LIST_HEAD_INIT(xfrm_km_list); 805static struct list_head xfrm_km_list = LIST_HEAD_INIT(xfrm_km_list);
797static DEFINE_RWLOCK(xfrm_km_lock); 806static DEFINE_RWLOCK(xfrm_km_lock);
798 807
799static void km_state_expired(struct xfrm_state *x, int hard) 808void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)
800{ 809{
801 struct xfrm_mgr *km; 810 struct xfrm_mgr *km;
802 811
803 if (hard) 812 read_lock(&xfrm_km_lock);
804 x->km.state = XFRM_STATE_EXPIRED; 813 list_for_each_entry(km, &xfrm_km_list, list)
805 else 814 if (km->notify_policy)
806 x->km.dying = 1; 815 km->notify_policy(xp, dir, c);
816 read_unlock(&xfrm_km_lock);
817}
807 818
819void km_state_notify(struct xfrm_state *x, struct km_event *c)
820{
821 struct xfrm_mgr *km;
808 read_lock(&xfrm_km_lock); 822 read_lock(&xfrm_km_lock);
809 list_for_each_entry(km, &xfrm_km_list, list) 823 list_for_each_entry(km, &xfrm_km_list, list)
810 km->notify(x, hard); 824 if (km->notify)
825 km->notify(x, c);
811 read_unlock(&xfrm_km_lock); 826 read_unlock(&xfrm_km_lock);
827}
828
829EXPORT_SYMBOL(km_policy_notify);
830EXPORT_SYMBOL(km_state_notify);
831
832static void km_state_expired(struct xfrm_state *x, int hard)
833{
834 struct km_event c;
835
836 if (hard)
837 x->km.state = XFRM_STATE_EXPIRED;
838 else
839 x->km.dying = 1;
840 c.data = hard;
841 c.event = XFRM_SAP_EXPIRED;
842 km_state_notify(x, &c);
812 843
813 if (hard) 844 if (hard)
814 wake_up(&km_waitq); 845 wake_up(&km_waitq);
815} 846}
816 847
848/*
849 * We send to all registered managers regardless of failure
850 * We are happy with one success
851*/
817static int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol) 852static int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol)
818{ 853{
819 int err = -EINVAL; 854 int err = -EINVAL, acqret;
820 struct xfrm_mgr *km; 855 struct xfrm_mgr *km;
821 856
822 read_lock(&xfrm_km_lock); 857 read_lock(&xfrm_km_lock);
823 list_for_each_entry(km, &xfrm_km_list, list) { 858 list_for_each_entry(km, &xfrm_km_list, list) {
824 err = km->acquire(x, t, pol, XFRM_POLICY_OUT); 859 acqret = km->acquire(x, t, pol, XFRM_POLICY_OUT);
825 if (!err) 860 if (!acqret)
826 break; 861 err = acqret;
827 } 862 }
828 read_unlock(&xfrm_km_lock); 863 read_unlock(&xfrm_km_lock);
829 return err; 864 return err;
@@ -848,13 +883,12 @@ EXPORT_SYMBOL(km_new_mapping);
848 883
849void km_policy_expired(struct xfrm_policy *pol, int dir, int hard) 884void km_policy_expired(struct xfrm_policy *pol, int dir, int hard)
850{ 885{
851 struct xfrm_mgr *km; 886 struct km_event c;
852 887
853 read_lock(&xfrm_km_lock); 888 c.data = hard;
854 list_for_each_entry(km, &xfrm_km_list, list) 889 c.data = hard;
855 if (km->notify_policy) 890 c.event = XFRM_SAP_EXPIRED;
856 km->notify_policy(pol, dir, hard); 891 km_policy_notify(pol, dir, &c);
857 read_unlock(&xfrm_km_lock);
858 892
859 if (hard) 893 if (hard)
860 wake_up(&km_waitq); 894 wake_up(&km_waitq);
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 97509011c274..bd8e6882c083 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -277,6 +277,7 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
277 struct xfrm_usersa_info *p = NLMSG_DATA(nlh); 277 struct xfrm_usersa_info *p = NLMSG_DATA(nlh);
278 struct xfrm_state *x; 278 struct xfrm_state *x;
279 int err; 279 int err;
280 struct km_event c;
280 281
281 err = verify_newsa_info(p, (struct rtattr **) xfrma); 282 err = verify_newsa_info(p, (struct rtattr **) xfrma);
282 if (err) 283 if (err)
@@ -286,6 +287,7 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
286 if (!x) 287 if (!x)
287 return err; 288 return err;
288 289
290 xfrm_state_hold(x);
289 if (nlh->nlmsg_type == XFRM_MSG_NEWSA) 291 if (nlh->nlmsg_type == XFRM_MSG_NEWSA)
290 err = xfrm_state_add(x); 292 err = xfrm_state_add(x);
291 else 293 else
@@ -294,14 +296,27 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
294 if (err < 0) { 296 if (err < 0) {
295 x->km.state = XFRM_STATE_DEAD; 297 x->km.state = XFRM_STATE_DEAD;
296 xfrm_state_put(x); 298 xfrm_state_put(x);
299 return err;
297 } 300 }
298 301
302 c.seq = nlh->nlmsg_seq;
303 c.pid = nlh->nlmsg_pid;
304 if (nlh->nlmsg_type == XFRM_MSG_NEWSA)
305 c.event = XFRM_SAP_ADDED;
306 else
307 c.event = XFRM_SAP_UPDATED;
308
309 km_state_notify(x, &c);
310 xfrm_state_put(x);
311
299 return err; 312 return err;
300} 313}
301 314
302static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) 315static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
303{ 316{
304 struct xfrm_state *x; 317 struct xfrm_state *x;
318 int err;
319 struct km_event c;
305 struct xfrm_usersa_id *p = NLMSG_DATA(nlh); 320 struct xfrm_usersa_id *p = NLMSG_DATA(nlh);
306 321
307 x = xfrm_state_lookup(&p->daddr, p->spi, p->proto, p->family); 322 x = xfrm_state_lookup(&p->daddr, p->spi, p->proto, p->family);
@@ -313,10 +328,19 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
313 return -EPERM; 328 return -EPERM;
314 } 329 }
315 330
316 xfrm_state_delete(x); 331 err = xfrm_state_delete(x);
332 if (err < 0) {
333 xfrm_state_put(x);
334 return err;
335 }
336
337 c.seq = nlh->nlmsg_seq;
338 c.pid = nlh->nlmsg_pid;
339 c.event = XFRM_SAP_DELETED;
340 km_state_notify(x, &c);
317 xfrm_state_put(x); 341 xfrm_state_put(x);
318 342
319 return 0; 343 return err;
320} 344}
321 345
322static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p) 346static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p)
@@ -681,6 +705,7 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
681{ 705{
682 struct xfrm_userpolicy_info *p = NLMSG_DATA(nlh); 706 struct xfrm_userpolicy_info *p = NLMSG_DATA(nlh);
683 struct xfrm_policy *xp; 707 struct xfrm_policy *xp;
708 struct km_event c;
684 int err; 709 int err;
685 int excl; 710 int excl;
686 711
@@ -692,6 +717,10 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
692 if (!xp) 717 if (!xp)
693 return err; 718 return err;
694 719
720 /* shouldnt excl be based on nlh flags??
721 * Aha! this is anti-netlink really i.e more pfkey derived
722 * in netlink excl is a flag and you wouldnt need
723 * a type XFRM_MSG_UPDPOLICY - JHS */
695 excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY; 724 excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY;
696 err = xfrm_policy_insert(p->dir, xp, excl); 725 err = xfrm_policy_insert(p->dir, xp, excl);
697 if (err) { 726 if (err) {
@@ -699,6 +728,15 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
699 return err; 728 return err;
700 } 729 }
701 730
731 if (!excl)
732 c.event = XFRM_SAP_UPDATED;
733 else
734 c.event = XFRM_SAP_ADDED;
735
736 c.seq = nlh->nlmsg_seq;
737 c.pid = nlh->nlmsg_pid;
738 km_policy_notify(xp, p->dir, &c);
739
702 xfrm_pol_put(xp); 740 xfrm_pol_put(xp);
703 741
704 return 0; 742 return 0;
@@ -816,6 +854,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
816 struct xfrm_policy *xp; 854 struct xfrm_policy *xp;
817 struct xfrm_userpolicy_id *p; 855 struct xfrm_userpolicy_id *p;
818 int err; 856 int err;
857 struct km_event c;
819 int delete; 858 int delete;
820 859
821 p = NLMSG_DATA(nlh); 860 p = NLMSG_DATA(nlh);
@@ -843,6 +882,11 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
843 NETLINK_CB(skb).pid, 882 NETLINK_CB(skb).pid,
844 MSG_DONTWAIT); 883 MSG_DONTWAIT);
845 } 884 }
885 } else {
886 c.event = XFRM_SAP_DELETED;
887 c.seq = nlh->nlmsg_seq;
888 c.pid = nlh->nlmsg_pid;
889 km_policy_notify(xp, p->dir, &c);
846 } 890 }
847 891
848 xfrm_pol_put(xp); 892 xfrm_pol_put(xp);
@@ -852,15 +896,28 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
852 896
853static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) 897static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
854{ 898{
899 struct km_event c;
855 struct xfrm_usersa_flush *p = NLMSG_DATA(nlh); 900 struct xfrm_usersa_flush *p = NLMSG_DATA(nlh);
856 901
857 xfrm_state_flush(p->proto); 902 xfrm_state_flush(p->proto);
903 c.data = p->proto;
904 c.event = XFRM_SAP_FLUSHED;
905 c.seq = nlh->nlmsg_seq;
906 c.pid = nlh->nlmsg_pid;
907 km_state_notify(NULL, &c);
908
858 return 0; 909 return 0;
859} 910}
860 911
861static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) 912static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
862{ 913{
914 struct km_event c;
915
863 xfrm_policy_flush(); 916 xfrm_policy_flush();
917 c.event = XFRM_SAP_FLUSHED;
918 c.seq = nlh->nlmsg_seq;
919 c.pid = nlh->nlmsg_pid;
920 km_policy_notify(NULL, 0, &c);
864 return 0; 921 return 0;
865} 922}
866 923
@@ -1069,10 +1126,12 @@ nlmsg_failure:
1069 return -1; 1126 return -1;
1070} 1127}
1071 1128
1072static int xfrm_send_state_notify(struct xfrm_state *x, int hard) 1129static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c)
1073{ 1130{
1074 struct sk_buff *skb; 1131 struct sk_buff *skb;
1132 int hard = c ->data;
1075 1133
1134 /* fix to do alloc using NLM macros */
1076 skb = alloc_skb(sizeof(struct xfrm_user_expire) + 16, GFP_ATOMIC); 1135 skb = alloc_skb(sizeof(struct xfrm_user_expire) + 16, GFP_ATOMIC);
1077 if (skb == NULL) 1136 if (skb == NULL)
1078 return -ENOMEM; 1137 return -ENOMEM;
@@ -1085,6 +1144,122 @@ static int xfrm_send_state_notify(struct xfrm_state *x, int hard)
1085 return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_EXPIRE, GFP_ATOMIC); 1144 return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_EXPIRE, GFP_ATOMIC);
1086} 1145}
1087 1146
1147static int xfrm_notify_sa_flush(struct km_event *c)
1148{
1149 struct xfrm_usersa_flush *p;
1150 struct nlmsghdr *nlh;
1151 struct sk_buff *skb;
1152 unsigned char *b;
1153 int len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_flush));
1154
1155 skb = alloc_skb(len, GFP_ATOMIC);
1156 if (skb == NULL)
1157 return -ENOMEM;
1158 b = skb->tail;
1159
1160 nlh = NLMSG_PUT(skb, c->pid, c->seq,
1161 XFRM_MSG_FLUSHSA, sizeof(*p));
1162 nlh->nlmsg_flags = 0;
1163
1164 p = NLMSG_DATA(nlh);
1165 p->proto = c->data;
1166
1167 nlh->nlmsg_len = skb->tail - b;
1168
1169 return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_SA, GFP_ATOMIC);
1170
1171nlmsg_failure:
1172 kfree_skb(skb);
1173 return -1;
1174}
1175
1176static int inline xfrm_sa_len(struct xfrm_state *x)
1177{
1178 int l = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));
1179 if (x->aalg)
1180 l += RTA_SPACE(sizeof(*x->aalg) + (x->aalg->alg_key_len+7)/8);
1181 if (x->ealg)
1182 l += RTA_SPACE(sizeof(*x->ealg) + (x->ealg->alg_key_len+7)/8);
1183 if (x->calg)
1184 l += RTA_SPACE(sizeof(*x->calg));
1185 if (x->encap)
1186 l += RTA_SPACE(sizeof(*x->encap));
1187
1188 return l;
1189}
1190
1191static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c)
1192{
1193 struct xfrm_usersa_info *p;
1194 struct nlmsghdr *nlh;
1195 struct sk_buff *skb;
1196 u32 nlt;
1197 unsigned char *b;
1198 int len = xfrm_sa_len(x);
1199
1200 skb = alloc_skb(len, GFP_ATOMIC);
1201 if (skb == NULL)
1202 return -ENOMEM;
1203 b = skb->tail;
1204
1205 if (c->event == XFRM_SAP_ADDED)
1206 nlt = XFRM_MSG_NEWSA;
1207 else if (c->event == XFRM_SAP_UPDATED)
1208 nlt = XFRM_MSG_UPDSA;
1209 else if (c->event == XFRM_SAP_DELETED)
1210 nlt = XFRM_MSG_DELSA;
1211 else
1212 goto nlmsg_failure;
1213
1214 nlh = NLMSG_PUT(skb, c->pid, c->seq, nlt, sizeof(*p));
1215 nlh->nlmsg_flags = 0;
1216
1217 p = NLMSG_DATA(nlh);
1218 copy_to_user_state(x, p);
1219
1220 if (x->aalg)
1221 RTA_PUT(skb, XFRMA_ALG_AUTH,
1222 sizeof(*(x->aalg))+(x->aalg->alg_key_len+7)/8, x->aalg);
1223 if (x->ealg)
1224 RTA_PUT(skb, XFRMA_ALG_CRYPT,
1225 sizeof(*(x->ealg))+(x->ealg->alg_key_len+7)/8, x->ealg);
1226 if (x->calg)
1227 RTA_PUT(skb, XFRMA_ALG_COMP, sizeof(*(x->calg)), x->calg);
1228
1229 if (x->encap)
1230 RTA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap);
1231
1232 nlh->nlmsg_len = skb->tail - b;
1233
1234 return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_SA, GFP_ATOMIC);
1235
1236nlmsg_failure:
1237rtattr_failure:
1238 kfree_skb(skb);
1239 return -1;
1240}
1241
1242static int xfrm_send_state_notify(struct xfrm_state *x, struct km_event *c)
1243{
1244
1245 switch (c->event) {
1246 case XFRM_SAP_EXPIRED:
1247 return xfrm_exp_state_notify(x, c);
1248 case XFRM_SAP_DELETED:
1249 case XFRM_SAP_UPDATED:
1250 case XFRM_SAP_ADDED:
1251 return xfrm_notify_sa(x, c);
1252 case XFRM_SAP_FLUSHED:
1253 return xfrm_notify_sa_flush(c);
1254 default:
1255 printk("xfrm_user: Unknown SA event %d\n", c->event);
1256 break;
1257 }
1258
1259 return 0;
1260
1261}
1262
1088static int build_acquire(struct sk_buff *skb, struct xfrm_state *x, 1263static int build_acquire(struct sk_buff *skb, struct xfrm_state *x,
1089 struct xfrm_tmpl *xt, struct xfrm_policy *xp, 1264 struct xfrm_tmpl *xt, struct xfrm_policy *xp,
1090 int dir) 1265 int dir)
@@ -1218,7 +1393,7 @@ nlmsg_failure:
1218 return -1; 1393 return -1;
1219} 1394}
1220 1395
1221static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, int hard) 1396static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)
1222{ 1397{
1223 struct sk_buff *skb; 1398 struct sk_buff *skb;
1224 size_t len; 1399 size_t len;
@@ -1229,7 +1404,7 @@ static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, int hard)
1229 if (skb == NULL) 1404 if (skb == NULL)
1230 return -ENOMEM; 1405 return -ENOMEM;
1231 1406
1232 if (build_polexpire(skb, xp, dir, hard) < 0) 1407 if (build_polexpire(skb, xp, dir, c->data) < 0)
1233 BUG(); 1408 BUG();
1234 1409
1235 NETLINK_CB(skb).dst_groups = XFRMGRP_EXPIRE; 1410 NETLINK_CB(skb).dst_groups = XFRMGRP_EXPIRE;
@@ -1237,6 +1412,93 @@ static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, int hard)
1237 return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_EXPIRE, GFP_ATOMIC); 1412 return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_EXPIRE, GFP_ATOMIC);
1238} 1413}
1239 1414
1415static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c)
1416{
1417 struct xfrm_userpolicy_info *p;
1418 struct nlmsghdr *nlh;
1419 struct sk_buff *skb;
1420 u32 nlt = 0 ;
1421 unsigned char *b;
1422 int len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr);
1423 len += NLMSG_SPACE(sizeof(struct xfrm_userpolicy_info));
1424
1425 skb = alloc_skb(len, GFP_ATOMIC);
1426 if (skb == NULL)
1427 return -ENOMEM;
1428 b = skb->tail;
1429
1430 if (c->event == XFRM_SAP_ADDED)
1431 nlt = XFRM_MSG_NEWPOLICY;
1432 else if (c->event == XFRM_SAP_UPDATED)
1433 nlt = XFRM_MSG_UPDPOLICY;
1434 else if (c->event == XFRM_SAP_DELETED)
1435 nlt = XFRM_MSG_DELPOLICY;
1436 else
1437 goto nlmsg_failure;
1438
1439 nlh = NLMSG_PUT(skb, c->pid, c->seq, nlt, sizeof(*p));
1440
1441 p = NLMSG_DATA(nlh);
1442
1443 nlh->nlmsg_flags = 0;
1444
1445 copy_to_user_policy(xp, p, dir);
1446 if (copy_to_user_tmpl(xp, skb) < 0)
1447 goto nlmsg_failure;
1448
1449 nlh->nlmsg_len = skb->tail - b;
1450
1451 return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_POLICY, GFP_ATOMIC);
1452
1453nlmsg_failure:
1454 kfree_skb(skb);
1455 return -1;
1456}
1457
1458static int xfrm_notify_policy_flush(struct km_event *c)
1459{
1460 struct nlmsghdr *nlh;
1461 struct sk_buff *skb;
1462 unsigned char *b;
1463 int len = NLMSG_LENGTH(0);
1464
1465 skb = alloc_skb(len, GFP_ATOMIC);
1466 if (skb == NULL)
1467 return -ENOMEM;
1468 b = skb->tail;
1469
1470
1471 nlh = NLMSG_PUT(skb, c->pid, c->seq, XFRM_MSG_FLUSHPOLICY, 0);
1472
1473 nlh->nlmsg_len = skb->tail - b;
1474
1475 return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_POLICY, GFP_ATOMIC);
1476
1477nlmsg_failure:
1478 kfree_skb(skb);
1479 return -1;
1480}
1481
1482static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)
1483{
1484
1485 switch (c->event) {
1486 case XFRM_SAP_ADDED:
1487 case XFRM_SAP_UPDATED:
1488 case XFRM_SAP_DELETED:
1489 return xfrm_notify_policy(xp, dir, c);
1490 case XFRM_SAP_FLUSHED:
1491 return xfrm_notify_policy_flush(c);
1492 case XFRM_SAP_EXPIRED:
1493 return xfrm_exp_policy_notify(xp, dir, c);
1494 default:
1495 printk("xfrm_user: Unknown Policy event %d\n", c->event);
1496 }
1497
1498 return 0;
1499
1500}
1501
1240static struct xfrm_mgr netlink_mgr = { 1502static struct xfrm_mgr netlink_mgr = {
1241 .id = "netlink", 1503 .id = "netlink",
1242 .notify = xfrm_send_state_notify, 1504 .notify = xfrm_send_state_notify,