aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2006-01-07 02:02:34 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-01-07 15:57:29 -0500
commit951dbc8ac714b04c36296b8b5c36c8e036ce433f (patch)
tree7f3599987f6b6db765f66c65d5c1cefe1457ea6a /net
parent16a6677fdf1d1194f688f8291b06fbaff248c353 (diff)
[IPV6]: Move nextheader offset to the IP6CB
Move nextheader offset to the IP6CB to make it possible to pass a packet to ip6_input_finish multiple times and have it skip already parsed headers. As a nice side effect this gets rid of the manual hopopts skipping in ip6_input_finish. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/dccp/ipv6.c2
-rw-r--r--net/ipv6/exthdrs.c19
-rw-r--r--net/ipv6/icmp.c4
-rw-r--r--net/ipv6/ip6_input.c21
-rw-r--r--net/ipv6/ip6_tunnel.c2
-rw-r--r--net/ipv6/reassembly.c11
-rw-r--r--net/ipv6/tcp_ipv6.c2
-rw-r--r--net/ipv6/udp.c2
-rw-r--r--net/ipv6/xfrm6_input.c8
-rw-r--r--net/ipv6/xfrm6_tunnel.c6
-rw-r--r--net/sctp/ipv6.c2
11 files changed, 37 insertions, 42 deletions
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 683250a05f58..df074259f9c3 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -1029,7 +1029,7 @@ discard:
1029 return 0; 1029 return 0;
1030} 1030}
1031 1031
1032static int dccp_v6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) 1032static int dccp_v6_rcv(struct sk_buff **pskb)
1033{ 1033{
1034 const struct dccp_hdr *dh; 1034 const struct dccp_hdr *dh;
1035 struct sk_buff *skb = *pskb; 1035 struct sk_buff *skb = *pskb;
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 113374dc342c..2a1e7e45b890 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -152,7 +152,7 @@ static struct tlvtype_proc tlvprocdestopt_lst[] = {
152 {-1, NULL} 152 {-1, NULL}
153}; 153};
154 154
155static int ipv6_destopt_rcv(struct sk_buff **skbp, unsigned int *nhoffp) 155static int ipv6_destopt_rcv(struct sk_buff **skbp)
156{ 156{
157 struct sk_buff *skb = *skbp; 157 struct sk_buff *skb = *skbp;
158 struct inet6_skb_parm *opt = IP6CB(skb); 158 struct inet6_skb_parm *opt = IP6CB(skb);
@@ -169,7 +169,7 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
169 169
170 if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) { 170 if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) {
171 skb->h.raw += ((skb->h.raw[1]+1)<<3); 171 skb->h.raw += ((skb->h.raw[1]+1)<<3);
172 *nhoffp = opt->dst1; 172 opt->nhoff = opt->dst1;
173 return 1; 173 return 1;
174 } 174 }
175 175
@@ -192,7 +192,7 @@ void __init ipv6_destopt_init(void)
192 NONE header. No data in packet. 192 NONE header. No data in packet.
193 ********************************/ 193 ********************************/
194 194
195static int ipv6_nodata_rcv(struct sk_buff **skbp, unsigned int *nhoffp) 195static int ipv6_nodata_rcv(struct sk_buff **skbp)
196{ 196{
197 struct sk_buff *skb = *skbp; 197 struct sk_buff *skb = *skbp;
198 198
@@ -215,7 +215,7 @@ void __init ipv6_nodata_init(void)
215 Routing header. 215 Routing header.
216 ********************************/ 216 ********************************/
217 217
218static int ipv6_rthdr_rcv(struct sk_buff **skbp, unsigned int *nhoffp) 218static int ipv6_rthdr_rcv(struct sk_buff **skbp)
219{ 219{
220 struct sk_buff *skb = *skbp; 220 struct sk_buff *skb = *skbp;
221 struct inet6_skb_parm *opt = IP6CB(skb); 221 struct inet6_skb_parm *opt = IP6CB(skb);
@@ -249,7 +249,7 @@ looped_back:
249 skb->h.raw += (hdr->hdrlen + 1) << 3; 249 skb->h.raw += (hdr->hdrlen + 1) << 3;
250 opt->dst0 = opt->dst1; 250 opt->dst0 = opt->dst1;
251 opt->dst1 = 0; 251 opt->dst1 = 0;
252 *nhoffp = (&hdr->nexthdr) - skb->nh.raw; 252 opt->nhoff = (&hdr->nexthdr) - skb->nh.raw;
253 return 1; 253 return 1;
254 } 254 }
255 255
@@ -487,9 +487,14 @@ static struct tlvtype_proc tlvprochopopt_lst[] = {
487 487
488int ipv6_parse_hopopts(struct sk_buff *skb, int nhoff) 488int ipv6_parse_hopopts(struct sk_buff *skb, int nhoff)
489{ 489{
490 IP6CB(skb)->hop = sizeof(struct ipv6hdr); 490 struct inet6_skb_parm *opt = IP6CB(skb);
491 if (ip6_parse_tlv(tlvprochopopt_lst, skb)) 491
492 opt->hop = sizeof(struct ipv6hdr);
493 if (ip6_parse_tlv(tlvprochopopt_lst, skb)) {
494 skb->h.raw += (skb->h.raw[1]+1)<<3;
495 opt->nhoff = sizeof(struct ipv6hdr);
492 return sizeof(struct ipv6hdr); 496 return sizeof(struct ipv6hdr);
497 }
493 return -1; 498 return -1;
494} 499}
495 500
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 6ec6a2b549bb..53c81fcd20ba 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -79,7 +79,7 @@ DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics) __read_mostly;
79static DEFINE_PER_CPU(struct socket *, __icmpv6_socket) = NULL; 79static DEFINE_PER_CPU(struct socket *, __icmpv6_socket) = NULL;
80#define icmpv6_socket __get_cpu_var(__icmpv6_socket) 80#define icmpv6_socket __get_cpu_var(__icmpv6_socket)
81 81
82static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp); 82static int icmpv6_rcv(struct sk_buff **pskb);
83 83
84static struct inet6_protocol icmpv6_protocol = { 84static struct inet6_protocol icmpv6_protocol = {
85 .handler = icmpv6_rcv, 85 .handler = icmpv6_rcv,
@@ -581,7 +581,7 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, u32 info)
581 * Handle icmp messages 581 * Handle icmp messages
582 */ 582 */
583 583
584static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) 584static int icmpv6_rcv(struct sk_buff **pskb)
585{ 585{
586 struct sk_buff *skb = *pskb; 586 struct sk_buff *skb = *pskb;
587 struct net_device *dev = skb->dev; 587 struct net_device *dev = skb->dev;
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index a6026d2787d2..13d724150f33 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -97,6 +97,9 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
97 if (hdr->version != 6) 97 if (hdr->version != 6)
98 goto err; 98 goto err;
99 99
100 skb->h.raw = (u8 *)(hdr + 1);
101 IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);
102
100 pkt_len = ntohs(hdr->payload_len); 103 pkt_len = ntohs(hdr->payload_len);
101 104
102 /* pkt_len may be zero if Jumbo payload option is present */ 105 /* pkt_len may be zero if Jumbo payload option is present */
@@ -111,8 +114,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
111 } 114 }
112 115
113 if (hdr->nexthdr == NEXTHDR_HOP) { 116 if (hdr->nexthdr == NEXTHDR_HOP) {
114 skb->h.raw = (u8*)(hdr+1); 117 if (ipv6_parse_hopopts(skb, IP6CB(skb)->nhoff) < 0) {
115 if (ipv6_parse_hopopts(skb, offsetof(struct ipv6hdr, nexthdr)) < 0) {
116 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); 118 IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
117 return 0; 119 return 0;
118 } 120 }
@@ -143,26 +145,15 @@ static inline int ip6_input_finish(struct sk_buff *skb)
143 int nexthdr; 145 int nexthdr;
144 u8 hash; 146 u8 hash;
145 147
146 skb->h.raw = skb->nh.raw + sizeof(struct ipv6hdr);
147
148 /* 148 /*
149 * Parse extension headers 149 * Parse extension headers
150 */ 150 */
151 151
152 nexthdr = skb->nh.ipv6h->nexthdr;
153 nhoff = offsetof(struct ipv6hdr, nexthdr);
154
155 /* Skip hop-by-hop options, they are already parsed. */
156 if (nexthdr == NEXTHDR_HOP) {
157 nhoff = sizeof(struct ipv6hdr);
158 nexthdr = skb->h.raw[0];
159 skb->h.raw += (skb->h.raw[1]+1)<<3;
160 }
161
162 rcu_read_lock(); 152 rcu_read_lock();
163resubmit: 153resubmit:
164 if (!pskb_pull(skb, skb->h.raw - skb->data)) 154 if (!pskb_pull(skb, skb->h.raw - skb->data))
165 goto discard; 155 goto discard;
156 nhoff = IP6CB(skb)->nhoff;
166 nexthdr = skb->nh.raw[nhoff]; 157 nexthdr = skb->nh.raw[nhoff];
167 158
168 raw_sk = sk_head(&raw_v6_htable[nexthdr & (MAX_INET_PROTOS - 1)]); 159 raw_sk = sk_head(&raw_v6_htable[nexthdr & (MAX_INET_PROTOS - 1)]);
@@ -194,7 +185,7 @@ resubmit:
194 !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) 185 !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
195 goto discard; 186 goto discard;
196 187
197 ret = ipprot->handler(&skb, &nhoff); 188 ret = ipprot->handler(&skb);
198 if (ret > 0) 189 if (ret > 0)
199 goto resubmit; 190 goto resubmit;
200 else if (ret == 0) 191 else if (ret == 0)
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index e315d0f80af1..f079621c8b67 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -510,7 +510,7 @@ static inline void ip6ip6_ecn_decapsulate(struct ipv6hdr *outer_iph,
510 **/ 510 **/
511 511
512static int 512static int
513ip6ip6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) 513ip6ip6_rcv(struct sk_buff **pskb)
514{ 514{
515 struct sk_buff *skb = *pskb; 515 struct sk_buff *skb = *pskb;
516 struct ipv6hdr *ipv6h; 516 struct ipv6hdr *ipv6h;
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 5d316cb72ec9..15e1456b3f18 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -581,7 +581,6 @@ err:
581 * the last and the first frames arrived and all the bits are here. 581 * the last and the first frames arrived and all the bits are here.
582 */ 582 */
583static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, 583static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
584 unsigned int *nhoffp,
585 struct net_device *dev) 584 struct net_device *dev)
586{ 585{
587 struct sk_buff *fp, *head = fq->fragments; 586 struct sk_buff *fp, *head = fq->fragments;
@@ -654,6 +653,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
654 head->dev = dev; 653 head->dev = dev;
655 skb_set_timestamp(head, &fq->stamp); 654 skb_set_timestamp(head, &fq->stamp);
656 head->nh.ipv6h->payload_len = htons(payload_len); 655 head->nh.ipv6h->payload_len = htons(payload_len);
656 IP6CB(head)->nhoff = nhoff;
657 657
658 *skb_in = head; 658 *skb_in = head;
659 659
@@ -663,7 +663,6 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
663 663
664 IP6_INC_STATS_BH(IPSTATS_MIB_REASMOKS); 664 IP6_INC_STATS_BH(IPSTATS_MIB_REASMOKS);
665 fq->fragments = NULL; 665 fq->fragments = NULL;
666 *nhoffp = nhoff;
667 return 1; 666 return 1;
668 667
669out_oversize: 668out_oversize:
@@ -678,7 +677,7 @@ out_fail:
678 return -1; 677 return -1;
679} 678}
680 679
681static int ipv6_frag_rcv(struct sk_buff **skbp, unsigned int *nhoffp) 680static int ipv6_frag_rcv(struct sk_buff **skbp)
682{ 681{
683 struct sk_buff *skb = *skbp; 682 struct sk_buff *skb = *skbp;
684 struct net_device *dev = skb->dev; 683 struct net_device *dev = skb->dev;
@@ -710,7 +709,7 @@ static int ipv6_frag_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
710 skb->h.raw += sizeof(struct frag_hdr); 709 skb->h.raw += sizeof(struct frag_hdr);
711 IP6_INC_STATS_BH(IPSTATS_MIB_REASMOKS); 710 IP6_INC_STATS_BH(IPSTATS_MIB_REASMOKS);
712 711
713 *nhoffp = (u8*)fhdr - skb->nh.raw; 712 IP6CB(skb)->nhoff = (u8*)fhdr - skb->nh.raw;
714 return 1; 713 return 1;
715 } 714 }
716 715
@@ -722,11 +721,11 @@ static int ipv6_frag_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
722 721
723 spin_lock(&fq->lock); 722 spin_lock(&fq->lock);
724 723
725 ip6_frag_queue(fq, skb, fhdr, *nhoffp); 724 ip6_frag_queue(fq, skb, fhdr, IP6CB(skb)->nhoff);
726 725
727 if (fq->last_in == (FIRST_IN|LAST_IN) && 726 if (fq->last_in == (FIRST_IN|LAST_IN) &&
728 fq->meat == fq->len) 727 fq->meat == fq->len)
729 ret = ip6_frag_reasm(fq, skbp, nhoffp, dev); 728 ret = ip6_frag_reasm(fq, skbp, dev);
730 729
731 spin_unlock(&fq->lock); 730 spin_unlock(&fq->lock);
732 fq_put(fq, NULL); 731 fq_put(fq, NULL);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 2947bc56d8a0..a25f4e8a8ada 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1153,7 +1153,7 @@ ipv6_pktoptions:
1153 return 0; 1153 return 0;
1154} 1154}
1155 1155
1156static int tcp_v6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) 1156static int tcp_v6_rcv(struct sk_buff **pskb)
1157{ 1157{
1158 struct sk_buff *skb = *pskb; 1158 struct sk_buff *skb = *pskb;
1159 struct tcphdr *th; 1159 struct tcphdr *th;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index d8538dcea813..c47648892c04 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -435,7 +435,7 @@ out:
435 read_unlock(&udp_hash_lock); 435 read_unlock(&udp_hash_lock);
436} 436}
437 437
438static int udpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) 438static int udpv6_rcv(struct sk_buff **pskb)
439{ 439{
440 struct sk_buff *skb = *pskb; 440 struct sk_buff *skb = *pskb;
441 struct sock *sk; 441 struct sock *sk;
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index 28c29d78338e..1079e47f3933 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -26,7 +26,7 @@ static inline void ipip6_ecn_decapsulate(struct sk_buff *skb)
26 IP6_ECN_set_ce(inner_iph); 26 IP6_ECN_set_ce(inner_iph);
27} 27}
28 28
29int xfrm6_rcv_spi(struct sk_buff **pskb, unsigned int *nhoffp, u32 spi) 29int xfrm6_rcv_spi(struct sk_buff **pskb, u32 spi)
30{ 30{
31 struct sk_buff *skb = *pskb; 31 struct sk_buff *skb = *pskb;
32 int err; 32 int err;
@@ -38,7 +38,7 @@ int xfrm6_rcv_spi(struct sk_buff **pskb, unsigned int *nhoffp, u32 spi)
38 int nexthdr; 38 int nexthdr;
39 unsigned int nhoff; 39 unsigned int nhoff;
40 40
41 nhoff = *nhoffp; 41 nhoff = IP6CB(skb)->nhoff;
42 nexthdr = skb->nh.raw[nhoff]; 42 nexthdr = skb->nh.raw[nhoff];
43 43
44 seq = 0; 44 seq = 0;
@@ -144,7 +144,7 @@ drop:
144 144
145EXPORT_SYMBOL(xfrm6_rcv_spi); 145EXPORT_SYMBOL(xfrm6_rcv_spi);
146 146
147int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) 147int xfrm6_rcv(struct sk_buff **pskb)
148{ 148{
149 return xfrm6_rcv_spi(pskb, nhoffp, 0); 149 return xfrm6_rcv_spi(pskb, 0);
150} 150}
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index fbef7826a74f..da09ff258648 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -397,7 +397,7 @@ int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler)
397 397
398EXPORT_SYMBOL(xfrm6_tunnel_deregister); 398EXPORT_SYMBOL(xfrm6_tunnel_deregister);
399 399
400static int xfrm6_tunnel_rcv(struct sk_buff **pskb, unsigned int *nhoffp) 400static int xfrm6_tunnel_rcv(struct sk_buff **pskb)
401{ 401{
402 struct sk_buff *skb = *pskb; 402 struct sk_buff *skb = *pskb;
403 struct xfrm6_tunnel *handler = xfrm6_tunnel_handler; 403 struct xfrm6_tunnel *handler = xfrm6_tunnel_handler;
@@ -405,11 +405,11 @@ static int xfrm6_tunnel_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
405 u32 spi; 405 u32 spi;
406 406
407 /* device-like_ip6ip6_handler() */ 407 /* device-like_ip6ip6_handler() */
408 if (handler && handler->handler(pskb, nhoffp) == 0) 408 if (handler && handler->handler(pskb) == 0)
409 return 0; 409 return 0;
410 410
411 spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr); 411 spi = xfrm6_tunnel_spi_lookup((xfrm_address_t *)&iph->saddr);
412 return xfrm6_rcv_spi(pskb, nhoffp, spi); 412 return xfrm6_rcv_spi(pskb, spi);
413} 413}
414 414
415static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 415static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 15c05165c905..04c7fab4edc4 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -905,7 +905,7 @@ static struct inet_protosw sctpv6_stream_protosw = {
905 .flags = SCTP_PROTOSW_FLAG, 905 .flags = SCTP_PROTOSW_FLAG,
906}; 906};
907 907
908static int sctp6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) 908static int sctp6_rcv(struct sk_buff **pskb)
909{ 909{
910 return sctp_rcv(*pskb) ? -1 : 0; 910 return sctp_rcv(*pskb) ? -1 : 0;
911} 911}