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 ---