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 };