int ipip_rcv(struct sk_buff *skb, unsigned short len) { struct iphdr *iph; struct ip_tunnel *tunnel; iph = skb->nh.iph; skb->mac.raw = skb->nh.raw; skb->nh.raw = skb_pull(skb, skb->h.raw - skb->data); memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); skb->protocol = __constant_htons(ETH_P_IP); skb->ip_summed = 0; skb->pkt_type = PACKET_HOST; if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) { tunnel->stat.rx_packets++; tunnel->stat.rx_bytes += skb->len; skb->dev = tunnel->dev; dst_release(skb->dst); skb->dst = NULL; netif_rx(skb); return 0; } icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0); kfree_skb(skb); return 0; }
static int ipip_rcv(struct sk_buff *skb) { struct ip_tunnel *tunnel; const struct iphdr *iph = ip_hdr(skb); read_lock(&ipip_lock); if ((tunnel = ipip_tunnel_lookup(dev_net(skb->dev), iph->saddr, iph->daddr)) != NULL) { if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { read_unlock(&ipip_lock); kfree_skb(skb); return 0; } secpath_reset(skb); skb->mac_header = skb->network_header; skb_reset_network_header(skb); skb->protocol = htons(ETH_P_IP); skb->pkt_type = PACKET_HOST; tunnel->dev->stats.rx_packets++; tunnel->dev->stats.rx_bytes += skb->len; skb->dev = tunnel->dev; skb_dst_drop(skb); nf_reset(skb); ipip_ecn_decapsulate(iph, skb); netif_rx(skb); read_unlock(&ipip_lock); return 0; } read_unlock(&ipip_lock); return -1; }
static struct net_device *ipip_dev_lookup(struct iphdr *iph) { struct ip_tunnel *t = ipip_tunnel_lookup(iph->saddr, iph->daddr); if (t != NULL) return t->dev; return NULL; }
int ipip6_rcv(struct sk_buff *skb) { struct iphdr *iph; struct ip_tunnel *tunnel; if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) goto out; iph = skb->nh.iph; #ifdef CONFIG_NET_IPIP_IPV6 read_lock(&ipip_lock); tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr); #else read_lock(&ipip6_lock); tunnel = ipip6_tunnel_lookup(iph->saddr, iph->daddr); #endif if (tunnel != NULL) { skb->mac.raw = skb->nh.raw; skb->nh.raw = skb->data; memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); skb->protocol = htons(ETH_P_IPV6); skb->pkt_type = PACKET_HOST; tunnel->stat.rx_packets++; tunnel->stat.rx_bytes += skb->len; skb->dev = tunnel->dev; dst_release(skb->dst); skb->dst = NULL; nf_reset(skb); ipip6_ecn_decapsulate(iph, skb); netif_rx(skb); #ifdef CONFIG_NET_IPIP_IPV6 read_unlock(&ipip_lock); #else read_unlock(&ipip6_lock); #endif return 0; } icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0); kfree_skb(skb); #ifdef CONFIG_NET_IPIP_IPV6 read_unlock(&ipip_lock); #else read_unlock(&ipip6_lock); #endif out: return 0; }
static int ipip_rcv(struct sk_buff *skb) { struct iphdr *iph; struct ip_tunnel *tunnel; if (!pskb_may_pull(skb, sizeof(struct iphdr))) goto out; iph = skb->nh.iph; read_lock(&ipip_lock); if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) { if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { read_unlock(&ipip_lock); kfree_skb(skb); return 0; } secpath_reset(skb); skb->mac.raw = skb->nh.raw; skb->nh.raw = skb->data; memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); skb->protocol = htons(ETH_P_IP); skb->pkt_type = PACKET_HOST; tunnel->stat.rx_packets++; tunnel->stat.rx_bytes += skb->len; skb->dev = tunnel->dev; dst_release(skb->dst); skb->dst = NULL; nf_reset(skb); ipip_ecn_decapsulate(iph, skb); netif_rx(skb); read_unlock(&ipip_lock); return 0; } read_unlock(&ipip_lock); out: return -1; }
int ipip_rcv(struct sk_buff *skb) { struct iphdr *iph; struct ip_tunnel *tunnel; if (!pskb_may_pull(skb, sizeof(struct iphdr))) goto out; iph = skb->nh.iph; skb->mac.raw = skb->nh.raw; skb->nh.raw = skb->data; memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); skb->protocol = htons(ETH_P_IP); skb->pkt_type = PACKET_HOST; read_lock(&ipip_lock); if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) { tunnel->stat.rx_packets++; tunnel->stat.rx_bytes += skb->len; skb->dev = tunnel->dev; dst_release(skb->dst); skb->dst = NULL; #ifdef CONFIG_NETFILTER nf_conntrack_put(skb->nfct); skb->nfct = NULL; #ifdef CONFIG_NETFILTER_DEBUG skb->nf_debug = 0; #endif #endif ipip_ecn_decapsulate(iph, skb); netif_rx(skb); read_unlock(&ipip_lock); return 0; } read_unlock(&ipip_lock); icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0); out: kfree_skb(skb); return 0; }
void ipip_err(struct sk_buff *skb, unsigned char *dp, int len) { #ifndef I_WISH_WORLD_WERE_PERFECT /* It is not :-( All the routers (except for Linux) return only 8 bytes of packet payload. It means, that precise relaying of ICMP in the real Internet is absolutely infeasible. */ struct iphdr *iph = (struct iphdr*)dp; int type = skb->h.icmph->type; int code = skb->h.icmph->code; struct ip_tunnel *t; if (len < sizeof(struct iphdr)) return; switch (type) { default: case ICMP_PARAMETERPROB: return; case ICMP_DEST_UNREACH: switch (code) { case ICMP_SR_FAILED: case ICMP_PORT_UNREACH: /* Impossible event. */ return; case ICMP_FRAG_NEEDED: /* Soft state for pmtu is maintained by IP core. */ return; default: /* All others are translated to HOST_UNREACH. rfc2003 contains "deep thoughts" about NET_UNREACH, I believe they are just ether pollution. --ANK */ break; } break; case ICMP_TIME_EXCEEDED: if (code != ICMP_EXC_TTL) return; break; } t = ipip_tunnel_lookup(iph->daddr, iph->saddr); if (t == NULL || t->parms.iph.daddr == 0) return; if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) return; if (jiffies - t->err_time < IPTUNNEL_ERR_TIMEO) t->err_count++; else t->err_count = 1; t->err_time = jiffies; return; #else struct iphdr *iph = (struct iphdr*)dp; int hlen = iph->ihl<<2; struct iphdr *eiph; int type = skb->h.icmph->type; int code = skb->h.icmph->code; int rel_type = 0; int rel_code = 0; int rel_info = 0; struct sk_buff *skb2; struct rtable *rt; if (len < hlen + sizeof(struct iphdr)) return; eiph = (struct iphdr*)(dp + hlen); switch (type) { default: return; case ICMP_PARAMETERPROB: if (skb->h.icmph->un.gateway < hlen) return; /* So... This guy found something strange INSIDE encapsulated packet. Well, he is fool, but what can we do ? */ rel_type = ICMP_PARAMETERPROB; rel_info = skb->h.icmph->un.gateway - hlen; break; case ICMP_DEST_UNREACH: switch (code) { case ICMP_SR_FAILED: case ICMP_PORT_UNREACH: /* Impossible event. */ return; case ICMP_FRAG_NEEDED: /* And it is the only really necessary thing :-) */ rel_info = ntohs(skb->h.icmph->un.frag.mtu); if (rel_info < hlen+68) return; rel_info -= hlen; /* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */ if (rel_info > ntohs(eiph->tot_len)) return; break; default: /* All others are translated to HOST_UNREACH. rfc2003 contains "deep thoughts" about NET_UNREACH, I believe, it is just ether pollution. --ANK */ rel_type = ICMP_DEST_UNREACH; rel_code = ICMP_HOST_UNREACH; break; } break; case ICMP_TIME_EXCEEDED: if (code != ICMP_EXC_TTL) return; break; } /* Prepare fake skb to feed it to icmp_send */ skb2 = skb_clone(skb, GFP_ATOMIC); if (skb2 == NULL) return; dst_release(skb2->dst); skb2->dst = NULL; skb_pull(skb2, skb->data - (u8*)eiph); skb2->nh.raw = skb2->data; /* Try to guess incoming interface */ if (ip_route_output(&rt, eiph->saddr, 0, RT_TOS(eiph->tos), 0)) { kfree_skb(skb2); return; } skb2->dev = rt->u.dst.dev; /* route "incoming" packet */ if (rt->rt_flags&RTCF_LOCAL) { ip_rt_put(rt); rt = NULL; if (ip_route_output(&rt, eiph->daddr, eiph->saddr, eiph->tos, 0) || rt->u.dst.dev->type != ARPHRD_IPGRE) { ip_rt_put(rt); kfree_skb(skb2); return; } } else { ip_rt_put(rt); if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos, skb2->dev) || skb2->dst->dev->type != ARPHRD_IPGRE) { kfree_skb(skb2); return; } } /* change mtu on this route */ if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { if (rel_info > skb2->dst->pmtu) { kfree_skb(skb2); return; } skb2->dst->pmtu = rel_info; rel_info = htonl(rel_info); } else if (type == ICMP_TIME_EXCEEDED) { struct ip_tunnel *t = (struct ip_tunnel*)skb2->dev->priv; if (t->parms.iph.ttl) { rel_type = ICMP_DEST_UNREACH; rel_code = ICMP_HOST_UNREACH; } } icmp_send(skb2, rel_type, rel_code, rel_info); kfree_skb(skb2); return; #endif }
void ipip6_err(struct sk_buff *skb, u32 info) { #ifndef I_WISH_WORLD_WERE_PERFECT /* It is not :-( All the routers (except for Linux) return only 8 bytes of packet payload. It means, that precise relaying of ICMP in the real Internet is absolutely infeasible. */ struct iphdr *iph = (struct iphdr*)skb->data; int type = skb->h.icmph->type; int code = skb->h.icmph->code; struct ip_tunnel *t; switch (type) { default: case ICMP_PARAMETERPROB: return; case ICMP_DEST_UNREACH: switch (code) { case ICMP_SR_FAILED: case ICMP_PORT_UNREACH: /* Impossible event. */ return; case ICMP_FRAG_NEEDED: /* Soft state for pmtu is maintained by IP core. */ return; default: /* All others are translated to HOST_UNREACH. rfc2003 contains "deep thoughts" about NET_UNREACH, I believe they are just ether pollution. --ANK */ break; } break; case ICMP_TIME_EXCEEDED: if (code != ICMP_EXC_TTL) return; break; } #ifdef CONFIG_NET_IPIP_IPV6 read_lock(&ipip_lock); t = ipip_tunnel_lookup(iph->daddr, iph->saddr); #else read_lock(&ipip6_lock); t = ipip6_tunnel_lookup(iph->daddr, iph->saddr); #endif if (t == NULL || t->parms.iph.daddr == 0) goto out; if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) goto out; if (jiffies - t->err_time < IPTUNNEL_ERR_TIMEO) t->err_count++; else t->err_count = 1; t->err_time = jiffies; out: #ifdef CONFIG_NET_IPIP_IPV6 read_unlock(&ipip_lock); #else read_unlock(&ipip6_lock); #endif return; #else struct iphdr *iph = (struct iphdr*)dp; int hlen = iph->ihl<<2; struct ipv6hdr *iph6; int type = skb->h.icmph->type; int code = skb->h.icmph->code; int rel_type = 0; int rel_code = 0; int rel_info = 0; struct sk_buff *skb2; struct rt6_info *rt6i; if (len < hlen + sizeof(struct ipv6hdr)) return; iph6 = (struct ipv6hdr*)(dp + hlen); switch (type) { default: return; case ICMP_PARAMETERPROB: if (skb->h.icmph->un.gateway < hlen) return; /* So... This guy found something strange INSIDE encapsulated packet. Well, he is fool, but what can we do ? */ rel_type = ICMPV6_PARAMPROB; rel_info = skb->h.icmph->un.gateway - hlen; break; case ICMP_DEST_UNREACH: switch (code) { case ICMP_SR_FAILED: case ICMP_PORT_UNREACH: /* Impossible event. */ return; case ICMP_FRAG_NEEDED: /* Too complicated case ... */ return; default: /* All others are translated to HOST_UNREACH. rfc2003 contains "deep thoughts" about NET_UNREACH, I believe, it is just ether pollution. --ANK */ rel_type = ICMPV6_DEST_UNREACH; rel_code = ICMPV6_ADDR_UNREACH; break; } break; case ICMP_TIME_EXCEEDED: if (code != ICMP_EXC_TTL) return; rel_type = ICMPV6_TIME_EXCEED; rel_code = ICMPV6_EXC_HOPLIMIT; break; } /* Prepare fake skb to feed it to icmpv6_send */ skb2 = skb_clone(skb, GFP_ATOMIC); if (skb2 == NULL) return; dst_release(skb2->dst); skb2->dst = NULL; skb_pull(skb2, skb->data - (u8*)iph6); skb2->nh.raw = skb2->data; /* Try to guess incoming interface */ rt6i = rt6_lookup(&iph6->saddr, NULL, NULL, 0); if (rt6i && rt6i->rt6i_dev) { skb2->dev = rt6i->rt6i_dev; rt6i = rt6_lookup(&iph6->daddr, &iph6->saddr, NULL, 0); if (rt6i && rt6i->rt6i_dev && rt6i->rt6i_dev->type == ARPHRD_SIT) { struct ip_tunnel * t = (struct ip_tunnel*)rt6i->rt6i_dev->priv; if (rel_type == ICMPV6_TIME_EXCEED && t->parms.iph.ttl) { rel_type = ICMPV6_DEST_UNREACH; rel_code = ICMPV6_ADDR_UNREACH; } icmpv6_send(skb2, rel_type, rel_code, rel_info, skb2->dev); } } kfree_skb(skb2); return; #endif }
static int ipip_err(struct sk_buff *skb, u32 info) { /* All the routers (except for Linux) return only 8 bytes of packet payload. It means, that precise relaying of ICMP in the real Internet is absolutely infeasible. */ struct iphdr *iph = (struct iphdr *)skb->data; const int type = icmp_hdr(skb)->type; const int code = icmp_hdr(skb)->code; struct ip_tunnel *t; int err; switch (type) { default: case ICMP_PARAMETERPROB: return 0; case ICMP_DEST_UNREACH: switch (code) { case ICMP_SR_FAILED: case ICMP_PORT_UNREACH: /* Impossible event. */ return 0; case ICMP_FRAG_NEEDED: /* Soft state for pmtu is maintained by IP core. */ return 0; default: /* All others are translated to HOST_UNREACH. rfc2003 contains "deep thoughts" about NET_UNREACH, I believe they are just ether pollution. --ANK */ break; } break; case ICMP_TIME_EXCEEDED: if (code != ICMP_EXC_TTL) return 0; break; } err = -ENOENT; read_lock(&ipip_lock); t = ipip_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr); if (t == NULL || t->parms.iph.daddr == 0) goto out; err = 0; if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) goto out; if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO)) t->err_count++; else t->err_count = 1; t->err_time = jiffies; out: read_unlock(&ipip_lock); return err; }
int ipip_rcv(struct sk_buff *skb) { struct iphdr *iph; struct ip_tunnel *tunnel; u16 proto; int hdrlen; switch(skb->nh.iph->protocol) { case IPPROTO_IPIP: proto = htons(ETH_P_IP); hdrlen = sizeof(struct iphdr); break; #ifdef CONFIG_NET_IPIP_IPV6 case IPPROTO_IPV6: proto = htons(ETH_P_IPV6); hdrlen = sizeof(struct ipv6hdr); break; #endif default: if (net_ratelimit()) printk(KERN_WARNING "ipip_rcv(): unsupported protocol (%u)\n", skb->nh.iph->protocol); goto protounreach; } if (!pskb_may_pull(skb, hdrlen)) goto out; iph = skb->nh.iph; skb->mac.raw = skb->nh.raw; skb->nh.raw = skb->data; memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); skb->protocol = proto; skb->pkt_type = PACKET_HOST; read_lock(&ipip_lock); if ((tunnel = ipip_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) { if (tunnel->parms.iph.protocol != 0 && tunnel->parms.iph.protocol != iph->protocol) { read_unlock(&ipip_lock); goto protounreach; } tunnel->stat.rx_packets++; tunnel->stat.rx_bytes += skb->len; skb->dev = tunnel->dev; dst_release(skb->dst); skb->dst = NULL; nf_reset(skb); ipip_ecn_decapsulate(iph, skb); netif_rx(skb); read_unlock(&ipip_lock); return 0; } read_unlock(&ipip_lock); protounreach: icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0); out: kfree_skb(skb); return 0; }