aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm
diff options
context:
space:
mode:
authorJamal Hadi Salim <hadi@cyberus.ca>2005-06-19 01:42:13 -0400
committerDavid S. Miller <davem@davemloft.net>2005-06-19 01:42:13 -0400
commit26b15dad9f1c19d6d4f7b999b07eaa6d98e4b375 (patch)
tree2ca3039488d9df023fb84eaa7c1f52aa8d1ce69c /net/xfrm
parent3aa3dfb372576f30835a94409556e3c8681b5756 (diff)
[IPSEC] Add complete xfrm event notification
Heres the final patch. What this patch provides - netlink xfrm events - ability to have events generated by netlink propagated to pfkey and vice versa. - fixes the acquire lets-be-happy-with-one-success issue Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'net/xfrm')
-rw-r--r--net/xfrm/xfrm_state.c74
-rw-r--r--net/xfrm/xfrm_user.c272
2 files changed, 321 insertions, 25 deletions
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index d11747c2a763..918a94c552a5 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -50,7 +50,7 @@ static DEFINE_SPINLOCK(xfrm_state_gc_lock);
50 50
51static int xfrm_state_gc_flush_bundles; 51static int xfrm_state_gc_flush_bundles;
52 52
53static void __xfrm_state_delete(struct xfrm_state *x); 53static int __xfrm_state_delete(struct xfrm_state *x);
54 54
55static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family); 55static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family);
56static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo); 56static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
@@ -215,8 +215,10 @@ void __xfrm_state_destroy(struct xfrm_state *x)
215} 215}
216EXPORT_SYMBOL(__xfrm_state_destroy); 216EXPORT_SYMBOL(__xfrm_state_destroy);
217 217
218static void __xfrm_state_delete(struct xfrm_state *x) 218static int __xfrm_state_delete(struct xfrm_state *x)
219{ 219{
220 int err = -ESRCH;
221
220 if (x->km.state != XFRM_STATE_DEAD) { 222 if (x->km.state != XFRM_STATE_DEAD) {
221 x->km.state = XFRM_STATE_DEAD; 223 x->km.state = XFRM_STATE_DEAD;
222 spin_lock(&xfrm_state_lock); 224 spin_lock(&xfrm_state_lock);
@@ -245,14 +247,21 @@ static void __xfrm_state_delete(struct xfrm_state *x)
245 * is what we are dropping here. 247 * is what we are dropping here.
246 */ 248 */
247 atomic_dec(&x->refcnt); 249 atomic_dec(&x->refcnt);
250 err = 0;
248 } 251 }
252
253 return err;
249} 254}
250 255
251void xfrm_state_delete(struct xfrm_state *x) 256int xfrm_state_delete(struct xfrm_state *x)
252{ 257{
258 int err;
259
253 spin_lock_bh(&x->lock); 260 spin_lock_bh(&x->lock);
254 __xfrm_state_delete(x); 261 err = __xfrm_state_delete(x);
255 spin_unlock_bh(&x->lock); 262 spin_unlock_bh(&x->lock);
263
264 return err;
256} 265}
257EXPORT_SYMBOL(xfrm_state_delete); 266EXPORT_SYMBOL(xfrm_state_delete);
258 267
@@ -796,34 +805,60 @@ EXPORT_SYMBOL(xfrm_replay_advance);
796static struct list_head xfrm_km_list = LIST_HEAD_INIT(xfrm_km_list); 805static struct list_head xfrm_km_list = LIST_HEAD_INIT(xfrm_km_list);
797static DEFINE_RWLOCK(xfrm_km_lock); 806static DEFINE_RWLOCK(xfrm_km_lock);
798 807
799static void km_state_expired(struct xfrm_state *x, int hard) 808void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)
800{ 809{
801 struct xfrm_mgr *km; 810 struct xfrm_mgr *km;
802 811
803 if (hard) 812 read_lock(&xfrm_km_lock);
804 x->km.state = XFRM_STATE_EXPIRED; 813 list_for_each_entry(km, &xfrm_km_list, list)
805 else 814 if (km->notify_policy)
806 x->km.dying = 1; 815 km->notify_policy(xp, dir, c);
816 read_unlock(&xfrm_km_lock);
817}
807 818
819void km_state_notify(struct xfrm_state *x, struct km_event *c)
820{
821 struct xfrm_mgr *km;
808 read_lock(&xfrm_km_lock); 822 read_lock(&xfrm_km_lock);
809 list_for_each_entry(km, &xfrm_km_list, list) 823 list_for_each_entry(km, &xfrm_km_list, list)
810 km->notify(x, hard); 824 if (km->notify)
825 km->notify(x, c);
811 read_unlock(&xfrm_km_lock); 826 read_unlock(&xfrm_km_lock);
827}
828
829EXPORT_SYMBOL(km_policy_notify);
830EXPORT_SYMBOL(km_state_notify);
831
832static void km_state_expired(struct xfrm_state *x, int hard)
833{
834 struct km_event c;
835
836 if (hard)
837 x->km.state = XFRM_STATE_EXPIRED;
838 else
839 x->km.dying = 1;
840 c.data = hard;
841 c.event = XFRM_SAP_EXPIRED;
842 km_state_notify(x, &c);
812 843
813 if (hard) 844 if (hard)
814 wake_up(&km_waitq); 845 wake_up(&km_waitq);
815} 846}
816 847
848/*
849 * We send to all registered managers regardless of failure
850 * We are happy with one success
851*/
817static int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol) 852static int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol)
818{ 853{
819 int err = -EINVAL; 854 int err = -EINVAL, acqret;
820 struct xfrm_mgr *km; 855 struct xfrm_mgr *km;
821 856
822 read_lock(&xfrm_km_lock); 857 read_lock(&xfrm_km_lock);
823 list_for_each_entry(km, &xfrm_km_list, list) { 858 list_for_each_entry(km, &xfrm_km_list, list) {
824 err = km->acquire(x, t, pol, XFRM_POLICY_OUT); 859 acqret = km->acquire(x, t, pol, XFRM_POLICY_OUT);
825 if (!err) 860 if (!acqret)
826 break; 861 err = acqret;
827 } 862 }
828 read_unlock(&xfrm_km_lock); 863 read_unlock(&xfrm_km_lock);
829 return err; 864 return err;
@@ -848,13 +883,12 @@ EXPORT_SYMBOL(km_new_mapping);
848 883
849void km_policy_expired(struct xfrm_policy *pol, int dir, int hard) 884void km_policy_expired(struct xfrm_policy *pol, int dir, int hard)
850{ 885{
851 struct xfrm_mgr *km; 886 struct km_event c;
852 887
853 read_lock(&xfrm_km_lock); 888 c.data = hard;
854 list_for_each_entry(km, &xfrm_km_list, list) 889 c.data = hard;
855 if (km->notify_policy) 890 c.event = XFRM_SAP_EXPIRED;
856 km->notify_policy(pol, dir, hard); 891 km_policy_notify(pol, dir, &c);
857 read_unlock(&xfrm_km_lock);
858 892
859 if (hard) 893 if (hard)
860 wake_up(&km_waitq); 894 wake_up(&km_waitq);
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 97509011c274..bd8e6882c083 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,27 @@ 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 return err;
297 } 300 }
298 301
302 c.seq = nlh->nlmsg_seq;
303 c.pid = nlh->nlmsg_pid;
304 if (nlh->nlmsg_type == XFRM_MSG_NEWSA)
305 c.event = XFRM_SAP_ADDED;
306 else
307 c.event = XFRM_SAP_UPDATED;
308
309 km_state_notify(x, &c);
310 xfrm_state_put(x);
311
299 return err; 312 return err;
300} 313}
301 314
302static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) 315static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
303{ 316{
304 struct xfrm_state *x; 317 struct xfrm_state *x;
318 int err;
319 struct km_event c;
305 struct xfrm_usersa_id *p = NLMSG_DATA(nlh); 320 struct xfrm_usersa_id *p = NLMSG_DATA(nlh);
306 321
307 x = xfrm_state_lookup(&p->daddr, p->spi, p->proto, p->family); 322 x = xfrm_state_lookup(&p->daddr, p->spi, p->proto, p->family);
@@ -313,10 +328,19 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
313 return -EPERM; 328 return -EPERM;
314 } 329 }
315 330
316 xfrm_state_delete(x); 331 err = xfrm_state_delete(x);
332 if (err < 0) {
333 xfrm_state_put(x);
334 return err;
335 }
336
337 c.seq = nlh->nlmsg_seq;
338 c.pid = nlh->nlmsg_pid;
339 c.event = XFRM_SAP_DELETED;
340 km_state_notify(x, &c);
317 xfrm_state_put(x); 341 xfrm_state_put(x);
318 342
319 return 0; 343 return err;
320} 344}
321 345
322static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p) 346static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p)
@@ -681,6 +705,7 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
681{ 705{
682 struct xfrm_userpolicy_info *p = NLMSG_DATA(nlh); 706 struct xfrm_userpolicy_info *p = NLMSG_DATA(nlh);
683 struct xfrm_policy *xp; 707 struct xfrm_policy *xp;
708 struct km_event c;
684 int err; 709 int err;
685 int excl; 710 int excl;
686 711
@@ -692,6 +717,10 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
692 if (!xp) 717 if (!xp)
693 return err; 718 return err;
694 719
720 /* shouldnt excl be based on nlh flags??
721 * Aha! this is anti-netlink really i.e more pfkey derived
722 * in netlink excl is a flag and you wouldnt need
723 * a type XFRM_MSG_UPDPOLICY - JHS */
695 excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY; 724 excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY;
696 err = xfrm_policy_insert(p->dir, xp, excl); 725 err = xfrm_policy_insert(p->dir, xp, excl);
697 if (err) { 726 if (err) {
@@ -699,6 +728,15 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
699 return err; 728 return err;
700 } 729 }
701 730
731 if (!excl)
732 c.event = XFRM_SAP_UPDATED;
733 else
734 c.event = XFRM_SAP_ADDED;
735
736 c.seq = nlh->nlmsg_seq;
737 c.pid = nlh->nlmsg_pid;
738 km_policy_notify(xp, p->dir, &c);
739
702 xfrm_pol_put(xp); 740 xfrm_pol_put(xp);
703 741
704 return 0; 742 return 0;
@@ -816,6 +854,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
816 struct xfrm_policy *xp; 854 struct xfrm_policy *xp;
817 struct xfrm_userpolicy_id *p; 855 struct xfrm_userpolicy_id *p;
818 int err; 856 int err;
857 struct km_event c;
819 int delete; 858 int delete;
820 859
821 p = NLMSG_DATA(nlh); 860 p = NLMSG_DATA(nlh);
@@ -843,6 +882,11 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
843 NETLINK_CB(skb).pid, 882 NETLINK_CB(skb).pid,
844 MSG_DONTWAIT); 883 MSG_DONTWAIT);
845 } 884 }
885 } else {
886 c.event = XFRM_SAP_DELETED;
887 c.seq = nlh->nlmsg_seq;
888 c.pid = nlh->nlmsg_pid;
889 km_policy_notify(xp, p->dir, &c);
846 } 890 }
847 891
848 xfrm_pol_put(xp); 892 xfrm_pol_put(xp);
@@ -852,15 +896,28 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
852 896
853static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) 897static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
854{ 898{
899 struct km_event c;
855 struct xfrm_usersa_flush *p = NLMSG_DATA(nlh); 900 struct xfrm_usersa_flush *p = NLMSG_DATA(nlh);
856 901
857 xfrm_state_flush(p->proto); 902 xfrm_state_flush(p->proto);
903 c.data = p->proto;
904 c.event = XFRM_SAP_FLUSHED;
905 c.seq = nlh->nlmsg_seq;
906 c.pid = nlh->nlmsg_pid;
907 km_state_notify(NULL, &c);
908
858 return 0; 909 return 0;
859} 910}
860 911
861static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) 912static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
862{ 913{
914 struct km_event c;
915
863 xfrm_policy_flush(); 916 xfrm_policy_flush();
917 c.event = XFRM_SAP_FLUSHED;
918 c.seq = nlh->nlmsg_seq;
919 c.pid = nlh->nlmsg_pid;
920 km_policy_notify(NULL, 0, &c);
864 return 0; 921 return 0;
865} 922}
866 923
@@ -1069,10 +1126,12 @@ nlmsg_failure:
1069 return -1; 1126 return -1;
1070} 1127}
1071 1128
1072static int xfrm_send_state_notify(struct xfrm_state *x, int hard) 1129static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c)
1073{ 1130{
1074 struct sk_buff *skb; 1131 struct sk_buff *skb;
1132 int hard = c ->data;
1075 1133
1134 /* fix to do alloc using NLM macros */
1076 skb = alloc_skb(sizeof(struct xfrm_user_expire) + 16, GFP_ATOMIC); 1135 skb = alloc_skb(sizeof(struct xfrm_user_expire) + 16, GFP_ATOMIC);
1077 if (skb == NULL) 1136 if (skb == NULL)
1078 return -ENOMEM; 1137 return -ENOMEM;
@@ -1085,6 +1144,122 @@ static int xfrm_send_state_notify(struct xfrm_state *x, int hard)
1085 return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_EXPIRE, GFP_ATOMIC); 1144 return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_EXPIRE, GFP_ATOMIC);
1086} 1145}
1087 1146
1147static int xfrm_notify_sa_flush(struct km_event *c)
1148{
1149 struct xfrm_usersa_flush *p;
1150 struct nlmsghdr *nlh;
1151 struct sk_buff *skb;
1152 unsigned char *b;
1153 int len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_flush));
1154
1155 skb = alloc_skb(len, GFP_ATOMIC);
1156 if (skb == NULL)
1157 return -ENOMEM;
1158 b = skb->tail;
1159
1160 nlh = NLMSG_PUT(skb, c->pid, c->seq,
1161 XFRM_MSG_FLUSHSA, sizeof(*p));
1162 nlh->nlmsg_flags = 0;
1163
1164 p = NLMSG_DATA(nlh);
1165 p->proto = c->data;
1166
1167 nlh->nlmsg_len = skb->tail - b;
1168
1169 return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_SA, GFP_ATOMIC);
1170
1171nlmsg_failure:
1172 kfree_skb(skb);
1173 return -1;
1174}
1175
1176static int inline xfrm_sa_len(struct xfrm_state *x)
1177{
1178 int l = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info));
1179 if (x->aalg)
1180 l += RTA_SPACE(sizeof(*x->aalg) + (x->aalg->alg_key_len+7)/8);
1181 if (x->ealg)
1182 l += RTA_SPACE(sizeof(*x->ealg) + (x->ealg->alg_key_len+7)/8);
1183 if (x->calg)
1184 l += RTA_SPACE(sizeof(*x->calg));
1185 if (x->encap)
1186 l += RTA_SPACE(sizeof(*x->encap));
1187
1188 return l;
1189}
1190
1191static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c)
1192{
1193 struct xfrm_usersa_info *p;
1194 struct nlmsghdr *nlh;
1195 struct sk_buff *skb;
1196 u32 nlt;
1197 unsigned char *b;
1198 int len = xfrm_sa_len(x);
1199
1200 skb = alloc_skb(len, GFP_ATOMIC);
1201 if (skb == NULL)
1202 return -ENOMEM;
1203 b = skb->tail;
1204
1205 if (c->event == XFRM_SAP_ADDED)
1206 nlt = XFRM_MSG_NEWSA;
1207 else if (c->event == XFRM_SAP_UPDATED)
1208 nlt = XFRM_MSG_UPDSA;
1209 else if (c->event == XFRM_SAP_DELETED)
1210 nlt = XFRM_MSG_DELSA;
1211 else
1212 goto nlmsg_failure;
1213
1214 nlh = NLMSG_PUT(skb, c->pid, c->seq, nlt, sizeof(*p));
1215 nlh->nlmsg_flags = 0;
1216
1217 p = NLMSG_DATA(nlh);
1218 copy_to_user_state(x, p);
1219
1220 if (x->aalg)
1221 RTA_PUT(skb, XFRMA_ALG_AUTH,
1222 sizeof(*(x->aalg))+(x->aalg->alg_key_len+7)/8, x->aalg);
1223 if (x->ealg)
1224 RTA_PUT(skb, XFRMA_ALG_CRYPT,
1225 sizeof(*(x->ealg))+(x->ealg->alg_key_len+7)/8, x->ealg);
1226 if (x->calg)
1227 RTA_PUT(skb, XFRMA_ALG_COMP, sizeof(*(x->calg)), x->calg);
1228
1229 if (x->encap)
1230 RTA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap);
1231
1232 nlh->nlmsg_len = skb->tail - b;
1233
1234 return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_SA, GFP_ATOMIC);
1235
1236nlmsg_failure:
1237rtattr_failure:
1238 kfree_skb(skb);
1239 return -1;
1240}
1241
1242static int xfrm_send_state_notify(struct xfrm_state *x, struct km_event *c)
1243{
1244
1245 switch (c->event) {
1246 case XFRM_SAP_EXPIRED:
1247 return xfrm_exp_state_notify(x, c);
1248 case XFRM_SAP_DELETED:
1249 case XFRM_SAP_UPDATED:
1250 case XFRM_SAP_ADDED:
1251 return xfrm_notify_sa(x, c);
1252 case XFRM_SAP_FLUSHED:
1253 return xfrm_notify_sa_flush(c);
1254 default:
1255 printk("xfrm_user: Unknown SA event %d\n", c->event);
1256 break;
1257 }
1258
1259 return 0;
1260
1261}
1262
1088static int build_acquire(struct sk_buff *skb, struct xfrm_state *x, 1263static int build_acquire(struct sk_buff *skb, struct xfrm_state *x,
1089 struct xfrm_tmpl *xt, struct xfrm_policy *xp, 1264 struct xfrm_tmpl *xt, struct xfrm_policy *xp,
1090 int dir) 1265 int dir)
@@ -1218,7 +1393,7 @@ nlmsg_failure:
1218 return -1; 1393 return -1;
1219} 1394}
1220 1395
1221static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, int hard) 1396static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)
1222{ 1397{
1223 struct sk_buff *skb; 1398 struct sk_buff *skb;
1224 size_t len; 1399 size_t len;
@@ -1229,7 +1404,7 @@ static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, int hard)
1229 if (skb == NULL) 1404 if (skb == NULL)
1230 return -ENOMEM; 1405 return -ENOMEM;
1231 1406
1232 if (build_polexpire(skb, xp, dir, hard) < 0) 1407 if (build_polexpire(skb, xp, dir, c->data) < 0)
1233 BUG(); 1408 BUG();
1234 1409
1235 NETLINK_CB(skb).dst_groups = XFRMGRP_EXPIRE; 1410 NETLINK_CB(skb).dst_groups = XFRMGRP_EXPIRE;
@@ -1237,6 +1412,93 @@ 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); 1412 return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_EXPIRE, GFP_ATOMIC);
1238} 1413}
1239 1414
1415static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c)
1416{
1417 struct xfrm_userpolicy_info *p;
1418 struct nlmsghdr *nlh;
1419 struct sk_buff *skb;
1420 u32 nlt = 0 ;
1421 unsigned char *b;
1422 int len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr);
1423 len += NLMSG_SPACE(sizeof(struct xfrm_userpolicy_info));
1424
1425 skb = alloc_skb(len, GFP_ATOMIC);
1426 if (skb == NULL)
1427 return -ENOMEM;
1428 b = skb->tail;
1429
1430 if (c->event == XFRM_SAP_ADDED)
1431 nlt = XFRM_MSG_NEWPOLICY;
1432 else if (c->event == XFRM_SAP_UPDATED)
1433 nlt = XFRM_MSG_UPDPOLICY;
1434 else if (c->event == XFRM_SAP_DELETED)
1435 nlt = XFRM_MSG_DELPOLICY;
1436 else
1437 goto nlmsg_failure;
1438
1439 nlh = NLMSG_PUT(skb, c->pid, c->seq, nlt, sizeof(*p));
1440
1441 p = NLMSG_DATA(nlh);
1442
1443 nlh->nlmsg_flags = 0;
1444
1445 copy_to_user_policy(xp, p, dir);
1446 if (copy_to_user_tmpl(xp, skb) < 0)
1447 goto nlmsg_failure;
1448
1449 nlh->nlmsg_len = skb->tail - b;
1450
1451 return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_POLICY, GFP_ATOMIC);
1452
1453nlmsg_failure:
1454 kfree_skb(skb);
1455 return -1;
1456}
1457
1458static int xfrm_notify_policy_flush(struct km_event *c)
1459{
1460 struct nlmsghdr *nlh;
1461 struct sk_buff *skb;
1462 unsigned char *b;
1463 int len = NLMSG_LENGTH(0);
1464
1465 skb = alloc_skb(len, GFP_ATOMIC);
1466 if (skb == NULL)
1467 return -ENOMEM;
1468 b = skb->tail;
1469
1470
1471 nlh = NLMSG_PUT(skb, c->pid, c->seq, XFRM_MSG_FLUSHPOLICY, 0);
1472
1473 nlh->nlmsg_len = skb->tail - b;
1474
1475 return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_POLICY, GFP_ATOMIC);
1476
1477nlmsg_failure:
1478 kfree_skb(skb);
1479 return -1;
1480}
1481
1482static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)
1483{
1484
1485 switch (c->event) {
1486 case XFRM_SAP_ADDED:
1487 case XFRM_SAP_UPDATED:
1488 case XFRM_SAP_DELETED:
1489 return xfrm_notify_policy(xp, dir, c);
1490 case XFRM_SAP_FLUSHED:
1491 return xfrm_notify_policy_flush(c);
1492 case XFRM_SAP_EXPIRED:
1493 return xfrm_exp_policy_notify(xp, dir, c);
1494 default:
1495 printk("xfrm_user: Unknown Policy event %d\n", c->event);
1496 }
1497
1498 return 0;
1499
1500}
1501
1240static struct xfrm_mgr netlink_mgr = { 1502static struct xfrm_mgr netlink_mgr = {
1241 .id = "netlink", 1503 .id = "netlink",
1242 .notify = xfrm_send_state_notify, 1504 .notify = xfrm_send_state_notify,