160 static int ip6_input_finish(struct sk_buff *skb)
161 {
162 struct inet6_protocol *ipprot; //注册协议结构体
163 unsigned int nhoff;
164 int nexthdr, raw;
165 u8 hash;
166 struct inet6_dev *idev;
167 struct net *net = dev_net(skb_dst(skb)->dev);
168
169 /*
170 * Parse extension headers
171 */
172
173 rcu_read_lock();
174 resubmit:
175 idev = ip6_dst_idev(skb_dst(skb));
176 if (!pskb_pull(skb, skb_transport_offset(skb)))
177 goto discard;
178 nhoff = IP6CB(skb)->nhoff;
179 nexthdr = skb_network_header(skb)[nhoff];
180
181 raw = raw6_local_deliver(skb, nexthdr);
182
183 hash = nexthdr & (MAX_INET_PROTOS - 1);
184 if ((ipprot = rcu_dereference(inet6_protos[hash])) != NULL) {
185 int ret;
186
187 if (ipprot->flags & INET6_PROTO_FINAL) {
188 struct ipv6hdr *hdr;
189
190 /* Free reference early: we don't need it any more,
191 and it may hold ip_conntrack module loaded
192 indefinitely. */
193 nf_reset(skb);
194
195 skb_postpull_rcsum(skb, skb_network_header(skb),
196 skb_network_header_len(skb));
197 hdr = ipv6_hdr(skb);
198 if (ipv6_addr_is_multicast(&hdr->daddr) &&
199 !ipv6_chk_mcast_addr(skb->dev, &hdr->daddr,
200 &hdr->saddr) &&
201 !ipv6_is_mld(skb, nexthdr))
202 goto discard;
203 }
204 if (!(ipprot->flags & INET6_PROTO_NOPOLICY) &&
205 !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
206 goto discard;
207
208 ret = ipprot->handler(skb); //此处调用当前扩展头部解析函数
209 if (ret > 0)
210 goto resubmit; //直到扩展头被解析完,否则提交到上面,继续解析
211 else if (ret == 0)
212 IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDELIVERS);
213 } else {
214 if (!raw) {
215 if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
216 IP6_INC_STATS_BH(net, idev,
217 IPSTATS_MIB_INUNKNOWNPROTOS);
218 icmpv6_send(skb, ICMPV6_PARAMPROB,
219 ICMPV6_UNK_NEXTHDR, nhoff,
220 skb->dev);
221 }
222 } else
223 IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDELIVERS);
224 kfree_skb(skb);
225 }
226 rcu_read_unlock();
227 return 0;
228
229 discard:
230 IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDISCARDS);
231 rcu_read_unlock();
232 kfree_skb(skb);
233 return 0;
234 }
协议注册结构体:
50 struct inet6_protocol
51 {
52 int (*handler)(struct sk_buff *skb);
53
54 void (*err_handler)(struct sk_buff *skb,
55 struct inet6_skb_parm *opt,
56 u8 type, u8 code, int offset,
57 __be32 info);
58
59 int (*gso_send_check)(struct sk_buff *skb);
60 struct sk_buff *(*gso_segment)(struct sk_buff *skb,
61 int features);
62 struct sk_buff **(*gro_receive)(struct sk_buff **head,
63 struct sk_buff *skb);
64 int (*gro_complete)(struct sk_buff *skb);
65
66 unsigned int flags; /* INET6_PROTO_xxx */
67 };
常用解析函数:
//ah协议头处理
530 static struct inet6_protocol ah6_protocol = {
531 .handler = xfrm6_rcv,
532 .err_handler = ah6_err,
533 .flags = INET6_PROTO_NOPOLICY,
534 };
//路由协议头处理
503 static struct inet6_protocol rthdr_protocol = {
504 .handler = ipv6_rthdr_rcv,
505 .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
506 };
//目的协议头处理
508 static struct inet6_protocol destopt_protocol = {
509 .handler = ipv6_destopt_rcv,
510 .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
511 };
513 static struct inet6_protocol nodata_protocol = {
514 .handler = dst_discard,
515 .flags = INET6_PROTO_NOPOLICY,
516 };
//tcp协议头处理
2095 static struct inet6_protocol tcpv6_protocol = {
2096 .handler = tcp_v6_rcv,
2097 .err_handler = tcp_v6_err,
2098 .gso_send_check = tcp_v6_gso_send_check,
2099 .gso_segment = tcp_tso_segment,
2100 .gro_receive = tcp6_gro_receive,
2101 .gro_complete = tcp6_gro_complete,
2102 .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
2103 };
1033 static struct inet6_protocol udpv6_protocol = {
1034 .handler = udpv6_rcv,
1035 .err_handler = udpv6_err,
1036 .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
1037 };
//esp协议头处理
561 static struct inet6_protocol esp6_protocol = {
562 .handler = xfrm6_rcv,
563 .err_handler = esp6_err,
564 .flags = INET6_PROTO_NOPOLICY,
565 };
//管道协议头处理
136 static struct inet6_protocol tunnel6_protocol = {
137 .handler = tunnel6_rcv,
138 .err_handler = tunnel6_err,
139 .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
140 };
141
142 static struct inet6_protocol tunnel46_protocol = {
143 .handler = tunnel46_rcv,
144 .err_handler = tunnel6_err,
145 .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
146 };