diff options
Diffstat (limited to 'net/xfrm/xfrm_policy.c')
-rw-r--r-- | net/xfrm/xfrm_policy.c | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index ba924d40df7d..f6c77bd36fdd 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -50,6 +50,40 @@ static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo); | |||
50 | static struct xfrm_policy_afinfo *xfrm_policy_lock_afinfo(unsigned int family); | 50 | static struct xfrm_policy_afinfo *xfrm_policy_lock_afinfo(unsigned int family); |
51 | static void xfrm_policy_unlock_afinfo(struct xfrm_policy_afinfo *afinfo); | 51 | static void xfrm_policy_unlock_afinfo(struct xfrm_policy_afinfo *afinfo); |
52 | 52 | ||
53 | static inline int | ||
54 | __xfrm4_selector_match(struct xfrm_selector *sel, struct flowi *fl) | ||
55 | { | ||
56 | return addr_match(&fl->fl4_dst, &sel->daddr, sel->prefixlen_d) && | ||
57 | addr_match(&fl->fl4_src, &sel->saddr, sel->prefixlen_s) && | ||
58 | !((xfrm_flowi_dport(fl) ^ sel->dport) & sel->dport_mask) && | ||
59 | !((xfrm_flowi_sport(fl) ^ sel->sport) & sel->sport_mask) && | ||
60 | (fl->proto == sel->proto || !sel->proto) && | ||
61 | (fl->oif == sel->ifindex || !sel->ifindex); | ||
62 | } | ||
63 | |||
64 | static inline int | ||
65 | __xfrm6_selector_match(struct xfrm_selector *sel, struct flowi *fl) | ||
66 | { | ||
67 | return addr_match(&fl->fl6_dst, &sel->daddr, sel->prefixlen_d) && | ||
68 | addr_match(&fl->fl6_src, &sel->saddr, sel->prefixlen_s) && | ||
69 | !((xfrm_flowi_dport(fl) ^ sel->dport) & sel->dport_mask) && | ||
70 | !((xfrm_flowi_sport(fl) ^ sel->sport) & sel->sport_mask) && | ||
71 | (fl->proto == sel->proto || !sel->proto) && | ||
72 | (fl->oif == sel->ifindex || !sel->ifindex); | ||
73 | } | ||
74 | |||
75 | int xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl, | ||
76 | unsigned short family) | ||
77 | { | ||
78 | switch (family) { | ||
79 | case AF_INET: | ||
80 | return __xfrm4_selector_match(sel, fl); | ||
81 | case AF_INET6: | ||
82 | return __xfrm6_selector_match(sel, fl); | ||
83 | } | ||
84 | return 0; | ||
85 | } | ||
86 | |||
53 | int xfrm_register_type(struct xfrm_type *type, unsigned short family) | 87 | int xfrm_register_type(struct xfrm_type *type, unsigned short family) |
54 | { | 88 | { |
55 | struct xfrm_policy_afinfo *afinfo = xfrm_policy_lock_afinfo(family); | 89 | struct xfrm_policy_afinfo *afinfo = xfrm_policy_lock_afinfo(family); |
@@ -1177,6 +1211,7 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, struct flowi *fl, | |||
1177 | if (tmpl->mode == XFRM_MODE_TUNNEL) { | 1211 | if (tmpl->mode == XFRM_MODE_TUNNEL) { |
1178 | remote = &tmpl->id.daddr; | 1212 | remote = &tmpl->id.daddr; |
1179 | local = &tmpl->saddr; | 1213 | local = &tmpl->saddr; |
1214 | family = tmpl->encap_family; | ||
1180 | if (xfrm_addr_any(local, family)) { | 1215 | if (xfrm_addr_any(local, family)) { |
1181 | error = xfrm_get_saddr(&tmp, remote, family); | 1216 | error = xfrm_get_saddr(&tmp, remote, family); |
1182 | if (error) | 1217 | if (error) |
@@ -1894,7 +1929,8 @@ int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first, | |||
1894 | 1929 | ||
1895 | if (fl && !xfrm_selector_match(&dst->xfrm->sel, fl, family)) | 1930 | if (fl && !xfrm_selector_match(&dst->xfrm->sel, fl, family)) |
1896 | return 0; | 1931 | return 0; |
1897 | if (fl && !security_xfrm_flow_state_match(fl, dst->xfrm, pol)) | 1932 | if (fl && pol && |
1933 | !security_xfrm_state_pol_flow_match(dst->xfrm, pol, fl)) | ||
1898 | return 0; | 1934 | return 0; |
1899 | if (dst->xfrm->km.state != XFRM_STATE_VALID) | 1935 | if (dst->xfrm->km.state != XFRM_STATE_VALID) |
1900 | return 0; | 1936 | return 0; |