aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2005-06-19 01:54:36 -0400
committerDavid S. Miller <davem@davemloft.net>2005-06-19 01:54:36 -0400
commit0603eac0d6b77acac5924a2734228cbaf072f993 (patch)
treee51536aab48997cc74f83bc618b95a9d88df12f2
parentb6544c0b4cf2bd96195f3cdb7cebfb35090fc557 (diff)
[IPSEC]: Add XFRMA_SA/XFRMA_POLICY for delete notification
This patch changes the format of the XFRM_MSG_DELSA and XFRM_MSG_DELPOLICY notification so that the main message sent is of the same format as that received by the kernel if the original message was via netlink. This also means that we won't lose the byid information carried in km_event. Since this user interface is introduced by Jamal's patch we can still afford to change it. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/xfrm.h2
-rw-r--r--net/xfrm/xfrm_user.c47
2 files changed, 45 insertions, 4 deletions
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index 03bc600516ea..d68391a9b9f3 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -174,6 +174,8 @@ enum xfrm_attr_type_t {
174 XFRMA_ALG_COMP, /* struct xfrm_algo */ 174 XFRMA_ALG_COMP, /* struct xfrm_algo */
175 XFRMA_ENCAP, /* struct xfrm_algo + struct xfrm_encap_tmpl */ 175 XFRMA_ENCAP, /* struct xfrm_algo + struct xfrm_encap_tmpl */
176 XFRMA_TMPL, /* 1 or more struct xfrm_user_tmpl */ 176 XFRMA_TMPL, /* 1 or more struct xfrm_user_tmpl */
177 XFRMA_SA,
178 XFRMA_POLICY,
177 __XFRMA_MAX 179 __XFRMA_MAX
178 180
179#define XFRMA_MAX (__XFRMA_MAX - 1) 181#define XFRMA_MAX (__XFRMA_MAX - 1)
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
1169static int inline xfrm_sa_len(struct xfrm_state *x) 1169static 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)
1184static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c) 1184static 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
1398static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c) 1417static 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
1426nlmsg_failure: 1464nlmsg_failure:
1465rtattr_failure:
1427 kfree_skb(skb); 1466 kfree_skb(skb);
1428 return -1; 1467 return -1;
1429} 1468}