static int ip6_rcv(struct sk_buff *skb, struct net_device *dev) { ip6hdr_t *ip6h = ip6_hdr(skb); const struct net_proto *nproto; if (ip6h->version != 6) { dev->stats.rx_err++; skb_free(skb); return 0; /* error: invalid hdr */ } if (skb->dev->hdr_len + IP6_HEADER_SIZE + ntohs(ip6h->payload_len) > skb->len) { dev->stats.rx_length_errors++; skb_free(skb); return 0; /* error: invalid length */ } /* Check recipiant */ assert(skb->dev != NULL); assert(inetdev_get_by_dev(skb->dev) != NULL); if (0 != memcmp(&inetdev_get_by_dev(skb->dev)->ifa6_address, &skb->nh.ip6h->daddr, sizeof(struct in6_addr))) { // skb_free(skb); // return 0; /* error: not for us */ } /* Setup transport layer header */ skb->h.raw = skb->nh.raw + IP6_HEADER_SIZE; nproto = net_proto_lookup(ETH_P_IPV6, ip6h->nexthdr); if (nproto != NULL) { return nproto->handle(skb); } // printk("ipv6 packet accepted, %#x\n", ip6h->nexthdr); skb_free(skb); return 0; /* error: nobody wants this packet */ }
static int udp_rcv(struct sk_buff *skb) { struct sock *sk; assert(skb != NULL); assert(ip_check_version(ip_hdr(skb)) || ip6_check_version(ip6_hdr(skb))); /* Check CRC */ if (MODOPS_VERIFY_CHKSUM) { uint16_t old_check; old_check = skb->h.uh->check; udp_set_check_field(skb->h.uh, skb->nh.raw); if (old_check != skb->h.uh->check) { return 0; /* error: bad checksum */ } } sk = sock_lookup(NULL, udp_sock_ops, ip_check_version(ip_hdr(skb)) ? udp4_rcv_tester : udp6_rcv_tester, skb); if (sk != NULL) { if (ip_check_version(ip_hdr(skb)) ? udp4_accept_dst(sk, skb) : udp6_accept_dst(sk, skb)) { sock_rcv(sk, skb, skb->h.raw + UDP_HEADER_SIZE, udp_data_length(udp_hdr(skb))); } else { skb_free(skb); } } else { icmp_discard(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH); } return 0; }