diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/xfrm/xfrm_user.c | 47 |
1 files changed, 43 insertions, 4 deletions
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index ffe1b217347c..5ce8558eac91 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -1168,7 +1168,7 @@ nlmsg_failure: | |||
1168 | 1168 | ||
1169 | static int inline xfrm_sa_len(struct xfrm_state *x) | 1169 | static int inline xfrm_sa_len(struct xfrm_state *x) |
1170 | { | 1170 | { |
1171 | int l = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info)); | 1171 | int l = 0; |
1172 | if (x->aalg) | 1172 | if (x->aalg) |
1173 | l += RTA_SPACE(sizeof(*x->aalg) + (x->aalg->alg_key_len+7)/8); | 1173 | l += RTA_SPACE(sizeof(*x->aalg) + (x->aalg->alg_key_len+7)/8); |
1174 | if (x->ealg) | 1174 | if (x->ealg) |
@@ -1184,20 +1184,39 @@ static int inline xfrm_sa_len(struct xfrm_state *x) | |||
1184 | static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c) | 1184 | static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c) |
1185 | { | 1185 | { |
1186 | struct xfrm_usersa_info *p; | 1186 | struct xfrm_usersa_info *p; |
1187 | struct xfrm_usersa_id *id; | ||
1187 | struct nlmsghdr *nlh; | 1188 | struct nlmsghdr *nlh; |
1188 | struct sk_buff *skb; | 1189 | struct sk_buff *skb; |
1189 | unsigned char *b; | 1190 | unsigned char *b; |
1190 | int len = xfrm_sa_len(x); | 1191 | int len = xfrm_sa_len(x); |
1192 | int headlen; | ||
1193 | |||
1194 | headlen = sizeof(*p); | ||
1195 | if (c->event == XFRM_MSG_DELSA) { | ||
1196 | len += RTA_SPACE(headlen); | ||
1197 | headlen = sizeof(*id); | ||
1198 | } | ||
1199 | len += NLMSG_SPACE(headlen); | ||
1191 | 1200 | ||
1192 | skb = alloc_skb(len, GFP_ATOMIC); | 1201 | skb = alloc_skb(len, GFP_ATOMIC); |
1193 | if (skb == NULL) | 1202 | if (skb == NULL) |
1194 | return -ENOMEM; | 1203 | return -ENOMEM; |
1195 | b = skb->tail; | 1204 | b = skb->tail; |
1196 | 1205 | ||
1197 | nlh = NLMSG_PUT(skb, c->pid, c->seq, c->event, sizeof(*p)); | 1206 | nlh = NLMSG_PUT(skb, c->pid, c->seq, c->event, headlen); |
1198 | nlh->nlmsg_flags = 0; | 1207 | nlh->nlmsg_flags = 0; |
1199 | 1208 | ||
1200 | p = NLMSG_DATA(nlh); | 1209 | p = NLMSG_DATA(nlh); |
1210 | if (c->event == XFRM_MSG_DELSA) { | ||
1211 | id = NLMSG_DATA(nlh); | ||
1212 | memcpy(&id->daddr, &x->id.daddr, sizeof(id->daddr)); | ||
1213 | id->spi = x->id.spi; | ||
1214 | id->family = x->props.family; | ||
1215 | id->proto = x->id.proto; | ||
1216 | |||
1217 | p = RTA_DATA(__RTA_PUT(skb, XFRMA_SA, sizeof(*p))); | ||
1218 | } | ||
1219 | |||
1201 | copy_to_user_state(x, p); | 1220 | copy_to_user_state(x, p); |
1202 | 1221 | ||
1203 | if (x->aalg) | 1222 | if (x->aalg) |
@@ -1398,20 +1417,39 @@ static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_eve | |||
1398 | static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c) | 1417 | static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c) |
1399 | { | 1418 | { |
1400 | struct xfrm_userpolicy_info *p; | 1419 | struct xfrm_userpolicy_info *p; |
1420 | struct xfrm_userpolicy_id *id; | ||
1401 | struct nlmsghdr *nlh; | 1421 | struct nlmsghdr *nlh; |
1402 | struct sk_buff *skb; | 1422 | struct sk_buff *skb; |
1403 | unsigned char *b; | 1423 | unsigned char *b; |
1404 | int len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr); | 1424 | int len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr); |
1405 | len += NLMSG_SPACE(sizeof(struct xfrm_userpolicy_info)); | 1425 | int headlen; |
1426 | |||
1427 | headlen = sizeof(*p); | ||
1428 | if (c->event == XFRM_MSG_DELPOLICY) { | ||
1429 | len += RTA_SPACE(headlen); | ||
1430 | headlen = sizeof(*id); | ||
1431 | } | ||
1432 | len += NLMSG_SPACE(headlen); | ||
1406 | 1433 | ||
1407 | skb = alloc_skb(len, GFP_ATOMIC); | 1434 | skb = alloc_skb(len, GFP_ATOMIC); |
1408 | if (skb == NULL) | 1435 | if (skb == NULL) |
1409 | return -ENOMEM; | 1436 | return -ENOMEM; |
1410 | b = skb->tail; | 1437 | b = skb->tail; |
1411 | 1438 | ||
1412 | nlh = NLMSG_PUT(skb, c->pid, c->seq, c->event, sizeof(*p)); | 1439 | nlh = NLMSG_PUT(skb, c->pid, c->seq, c->event, headlen); |
1413 | 1440 | ||
1414 | p = NLMSG_DATA(nlh); | 1441 | p = NLMSG_DATA(nlh); |
1442 | if (c->event == XFRM_MSG_DELPOLICY) { | ||
1443 | id = NLMSG_DATA(nlh); | ||
1444 | memset(id, 0, sizeof(*id)); | ||
1445 | id->dir = dir; | ||
1446 | if (c->data.byid) | ||
1447 | id->index = xp->index; | ||
1448 | else | ||
1449 | memcpy(&id->sel, &xp->selector, sizeof(id->sel)); | ||
1450 | |||
1451 | p = RTA_DATA(__RTA_PUT(skb, XFRMA_POLICY, sizeof(*p))); | ||
1452 | } | ||
1415 | 1453 | ||
1416 | nlh->nlmsg_flags = 0; | 1454 | nlh->nlmsg_flags = 0; |
1417 | 1455 | ||
@@ -1424,6 +1462,7 @@ static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event * | |||
1424 | return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_POLICY, GFP_ATOMIC); | 1462 | return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_POLICY, GFP_ATOMIC); |
1425 | 1463 | ||
1426 | nlmsg_failure: | 1464 | nlmsg_failure: |
1465 | rtattr_failure: | ||
1427 | kfree_skb(skb); | 1466 | kfree_skb(skb); |
1428 | return -1; | 1467 | return -1; |
1429 | } | 1468 | } |