aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_user.c
diff options
context:
space:
mode:
authorJaroslav Kysela <perex@hera.kernel.org>2005-06-21 10:39:41 -0400
committerJaroslav Kysela <perex@hera.kernel.org>2005-06-21 10:39:41 -0400
commitfae6ec69c84d71b1d5bda9ede1a262c1681684aa (patch)
treeeb4aff9a5c2b7d04ce09a3717bb1dd4a79fe7595 /net/xfrm/xfrm_user.c
parentbbc0274e9bb2e3f1d724d445a2bd32566b9b66f7 (diff)
parent1d345dac1f30af1cd9f3a1faa12f9f18f17f236e (diff)
Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
Diffstat (limited to 'net/xfrm/xfrm_user.c')
-rw-r--r--net/xfrm/xfrm_user.c297
1 files changed, 282 insertions, 15 deletions
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 97509011c274..ecade4893a13 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -249,17 +249,10 @@ static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p,
249 if ((err = attach_encap_tmpl(&x->encap, xfrma[XFRMA_ENCAP-1]))) 249 if ((err = attach_encap_tmpl(&x->encap, xfrma[XFRMA_ENCAP-1])))
250 goto error; 250 goto error;
251 251
252 err = -ENOENT; 252 err = xfrm_init_state(x);
253 x->type = xfrm_get_type(x->id.proto, x->props.family);
254 if (x->type == NULL)
255 goto error;
256
257 err = x->type->init_state(x, NULL);
258 if (err) 253 if (err)
259 goto error; 254 goto error;
260 255
261 x->curlft.add_time = (unsigned long) xtime.tv_sec;
262 x->km.state = XFRM_STATE_VALID;
263 x->km.seq = p->seq; 256 x->km.seq = p->seq;
264 257
265 return x; 258 return x;
@@ -277,6 +270,7 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
277 struct xfrm_usersa_info *p = NLMSG_DATA(nlh); 270 struct xfrm_usersa_info *p = NLMSG_DATA(nlh);
278 struct xfrm_state *x; 271 struct xfrm_state *x;
279 int err; 272 int err;
273 struct km_event c;
280 274
281 err = verify_newsa_info(p, (struct rtattr **) xfrma); 275 err = verify_newsa_info(p, (struct rtattr **) xfrma);
282 if (err) 276 if (err)
@@ -286,6 +280,7 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
286 if (!x) 280 if (!x)
287 return err; 281 return err;
288 282
283 xfrm_state_hold(x);
289 if (nlh->nlmsg_type == XFRM_MSG_NEWSA) 284 if (nlh->nlmsg_type == XFRM_MSG_NEWSA)
290 err = xfrm_state_add(x); 285 err = xfrm_state_add(x);
291 else 286 else
@@ -294,14 +289,24 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
294 if (err < 0) { 289 if (err < 0) {
295 x->km.state = XFRM_STATE_DEAD; 290 x->km.state = XFRM_STATE_DEAD;
296 xfrm_state_put(x); 291 xfrm_state_put(x);
292 goto out;
297 } 293 }
298 294
295 c.seq = nlh->nlmsg_seq;
296 c.pid = nlh->nlmsg_pid;
297 c.event = nlh->nlmsg_type;
298
299 km_state_notify(x, &c);
300out:
301 xfrm_state_put(x);
299 return err; 302 return err;
300} 303}
301 304
302static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) 305static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
303{ 306{
304 struct xfrm_state *x; 307 struct xfrm_state *x;
308 int err;
309 struct km_event c;
305 struct xfrm_usersa_id *p = NLMSG_DATA(nlh); 310 struct xfrm_usersa_id *p = NLMSG_DATA(nlh);
306 311
307 x = xfrm_state_lookup(&p->daddr, p->spi, p->proto, p->family); 312 x = xfrm_state_lookup(&p->daddr, p->spi, p->proto, p->family);
@@ -313,10 +318,19 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
313 return -EPERM; 318 return -EPERM;
314 } 319 }
315 320
316 xfrm_state_delete(x); 321 err = xfrm_state_delete(x);
322 if (err < 0) {
323 xfrm_state_put(x);
324 return err;
325 }
326
327 c.seq = nlh->nlmsg_seq;
328 c.pid = nlh->nlmsg_pid;
329 c.event = nlh->nlmsg_type;
330 km_state_notify(x, &c);
317 xfrm_state_put(x); 331 xfrm_state_put(x);
318 332
319 return 0; 333 return err;
320} 334}
321 335
322static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p) 336static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p)
@@ -681,6 +695,7 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
681{ 695{
682 struct xfrm_userpolicy_info *p = NLMSG_DATA(nlh); 696 struct xfrm_userpolicy_info *p = NLMSG_DATA(nlh);
683 struct xfrm_policy *xp; 697 struct xfrm_policy *xp;
698 struct km_event c;
684 int err; 699 int err;
685 int excl; 700 int excl;
686 701
@@ -692,6 +707,10 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
692 if (!xp) 707 if (!xp)
693 return err; 708 return err;
694 709
710 /* shouldnt excl be based on nlh flags??
711 * Aha! this is anti-netlink really i.e more pfkey derived
712 * in netlink excl is a flag and you wouldnt need
713 * a type XFRM_MSG_UPDPOLICY - JHS */
695 excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY; 714 excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY;
696 err = xfrm_policy_insert(p->dir, xp, excl); 715 err = xfrm_policy_insert(p->dir, xp, excl);
697 if (err) { 716 if (err) {
@@ -699,6 +718,11 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
699 return err; 718 return err;
700 } 719 }
701 720
721 c.event = nlh->nlmsg_type;
722 c.seq = nlh->nlmsg_seq;
723 c.pid = nlh->nlmsg_pid;
724 km_policy_notify(xp, p->dir, &c);
725
702 xfrm_pol_put(xp); 726 xfrm_pol_put(xp);
703 727
704 return 0; 728 return 0;
@@ -816,6 +840,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
816 struct xfrm_policy *xp; 840 struct xfrm_policy *xp;
817 struct xfrm_userpolicy_id *p; 841 struct xfrm_userpolicy_id *p;
818 int err; 842 int err;
843 struct km_event c;
819 int delete; 844 int delete;
820 845
821 p = NLMSG_DATA(nlh); 846 p = NLMSG_DATA(nlh);
@@ -843,6 +868,12 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
843 NETLINK_CB(skb).pid, 868 NETLINK_CB(skb).pid,
844 MSG_DONTWAIT); 869 MSG_DONTWAIT);
845 } 870 }
871 } else {
872 c.data.byid = p->index;
873 c.event = nlh->nlmsg_type;
874 c.seq = nlh->nlmsg_seq;
875 c.pid = nlh->nlmsg_pid;
876 km_policy_notify(xp, p->dir, &c);
846 } 877 }
847 878
848 xfrm_pol_put(xp); 879 xfrm_pol_put(xp);
@@ -852,15 +883,28 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
852 883
853static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) 884static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
854{ 885{
886 struct km_event c;
855 struct xfrm_usersa_flush *p = NLMSG_DATA(nlh); 887 struct xfrm_usersa_flush *p = NLMSG_DATA(nlh);
856 888
857 xfrm_state_flush(p->proto); 889 xfrm_state_flush(p->proto);
890 c.data.proto = p->proto;
891 c.event = nlh->nlmsg_type;
892 c.seq = nlh->nlmsg_seq;
893 c.pid = nlh->nlmsg_pid;
894 km_state_notify(NULL, &c);
895
858 return 0; 896 return 0;
859} 897}
860 898
861static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) 899static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
862{ 900{
901 struct km_event c;
902
863 xfrm_policy_flush(); 903 xfrm_policy_flush();
904 c.event = nlh->nlmsg_type;
905 c.seq = nlh->nlmsg_seq;
906 c.pid = nlh->nlmsg_pid;
907 km_policy_notify(NULL, 0, &c);
864 return 0; 908 return 0;
865} 909}
866 910
@@ -1069,15 +1113,16 @@ nlmsg_failure:
1069 return -1; 1113 return -1;
1070} 1114}
1071 1115
1072static int xfrm_send_state_notify(struct xfrm_state *x, int hard) 1116static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c)
1073{ 1117{
1074 struct sk_buff *skb; 1118 struct sk_buff *skb;
1119 int len = NLMSG_LENGTH(sizeof(struct xfrm_user_expire));
1075 1120
1076 skb = alloc_skb(sizeof(struct xfrm_user_expire) + 16, GFP_ATOMIC); 1121 skb = alloc_skb(len, GFP_ATOMIC);
1077 if (skb == NULL) 1122 if (skb == NULL)
1078 return -ENOMEM; 1123 return -ENOMEM;
1079 1124
1080 if (build_expire(skb, x, hard) < 0) 1125 if (build_expire(skb, x, c->data.hard) < 0)
1081 BUG(); 1126 BUG();
1082 1127
1083 NETLINK_CB(skb).dst_groups = XFRMGRP_EXPIRE; 1128 NETLINK_CB(skb).dst_groups = XFRMGRP_EXPIRE;
@@ -1085,6 +1130,131 @@ static int xfrm_send_state_notify(struct xfrm_state *x, int hard)
1085 return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_EXPIRE, GFP_ATOMIC); 1130 return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_EXPIRE, GFP_ATOMIC);
1086} 1131}
1087 1132
1133static int xfrm_notify_sa_flush(struct km_event *c)
1134{
1135 struct xfrm_usersa_flush *p;
1136 struct nlmsghdr *nlh;
1137 struct sk_buff *skb;
1138 unsigned char *b;
1139 int len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_flush));
1140
1141 skb = alloc_skb(len, GFP_ATOMIC);
1142 if (skb == NULL)
1143 return -ENOMEM;
1144 b = skb->tail;
1145
1146 nlh = NLMSG_PUT(skb, c->pid, c->seq,
1147 XFRM_MSG_FLUSHSA, sizeof(*p));
1148 nlh->nlmsg_flags = 0;
1149
1150 p = NLMSG_DATA(nlh);
1151 p->proto = c->data.proto;
1152
1153 nlh->nlmsg_len = skb->tail - b;
1154
1155 return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_SA, GFP_ATOMIC);
1156
1157nlmsg_failure:
1158 kfree_skb(skb);
1159 return -1;
1160}
1161
1162static int inline xfrm_sa_len(struct xfrm_state *x)
1163{
1164 int l = 0;
1165 if (x->aalg)
1166 l += RTA_SPACE(sizeof(*x->aalg) + (x->aalg->alg_key_len+7)/8);
1167 if (x->ealg)
1168 l += RTA_SPACE(sizeof(*x->ealg) + (x->ealg->alg_key_len+7)/8);
1169 if (x->calg)
1170 l += RTA_SPACE(sizeof(*x->calg));
1171 if (x->encap)
1172 l += RTA_SPACE(sizeof(*x->encap));
1173
1174 return l;
1175}
1176
1177static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c)
1178{
1179 struct xfrm_usersa_info *p;
1180 struct xfrm_usersa_id *id;
1181 struct nlmsghdr *nlh;
1182 struct sk_buff *skb;
1183 unsigned char *b;
1184 int len = xfrm_sa_len(x);
1185 int headlen;
1186
1187 headlen = sizeof(*p);
1188 if (c->event == XFRM_MSG_DELSA) {
1189 len += RTA_SPACE(headlen);
1190 headlen = sizeof(*id);
1191 }
1192 len += NLMSG_SPACE(headlen);
1193
1194 skb = alloc_skb(len, GFP_ATOMIC);
1195 if (skb == NULL)
1196 return -ENOMEM;
1197 b = skb->tail;
1198
1199 nlh = NLMSG_PUT(skb, c->pid, c->seq, c->event, headlen);
1200 nlh->nlmsg_flags = 0;
1201
1202 p = NLMSG_DATA(nlh);
1203 if (c->event == XFRM_MSG_DELSA) {
1204 id = NLMSG_DATA(nlh);
1205 memcpy(&id->daddr, &x->id.daddr, sizeof(id->daddr));
1206 id->spi = x->id.spi;
1207 id->family = x->props.family;
1208 id->proto = x->id.proto;
1209
1210 p = RTA_DATA(__RTA_PUT(skb, XFRMA_SA, sizeof(*p)));
1211 }
1212
1213 copy_to_user_state(x, p);
1214
1215 if (x->aalg)
1216 RTA_PUT(skb, XFRMA_ALG_AUTH,
1217 sizeof(*(x->aalg))+(x->aalg->alg_key_len+7)/8, x->aalg);
1218 if (x->ealg)
1219 RTA_PUT(skb, XFRMA_ALG_CRYPT,
1220 sizeof(*(x->ealg))+(x->ealg->alg_key_len+7)/8, x->ealg);
1221 if (x->calg)
1222 RTA_PUT(skb, XFRMA_ALG_COMP, sizeof(*(x->calg)), x->calg);
1223
1224 if (x->encap)
1225 RTA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap);
1226
1227 nlh->nlmsg_len = skb->tail - b;
1228
1229 return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_SA, GFP_ATOMIC);
1230
1231nlmsg_failure:
1232rtattr_failure:
1233 kfree_skb(skb);
1234 return -1;
1235}
1236
1237static int xfrm_send_state_notify(struct xfrm_state *x, struct km_event *c)
1238{
1239
1240 switch (c->event) {
1241 case XFRM_MSG_EXPIRE:
1242 return xfrm_exp_state_notify(x, c);
1243 case XFRM_MSG_DELSA:
1244 case XFRM_MSG_UPDSA:
1245 case XFRM_MSG_NEWSA:
1246 return xfrm_notify_sa(x, c);
1247 case XFRM_MSG_FLUSHSA:
1248 return xfrm_notify_sa_flush(c);
1249 default:
1250 printk("xfrm_user: Unknown SA event %d\n", c->event);
1251 break;
1252 }
1253
1254 return 0;
1255
1256}
1257
1088static int build_acquire(struct sk_buff *skb, struct xfrm_state *x, 1258static int build_acquire(struct sk_buff *skb, struct xfrm_state *x,
1089 struct xfrm_tmpl *xt, struct xfrm_policy *xp, 1259 struct xfrm_tmpl *xt, struct xfrm_policy *xp,
1090 int dir) 1260 int dir)
@@ -1218,7 +1388,7 @@ nlmsg_failure:
1218 return -1; 1388 return -1;
1219} 1389}
1220 1390
1221static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, int hard) 1391static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)
1222{ 1392{
1223 struct sk_buff *skb; 1393 struct sk_buff *skb;
1224 size_t len; 1394 size_t len;
@@ -1229,7 +1399,7 @@ static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, int hard)
1229 if (skb == NULL) 1399 if (skb == NULL)
1230 return -ENOMEM; 1400 return -ENOMEM;
1231 1401
1232 if (build_polexpire(skb, xp, dir, hard) < 0) 1402 if (build_polexpire(skb, xp, dir, c->data.hard) < 0)
1233 BUG(); 1403 BUG();
1234 1404
1235 NETLINK_CB(skb).dst_groups = XFRMGRP_EXPIRE; 1405 NETLINK_CB(skb).dst_groups = XFRMGRP_EXPIRE;
@@ -1237,6 +1407,103 @@ 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); 1407 return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_EXPIRE, GFP_ATOMIC);
1238} 1408}
1239 1409
1410static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c)
1411{
1412 struct xfrm_userpolicy_info *p;
1413 struct xfrm_userpolicy_id *id;
1414 struct nlmsghdr *nlh;
1415 struct sk_buff *skb;
1416 unsigned char *b;
1417 int len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr);
1418 int headlen;
1419
1420 headlen = sizeof(*p);
1421 if (c->event == XFRM_MSG_DELPOLICY) {
1422 len += RTA_SPACE(headlen);
1423 headlen = sizeof(*id);
1424 }
1425 len += NLMSG_SPACE(headlen);
1426
1427 skb = alloc_skb(len, GFP_ATOMIC);
1428 if (skb == NULL)
1429 return -ENOMEM;
1430 b = skb->tail;
1431
1432 nlh = NLMSG_PUT(skb, c->pid, c->seq, c->event, headlen);
1433
1434 p = NLMSG_DATA(nlh);
1435 if (c->event == XFRM_MSG_DELPOLICY) {
1436 id = NLMSG_DATA(nlh);
1437 memset(id, 0, sizeof(*id));
1438 id->dir = dir;
1439 if (c->data.byid)
1440 id->index = xp->index;
1441 else
1442 memcpy(&id->sel, &xp->selector, sizeof(id->sel));
1443
1444 p = RTA_DATA(__RTA_PUT(skb, XFRMA_POLICY, sizeof(*p)));
1445 }
1446
1447 nlh->nlmsg_flags = 0;
1448
1449 copy_to_user_policy(xp, p, dir);
1450 if (copy_to_user_tmpl(xp, skb) < 0)
1451 goto nlmsg_failure;
1452
1453 nlh->nlmsg_len = skb->tail - b;
1454
1455 return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_POLICY, GFP_ATOMIC);
1456
1457nlmsg_failure:
1458rtattr_failure:
1459 kfree_skb(skb);
1460 return -1;
1461}
1462
1463static int xfrm_notify_policy_flush(struct km_event *c)
1464{
1465 struct nlmsghdr *nlh;
1466 struct sk_buff *skb;
1467 unsigned char *b;
1468 int len = NLMSG_LENGTH(0);
1469
1470 skb = alloc_skb(len, GFP_ATOMIC);
1471 if (skb == NULL)
1472 return -ENOMEM;
1473 b = skb->tail;
1474
1475
1476 nlh = NLMSG_PUT(skb, c->pid, c->seq, XFRM_MSG_FLUSHPOLICY, 0);
1477
1478 nlh->nlmsg_len = skb->tail - b;
1479
1480 return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_POLICY, GFP_ATOMIC);
1481
1482nlmsg_failure:
1483 kfree_skb(skb);
1484 return -1;
1485}
1486
1487static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)
1488{
1489
1490 switch (c->event) {
1491 case XFRM_MSG_NEWPOLICY:
1492 case XFRM_MSG_UPDPOLICY:
1493 case XFRM_MSG_DELPOLICY:
1494 return xfrm_notify_policy(xp, dir, c);
1495 case XFRM_MSG_FLUSHPOLICY:
1496 return xfrm_notify_policy_flush(c);
1497 case XFRM_MSG_POLEXPIRE:
1498 return xfrm_exp_policy_notify(xp, dir, c);
1499 default:
1500 printk("xfrm_user: Unknown Policy event %d\n", c->event);
1501 }
1502
1503 return 0;
1504
1505}
1506
1240static struct xfrm_mgr netlink_mgr = { 1507static struct xfrm_mgr netlink_mgr = {
1241 .id = "netlink", 1508 .id = "netlink",
1242 .notify = xfrm_send_state_notify, 1509 .notify = xfrm_send_state_notify,