| .. | .. |
|---|
| 12 | 12 | #include <linux/err.h> |
|---|
| 13 | 13 | #include <linux/kernel.h> |
|---|
| 14 | 14 | #include <linux/inetdevice.h> |
|---|
| 15 | | -#include <linux/if_tunnel.h> |
|---|
| 16 | 15 | #include <net/dst.h> |
|---|
| 17 | 16 | #include <net/xfrm.h> |
|---|
| 18 | 17 | #include <net/ip.h> |
|---|
| 19 | 18 | #include <net/l3mdev.h> |
|---|
| 20 | | -#include <net/inet_ecn.h> |
|---|
| 21 | 19 | |
|---|
| 22 | 20 | static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4, |
|---|
| 23 | 21 | int tos, int oif, |
|---|
| .. | .. |
|---|
| 70 | 68 | return 0; |
|---|
| 71 | 69 | } |
|---|
| 72 | 70 | |
|---|
| 73 | | -static int xfrm4_get_tos(const struct flowi *fl) |
|---|
| 74 | | -{ |
|---|
| 75 | | - return IPTOS_RT_MASK & fl->u.ip4.flowi4_tos; /* Strip ECN bits */ |
|---|
| 76 | | -} |
|---|
| 77 | | - |
|---|
| 78 | | -static int xfrm4_init_path(struct xfrm_dst *path, struct dst_entry *dst, |
|---|
| 79 | | - int nfheader_len) |
|---|
| 80 | | -{ |
|---|
| 81 | | - return 0; |
|---|
| 82 | | -} |
|---|
| 83 | | - |
|---|
| 84 | 71 | static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, |
|---|
| 85 | 72 | const struct flowi *fl) |
|---|
| 86 | 73 | { |
|---|
| .. | .. |
|---|
| 98 | 85 | xdst->u.rt.rt_flags = rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST | |
|---|
| 99 | 86 | RTCF_LOCAL); |
|---|
| 100 | 87 | xdst->u.rt.rt_type = rt->rt_type; |
|---|
| 101 | | - xdst->u.rt.rt_gateway = rt->rt_gateway; |
|---|
| 102 | 88 | xdst->u.rt.rt_uses_gateway = rt->rt_uses_gateway; |
|---|
| 89 | + xdst->u.rt.rt_gw_family = rt->rt_gw_family; |
|---|
| 90 | + if (rt->rt_gw_family == AF_INET) |
|---|
| 91 | + xdst->u.rt.rt_gw4 = rt->rt_gw4; |
|---|
| 92 | + else if (rt->rt_gw_family == AF_INET6) |
|---|
| 93 | + xdst->u.rt.rt_gw6 = rt->rt_gw6; |
|---|
| 103 | 94 | xdst->u.rt.rt_pmtu = rt->rt_pmtu; |
|---|
| 104 | 95 | xdst->u.rt.rt_mtu_locked = rt->rt_mtu_locked; |
|---|
| 105 | 96 | INIT_LIST_HEAD(&xdst->u.rt.rt_uncached); |
|---|
| 106 | 97 | rt_add_uncached_list(&xdst->u.rt); |
|---|
| 107 | 98 | |
|---|
| 108 | 99 | return 0; |
|---|
| 109 | | -} |
|---|
| 110 | | - |
|---|
| 111 | | -static void |
|---|
| 112 | | -_decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) |
|---|
| 113 | | -{ |
|---|
| 114 | | - const struct iphdr *iph = ip_hdr(skb); |
|---|
| 115 | | - int ihl = iph->ihl; |
|---|
| 116 | | - u8 *xprth = skb_network_header(skb) + ihl * 4; |
|---|
| 117 | | - struct flowi4 *fl4 = &fl->u.ip4; |
|---|
| 118 | | - int oif = 0; |
|---|
| 119 | | - |
|---|
| 120 | | - if (skb_dst(skb)) |
|---|
| 121 | | - oif = skb_dst(skb)->dev->ifindex; |
|---|
| 122 | | - |
|---|
| 123 | | - memset(fl4, 0, sizeof(struct flowi4)); |
|---|
| 124 | | - fl4->flowi4_mark = skb->mark; |
|---|
| 125 | | - fl4->flowi4_oif = reverse ? skb->skb_iif : oif; |
|---|
| 126 | | - |
|---|
| 127 | | - fl4->flowi4_proto = iph->protocol; |
|---|
| 128 | | - fl4->daddr = reverse ? iph->saddr : iph->daddr; |
|---|
| 129 | | - fl4->saddr = reverse ? iph->daddr : iph->saddr; |
|---|
| 130 | | - fl4->flowi4_tos = iph->tos & ~INET_ECN_MASK; |
|---|
| 131 | | - |
|---|
| 132 | | - if (!ip_is_fragment(iph)) { |
|---|
| 133 | | - switch (iph->protocol) { |
|---|
| 134 | | - case IPPROTO_UDP: |
|---|
| 135 | | - case IPPROTO_UDPLITE: |
|---|
| 136 | | - case IPPROTO_TCP: |
|---|
| 137 | | - case IPPROTO_SCTP: |
|---|
| 138 | | - case IPPROTO_DCCP: |
|---|
| 139 | | - if (xprth + 4 < skb->data || |
|---|
| 140 | | - pskb_may_pull(skb, xprth + 4 - skb->data)) { |
|---|
| 141 | | - __be16 *ports; |
|---|
| 142 | | - |
|---|
| 143 | | - xprth = skb_network_header(skb) + ihl * 4; |
|---|
| 144 | | - ports = (__be16 *)xprth; |
|---|
| 145 | | - |
|---|
| 146 | | - fl4->fl4_sport = ports[!!reverse]; |
|---|
| 147 | | - fl4->fl4_dport = ports[!reverse]; |
|---|
| 148 | | - } |
|---|
| 149 | | - break; |
|---|
| 150 | | - |
|---|
| 151 | | - case IPPROTO_ICMP: |
|---|
| 152 | | - if (xprth + 2 < skb->data || |
|---|
| 153 | | - pskb_may_pull(skb, xprth + 2 - skb->data)) { |
|---|
| 154 | | - u8 *icmp; |
|---|
| 155 | | - |
|---|
| 156 | | - xprth = skb_network_header(skb) + ihl * 4; |
|---|
| 157 | | - icmp = xprth; |
|---|
| 158 | | - |
|---|
| 159 | | - fl4->fl4_icmp_type = icmp[0]; |
|---|
| 160 | | - fl4->fl4_icmp_code = icmp[1]; |
|---|
| 161 | | - } |
|---|
| 162 | | - break; |
|---|
| 163 | | - |
|---|
| 164 | | - case IPPROTO_ESP: |
|---|
| 165 | | - if (xprth + 4 < skb->data || |
|---|
| 166 | | - pskb_may_pull(skb, xprth + 4 - skb->data)) { |
|---|
| 167 | | - __be32 *ehdr; |
|---|
| 168 | | - |
|---|
| 169 | | - xprth = skb_network_header(skb) + ihl * 4; |
|---|
| 170 | | - ehdr = (__be32 *)xprth; |
|---|
| 171 | | - |
|---|
| 172 | | - fl4->fl4_ipsec_spi = ehdr[0]; |
|---|
| 173 | | - } |
|---|
| 174 | | - break; |
|---|
| 175 | | - |
|---|
| 176 | | - case IPPROTO_AH: |
|---|
| 177 | | - if (xprth + 8 < skb->data || |
|---|
| 178 | | - pskb_may_pull(skb, xprth + 8 - skb->data)) { |
|---|
| 179 | | - __be32 *ah_hdr; |
|---|
| 180 | | - |
|---|
| 181 | | - xprth = skb_network_header(skb) + ihl * 4; |
|---|
| 182 | | - ah_hdr = (__be32 *)xprth; |
|---|
| 183 | | - |
|---|
| 184 | | - fl4->fl4_ipsec_spi = ah_hdr[1]; |
|---|
| 185 | | - } |
|---|
| 186 | | - break; |
|---|
| 187 | | - |
|---|
| 188 | | - case IPPROTO_COMP: |
|---|
| 189 | | - if (xprth + 4 < skb->data || |
|---|
| 190 | | - pskb_may_pull(skb, xprth + 4 - skb->data)) { |
|---|
| 191 | | - __be16 *ipcomp_hdr; |
|---|
| 192 | | - |
|---|
| 193 | | - xprth = skb_network_header(skb) + ihl * 4; |
|---|
| 194 | | - ipcomp_hdr = (__be16 *)xprth; |
|---|
| 195 | | - |
|---|
| 196 | | - fl4->fl4_ipsec_spi = htonl(ntohs(ipcomp_hdr[1])); |
|---|
| 197 | | - } |
|---|
| 198 | | - break; |
|---|
| 199 | | - |
|---|
| 200 | | - case IPPROTO_GRE: |
|---|
| 201 | | - if (xprth + 12 < skb->data || |
|---|
| 202 | | - pskb_may_pull(skb, xprth + 12 - skb->data)) { |
|---|
| 203 | | - __be16 *greflags; |
|---|
| 204 | | - __be32 *gre_hdr; |
|---|
| 205 | | - |
|---|
| 206 | | - xprth = skb_network_header(skb) + ihl * 4; |
|---|
| 207 | | - greflags = (__be16 *)xprth; |
|---|
| 208 | | - gre_hdr = (__be32 *)xprth; |
|---|
| 209 | | - |
|---|
| 210 | | - if (greflags[0] & GRE_KEY) { |
|---|
| 211 | | - if (greflags[0] & GRE_CSUM) |
|---|
| 212 | | - gre_hdr++; |
|---|
| 213 | | - fl4->fl4_gre_key = gre_hdr[1]; |
|---|
| 214 | | - } |
|---|
| 215 | | - } |
|---|
| 216 | | - break; |
|---|
| 217 | | - |
|---|
| 218 | | - default: |
|---|
| 219 | | - fl4->fl4_ipsec_spi = 0; |
|---|
| 220 | | - break; |
|---|
| 221 | | - } |
|---|
| 222 | | - } |
|---|
| 223 | 100 | } |
|---|
| 224 | 101 | |
|---|
| 225 | 102 | static void xfrm4_update_pmtu(struct dst_entry *dst, struct sock *sk, |
|---|
| .. | .. |
|---|
| 275 | 152 | .dst_ops = &xfrm4_dst_ops_template, |
|---|
| 276 | 153 | .dst_lookup = xfrm4_dst_lookup, |
|---|
| 277 | 154 | .get_saddr = xfrm4_get_saddr, |
|---|
| 278 | | - .decode_session = _decode_session4, |
|---|
| 279 | | - .get_tos = xfrm4_get_tos, |
|---|
| 280 | | - .init_path = xfrm4_init_path, |
|---|
| 281 | 155 | .fill_dst = xfrm4_fill_dst, |
|---|
| 282 | 156 | .blackhole_route = ipv4_blackhole_route, |
|---|
| 283 | 157 | }; |
|---|