aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm
diff options
context:
space:
mode:
Diffstat (limited to 'net/xfrm')
-rw-r--r--net/xfrm/xfrm_policy.c8
-rw-r--r--net/xfrm/xfrm_state.c81
-rw-r--r--net/xfrm/xfrm_user.c288
3 files changed, 342 insertions, 35 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index d07f5ce31824..0a4260719a12 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -216,8 +216,8 @@ out:
216 216
217expired: 217expired:
218 read_unlock(&xp->lock); 218 read_unlock(&xp->lock);
219 km_policy_expired(xp, dir, 1); 219 if (!xfrm_policy_delete(xp, dir))
220 xfrm_policy_delete(xp, dir); 220 km_policy_expired(xp, dir, 1);
221 xfrm_pol_put(xp); 221 xfrm_pol_put(xp);
222} 222}
223 223
@@ -555,7 +555,7 @@ static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol,
555 return NULL; 555 return NULL;
556} 556}
557 557
558void xfrm_policy_delete(struct xfrm_policy *pol, int dir) 558int xfrm_policy_delete(struct xfrm_policy *pol, int dir)
559{ 559{
560 write_lock_bh(&xfrm_policy_lock); 560 write_lock_bh(&xfrm_policy_lock);
561 pol = __xfrm_policy_unlink(pol, dir); 561 pol = __xfrm_policy_unlink(pol, dir);
@@ -564,7 +564,9 @@ void xfrm_policy_delete(struct xfrm_policy *pol, int dir)
564 if (dir < XFRM_POLICY_MAX) 564 if (dir < XFRM_POLICY_MAX)
565 atomic_inc(&flow_cache_genid); 565 atomic_inc(&flow_cache_genid);
566 xfrm_policy_kill(pol); 566 xfrm_policy_kill(pol);
567 return 0;
567 } 568 }
569 return -ENOENT;
568} 570}
569 571
570int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol) 572int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol)
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index d11747c2a763..2537f26f097c 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);
@@ -154,6 +154,7 @@ static void xfrm_timer_handler(unsigned long data)
154 next = tmo; 154 next = tmo;
155 } 155 }
156 156
157 x->km.dying = warn;
157 if (warn) 158 if (warn)
158 km_state_expired(x, 0); 159 km_state_expired(x, 0);
159resched: 160resched:
@@ -169,9 +170,8 @@ expired:
169 next = 2; 170 next = 2;
170 goto resched; 171 goto resched;
171 } 172 }
172 if (x->id.spi != 0) 173 if (!__xfrm_state_delete(x) && x->id.spi)
173 km_state_expired(x, 1); 174 km_state_expired(x, 1);
174 __xfrm_state_delete(x);
175 175
176out: 176out:
177 spin_unlock(&x->lock); 177 spin_unlock(&x->lock);
@@ -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
@@ -557,16 +566,18 @@ int xfrm_state_check_expire(struct xfrm_state *x)
557 566
558 if (x->curlft.bytes >= x->lft.hard_byte_limit || 567 if (x->curlft.bytes >= x->lft.hard_byte_limit ||
559 x->curlft.packets >= x->lft.hard_packet_limit) { 568 x->curlft.packets >= x->lft.hard_packet_limit) {
560 km_state_expired(x, 1); 569 x->km.state = XFRM_STATE_EXPIRED;
561 if (!mod_timer(&x->timer, jiffies + XFRM_ACQ_EXPIRES*HZ)) 570 if (!mod_timer(&x->timer, jiffies))
562 xfrm_state_hold(x); 571 xfrm_state_hold(x);
563 return -EINVAL; 572 return -EINVAL;
564 } 573 }
565 574
566 if (!x->km.dying && 575 if (!x->km.dying &&
567 (x->curlft.bytes >= x->lft.soft_byte_limit || 576 (x->curlft.bytes >= x->lft.soft_byte_limit ||
568 x->curlft.packets >= x->lft.soft_packet_limit)) 577 x->curlft.packets >= x->lft.soft_packet_limit)) {
578 x->km.dying = 1;
569 km_state_expired(x, 0); 579 km_state_expired(x, 0);
580 }
570 return 0; 581 return 0;
571} 582}
572EXPORT_SYMBOL(xfrm_state_check_expire); 583EXPORT_SYMBOL(xfrm_state_check_expire);
@@ -796,34 +807,56 @@ EXPORT_SYMBOL(xfrm_replay_advance);
796static struct list_head xfrm_km_list = LIST_HEAD_INIT(xfrm_km_list); 807static struct list_head xfrm_km_list = LIST_HEAD_INIT(xfrm_km_list);
797static DEFINE_RWLOCK(xfrm_km_lock); 808static DEFINE_RWLOCK(xfrm_km_lock);
798 809
799static void km_state_expired(struct xfrm_state *x, int hard) 810void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)
800{ 811{
801 struct xfrm_mgr *km; 812 struct xfrm_mgr *km;
802 813
803 if (hard) 814 read_lock(&xfrm_km_lock);
804 x->km.state = XFRM_STATE_EXPIRED; 815 list_for_each_entry(km, &xfrm_km_list, list)
805 else 816 if (km->notify_policy)
806 x->km.dying = 1; 817 km->notify_policy(xp, dir, c);
818 read_unlock(&xfrm_km_lock);
819}
807 820
821void km_state_notify(struct xfrm_state *x, struct km_event *c)
822{
823 struct xfrm_mgr *km;
808 read_lock(&xfrm_km_lock); 824 read_lock(&xfrm_km_lock);
809 list_for_each_entry(km, &xfrm_km_list, list) 825 list_for_each_entry(km, &xfrm_km_list, list)
810 km->notify(x, hard); 826 if (km->notify)
827 km->notify(x, c);
811 read_unlock(&xfrm_km_lock); 828 read_unlock(&xfrm_km_lock);
829}
830
831EXPORT_SYMBOL(km_policy_notify);
832EXPORT_SYMBOL(km_state_notify);
833
834static void km_state_expired(struct xfrm_state *x, int hard)
835{
836 struct km_event c;
837
838 c.data.hard = hard;
839 c.event = XFRM_MSG_EXPIRE;
840 km_state_notify(x, &c);
812 841
813 if (hard) 842 if (hard)
814 wake_up(&km_waitq); 843 wake_up(&km_waitq);
815} 844}
816 845
846/*
847 * We send to all registered managers regardless of failure
848 * We are happy with one success
849*/
817static int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol) 850static int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol)
818{ 851{
819 int err = -EINVAL; 852 int err = -EINVAL, acqret;
820 struct xfrm_mgr *km; 853 struct xfrm_mgr *km;
821 854
822 read_lock(&xfrm_km_lock); 855 read_lock(&xfrm_km_lock);
823 list_for_each_entry(km, &xfrm_km_list, list) { 856 list_for_each_entry(km, &xfrm_km_list, list) {
824 err = km->acquire(x, t, pol, XFRM_POLICY_OUT); 857 acqret = km->acquire(x, t, pol, XFRM_POLICY_OUT);
825 if (!err) 858 if (!acqret)
826 break; 859 err = acqret;
827 } 860 }
828 read_unlock(&xfrm_km_lock); 861 read_unlock(&xfrm_km_lock);
829 return err; 862 return err;
@@ -848,13 +881,11 @@ EXPORT_SYMBOL(km_new_mapping);
848 881
849void km_policy_expired(struct xfrm_policy *pol, int dir, int hard) 882void km_policy_expired(struct xfrm_policy *pol, int dir, int hard)
850{ 883{
851 struct xfrm_mgr *km; 884 struct km_event c;
852 885
853 read_lock(&xfrm_km_lock); 886 c.data.hard = hard;
854 list_for_each_entry(km, &xfrm_km_list, list) 887 c.event = XFRM_MSG_POLEXPIRE;
855 if (km->notify_policy) 888 km_policy_notify(pol, dir, &c);
856 km->notify_policy(pol, dir, hard);
857 read_unlock(&xfrm_km_lock);
858 889
859 if (hard) 890 if (hard)
860 wake_up(&km_waitq); 891 wake_up(&km_waitq);
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);
307out:
308 xfrm_state_put(x);
299 return err; 309 return err;
300} 310}
301 311
302static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) 312static 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
322static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p) 343static 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
853static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) 891static 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
861static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) 906static 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
1072static int xfrm_send_state_notify(struct xfrm_state *x, int hard) 1123static 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
1140static 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
1164nlmsg_failure:
1165 kfree_skb(skb);
1166 return -1;
1167}
1168
1169static 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
1184static 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
1238nlmsg_failure:
1239rtattr_failure:
1240 kfree_skb(skb);
1241 return -1;
1242}
1243
1244static 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
1088static int build_acquire(struct sk_buff *skb, struct xfrm_state *x, 1265static 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
1221static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, int hard) 1398static 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
1417static 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
1464nlmsg_failure:
1465rtattr_failure:
1466 kfree_skb(skb);
1467 return -1;
1468}
1469
1470static 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
1489nlmsg_failure:
1490 kfree_skb(skb);
1491 return -1;
1492}
1493
1494static 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
1240static struct xfrm_mgr netlink_mgr = { 1514static struct xfrm_mgr netlink_mgr = {
1241 .id = "netlink", 1515 .id = "netlink",
1242 .notify = xfrm_send_state_notify, 1516 .notify = xfrm_send_state_notify,