xfrm_state.c (12604d8aaa38ac4e24299c9803fefdb301a16421) | xfrm_state.c (5447c5e401c49aba0c36bb1066f2d25b152553b7) |
---|---|
1/* 2 * xfrm_state.c 3 * 4 * Changes: 5 * Mitsuru KANDA @USAGI 6 * Kazunori MIYAZAWA @USAGI 7 * Kunihiro Ishiguro <kunihiro@ipinfusion.com> 8 * IPv6 support --- 751 unchanged lines hidden (view full) --- 760} 761 762struct xfrm_state * 763xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, 764 struct flowi *fl, struct xfrm_tmpl *tmpl, 765 struct xfrm_policy *pol, int *err, 766 unsigned short family) 767{ | 1/* 2 * xfrm_state.c 3 * 4 * Changes: 5 * Mitsuru KANDA @USAGI 6 * Kazunori MIYAZAWA @USAGI 7 * Kunihiro Ishiguro <kunihiro@ipinfusion.com> 8 * IPv6 support --- 751 unchanged lines hidden (view full) --- 760} 761 762struct xfrm_state * 763xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, 764 struct flowi *fl, struct xfrm_tmpl *tmpl, 765 struct xfrm_policy *pol, int *err, 766 unsigned short family) 767{ |
768 struct net *net = xp_net(pol); |
|
768 unsigned int h; 769 struct hlist_node *entry; 770 struct xfrm_state *x, *x0, *to_put; 771 int acquire_in_progress = 0; 772 int error = 0; 773 struct xfrm_state *best = NULL; 774 775 to_put = NULL; 776 777 spin_lock_bh(&xfrm_state_lock); | 769 unsigned int h; 770 struct hlist_node *entry; 771 struct xfrm_state *x, *x0, *to_put; 772 int acquire_in_progress = 0; 773 int error = 0; 774 struct xfrm_state *best = NULL; 775 776 to_put = NULL; 777 778 spin_lock_bh(&xfrm_state_lock); |
778 h = xfrm_dst_hash(&init_net, daddr, saddr, tmpl->reqid, family); 779 hlist_for_each_entry(x, entry, init_net.xfrm.state_bydst+h, bydst) { | 779 h = xfrm_dst_hash(net, daddr, saddr, tmpl->reqid, family); 780 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { |
780 if (x->props.family == family && 781 x->props.reqid == tmpl->reqid && 782 !(x->props.flags & XFRM_STATE_WILDRECV) && 783 xfrm_state_addr_check(x, daddr, saddr, family) && 784 tmpl->mode == x->props.mode && 785 tmpl->id.proto == x->id.proto && 786 (tmpl->id.spi == x->id.spi || !tmpl->id.spi)) { 787 /* Resolution logic: --- 27 unchanged lines hidden (view full) --- 815 error = -ESRCH; 816 } 817 } 818 } 819 820 x = best; 821 if (!x && !error && !acquire_in_progress) { 822 if (tmpl->id.spi && | 781 if (x->props.family == family && 782 x->props.reqid == tmpl->reqid && 783 !(x->props.flags & XFRM_STATE_WILDRECV) && 784 xfrm_state_addr_check(x, daddr, saddr, family) && 785 tmpl->mode == x->props.mode && 786 tmpl->id.proto == x->id.proto && 787 (tmpl->id.spi == x->id.spi || !tmpl->id.spi)) { 788 /* Resolution logic: --- 27 unchanged lines hidden (view full) --- 816 error = -ESRCH; 817 } 818 } 819 } 820 821 x = best; 822 if (!x && !error && !acquire_in_progress) { 823 if (tmpl->id.spi && |
823 (x0 = __xfrm_state_lookup(&init_net, daddr, tmpl->id.spi, | 824 (x0 = __xfrm_state_lookup(net, daddr, tmpl->id.spi, |
824 tmpl->id.proto, family)) != NULL) { 825 to_put = x0; 826 error = -EEXIST; 827 goto out; 828 } | 825 tmpl->id.proto, family)) != NULL) { 826 to_put = x0; 827 error = -EEXIST; 828 goto out; 829 } |
829 x = xfrm_state_alloc(&init_net); | 830 x = xfrm_state_alloc(net); |
830 if (x == NULL) { 831 error = -ENOMEM; 832 goto out; 833 } 834 /* Initialize temporary selector matching only 835 * to current session. */ 836 xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family); 837 838 error = security_xfrm_state_alloc_acquire(x, pol->security, fl->secid); 839 if (error) { 840 x->km.state = XFRM_STATE_DEAD; 841 to_put = x; 842 x = NULL; 843 goto out; 844 } 845 846 if (km_query(x, tmpl, pol) == 0) { 847 x->km.state = XFRM_STATE_ACQ; | 831 if (x == NULL) { 832 error = -ENOMEM; 833 goto out; 834 } 835 /* Initialize temporary selector matching only 836 * to current session. */ 837 xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family); 838 839 error = security_xfrm_state_alloc_acquire(x, pol->security, fl->secid); 840 if (error) { 841 x->km.state = XFRM_STATE_DEAD; 842 to_put = x; 843 x = NULL; 844 goto out; 845 } 846 847 if (km_query(x, tmpl, pol) == 0) { 848 x->km.state = XFRM_STATE_ACQ; |
848 list_add(&x->km.all, &init_net.xfrm.state_all); 849 hlist_add_head(&x->bydst, init_net.xfrm.state_bydst+h); 850 h = xfrm_src_hash(&init_net, daddr, saddr, family); 851 hlist_add_head(&x->bysrc, init_net.xfrm.state_bysrc+h); | 849 list_add(&x->km.all, &net->xfrm.state_all); 850 hlist_add_head(&x->bydst, net->xfrm.state_bydst+h); 851 h = xfrm_src_hash(net, daddr, saddr, family); 852 hlist_add_head(&x->bysrc, net->xfrm.state_bysrc+h); |
852 if (x->id.spi) { | 853 if (x->id.spi) { |
853 h = xfrm_spi_hash(&init_net, &x->id.daddr, x->id.spi, x->id.proto, family); 854 hlist_add_head(&x->byspi, init_net.xfrm.state_byspi+h); | 854 h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, family); 855 hlist_add_head(&x->byspi, net->xfrm.state_byspi+h); |
855 } 856 x->lft.hard_add_expires_seconds = sysctl_xfrm_acq_expires; 857 x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ; 858 add_timer(&x->timer); | 856 } 857 x->lft.hard_add_expires_seconds = sysctl_xfrm_acq_expires; 858 x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ; 859 add_timer(&x->timer); |
859 init_net.xfrm.state_num++; 860 xfrm_hash_grow_check(&init_net, x->bydst.next != NULL); | 860 net->xfrm.state_num++; 861 xfrm_hash_grow_check(net, x->bydst.next != NULL); |
861 } else { 862 x->km.state = XFRM_STATE_DEAD; 863 to_put = x; 864 x = NULL; 865 error = -ESRCH; 866 } 867 } 868out: 869 if (x) 870 xfrm_state_hold(x); 871 else 872 *err = acquire_in_progress ? -EAGAIN : error; 873 spin_unlock_bh(&xfrm_state_lock); 874 if (to_put) 875 xfrm_state_put(to_put); 876 return x; 877} 878 879struct xfrm_state * | 862 } else { 863 x->km.state = XFRM_STATE_DEAD; 864 to_put = x; 865 x = NULL; 866 error = -ESRCH; 867 } 868 } 869out: 870 if (x) 871 xfrm_state_hold(x); 872 else 873 *err = acquire_in_progress ? -EAGAIN : error; 874 spin_unlock_bh(&xfrm_state_lock); 875 if (to_put) 876 xfrm_state_put(to_put); 877 return x; 878} 879 880struct xfrm_state * |
880xfrm_stateonly_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | 881xfrm_stateonly_find(struct net *net, 882 xfrm_address_t *daddr, xfrm_address_t *saddr, |
881 unsigned short family, u8 mode, u8 proto, u32 reqid) 882{ 883 unsigned int h; 884 struct xfrm_state *rx = NULL, *x = NULL; 885 struct hlist_node *entry; 886 887 spin_lock(&xfrm_state_lock); | 883 unsigned short family, u8 mode, u8 proto, u32 reqid) 884{ 885 unsigned int h; 886 struct xfrm_state *rx = NULL, *x = NULL; 887 struct hlist_node *entry; 888 889 spin_lock(&xfrm_state_lock); |
888 h = xfrm_dst_hash(&init_net, daddr, saddr, reqid, family); 889 hlist_for_each_entry(x, entry, init_net.xfrm.state_bydst+h, bydst) { | 890 h = xfrm_dst_hash(net, daddr, saddr, reqid, family); 891 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { |
890 if (x->props.family == family && 891 x->props.reqid == reqid && 892 !(x->props.flags & XFRM_STATE_WILDRECV) && 893 xfrm_state_addr_check(x, daddr, saddr, family) && 894 mode == x->props.mode && 895 proto == x->id.proto && 896 x->km.state == XFRM_STATE_VALID) { 897 rx = x; --- 69 unchanged lines hidden (view full) --- 967 spin_lock_bh(&xfrm_state_lock); 968 __xfrm_state_bump_genids(x); 969 __xfrm_state_insert(x); 970 spin_unlock_bh(&xfrm_state_lock); 971} 972EXPORT_SYMBOL(xfrm_state_insert); 973 974/* xfrm_state_lock is held */ | 892 if (x->props.family == family && 893 x->props.reqid == reqid && 894 !(x->props.flags & XFRM_STATE_WILDRECV) && 895 xfrm_state_addr_check(x, daddr, saddr, family) && 896 mode == x->props.mode && 897 proto == x->id.proto && 898 x->km.state == XFRM_STATE_VALID) { 899 rx = x; --- 69 unchanged lines hidden (view full) --- 969 spin_lock_bh(&xfrm_state_lock); 970 __xfrm_state_bump_genids(x); 971 __xfrm_state_insert(x); 972 spin_unlock_bh(&xfrm_state_lock); 973} 974EXPORT_SYMBOL(xfrm_state_insert); 975 976/* xfrm_state_lock is held */ |
975static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 reqid, u8 proto, xfrm_address_t *daddr, xfrm_address_t *saddr, int create) | 977static struct xfrm_state *__find_acq_core(struct net *net, unsigned short family, u8 mode, u32 reqid, u8 proto, xfrm_address_t *daddr, xfrm_address_t *saddr, int create) |
976{ | 978{ |
977 unsigned int h = xfrm_dst_hash(&init_net, daddr, saddr, reqid, family); | 979 unsigned int h = xfrm_dst_hash(net, daddr, saddr, reqid, family); |
978 struct hlist_node *entry; 979 struct xfrm_state *x; 980 | 980 struct hlist_node *entry; 981 struct xfrm_state *x; 982 |
981 hlist_for_each_entry(x, entry, init_net.xfrm.state_bydst+h, bydst) { | 983 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+h, bydst) { |
982 if (x->props.reqid != reqid || 983 x->props.mode != mode || 984 x->props.family != family || 985 x->km.state != XFRM_STATE_ACQ || 986 x->id.spi != 0 || 987 x->id.proto != proto) 988 continue; 989 --- 15 unchanged lines hidden (view full) --- 1005 1006 xfrm_state_hold(x); 1007 return x; 1008 } 1009 1010 if (!create) 1011 return NULL; 1012 | 984 if (x->props.reqid != reqid || 985 x->props.mode != mode || 986 x->props.family != family || 987 x->km.state != XFRM_STATE_ACQ || 988 x->id.spi != 0 || 989 x->id.proto != proto) 990 continue; 991 --- 15 unchanged lines hidden (view full) --- 1007 1008 xfrm_state_hold(x); 1009 return x; 1010 } 1011 1012 if (!create) 1013 return NULL; 1014 |
1013 x = xfrm_state_alloc(&init_net); | 1015 x = xfrm_state_alloc(net); |
1014 if (likely(x)) { 1015 switch (family) { 1016 case AF_INET: 1017 x->sel.daddr.a4 = daddr->a4; 1018 x->sel.saddr.a4 = saddr->a4; 1019 x->sel.prefixlen_d = 32; 1020 x->sel.prefixlen_s = 32; 1021 x->props.saddr.a4 = saddr->a4; --- 18 unchanged lines hidden (view full) --- 1040 x->id.proto = proto; 1041 x->props.family = family; 1042 x->props.mode = mode; 1043 x->props.reqid = reqid; 1044 x->lft.hard_add_expires_seconds = sysctl_xfrm_acq_expires; 1045 xfrm_state_hold(x); 1046 x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ; 1047 add_timer(&x->timer); | 1016 if (likely(x)) { 1017 switch (family) { 1018 case AF_INET: 1019 x->sel.daddr.a4 = daddr->a4; 1020 x->sel.saddr.a4 = saddr->a4; 1021 x->sel.prefixlen_d = 32; 1022 x->sel.prefixlen_s = 32; 1023 x->props.saddr.a4 = saddr->a4; --- 18 unchanged lines hidden (view full) --- 1042 x->id.proto = proto; 1043 x->props.family = family; 1044 x->props.mode = mode; 1045 x->props.reqid = reqid; 1046 x->lft.hard_add_expires_seconds = sysctl_xfrm_acq_expires; 1047 xfrm_state_hold(x); 1048 x->timer.expires = jiffies + sysctl_xfrm_acq_expires*HZ; 1049 add_timer(&x->timer); |
1048 list_add(&x->km.all, &init_net.xfrm.state_all); 1049 hlist_add_head(&x->bydst, init_net.xfrm.state_bydst+h); 1050 h = xfrm_src_hash(&init_net, daddr, saddr, family); 1051 hlist_add_head(&x->bysrc, init_net.xfrm.state_bysrc+h); | 1050 list_add(&x->km.all, &net->xfrm.state_all); 1051 hlist_add_head(&x->bydst, net->xfrm.state_bydst+h); 1052 h = xfrm_src_hash(net, daddr, saddr, family); 1053 hlist_add_head(&x->bysrc, net->xfrm.state_bysrc+h); |
1052 | 1054 |
1053 init_net.xfrm.state_num++; | 1055 net->xfrm.state_num++; |
1054 | 1056 |
1055 xfrm_hash_grow_check(&init_net, x->bydst.next != NULL); | 1057 xfrm_hash_grow_check(net, x->bydst.next != NULL); |
1056 } 1057 1058 return x; 1059} 1060 | 1058 } 1059 1060 return x; 1061} 1062 |
1061static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq); | 1063static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 seq); |
1062 1063int xfrm_state_add(struct xfrm_state *x) 1064{ | 1064 1065int xfrm_state_add(struct xfrm_state *x) 1066{ |
1067 struct net *net = xs_net(x); |
|
1065 struct xfrm_state *x1, *to_put; 1066 int family; 1067 int err; 1068 int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY); 1069 1070 family = x->props.family; 1071 1072 to_put = NULL; --- 4 unchanged lines hidden (view full) --- 1077 if (x1) { 1078 to_put = x1; 1079 x1 = NULL; 1080 err = -EEXIST; 1081 goto out; 1082 } 1083 1084 if (use_spi && x->km.seq) { | 1068 struct xfrm_state *x1, *to_put; 1069 int family; 1070 int err; 1071 int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY); 1072 1073 family = x->props.family; 1074 1075 to_put = NULL; --- 4 unchanged lines hidden (view full) --- 1080 if (x1) { 1081 to_put = x1; 1082 x1 = NULL; 1083 err = -EEXIST; 1084 goto out; 1085 } 1086 1087 if (use_spi && x->km.seq) { |
1085 x1 = __xfrm_find_acq_byseq(x->km.seq); | 1088 x1 = __xfrm_find_acq_byseq(net, x->km.seq); |
1086 if (x1 && ((x1->id.proto != x->id.proto) || 1087 xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family))) { 1088 to_put = x1; 1089 x1 = NULL; 1090 } 1091 } 1092 1093 if (use_spi && !x1) | 1089 if (x1 && ((x1->id.proto != x->id.proto) || 1090 xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family))) { 1091 to_put = x1; 1092 x1 = NULL; 1093 } 1094 } 1095 1096 if (use_spi && !x1) |
1094 x1 = __find_acq_core(family, x->props.mode, x->props.reqid, | 1097 x1 = __find_acq_core(net, family, x->props.mode, x->props.reqid, |
1095 x->id.proto, 1096 &x->id.daddr, &x->props.saddr, 0); 1097 1098 __xfrm_state_bump_genids(x); 1099 __xfrm_state_insert(x); 1100 err = 0; 1101 1102out: --- 282 unchanged lines hidden (view full) --- 1385 spin_lock_bh(&xfrm_state_lock); 1386 x = __xfrm_state_lookup_byaddr(net, daddr, saddr, proto, family); 1387 spin_unlock_bh(&xfrm_state_lock); 1388 return x; 1389} 1390EXPORT_SYMBOL(xfrm_state_lookup_byaddr); 1391 1392struct xfrm_state * | 1098 x->id.proto, 1099 &x->id.daddr, &x->props.saddr, 0); 1100 1101 __xfrm_state_bump_genids(x); 1102 __xfrm_state_insert(x); 1103 err = 0; 1104 1105out: --- 282 unchanged lines hidden (view full) --- 1388 spin_lock_bh(&xfrm_state_lock); 1389 x = __xfrm_state_lookup_byaddr(net, daddr, saddr, proto, family); 1390 spin_unlock_bh(&xfrm_state_lock); 1391 return x; 1392} 1393EXPORT_SYMBOL(xfrm_state_lookup_byaddr); 1394 1395struct xfrm_state * |
1393xfrm_find_acq(u8 mode, u32 reqid, u8 proto, | 1396xfrm_find_acq(struct net *net, u8 mode, u32 reqid, u8 proto, |
1394 xfrm_address_t *daddr, xfrm_address_t *saddr, 1395 int create, unsigned short family) 1396{ 1397 struct xfrm_state *x; 1398 1399 spin_lock_bh(&xfrm_state_lock); | 1397 xfrm_address_t *daddr, xfrm_address_t *saddr, 1398 int create, unsigned short family) 1399{ 1400 struct xfrm_state *x; 1401 1402 spin_lock_bh(&xfrm_state_lock); |
1400 x = __find_acq_core(family, mode, reqid, proto, daddr, saddr, create); | 1403 x = __find_acq_core(net, family, mode, reqid, proto, daddr, saddr, create); |
1401 spin_unlock_bh(&xfrm_state_lock); 1402 1403 return x; 1404} 1405EXPORT_SYMBOL(xfrm_find_acq); 1406 1407#ifdef CONFIG_XFRM_SUB_POLICY 1408int --- 30 unchanged lines hidden (view full) --- 1439 xfrm_state_put_afinfo(afinfo); 1440 return err; 1441} 1442EXPORT_SYMBOL(xfrm_state_sort); 1443#endif 1444 1445/* Silly enough, but I'm lazy to build resolution list */ 1446 | 1404 spin_unlock_bh(&xfrm_state_lock); 1405 1406 return x; 1407} 1408EXPORT_SYMBOL(xfrm_find_acq); 1409 1410#ifdef CONFIG_XFRM_SUB_POLICY 1411int --- 30 unchanged lines hidden (view full) --- 1442 xfrm_state_put_afinfo(afinfo); 1443 return err; 1444} 1445EXPORT_SYMBOL(xfrm_state_sort); 1446#endif 1447 1448/* Silly enough, but I'm lazy to build resolution list */ 1449 |
1447static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq) | 1450static struct xfrm_state *__xfrm_find_acq_byseq(struct net *net, u32 seq) |
1448{ 1449 int i; 1450 | 1451{ 1452 int i; 1453 |
1451 for (i = 0; i <= init_net.xfrm.state_hmask; i++) { | 1454 for (i = 0; i <= net->xfrm.state_hmask; i++) { |
1452 struct hlist_node *entry; 1453 struct xfrm_state *x; 1454 | 1455 struct hlist_node *entry; 1456 struct xfrm_state *x; 1457 |
1455 hlist_for_each_entry(x, entry, init_net.xfrm.state_bydst+i, bydst) { | 1458 hlist_for_each_entry(x, entry, net->xfrm.state_bydst+i, bydst) { |
1456 if (x->km.seq == seq && 1457 x->km.state == XFRM_STATE_ACQ) { 1458 xfrm_state_hold(x); 1459 return x; 1460 } 1461 } 1462 } 1463 return NULL; 1464} 1465 | 1459 if (x->km.seq == seq && 1460 x->km.state == XFRM_STATE_ACQ) { 1461 xfrm_state_hold(x); 1462 return x; 1463 } 1464 } 1465 } 1466 return NULL; 1467} 1468 |
1466struct xfrm_state *xfrm_find_acq_byseq(u32 seq) | 1469struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 seq) |
1467{ 1468 struct xfrm_state *x; 1469 1470 spin_lock_bh(&xfrm_state_lock); | 1470{ 1471 struct xfrm_state *x; 1472 1473 spin_lock_bh(&xfrm_state_lock); |
1471 x = __xfrm_find_acq_byseq(seq); | 1474 x = __xfrm_find_acq_byseq(net, seq); |
1472 spin_unlock_bh(&xfrm_state_lock); 1473 return x; 1474} 1475EXPORT_SYMBOL(xfrm_find_acq_byseq); 1476 1477u32 xfrm_get_acqseq(void) 1478{ 1479 u32 res; --- 812 unchanged lines hidden --- | 1475 spin_unlock_bh(&xfrm_state_lock); 1476 return x; 1477} 1478EXPORT_SYMBOL(xfrm_find_acq_byseq); 1479 1480u32 xfrm_get_acqseq(void) 1481{ 1482 u32 res; --- 812 unchanged lines hidden --- |