aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_user.c
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 /net/xfrm/xfrm_user.c
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>
Diffstat (limited to 'net/xfrm/xfrm_user.c')
-rw-r--r--net/xfrm/xfrm_user.c272
1 files changed, 267 insertions, 5 deletions
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,