diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/key/af_key.c | 2 | ||||
-rw-r--r-- | net/xfrm/xfrm_user.c | 238 |
2 files changed, 230 insertions, 10 deletions
diff --git a/net/key/af_key.c b/net/key/af_key.c index b2d4d1dd2116..520fe70d0993 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -2651,6 +2651,8 @@ static int pfkey_send_notify(struct xfrm_state *x, struct km_event *c) | |||
2651 | return key_notify_sa(x, c); | 2651 | return key_notify_sa(x, c); |
2652 | case XFRM_MSG_FLUSHSA: | 2652 | case XFRM_MSG_FLUSHSA: |
2653 | return key_notify_sa_flush(c); | 2653 | return key_notify_sa_flush(c); |
2654 | case XFRM_MSG_NEWAE: /* not yet supported */ | ||
2655 | break; | ||
2654 | default: | 2656 | default: |
2655 | printk("pfkey: Unknown SA event %d\n", c->event); | 2657 | printk("pfkey: Unknown SA event %d\n", c->event); |
2656 | break; | 2658 | break; |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 6f643e58e044..e230ba5328d3 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -276,6 +276,56 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info * | |||
276 | x->props.flags = p->flags; | 276 | x->props.flags = p->flags; |
277 | } | 277 | } |
278 | 278 | ||
279 | /* | ||
280 | * someday when pfkey also has support, we could have the code | ||
281 | * somehow made shareable and move it to xfrm_state.c - JHS | ||
282 | * | ||
283 | */ | ||
284 | static int xfrm_update_ae_params(struct xfrm_state *x, struct rtattr **xfrma) | ||
285 | { | ||
286 | int err = - EINVAL; | ||
287 | struct rtattr *rp = xfrma[XFRMA_REPLAY_VAL-1]; | ||
288 | struct rtattr *lt = xfrma[XFRMA_LTIME_VAL-1]; | ||
289 | struct rtattr *et = xfrma[XFRMA_ETIMER_THRESH-1]; | ||
290 | struct rtattr *rt = xfrma[XFRMA_REPLAY_THRESH-1]; | ||
291 | |||
292 | if (rp) { | ||
293 | struct xfrm_replay_state *replay; | ||
294 | if (RTA_PAYLOAD(rp) < sizeof(*replay)) | ||
295 | goto error; | ||
296 | replay = RTA_DATA(rp); | ||
297 | memcpy(&x->replay, replay, sizeof(*replay)); | ||
298 | memcpy(&x->preplay, replay, sizeof(*replay)); | ||
299 | } | ||
300 | |||
301 | if (lt) { | ||
302 | struct xfrm_lifetime_cur *ltime; | ||
303 | if (RTA_PAYLOAD(lt) < sizeof(*ltime)) | ||
304 | goto error; | ||
305 | ltime = RTA_DATA(lt); | ||
306 | x->curlft.bytes = ltime->bytes; | ||
307 | x->curlft.packets = ltime->packets; | ||
308 | x->curlft.add_time = ltime->add_time; | ||
309 | x->curlft.use_time = ltime->use_time; | ||
310 | } | ||
311 | |||
312 | if (et) { | ||
313 | if (RTA_PAYLOAD(et) < sizeof(u32)) | ||
314 | goto error; | ||
315 | x->replay_maxage = *(u32*)RTA_DATA(et); | ||
316 | } | ||
317 | |||
318 | if (rt) { | ||
319 | if (RTA_PAYLOAD(rt) < sizeof(u32)) | ||
320 | goto error; | ||
321 | x->replay_maxdiff = *(u32*)RTA_DATA(rt); | ||
322 | } | ||
323 | |||
324 | return 0; | ||
325 | error: | ||
326 | return err; | ||
327 | } | ||
328 | |||
279 | static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p, | 329 | static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p, |
280 | struct rtattr **xfrma, | 330 | struct rtattr **xfrma, |
281 | int *errp) | 331 | int *errp) |
@@ -311,6 +361,18 @@ static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p, | |||
311 | goto error; | 361 | goto error; |
312 | 362 | ||
313 | x->km.seq = p->seq; | 363 | x->km.seq = p->seq; |
364 | x->replay_maxdiff = sysctl_xfrm_aevent_rseqth; | ||
365 | /* sysctl_xfrm_aevent_etime is in 100ms units */ | ||
366 | x->replay_maxage = (sysctl_xfrm_aevent_etime*HZ)/XFRM_AE_ETH_M; | ||
367 | x->preplay.bitmap = 0; | ||
368 | x->preplay.seq = x->replay.seq+x->replay_maxdiff; | ||
369 | x->preplay.oseq = x->replay.oseq +x->replay_maxdiff; | ||
370 | |||
371 | /* override default values from above */ | ||
372 | |||
373 | err = xfrm_update_ae_params(x, (struct rtattr **)xfrma); | ||
374 | if (err < 0) | ||
375 | goto error; | ||
314 | 376 | ||
315 | return x; | 377 | return x; |
316 | 378 | ||
@@ -1025,6 +1087,139 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma | |||
1025 | return 0; | 1087 | return 0; |
1026 | } | 1088 | } |
1027 | 1089 | ||
1090 | |||
1091 | static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, struct km_event *c) | ||
1092 | { | ||
1093 | struct xfrm_aevent_id *id; | ||
1094 | struct nlmsghdr *nlh; | ||
1095 | struct xfrm_lifetime_cur ltime; | ||
1096 | unsigned char *b = skb->tail; | ||
1097 | |||
1098 | nlh = NLMSG_PUT(skb, c->pid, c->seq, XFRM_MSG_NEWAE, sizeof(*id)); | ||
1099 | id = NLMSG_DATA(nlh); | ||
1100 | nlh->nlmsg_flags = 0; | ||
1101 | |||
1102 | id->sa_id.daddr = x->id.daddr; | ||
1103 | id->sa_id.spi = x->id.spi; | ||
1104 | id->sa_id.family = x->props.family; | ||
1105 | id->sa_id.proto = x->id.proto; | ||
1106 | id->flags = c->data.aevent; | ||
1107 | |||
1108 | RTA_PUT(skb, XFRMA_REPLAY_VAL, sizeof(x->replay), &x->replay); | ||
1109 | |||
1110 | ltime.bytes = x->curlft.bytes; | ||
1111 | ltime.packets = x->curlft.packets; | ||
1112 | ltime.add_time = x->curlft.add_time; | ||
1113 | ltime.use_time = x->curlft.use_time; | ||
1114 | |||
1115 | RTA_PUT(skb, XFRMA_LTIME_VAL, sizeof(struct xfrm_lifetime_cur), <ime); | ||
1116 | |||
1117 | if (id->flags&XFRM_AE_RTHR) { | ||
1118 | RTA_PUT(skb,XFRMA_REPLAY_THRESH,sizeof(u32),&x->replay_maxdiff); | ||
1119 | } | ||
1120 | |||
1121 | if (id->flags&XFRM_AE_ETHR) { | ||
1122 | u32 etimer = x->replay_maxage*10/HZ; | ||
1123 | RTA_PUT(skb,XFRMA_ETIMER_THRESH,sizeof(u32),&etimer); | ||
1124 | } | ||
1125 | |||
1126 | nlh->nlmsg_len = skb->tail - b; | ||
1127 | return skb->len; | ||
1128 | |||
1129 | rtattr_failure: | ||
1130 | nlmsg_failure: | ||
1131 | skb_trim(skb, b - skb->data); | ||
1132 | return -1; | ||
1133 | } | ||
1134 | |||
1135 | static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) | ||
1136 | { | ||
1137 | struct xfrm_state *x; | ||
1138 | struct sk_buff *r_skb; | ||
1139 | int err; | ||
1140 | struct km_event c; | ||
1141 | struct xfrm_aevent_id *p = NLMSG_DATA(nlh); | ||
1142 | int len = NLMSG_LENGTH(sizeof(struct xfrm_aevent_id)); | ||
1143 | struct xfrm_usersa_id *id = &p->sa_id; | ||
1144 | |||
1145 | len += RTA_SPACE(sizeof(struct xfrm_replay_state)); | ||
1146 | len += RTA_SPACE(sizeof(struct xfrm_lifetime_cur)); | ||
1147 | |||
1148 | if (p->flags&XFRM_AE_RTHR) | ||
1149 | len+=RTA_SPACE(sizeof(u32)); | ||
1150 | |||
1151 | if (p->flags&XFRM_AE_ETHR) | ||
1152 | len+=RTA_SPACE(sizeof(u32)); | ||
1153 | |||
1154 | r_skb = alloc_skb(len, GFP_ATOMIC); | ||
1155 | if (r_skb == NULL) | ||
1156 | return -ENOMEM; | ||
1157 | |||
1158 | x = xfrm_state_lookup(&id->daddr, id->spi, id->proto, id->family); | ||
1159 | if (x == NULL) { | ||
1160 | kfree(r_skb); | ||
1161 | return -ESRCH; | ||
1162 | } | ||
1163 | |||
1164 | /* | ||
1165 | * XXX: is this lock really needed - none of the other | ||
1166 | * gets lock (the concern is things getting updated | ||
1167 | * while we are still reading) - jhs | ||
1168 | */ | ||
1169 | spin_lock_bh(&x->lock); | ||
1170 | c.data.aevent = p->flags; | ||
1171 | c.seq = nlh->nlmsg_seq; | ||
1172 | c.pid = nlh->nlmsg_pid; | ||
1173 | |||
1174 | if (build_aevent(r_skb, x, &c) < 0) | ||
1175 | BUG(); | ||
1176 | err = netlink_unicast(xfrm_nl, r_skb, | ||
1177 | NETLINK_CB(skb).pid, MSG_DONTWAIT); | ||
1178 | spin_unlock_bh(&x->lock); | ||
1179 | xfrm_state_put(x); | ||
1180 | return err; | ||
1181 | } | ||
1182 | |||
1183 | static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) | ||
1184 | { | ||
1185 | struct xfrm_state *x; | ||
1186 | struct km_event c; | ||
1187 | int err = - EINVAL; | ||
1188 | struct xfrm_aevent_id *p = NLMSG_DATA(nlh); | ||
1189 | struct rtattr *rp = xfrma[XFRMA_REPLAY_VAL-1]; | ||
1190 | struct rtattr *lt = xfrma[XFRMA_LTIME_VAL-1]; | ||
1191 | |||
1192 | if (!lt && !rp) | ||
1193 | return err; | ||
1194 | |||
1195 | /* pedantic mode - thou shalt sayeth replaceth */ | ||
1196 | if (!(nlh->nlmsg_flags&NLM_F_REPLACE)) | ||
1197 | return err; | ||
1198 | |||
1199 | x = xfrm_state_lookup(&p->sa_id.daddr, p->sa_id.spi, p->sa_id.proto, p->sa_id.family); | ||
1200 | if (x == NULL) | ||
1201 | return -ESRCH; | ||
1202 | |||
1203 | if (x->km.state != XFRM_STATE_VALID) | ||
1204 | goto out; | ||
1205 | |||
1206 | spin_lock_bh(&x->lock); | ||
1207 | err = xfrm_update_ae_params(x,(struct rtattr **)xfrma); | ||
1208 | spin_unlock_bh(&x->lock); | ||
1209 | if (err < 0) | ||
1210 | goto out; | ||
1211 | |||
1212 | c.event = nlh->nlmsg_type; | ||
1213 | c.seq = nlh->nlmsg_seq; | ||
1214 | c.pid = nlh->nlmsg_pid; | ||
1215 | c.data.aevent = XFRM_AE_CU; | ||
1216 | km_state_notify(x, &c); | ||
1217 | err = 0; | ||
1218 | out: | ||
1219 | xfrm_state_put(x); | ||
1220 | return err; | ||
1221 | } | ||
1222 | |||
1028 | static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) | 1223 | static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) |
1029 | { | 1224 | { |
1030 | struct km_event c; | 1225 | struct km_event c; |
@@ -1037,6 +1232,7 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **x | |||
1037 | return 0; | 1232 | return 0; |
1038 | } | 1233 | } |
1039 | 1234 | ||
1235 | |||
1040 | #define XMSGSIZE(type) NLMSG_LENGTH(sizeof(struct type)) | 1236 | #define XMSGSIZE(type) NLMSG_LENGTH(sizeof(struct type)) |
1041 | 1237 | ||
1042 | static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = { | 1238 | static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = { |
@@ -1047,13 +1243,12 @@ static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = { | |||
1047 | [XFRM_MSG_DELPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id), | 1243 | [XFRM_MSG_DELPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id), |
1048 | [XFRM_MSG_GETPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id), | 1244 | [XFRM_MSG_GETPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id), |
1049 | [XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userspi_info), | 1245 | [XFRM_MSG_ALLOCSPI - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userspi_info), |
1050 | [XFRM_MSG_ACQUIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_acquire), | ||
1051 | [XFRM_MSG_EXPIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_expire), | ||
1052 | [XFRM_MSG_UPDPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_info), | 1246 | [XFRM_MSG_UPDPOLICY - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_info), |
1053 | [XFRM_MSG_UPDSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_info), | 1247 | [XFRM_MSG_UPDSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_info), |
1054 | [XFRM_MSG_POLEXPIRE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_polexpire), | ||
1055 | [XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_flush), | 1248 | [XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = XMSGSIZE(xfrm_usersa_flush), |
1056 | [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = NLMSG_LENGTH(0), | 1249 | [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = NLMSG_LENGTH(0), |
1250 | [XFRM_MSG_NEWAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id), | ||
1251 | [XFRM_MSG_GETAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id), | ||
1057 | }; | 1252 | }; |
1058 | 1253 | ||
1059 | #undef XMSGSIZE | 1254 | #undef XMSGSIZE |
@@ -1075,6 +1270,8 @@ static struct xfrm_link { | |||
1075 | [XFRM_MSG_UPDSA - XFRM_MSG_BASE] = { .doit = xfrm_add_sa }, | 1270 | [XFRM_MSG_UPDSA - XFRM_MSG_BASE] = { .doit = xfrm_add_sa }, |
1076 | [XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = { .doit = xfrm_flush_sa }, | 1271 | [XFRM_MSG_FLUSHSA - XFRM_MSG_BASE] = { .doit = xfrm_flush_sa }, |
1077 | [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_flush_policy }, | 1272 | [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = { .doit = xfrm_flush_policy }, |
1273 | [XFRM_MSG_NEWAE - XFRM_MSG_BASE] = { .doit = xfrm_new_ae }, | ||
1274 | [XFRM_MSG_GETAE - XFRM_MSG_BASE] = { .doit = xfrm_get_ae }, | ||
1078 | }; | 1275 | }; |
1079 | 1276 | ||
1080 | static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) | 1277 | static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) |
@@ -1163,19 +1360,19 @@ static void xfrm_netlink_rcv(struct sock *sk, int len) | |||
1163 | } while (qlen); | 1360 | } while (qlen); |
1164 | } | 1361 | } |
1165 | 1362 | ||
1166 | static int build_expire(struct sk_buff *skb, struct xfrm_state *x, int hard) | 1363 | static int build_expire(struct sk_buff *skb, struct xfrm_state *x, struct km_event *c) |
1167 | { | 1364 | { |
1168 | struct xfrm_user_expire *ue; | 1365 | struct xfrm_user_expire *ue; |
1169 | struct nlmsghdr *nlh; | 1366 | struct nlmsghdr *nlh; |
1170 | unsigned char *b = skb->tail; | 1367 | unsigned char *b = skb->tail; |
1171 | 1368 | ||
1172 | nlh = NLMSG_PUT(skb, 0, 0, XFRM_MSG_EXPIRE, | 1369 | nlh = NLMSG_PUT(skb, c->pid, 0, XFRM_MSG_EXPIRE, |
1173 | sizeof(*ue)); | 1370 | sizeof(*ue)); |
1174 | ue = NLMSG_DATA(nlh); | 1371 | ue = NLMSG_DATA(nlh); |
1175 | nlh->nlmsg_flags = 0; | 1372 | nlh->nlmsg_flags = 0; |
1176 | 1373 | ||
1177 | copy_to_user_state(x, &ue->state); | 1374 | copy_to_user_state(x, &ue->state); |
1178 | ue->hard = (hard != 0) ? 1 : 0; | 1375 | ue->hard = (c->data.hard != 0) ? 1 : 0; |
1179 | 1376 | ||
1180 | nlh->nlmsg_len = skb->tail - b; | 1377 | nlh->nlmsg_len = skb->tail - b; |
1181 | return skb->len; | 1378 | return skb->len; |
@@ -1194,13 +1391,31 @@ static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c) | |||
1194 | if (skb == NULL) | 1391 | if (skb == NULL) |
1195 | return -ENOMEM; | 1392 | return -ENOMEM; |
1196 | 1393 | ||
1197 | if (build_expire(skb, x, c->data.hard) < 0) | 1394 | if (build_expire(skb, x, c) < 0) |
1198 | BUG(); | 1395 | BUG(); |
1199 | 1396 | ||
1200 | NETLINK_CB(skb).dst_group = XFRMNLGRP_EXPIRE; | 1397 | NETLINK_CB(skb).dst_group = XFRMNLGRP_EXPIRE; |
1201 | return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); | 1398 | return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC); |
1202 | } | 1399 | } |
1203 | 1400 | ||
1401 | static int xfrm_aevent_state_notify(struct xfrm_state *x, struct km_event *c) | ||
1402 | { | ||
1403 | struct sk_buff *skb; | ||
1404 | int len = NLMSG_LENGTH(sizeof(struct xfrm_aevent_id)); | ||
1405 | |||
1406 | len += RTA_SPACE(sizeof(struct xfrm_replay_state)); | ||
1407 | len += RTA_SPACE(sizeof(struct xfrm_lifetime_cur)); | ||
1408 | skb = alloc_skb(len, GFP_ATOMIC); | ||
1409 | if (skb == NULL) | ||
1410 | return -ENOMEM; | ||
1411 | |||
1412 | if (build_aevent(skb, x, c) < 0) | ||
1413 | BUG(); | ||
1414 | |||
1415 | NETLINK_CB(skb).dst_group = XFRMNLGRP_AEVENTS; | ||
1416 | return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_AEVENTS, GFP_ATOMIC); | ||
1417 | } | ||
1418 | |||
1204 | static int xfrm_notify_sa_flush(struct km_event *c) | 1419 | static int xfrm_notify_sa_flush(struct km_event *c) |
1205 | { | 1420 | { |
1206 | struct xfrm_usersa_flush *p; | 1421 | struct xfrm_usersa_flush *p; |
@@ -1313,6 +1528,8 @@ static int xfrm_send_state_notify(struct xfrm_state *x, struct km_event *c) | |||
1313 | switch (c->event) { | 1528 | switch (c->event) { |
1314 | case XFRM_MSG_EXPIRE: | 1529 | case XFRM_MSG_EXPIRE: |
1315 | return xfrm_exp_state_notify(x, c); | 1530 | return xfrm_exp_state_notify(x, c); |
1531 | case XFRM_MSG_NEWAE: | ||
1532 | return xfrm_aevent_state_notify(x, c); | ||
1316 | case XFRM_MSG_DELSA: | 1533 | case XFRM_MSG_DELSA: |
1317 | case XFRM_MSG_UPDSA: | 1534 | case XFRM_MSG_UPDSA: |
1318 | case XFRM_MSG_NEWSA: | 1535 | case XFRM_MSG_NEWSA: |
@@ -1443,13 +1660,14 @@ static struct xfrm_policy *xfrm_compile_policy(u16 family, int opt, | |||
1443 | } | 1660 | } |
1444 | 1661 | ||
1445 | static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp, | 1662 | static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp, |
1446 | int dir, int hard) | 1663 | int dir, struct km_event *c) |
1447 | { | 1664 | { |
1448 | struct xfrm_user_polexpire *upe; | 1665 | struct xfrm_user_polexpire *upe; |
1449 | struct nlmsghdr *nlh; | 1666 | struct nlmsghdr *nlh; |
1667 | int hard = c->data.hard; | ||
1450 | unsigned char *b = skb->tail; | 1668 | unsigned char *b = skb->tail; |
1451 | 1669 | ||
1452 | nlh = NLMSG_PUT(skb, 0, 0, XFRM_MSG_POLEXPIRE, sizeof(*upe)); | 1670 | nlh = NLMSG_PUT(skb, c->pid, 0, XFRM_MSG_POLEXPIRE, sizeof(*upe)); |
1453 | upe = NLMSG_DATA(nlh); | 1671 | upe = NLMSG_DATA(nlh); |
1454 | nlh->nlmsg_flags = 0; | 1672 | nlh->nlmsg_flags = 0; |
1455 | 1673 | ||
@@ -1480,7 +1698,7 @@ static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_eve | |||
1480 | if (skb == NULL) | 1698 | if (skb == NULL) |
1481 | return -ENOMEM; | 1699 | return -ENOMEM; |
1482 | 1700 | ||
1483 | if (build_polexpire(skb, xp, dir, c->data.hard) < 0) | 1701 | if (build_polexpire(skb, xp, dir, c) < 0) |
1484 | BUG(); | 1702 | BUG(); |
1485 | 1703 | ||
1486 | NETLINK_CB(skb).dst_group = XFRMNLGRP_EXPIRE; | 1704 | NETLINK_CB(skb).dst_group = XFRMNLGRP_EXPIRE; |