diff options
Diffstat (limited to 'net/xfrm/xfrm_user.c')
| -rw-r--r-- | net/xfrm/xfrm_user.c | 288 |
1 files changed, 281 insertions, 7 deletions
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 97509011c274..5ce8558eac91 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,24 @@ 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 | goto out; | ||
| 297 | } | 300 | } |
| 298 | 301 | ||
| 302 | c.seq = nlh->nlmsg_seq; | ||
| 303 | c.pid = nlh->nlmsg_pid; | ||
| 304 | c.event = nlh->nlmsg_type; | ||
| 305 | |||
| 306 | km_state_notify(x, &c); | ||
| 307 | out: | ||
| 308 | xfrm_state_put(x); | ||
| 299 | return err; | 309 | return err; |
| 300 | } | 310 | } |
| 301 | 311 | ||
| 302 | static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) | 312 | static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) |
| 303 | { | 313 | { |
| 304 | struct xfrm_state *x; | 314 | struct xfrm_state *x; |
| 315 | int err; | ||
| 316 | struct km_event c; | ||
| 305 | struct xfrm_usersa_id *p = NLMSG_DATA(nlh); | 317 | struct xfrm_usersa_id *p = NLMSG_DATA(nlh); |
| 306 | 318 | ||
| 307 | x = xfrm_state_lookup(&p->daddr, p->spi, p->proto, p->family); | 319 | x = xfrm_state_lookup(&p->daddr, p->spi, p->proto, p->family); |
| @@ -313,10 +325,19 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) | |||
| 313 | return -EPERM; | 325 | return -EPERM; |
| 314 | } | 326 | } |
| 315 | 327 | ||
| 316 | xfrm_state_delete(x); | 328 | err = xfrm_state_delete(x); |
| 329 | if (err < 0) { | ||
| 330 | xfrm_state_put(x); | ||
| 331 | return err; | ||
| 332 | } | ||
| 333 | |||
| 334 | c.seq = nlh->nlmsg_seq; | ||
| 335 | c.pid = nlh->nlmsg_pid; | ||
| 336 | c.event = nlh->nlmsg_type; | ||
| 337 | km_state_notify(x, &c); | ||
| 317 | xfrm_state_put(x); | 338 | xfrm_state_put(x); |
| 318 | 339 | ||
| 319 | return 0; | 340 | return err; |
| 320 | } | 341 | } |
| 321 | 342 | ||
| 322 | static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p) | 343 | static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p) |
| @@ -681,6 +702,7 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr | |||
| 681 | { | 702 | { |
| 682 | struct xfrm_userpolicy_info *p = NLMSG_DATA(nlh); | 703 | struct xfrm_userpolicy_info *p = NLMSG_DATA(nlh); |
| 683 | struct xfrm_policy *xp; | 704 | struct xfrm_policy *xp; |
| 705 | struct km_event c; | ||
| 684 | int err; | 706 | int err; |
| 685 | int excl; | 707 | int excl; |
| 686 | 708 | ||
| @@ -692,6 +714,10 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr | |||
| 692 | if (!xp) | 714 | if (!xp) |
| 693 | return err; | 715 | return err; |
| 694 | 716 | ||
| 717 | /* shouldnt excl be based on nlh flags?? | ||
| 718 | * Aha! this is anti-netlink really i.e more pfkey derived | ||
| 719 | * in netlink excl is a flag and you wouldnt need | ||
| 720 | * a type XFRM_MSG_UPDPOLICY - JHS */ | ||
| 695 | excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY; | 721 | excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY; |
| 696 | err = xfrm_policy_insert(p->dir, xp, excl); | 722 | err = xfrm_policy_insert(p->dir, xp, excl); |
| 697 | if (err) { | 723 | if (err) { |
| @@ -699,6 +725,11 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr | |||
| 699 | return err; | 725 | return err; |
| 700 | } | 726 | } |
| 701 | 727 | ||
| 728 | c.event = nlh->nlmsg_type; | ||
| 729 | c.seq = nlh->nlmsg_seq; | ||
| 730 | c.pid = nlh->nlmsg_pid; | ||
| 731 | km_policy_notify(xp, p->dir, &c); | ||
| 732 | |||
| 702 | xfrm_pol_put(xp); | 733 | xfrm_pol_put(xp); |
| 703 | 734 | ||
| 704 | return 0; | 735 | return 0; |
| @@ -816,6 +847,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr | |||
| 816 | struct xfrm_policy *xp; | 847 | struct xfrm_policy *xp; |
| 817 | struct xfrm_userpolicy_id *p; | 848 | struct xfrm_userpolicy_id *p; |
| 818 | int err; | 849 | int err; |
| 850 | struct km_event c; | ||
| 819 | int delete; | 851 | int delete; |
| 820 | 852 | ||
| 821 | p = NLMSG_DATA(nlh); | 853 | p = NLMSG_DATA(nlh); |
| @@ -843,6 +875,12 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr | |||
| 843 | NETLINK_CB(skb).pid, | 875 | NETLINK_CB(skb).pid, |
| 844 | MSG_DONTWAIT); | 876 | MSG_DONTWAIT); |
| 845 | } | 877 | } |
| 878 | } else { | ||
| 879 | c.data.byid = p->index; | ||
| 880 | c.event = nlh->nlmsg_type; | ||
| 881 | c.seq = nlh->nlmsg_seq; | ||
| 882 | c.pid = nlh->nlmsg_pid; | ||
| 883 | km_policy_notify(xp, p->dir, &c); | ||
| 846 | } | 884 | } |
| 847 | 885 | ||
| 848 | xfrm_pol_put(xp); | 886 | xfrm_pol_put(xp); |
| @@ -852,15 +890,28 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr | |||
| 852 | 890 | ||
| 853 | static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) | 891 | static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) |
| 854 | { | 892 | { |
| 893 | struct km_event c; | ||
| 855 | struct xfrm_usersa_flush *p = NLMSG_DATA(nlh); | 894 | struct xfrm_usersa_flush *p = NLMSG_DATA(nlh); |
| 856 | 895 | ||
| 857 | xfrm_state_flush(p->proto); | 896 | xfrm_state_flush(p->proto); |
| 897 | c.data.proto = p->proto; | ||
| 898 | c.event = nlh->nlmsg_type; | ||
| 899 | c.seq = nlh->nlmsg_seq; | ||
| 900 | c.pid = nlh->nlmsg_pid; | ||
| 901 | km_state_notify(NULL, &c); | ||
| 902 | |||
| 858 | return 0; | 903 | return 0; |
| 859 | } | 904 | } |
| 860 | 905 | ||
| 861 | static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) | 906 | static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) |
| 862 | { | 907 | { |
| 908 | struct km_event c; | ||
| 909 | |||
| 863 | xfrm_policy_flush(); | 910 | xfrm_policy_flush(); |
| 911 | c.event = nlh->nlmsg_type; | ||
| 912 | c.seq = nlh->nlmsg_seq; | ||
| 913 | c.pid = nlh->nlmsg_pid; | ||
| 914 | km_policy_notify(NULL, 0, &c); | ||
| 864 | return 0; | 915 | return 0; |
| 865 | } | 916 | } |
| 866 | 917 | ||
| @@ -1069,15 +1120,16 @@ nlmsg_failure: | |||
| 1069 | return -1; | 1120 | return -1; |
| 1070 | } | 1121 | } |
| 1071 | 1122 | ||
| 1072 | static int xfrm_send_state_notify(struct xfrm_state *x, int hard) | 1123 | static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c) |
| 1073 | { | 1124 | { |
| 1074 | struct sk_buff *skb; | 1125 | struct sk_buff *skb; |
| 1126 | int len = NLMSG_LENGTH(sizeof(struct xfrm_user_expire)); | ||
| 1075 | 1127 | ||
| 1076 | skb = alloc_skb(sizeof(struct xfrm_user_expire) + 16, GFP_ATOMIC); | 1128 | skb = alloc_skb(len, GFP_ATOMIC); |
| 1077 | if (skb == NULL) | 1129 | if (skb == NULL) |
| 1078 | return -ENOMEM; | 1130 | return -ENOMEM; |
| 1079 | 1131 | ||
| 1080 | if (build_expire(skb, x, hard) < 0) | 1132 | if (build_expire(skb, x, c->data.hard) < 0) |
| 1081 | BUG(); | 1133 | BUG(); |
| 1082 | 1134 | ||
| 1083 | NETLINK_CB(skb).dst_groups = XFRMGRP_EXPIRE; | 1135 | NETLINK_CB(skb).dst_groups = XFRMGRP_EXPIRE; |
| @@ -1085,6 +1137,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); | 1137 | return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_EXPIRE, GFP_ATOMIC); |
| 1086 | } | 1138 | } |
| 1087 | 1139 | ||
| 1140 | static int xfrm_notify_sa_flush(struct km_event *c) | ||
| 1141 | { | ||
| 1142 | struct xfrm_usersa_flush *p; | ||
| 1143 | struct nlmsghdr *nlh; | ||
| 1144 | struct sk_buff *skb; | ||
| 1145 | unsigned char *b; | ||
| 1146 | int len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_flush)); | ||
| 1147 | |||
| 1148 | skb = alloc_skb(len, GFP_ATOMIC); | ||
| 1149 | if (skb == NULL) | ||
| 1150 | return -ENOMEM; | ||
| 1151 | b = skb->tail; | ||
| 1152 | |||
| 1153 | nlh = NLMSG_PUT(skb, c->pid, c->seq, | ||
| 1154 | XFRM_MSG_FLUSHSA, sizeof(*p)); | ||
| 1155 | nlh->nlmsg_flags = 0; | ||
| 1156 | |||
| 1157 | p = NLMSG_DATA(nlh); | ||
| 1158 | p->proto = c->data.proto; | ||
| 1159 | |||
| 1160 | nlh->nlmsg_len = skb->tail - b; | ||
| 1161 | |||
| 1162 | return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_SA, GFP_ATOMIC); | ||
| 1163 | |||
| 1164 | nlmsg_failure: | ||
| 1165 | kfree_skb(skb); | ||
| 1166 | return -1; | ||
| 1167 | } | ||
| 1168 | |||
| 1169 | static int inline xfrm_sa_len(struct xfrm_state *x) | ||
| 1170 | { | ||
| 1171 | int l = 0; | ||
| 1172 | if (x->aalg) | ||
| 1173 | l += RTA_SPACE(sizeof(*x->aalg) + (x->aalg->alg_key_len+7)/8); | ||
| 1174 | if (x->ealg) | ||
| 1175 | l += RTA_SPACE(sizeof(*x->ealg) + (x->ealg->alg_key_len+7)/8); | ||
| 1176 | if (x->calg) | ||
| 1177 | l += RTA_SPACE(sizeof(*x->calg)); | ||
| 1178 | if (x->encap) | ||
| 1179 | l += RTA_SPACE(sizeof(*x->encap)); | ||
| 1180 | |||
| 1181 | return l; | ||
| 1182 | } | ||
| 1183 | |||
| 1184 | static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c) | ||
| 1185 | { | ||
| 1186 | struct xfrm_usersa_info *p; | ||
| 1187 | struct xfrm_usersa_id *id; | ||
| 1188 | struct nlmsghdr *nlh; | ||
| 1189 | struct sk_buff *skb; | ||
| 1190 | unsigned char *b; | ||
| 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); | ||
| 1200 | |||
| 1201 | skb = alloc_skb(len, GFP_ATOMIC); | ||
| 1202 | if (skb == NULL) | ||
| 1203 | return -ENOMEM; | ||
| 1204 | b = skb->tail; | ||
| 1205 | |||
| 1206 | nlh = NLMSG_PUT(skb, c->pid, c->seq, c->event, headlen); | ||
| 1207 | nlh->nlmsg_flags = 0; | ||
| 1208 | |||
| 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 | |||
| 1220 | copy_to_user_state(x, p); | ||
| 1221 | |||
| 1222 | if (x->aalg) | ||
| 1223 | RTA_PUT(skb, XFRMA_ALG_AUTH, | ||
| 1224 | sizeof(*(x->aalg))+(x->aalg->alg_key_len+7)/8, x->aalg); | ||
| 1225 | if (x->ealg) | ||
| 1226 | RTA_PUT(skb, XFRMA_ALG_CRYPT, | ||
| 1227 | sizeof(*(x->ealg))+(x->ealg->alg_key_len+7)/8, x->ealg); | ||
| 1228 | if (x->calg) | ||
| 1229 | RTA_PUT(skb, XFRMA_ALG_COMP, sizeof(*(x->calg)), x->calg); | ||
| 1230 | |||
| 1231 | if (x->encap) | ||
| 1232 | RTA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap); | ||
| 1233 | |||
| 1234 | nlh->nlmsg_len = skb->tail - b; | ||
| 1235 | |||
| 1236 | return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_SA, GFP_ATOMIC); | ||
| 1237 | |||
| 1238 | nlmsg_failure: | ||
| 1239 | rtattr_failure: | ||
| 1240 | kfree_skb(skb); | ||
| 1241 | return -1; | ||
| 1242 | } | ||
| 1243 | |||
| 1244 | static int xfrm_send_state_notify(struct xfrm_state *x, struct km_event *c) | ||
| 1245 | { | ||
| 1246 | |||
| 1247 | switch (c->event) { | ||
| 1248 | case XFRM_MSG_EXPIRE: | ||
| 1249 | return xfrm_exp_state_notify(x, c); | ||
| 1250 | case XFRM_MSG_DELSA: | ||
| 1251 | case XFRM_MSG_UPDSA: | ||
| 1252 | case XFRM_MSG_NEWSA: | ||
| 1253 | return xfrm_notify_sa(x, c); | ||
| 1254 | case XFRM_MSG_FLUSHSA: | ||
| 1255 | return xfrm_notify_sa_flush(c); | ||
| 1256 | default: | ||
| 1257 | printk("xfrm_user: Unknown SA event %d\n", c->event); | ||
| 1258 | break; | ||
| 1259 | } | ||
| 1260 | |||
| 1261 | return 0; | ||
| 1262 | |||
| 1263 | } | ||
| 1264 | |||
| 1088 | static int build_acquire(struct sk_buff *skb, struct xfrm_state *x, | 1265 | static int build_acquire(struct sk_buff *skb, struct xfrm_state *x, |
| 1089 | struct xfrm_tmpl *xt, struct xfrm_policy *xp, | 1266 | struct xfrm_tmpl *xt, struct xfrm_policy *xp, |
| 1090 | int dir) | 1267 | int dir) |
| @@ -1218,7 +1395,7 @@ nlmsg_failure: | |||
| 1218 | return -1; | 1395 | return -1; |
| 1219 | } | 1396 | } |
| 1220 | 1397 | ||
| 1221 | static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, int hard) | 1398 | static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c) |
| 1222 | { | 1399 | { |
| 1223 | struct sk_buff *skb; | 1400 | struct sk_buff *skb; |
| 1224 | size_t len; | 1401 | size_t len; |
| @@ -1229,7 +1406,7 @@ static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, int hard) | |||
| 1229 | if (skb == NULL) | 1406 | if (skb == NULL) |
| 1230 | return -ENOMEM; | 1407 | return -ENOMEM; |
| 1231 | 1408 | ||
| 1232 | if (build_polexpire(skb, xp, dir, hard) < 0) | 1409 | if (build_polexpire(skb, xp, dir, c->data.hard) < 0) |
| 1233 | BUG(); | 1410 | BUG(); |
| 1234 | 1411 | ||
| 1235 | NETLINK_CB(skb).dst_groups = XFRMGRP_EXPIRE; | 1412 | NETLINK_CB(skb).dst_groups = XFRMGRP_EXPIRE; |
| @@ -1237,6 +1414,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); | 1414 | return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_EXPIRE, GFP_ATOMIC); |
| 1238 | } | 1415 | } |
| 1239 | 1416 | ||
| 1417 | static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c) | ||
| 1418 | { | ||
| 1419 | struct xfrm_userpolicy_info *p; | ||
| 1420 | struct xfrm_userpolicy_id *id; | ||
| 1421 | struct nlmsghdr *nlh; | ||
| 1422 | struct sk_buff *skb; | ||
| 1423 | unsigned char *b; | ||
| 1424 | int len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr); | ||
| 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); | ||
| 1433 | |||
| 1434 | skb = alloc_skb(len, GFP_ATOMIC); | ||
| 1435 | if (skb == NULL) | ||
| 1436 | return -ENOMEM; | ||
| 1437 | b = skb->tail; | ||
| 1438 | |||
| 1439 | nlh = NLMSG_PUT(skb, c->pid, c->seq, c->event, headlen); | ||
| 1440 | |||
| 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 | } | ||
| 1453 | |||
| 1454 | nlh->nlmsg_flags = 0; | ||
| 1455 | |||
| 1456 | copy_to_user_policy(xp, p, dir); | ||
| 1457 | if (copy_to_user_tmpl(xp, skb) < 0) | ||
| 1458 | goto nlmsg_failure; | ||
| 1459 | |||
| 1460 | nlh->nlmsg_len = skb->tail - b; | ||
| 1461 | |||
| 1462 | return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_POLICY, GFP_ATOMIC); | ||
| 1463 | |||
| 1464 | nlmsg_failure: | ||
| 1465 | rtattr_failure: | ||
| 1466 | kfree_skb(skb); | ||
| 1467 | return -1; | ||
| 1468 | } | ||
| 1469 | |||
| 1470 | static int xfrm_notify_policy_flush(struct km_event *c) | ||
| 1471 | { | ||
| 1472 | struct nlmsghdr *nlh; | ||
| 1473 | struct sk_buff *skb; | ||
| 1474 | unsigned char *b; | ||
| 1475 | int len = NLMSG_LENGTH(0); | ||
| 1476 | |||
| 1477 | skb = alloc_skb(len, GFP_ATOMIC); | ||
| 1478 | if (skb == NULL) | ||
| 1479 | return -ENOMEM; | ||
| 1480 | b = skb->tail; | ||
| 1481 | |||
| 1482 | |||
| 1483 | nlh = NLMSG_PUT(skb, c->pid, c->seq, XFRM_MSG_FLUSHPOLICY, 0); | ||
| 1484 | |||
| 1485 | nlh->nlmsg_len = skb->tail - b; | ||
| 1486 | |||
| 1487 | return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_POLICY, GFP_ATOMIC); | ||
| 1488 | |||
| 1489 | nlmsg_failure: | ||
| 1490 | kfree_skb(skb); | ||
| 1491 | return -1; | ||
| 1492 | } | ||
| 1493 | |||
| 1494 | static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c) | ||
| 1495 | { | ||
| 1496 | |||
| 1497 | switch (c->event) { | ||
| 1498 | case XFRM_MSG_NEWPOLICY: | ||
| 1499 | case XFRM_MSG_UPDPOLICY: | ||
| 1500 | case XFRM_MSG_DELPOLICY: | ||
| 1501 | return xfrm_notify_policy(xp, dir, c); | ||
| 1502 | case XFRM_MSG_FLUSHPOLICY: | ||
| 1503 | return xfrm_notify_policy_flush(c); | ||
| 1504 | case XFRM_MSG_POLEXPIRE: | ||
| 1505 | return xfrm_exp_policy_notify(xp, dir, c); | ||
| 1506 | default: | ||
| 1507 | printk("xfrm_user: Unknown Policy event %d\n", c->event); | ||
| 1508 | } | ||
| 1509 | |||
| 1510 | return 0; | ||
| 1511 | |||
| 1512 | } | ||
| 1513 | |||
| 1240 | static struct xfrm_mgr netlink_mgr = { | 1514 | static struct xfrm_mgr netlink_mgr = { |
| 1241 | .id = "netlink", | 1515 | .id = "netlink", |
| 1242 | .notify = xfrm_send_state_notify, | 1516 | .notify = xfrm_send_state_notify, |
