Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[IPSEC]: Use IPv6 calling convention as the convention for x->mode->output

The IPv6 calling convention for x->mode->output is more general and could
help an eventual protocol-generic x->type->output implementation. This
patch adopts it for IPv4 as well and modifies the IPv4 type output functions
accordingly.

It also rewrites the IPv6 mac/transport header calculation to be based off
the network header where practical.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Herbert Xu and committed by
David S. Miller
37fedd3a 7b277b1a

+44 -67
+12
include/net/xfrm.h
··· 300 300 301 301 struct xfrm_mode { 302 302 int (*input)(struct xfrm_state *x, struct sk_buff *skb); 303 + 304 + /* 305 + * Add encapsulation header. 306 + * 307 + * On exit, the transport header will be set to the start of the 308 + * encapsulation header to be filled in by x->type->output and 309 + * the mac header will be set to the nextheader (protocol for 310 + * IPv4) field of the extension header directly preceding the 311 + * encapsulation header, or in its absence, that of the top IP 312 + * header. The value of the network header will always point 313 + * to the top IP header while skb->data will point to the payload. 314 + */ 303 315 int (*output)(struct xfrm_state *x,struct sk_buff *skb); 304 316 305 317 struct module *owner;
+3 -3
net/ipv4/ah4.c
··· 82 82 goto error; 83 83 } 84 84 85 - ah = (struct ip_auth_hdr *)((char *)top_iph+top_iph->ihl*4); 86 - ah->nexthdr = top_iph->protocol; 85 + ah = (struct ip_auth_hdr *)skb_transport_header(skb); 86 + ah->nexthdr = *skb_mac_header(skb); 87 + *skb_mac_header(skb) = IPPROTO_AH; 87 88 88 89 top_iph->tos = 0; 89 90 top_iph->tot_len = htons(skb->len); 90 91 top_iph->frag_off = 0; 91 92 top_iph->ttl = 0; 92 - top_iph->protocol = IPPROTO_AH; 93 93 top_iph->check = 0; 94 94 95 95 ahp = x->data;
+5 -6
net/ipv4/esp4.c
··· 60 60 61 61 skb_push(skb, -skb_network_offset(skb)); 62 62 top_iph = ip_hdr(skb); 63 - esph = (struct ip_esp_hdr *)(skb_network_header(skb) + 64 - top_iph->ihl * 4); 63 + esph = (struct ip_esp_hdr *)skb_transport_header(skb); 65 64 top_iph->tot_len = htons(skb->len + alen); 66 - *(skb_tail_pointer(trailer) - 1) = top_iph->protocol; 65 + *(skb_tail_pointer(trailer) - 1) = *skb_mac_header(skb); 66 + *skb_mac_header(skb) = IPPROTO_ESP; 67 67 68 68 spin_lock_bh(&x->lock); 69 69 ··· 91 91 break; 92 92 } 93 93 94 - top_iph->protocol = IPPROTO_UDP; 95 - } else 96 - top_iph->protocol = IPPROTO_ESP; 94 + *skb_mac_header(skb) = IPPROTO_UDP; 95 + } 97 96 98 97 esph->spi = x->id.spi; 99 98 esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq);
+5 -5
net/ipv4/ipcomp.c
··· 98 98 static int ipcomp_compress(struct xfrm_state *x, struct sk_buff *skb) 99 99 { 100 100 struct ipcomp_data *ipcd = x->data; 101 - const int ihlen = ip_hdrlen(skb); 101 + const int ihlen = skb_transport_offset(skb); 102 102 const int plen = skb->len - ihlen; 103 103 int dlen = IPCOMP_SCRATCH_SIZE; 104 - u8 *start = skb->data + ihlen; 104 + u8 *start = skb_transport_header(skb); 105 105 const int cpu = get_cpu(); 106 106 u8 *scratch = *per_cpu_ptr(ipcomp_scratches, cpu); 107 107 struct crypto_comp *tfm = *per_cpu_ptr(ipcd->tfms, cpu); ··· 154 154 155 155 /* Install ipcomp header, convert into ipcomp datagram. */ 156 156 iph->tot_len = htons(skb->len); 157 - ipch = (struct ip_comp_hdr *)((char *)iph + iph->ihl * 4); 158 - ipch->nexthdr = iph->protocol; 157 + ipch = (struct ip_comp_hdr *)skb_transport_header(skb); 158 + ipch->nexthdr = *skb_mac_header(skb); 159 159 ipch->flags = 0; 160 160 ipch->cpi = htons((u16 )ntohl(x->id.spi)); 161 - iph->protocol = IPPROTO_COMP; 161 + *skb_mac_header(skb) = IPPROTO_COMP; 162 162 ip_send_check(iph); 163 163 return 0; 164 164
+7 -10
net/ipv4/xfrm4_mode_beet.c
··· 23 23 * The following fields in it shall be filled in by x->type->output: 24 24 * tot_len 25 25 * check 26 - * 27 - * On exit, skb->h will be set to the start of the payload to be processed 28 - * by x->type->output and skb->nh will be set to the top IP header. 29 26 */ 30 27 static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb) 31 28 { 29 + struct ip_beet_phdr *ph; 32 30 struct iphdr *iph, *top_iph; 33 31 int hdrlen, optlen; 34 32 35 33 iph = ip_hdr(skb); 36 - skb->transport_header = skb->network_header; 37 34 38 35 hdrlen = 0; 39 36 optlen = iph->ihl * 4 - sizeof(*iph); ··· 39 42 40 43 skb_set_network_header(skb, IPV4_BEET_PHMAXLEN - x->props.header_len - 41 44 hdrlen); 42 - top_iph = ip_hdr(skb); 43 - skb->transport_header += sizeof(*iph) - hdrlen; 44 - __skb_pull(skb, sizeof(*iph) - hdrlen); 45 + skb->mac_header = skb->network_header + 46 + offsetof(struct iphdr, protocol); 47 + skb->transport_header = skb->network_header + sizeof(*iph); 45 48 49 + ph = (struct ip_beet_phdr *)__skb_pull(skb, sizeof(*iph) - hdrlen); 50 + 51 + top_iph = ip_hdr(skb); 46 52 memmove(top_iph, iph, sizeof(*iph)); 47 53 if (unlikely(optlen)) { 48 - struct ip_beet_phdr *ph; 49 - 50 54 BUG_ON(optlen < 0); 51 55 52 - ph = (struct ip_beet_phdr *)skb_transport_header(skb); 53 56 ph->padlen = 4 - (optlen & 4); 54 57 ph->hdrlen = optlen / 8; 55 58 ph->nexthdr = top_iph->protocol;
+3 -4
net/ipv4/xfrm4_mode_transport.c
··· 17 17 * 18 18 * The IP header will be moved forward to make space for the encapsulation 19 19 * header. 20 - * 21 - * On exit, skb->h will be set to the start of the payload to be processed 22 - * by x->type->output and skb->nh will be set to the top IP header. 23 20 */ 24 21 static int xfrm4_transport_output(struct xfrm_state *x, struct sk_buff *skb) 25 22 { 26 23 struct iphdr *iph = ip_hdr(skb); 27 24 int ihl = iph->ihl * 4; 28 25 29 - skb->transport_header = skb->network_header + ihl; 30 26 skb_set_network_header(skb, -x->props.header_len); 27 + skb->mac_header = skb->network_header + 28 + offsetof(struct iphdr, protocol); 29 + skb->transport_header = skb->network_header + ihl; 31 30 __skb_pull(skb, ihl); 32 31 memmove(skb_network_header(skb), iph, ihl); 33 32 return 0;
+3 -4
net/ipv4/xfrm4_mode_tunnel.c
··· 35 35 * in it shall be filled in by x->type->output: 36 36 * tot_len 37 37 * check 38 - * 39 - * On exit, skb->h will be set to the start of the payload to be processed 40 - * by x->type->output and skb->nh will be set to the top IP header. 41 38 */ 42 39 static int xfrm4_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) 43 40 { ··· 44 47 int flags; 45 48 46 49 iph = ip_hdr(skb); 47 - skb->transport_header = skb->network_header; 48 50 49 51 skb_set_network_header(skb, -x->props.header_len); 52 + skb->mac_header = skb->network_header + 53 + offsetof(struct iphdr, protocol); 54 + skb->transport_header = skb->network_header + sizeof(*iph); 50 55 top_iph = ip_hdr(skb); 51 56 52 57 top_iph->ihl = 5;
+1 -8
net/ipv6/xfrm6_mode_beet.c
··· 24 24 * The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt. 25 25 * The following fields in it shall be filled in by x->type->output: 26 26 * payload_len 27 - * 28 - * On exit, skb->h will be set to the start of the encapsulation header to be 29 - * filled in by x->type->output and the mac header will be set to the 30 - * nextheader field of the extension header directly preceding the 31 - * encapsulation header, or in its absence, that of the top IP header. 32 - * The value of the network header will always point to the top IP header 33 - * while skb->data will point to the payload. 34 27 */ 35 28 static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb) 36 29 { ··· 37 44 38 45 skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data); 39 46 skb_set_network_header(skb, -x->props.header_len); 40 - skb_set_transport_header(skb, hdr_len - x->props.header_len); 47 + skb->transport_header = skb->network_header + hdr_len; 41 48 __skb_pull(skb, hdr_len); 42 49 43 50 top_iph = ipv6_hdr(skb);
+1 -8
net/ipv6/xfrm6_mode_ro.c
··· 37 37 * 38 38 * The IP header and mutable extension headers will be moved forward to make 39 39 * space for the route optimization header. 40 - * 41 - * On exit, skb->h will be set to the start of the encapsulation header to be 42 - * filled in by x->type->output and the mac header will be set to the 43 - * nextheader field of the extension header directly preceding the 44 - * encapsulation header, or in its absence, that of the top IP header. 45 - * The value of the network header will always point to the top IP header 46 - * while skb->data will point to the payload. 47 40 */ 48 41 static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb) 49 42 { ··· 49 56 hdr_len = x->type->hdr_offset(x, skb, &prevhdr); 50 57 skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data); 51 58 skb_set_network_header(skb, -x->props.header_len); 52 - skb_set_transport_header(skb, hdr_len - x->props.header_len); 59 + skb->transport_header = skb->network_header + hdr_len; 53 60 __skb_pull(skb, hdr_len); 54 61 memmove(ipv6_hdr(skb), iph, hdr_len); 55 62
+1 -8
net/ipv6/xfrm6_mode_transport.c
··· 18 18 * 19 19 * The IP header and mutable extension headers will be moved forward to make 20 20 * space for the encapsulation header. 21 - * 22 - * On exit, skb->h will be set to the start of the encapsulation header to be 23 - * filled in by x->type->output and the mac header will be set to the 24 - * nextheader field of the extension header directly preceding the 25 - * encapsulation header, or in its absence, that of the top IP header. 26 - * The value of the network header will always point to the top IP header 27 - * while skb->data will point to the payload. 28 21 */ 29 22 static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb) 30 23 { ··· 30 37 hdr_len = x->type->hdr_offset(x, skb, &prevhdr); 31 38 skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data); 32 39 skb_set_network_header(skb, -x->props.header_len); 33 - skb_set_transport_header(skb, hdr_len - x->props.header_len); 40 + skb->transport_header = skb->network_header + hdr_len; 34 41 __skb_pull(skb, hdr_len); 35 42 memmove(ipv6_hdr(skb), iph, hdr_len); 36 43 return 0;
+3 -11
net/ipv6/xfrm6_mode_tunnel.c
··· 36 36 * The top IP header will be constructed per RFC 2401. The following fields 37 37 * in it shall be filled in by x->type->output: 38 38 * payload_len 39 - * 40 - * On exit, skb->h will be set to the start of the encapsulation header to be 41 - * filled in by x->type->output and the mac header will be set to the 42 - * nextheader field of the extension header directly preceding the 43 - * encapsulation header, or in its absence, that of the top IP header. 44 - * The value of the network header will always point to the top IP header 45 - * while skb->data will point to the payload. 46 39 */ 47 40 static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) 48 41 { ··· 46 53 47 54 iph = ipv6_hdr(skb); 48 55 49 - skb_set_mac_header(skb, offsetof(struct ipv6hdr, nexthdr) - 50 - x->props.header_len); 51 56 skb_set_network_header(skb, -x->props.header_len); 52 - skb_set_transport_header(skb, sizeof(struct ipv6hdr) - 53 - x->props.header_len); 57 + skb->mac_header = skb->network_header + 58 + offsetof(struct ipv6hdr, nexthdr); 59 + skb->transport_header = skb->network_header + sizeof(*iph); 54 60 top_iph = ipv6_hdr(skb); 55 61 56 62 top_iph->version = 6;