diff options
Diffstat (limited to 'net/ipv6/ip6_output.c')
-rw-r--r-- | net/ipv6/ip6_output.c | 80 |
1 files changed, 69 insertions, 11 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 5c618f20523e..28209b2d254d 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -1002,29 +1002,87 @@ int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl) | |||
1002 | EXPORT_SYMBOL_GPL(ip6_dst_lookup); | 1002 | EXPORT_SYMBOL_GPL(ip6_dst_lookup); |
1003 | 1003 | ||
1004 | /** | 1004 | /** |
1005 | * ip6_sk_dst_lookup - perform socket cached route lookup on flow | 1005 | * ip6_dst_lookup_flow - perform route lookup on flow with ipsec |
1006 | * @sk: socket which provides route info | ||
1007 | * @fl: flow to lookup | ||
1008 | * @final_dst: final destination address for ipsec lookup | ||
1009 | * @want_blackhole: IPSEC blackhole handling desired | ||
1010 | * | ||
1011 | * This function performs a route lookup on the given flow. | ||
1012 | * | ||
1013 | * It returns a valid dst pointer on success, or a pointer encoded | ||
1014 | * error code. | ||
1015 | */ | ||
1016 | struct dst_entry *ip6_dst_lookup_flow(struct sock *sk, struct flowi *fl, | ||
1017 | const struct in6_addr *final_dst, | ||
1018 | bool want_blackhole) | ||
1019 | { | ||
1020 | struct dst_entry *dst = NULL; | ||
1021 | int err; | ||
1022 | |||
1023 | err = ip6_dst_lookup_tail(sk, &dst, fl); | ||
1024 | if (err) | ||
1025 | return ERR_PTR(err); | ||
1026 | if (final_dst) | ||
1027 | ipv6_addr_copy(&fl->fl6_dst, final_dst); | ||
1028 | if (want_blackhole) { | ||
1029 | err = __xfrm_lookup(sock_net(sk), &dst, fl, sk, XFRM_LOOKUP_WAIT); | ||
1030 | if (err == -EREMOTE) | ||
1031 | err = ip6_dst_blackhole(sk, &dst, fl); | ||
1032 | if (err) | ||
1033 | return ERR_PTR(err); | ||
1034 | } else { | ||
1035 | err = xfrm_lookup(sock_net(sk), &dst, fl, sk, 0); | ||
1036 | if (err) | ||
1037 | return ERR_PTR(err); | ||
1038 | } | ||
1039 | return dst; | ||
1040 | } | ||
1041 | EXPORT_SYMBOL_GPL(ip6_dst_lookup_flow); | ||
1042 | |||
1043 | /** | ||
1044 | * ip6_sk_dst_lookup_flow - perform socket cached route lookup on flow | ||
1006 | * @sk: socket which provides the dst cache and route info | 1045 | * @sk: socket which provides the dst cache and route info |
1007 | * @dst: pointer to dst_entry * for result | ||
1008 | * @fl: flow to lookup | 1046 | * @fl: flow to lookup |
1047 | * @final_dst: final destination address for ipsec lookup | ||
1048 | * @want_blackhole: IPSEC blackhole handling desired | ||
1009 | * | 1049 | * |
1010 | * This function performs a route lookup on the given flow with the | 1050 | * This function performs a route lookup on the given flow with the |
1011 | * possibility of using the cached route in the socket if it is valid. | 1051 | * possibility of using the cached route in the socket if it is valid. |
1012 | * It will take the socket dst lock when operating on the dst cache. | 1052 | * It will take the socket dst lock when operating on the dst cache. |
1013 | * As a result, this function can only be used in process context. | 1053 | * As a result, this function can only be used in process context. |
1014 | * | 1054 | * |
1015 | * It returns zero on success, or a standard errno code on error. | 1055 | * It returns a valid dst pointer on success, or a pointer encoded |
1056 | * error code. | ||
1016 | */ | 1057 | */ |
1017 | int ip6_sk_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl) | 1058 | struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi *fl, |
1059 | const struct in6_addr *final_dst, | ||
1060 | bool want_blackhole) | ||
1018 | { | 1061 | { |
1019 | *dst = NULL; | 1062 | struct dst_entry *dst = sk_dst_check(sk, inet6_sk(sk)->dst_cookie); |
1020 | if (sk) { | 1063 | int err; |
1021 | *dst = sk_dst_check(sk, inet6_sk(sk)->dst_cookie); | ||
1022 | *dst = ip6_sk_dst_check(sk, *dst, fl); | ||
1023 | } | ||
1024 | 1064 | ||
1025 | return ip6_dst_lookup_tail(sk, dst, fl); | 1065 | dst = ip6_sk_dst_check(sk, dst, fl); |
1066 | |||
1067 | err = ip6_dst_lookup_tail(sk, &dst, fl); | ||
1068 | if (err) | ||
1069 | return ERR_PTR(err); | ||
1070 | if (final_dst) | ||
1071 | ipv6_addr_copy(&fl->fl6_dst, final_dst); | ||
1072 | if (want_blackhole) { | ||
1073 | err = __xfrm_lookup(sock_net(sk), &dst, fl, sk, XFRM_LOOKUP_WAIT); | ||
1074 | if (err == -EREMOTE) | ||
1075 | err = ip6_dst_blackhole(sk, &dst, fl); | ||
1076 | if (err) | ||
1077 | return ERR_PTR(err); | ||
1078 | } else { | ||
1079 | err = xfrm_lookup(sock_net(sk), &dst, fl, sk, 0); | ||
1080 | if (err) | ||
1081 | return ERR_PTR(err); | ||
1082 | } | ||
1083 | return dst; | ||
1026 | } | 1084 | } |
1027 | EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup); | 1085 | EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup_flow); |
1028 | 1086 | ||
1029 | static inline int ip6_ufo_append_data(struct sock *sk, | 1087 | static inline int ip6_ufo_append_data(struct sock *sk, |
1030 | int getfrag(void *from, char *to, int offset, int len, | 1088 | int getfrag(void *from, char *to, int offset, int len, |