int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt) { struct ipv6hdr *hdr; u32 pkt_len; if (skb->pkt_type == PACKET_OTHERHOST) goto drop; IP6_INC_STATS_BH(InReceives); if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { IP6_INC_STATS_BH(InDiscards); goto out; } /* Store incoming device index. When the packet will be queued, we cannot refer to skb->dev anymore. */ IP6CB(skb)->iif = dev->ifindex; if (skb->len < sizeof(struct ipv6hdr)) goto err; if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) { IP6_INC_STATS_BH(InHdrErrors); goto drop; } hdr = skb->nh.ipv6h; if (hdr->version != 6) goto err; pkt_len = ntohs(hdr->payload_len); /* pkt_len may be zero if Jumbo payload option is present */ if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) { if (pkt_len + sizeof(struct ipv6hdr) > skb->len) goto truncated; if (pkt_len + sizeof(struct ipv6hdr) < skb->len) { if (__pskb_trim(skb, pkt_len + sizeof(struct ipv6hdr))){ IP6_INC_STATS_BH(InHdrErrors); goto drop; } hdr = skb->nh.ipv6h; if (skb->ip_summed == CHECKSUM_HW) skb->ip_summed = CHECKSUM_NONE; } } if (hdr->nexthdr == NEXTHDR_HOP) { skb->h.raw = (u8*)(hdr+1); if (ipv6_parse_hopopts(skb, offsetof(struct ipv6hdr, nexthdr)) < 0) { IP6_INC_STATS_BH(InHdrErrors); return 0; } hdr = skb->nh.ipv6h; }
int udpv6_rcv(struct sk_buff *skb) { struct sock *sk; struct udphdr *uh; struct net_device *dev = skb->dev; struct in6_addr *saddr, *daddr; u32 ulen = 0; if (!pskb_may_pull(skb, sizeof(struct udphdr))) goto short_packet; saddr = &skb->nh.ipv6h->saddr; daddr = &skb->nh.ipv6h->daddr; uh = skb->h.uh; ulen = ntohs(uh->len); /* Check for jumbo payload */ if (ulen == 0) ulen = skb->len; if (ulen > skb->len || ulen < sizeof(*uh)) goto short_packet; if (uh->check == 0) { /* IPv6 draft-v2 section 8.1 says that we SHOULD log this error. Well, it is reasonable. */ if (net_ratelimit()) printk(KERN_INFO "IPv6: udp checksum is 0\n"); goto discard; } if (ulen < skb->len) { if (__pskb_trim(skb, ulen)) goto discard; saddr = &skb->nh.ipv6h->saddr; daddr = &skb->nh.ipv6h->daddr; uh = skb->h.uh; } if (skb->ip_summed==CHECKSUM_HW) { skb->ip_summed = CHECKSUM_UNNECESSARY; if (csum_ipv6_magic(saddr, daddr, ulen, IPPROTO_UDP, skb->csum)) { NETDEBUG(if (net_ratelimit()) printk(KERN_DEBUG "udp v6 hw csum failure.\n")); skb->ip_summed = CHECKSUM_NONE; }
int pskb_trim(void) { return __pskb_trim(); }
/* * Main IP Receive routine. */ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt) { struct iphdr *iph; /* When the interface is in promisc. mode, drop all the crap * that it receives, do not try to analyse it. */ if (skb->pkt_type == PACKET_OTHERHOST) goto drop; IP_INC_STATS_BH(IpInReceives); if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) goto out; if (!pskb_may_pull(skb, sizeof(struct iphdr))) goto inhdr_error; iph = skb->nh.iph; /* * RFC1122: 3.1.2.2 MUST silently discard any IP frame that fails the checksum. * * Is the datagram acceptable? * * 1. Length at least the size of an ip header * 2. Version of 4 * 3. Checksums correctly. [Speed optimisation for later, skip loopback checksums] * 4. Doesn't have a bogus length */ if (iph->ihl < 5 || iph->version != 4) goto inhdr_error; if (!pskb_may_pull(skb, iph->ihl*4)) goto inhdr_error; iph = skb->nh.iph; if (ip_fast_csum((u8 *)iph, iph->ihl) != 0) goto inhdr_error; { __u32 len = ntohs(iph->tot_len); if (skb->len < len || len < (iph->ihl<<2)) goto inhdr_error; /* Our transport medium may have padded the buffer out. Now we know it * is IP we can trim to the true length of the frame. * Note this now means skb->len holds ntohs(iph->tot_len). */ if (skb->len > len) { __pskb_trim(skb, len); if (skb->ip_summed == CHECKSUM_HW) skb->ip_summed = CHECKSUM_NONE; } } return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL, ip_rcv_finish); inhdr_error: IP_INC_STATS_BH(IpInHdrErrors); drop: kfree_skb(skb); out: return NET_RX_DROP; }
int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt) { struct ipv6hdr *hdr; #ifdef CONFIG_IPV6_STATISTICS struct inet6_dev *idev = NULL; #endif u32 pkt_len; if (skb->pkt_type == PACKET_OTHERHOST) goto drop; #ifdef CONFIG_IPV6_STATISTICS idev = in6_dev_get(dev); IP6_INC_STATS_BH(idev, IPSTATS_MIB_INRECEIVES); #else IP6_INC_STATS_BH(IPSTATS_MIB_INRECEIVES); #endif if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { #ifdef CONFIG_IPV6_STATISTICS IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDISCARDS); #else IP6_INC_STATS_BH(IPSTATS_MIB_INDISCARDS); #endif goto out; } /* Store incoming device index. When the packet will be queued, we cannot refer to skb->dev anymore. */ IP6CB(skb)->iif = dev->ifindex; if (skb->len < sizeof(struct ipv6hdr)) goto err; if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) goto err; hdr = skb->nh.ipv6h; if (hdr->version != 6) goto err; pkt_len = ntohs(hdr->payload_len); /* pkt_len may be zero if Jumbo payload option is present */ if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) { if (pkt_len + sizeof(struct ipv6hdr) > skb->len) { #ifdef CONFIG_IPV6_STATISTICS IP6_INC_STATS_BH(idev, IPSTATS_MIB_INTRUNCATEDPKTS); #else IP6_INC_STATS_BH(IPSTATS_MIB_INTRUNCATEDPKTS); #endif goto drop; } if (pkt_len + sizeof(struct ipv6hdr) < skb->len) { if (__pskb_trim(skb, pkt_len + sizeof(struct ipv6hdr))) goto err; hdr = skb->nh.ipv6h; if (skb->ip_summed == CHECKSUM_HW) skb->ip_summed = CHECKSUM_NONE; } } if (hdr->nexthdr == NEXTHDR_HOP) { unsigned int nhoff = offsetof(struct ipv6hdr, nexthdr); skb->h.raw = (u8*)(hdr+1); if (ipv6_parse_hopopts(&skb, &nhoff) < 0) { skb = NULL; goto err; } }
/** * efx_tx_tso_sw - segment and transmit a TSO socket buffer using SW or FATSOv1 * @tx_queue: Efx TX queue * @skb: Socket buffer * @data_mapped: Did we map the data? Always set to true * by this on success. * * Context: You must hold netif_tx_lock() to call this function. * * Add socket buffer @skb to @tx_queue, doing TSO or return != 0 if * @skb was not enqueued. In all cases @skb is consumed. Return * %NETDEV_TX_OK. */ int efx_tx_tso_sw(struct efx_tx_queue *tx_queue, struct sk_buff *skb, bool *data_mapped) { struct efx_nic *efx = tx_queue->efx; int frag_i, rc; struct tso_state state; #if defined(EFX_USE_KCOMPAT) && !defined(EFX_HAVE_GSO_MAX_SEGS) /* Since the stack does not limit the number of segments per * skb, we must do so. Otherwise an attacker may be able to * make the TCP produce skbs that will never fit in our TX * queue, causing repeated resets. */ if (unlikely(skb_shinfo(skb)->gso_segs > EFX_TSO_MAX_SEGS)) { unsigned int excess = (skb_shinfo(skb)->gso_segs - EFX_TSO_MAX_SEGS) * skb_shinfo(skb)->gso_size; if (__pskb_trim(skb, skb->len - excess)) return -E2BIG; } #endif prefetch(skb->data); /* Find the packet protocol and sanity-check it */ rc = efx_tso_check_protocol(skb, &state.protocol); if (rc) return rc; rc = tso_start(&state, efx, tx_queue, skb); if (rc) goto mem_err; if (likely(state.in_len == 0)) { /* Grab the first payload fragment. */ EFX_WARN_ON_ONCE_PARANOID(skb_shinfo(skb)->nr_frags < 1); frag_i = 0; rc = tso_get_fragment(&state, efx, skb_shinfo(skb)->frags + frag_i); if (rc) goto mem_err; } else { /* Payload starts in the header area. */ frag_i = -1; } if (tso_start_new_packet(tx_queue, skb, &state, true) < 0) goto mem_err; prefetch_ptr(tx_queue); while (1) { tso_fill_packet_with_fragment(tx_queue, skb, &state); /* Move onto the next fragment? */ if (state.in_len == 0) { if (++frag_i >= skb_shinfo(skb)->nr_frags) /* End of payload reached. */ break; rc = tso_get_fragment(&state, efx, skb_shinfo(skb)->frags + frag_i); if (rc) goto mem_err; } /* Start at new packet? */ if (state.packet_space == 0 && tso_start_new_packet(tx_queue, skb, &state, false) < 0) goto mem_err; } *data_mapped = true; return 0; mem_err: netif_err(efx, tx_err, efx->net_dev, "Out of memory for TSO headers, or DMA mapping error\n"); /* Free the DMA mapping we were in the process of writing out */ if (state.unmap_len) { if (state.dma_flags & EFX_TX_BUF_MAP_SINGLE) dma_unmap_single(&efx->pci_dev->dev, state.unmap_addr, state.unmap_len, DMA_TO_DEVICE); else dma_unmap_page(&efx->pci_dev->dev, state.unmap_addr, state.unmap_len, DMA_TO_DEVICE); } /* Free the header DMA mapping, if using option descriptors */ if (state.header_unmap_len) dma_unmap_single(&efx->pci_dev->dev, state.header_dma_addr, state.header_unmap_len, DMA_TO_DEVICE); return -ENOMEM; }
int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt) { struct ipv6hdr *hdr; u32 pkt_len; if (skb->pkt_type == PACKET_OTHERHOST) goto drop; IP6_INC_STATS_BH(IPSTATS_MIB_INRECEIVES); if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { IP6_INC_STATS_BH(IPSTATS_MIB_INDISCARDS); goto out; } /* * Store incoming device index. When the packet will * be queued, we cannot refer to skb->dev anymore. * * BTW, when we send a packet for our own local address on a * non-loopback interface (e.g. ethX), it is being delivered * via the loopback interface (lo) here; skb->dev = &loopback_dev. * It, however, should be considered as if it is being * arrived via the sending interface (ethX), because of the * nature of scoping architecture. --yoshfuji */ IP6CB(skb)->iif = skb->dst ? ((struct rt6_info *)skb->dst)->rt6i_idev->dev->ifindex : dev->ifindex; if (skb->len < sizeof(struct ipv6hdr)) goto err; if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) { IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); goto drop; } hdr = skb->nh.ipv6h; if (hdr->version != 6) goto err; pkt_len = ntohs(hdr->payload_len); /* pkt_len may be zero if Jumbo payload option is present */ if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) { if (pkt_len + sizeof(struct ipv6hdr) > skb->len) goto truncated; if (pkt_len + sizeof(struct ipv6hdr) < skb->len) { if (__pskb_trim(skb, pkt_len + sizeof(struct ipv6hdr))){ IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); goto drop; } hdr = skb->nh.ipv6h; if (skb->ip_summed == CHECKSUM_HW) skb->ip_summed = CHECKSUM_NONE; } } if (hdr->nexthdr == NEXTHDR_HOP) { skb->h.raw = (u8*)(hdr+1); if (ipv6_parse_hopopts(skb, offsetof(struct ipv6hdr, nexthdr)) < 0) { IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); return 0; } hdr = skb->nh.ipv6h; }
int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt) { struct ipv6hdr *hdr; u32 pkt_len; struct inet6_dev *idev = NULL; int saddr_type, daddr_type; if (skb->pkt_type == PACKET_OTHERHOST) goto drop; idev = in6_dev_get(dev); IP6_INC_STATS_BH(idev,Ip6InReceives); if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) goto out; /* Store incoming device index. When the packet will be queued, we cannot refer to skb->dev anymore. */ ((struct inet6_skb_parm *)skb->cb)->iif = dev->ifindex; if (skb->len < sizeof(struct ipv6hdr)) goto err; if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) goto drop; hdr = skb->nh.ipv6h; if (hdr->version != 6) goto err; saddr_type = ipv6_addr_type(&hdr->saddr); daddr_type = ipv6_addr_type(&hdr->daddr); if ((saddr_type & IPV6_ADDR_MULTICAST) || (daddr_type == IPV6_ADDR_ANY)) goto drop; /*XXX*/ if (((saddr_type & IPV6_ADDR_LOOPBACK) || (daddr_type & IPV6_ADDR_LOOPBACK)) && !(dev->flags & IFF_LOOPBACK)) goto drop; /*XXX*/ #ifdef CONFIG_IPV6_DROP_FAKE_V4MAPPED if (saddr_type == IPV6_ADDR_MAPPED || daddr_type == IPV6_ADDR_MAPPED) goto drop; /*XXX*/ #endif pkt_len = ntohs(hdr->payload_len); /* pkt_len may be zero if Jumbo payload option is present */ if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) { if (pkt_len + sizeof(struct ipv6hdr) > skb->len) goto truncated; if (pkt_len + sizeof(struct ipv6hdr) < skb->len) { if (__pskb_trim(skb, pkt_len + sizeof(struct ipv6hdr))) goto drop; hdr = skb->nh.ipv6h; if (skb->ip_summed == CHECKSUM_HW) skb->ip_summed = CHECKSUM_NONE; } } if (hdr->nexthdr == NEXTHDR_HOP) { skb->h.raw = (u8*)(hdr+1); if (ipv6_parse_hopopts(skb, offsetof(struct ipv6hdr, nexthdr)) < 0) { IP6_INC_STATS_BH(idev,Ip6InHdrErrors); if (idev) in6_dev_put(idev); return 0; } hdr = skb->nh.ipv6h; }
/** * efx_enqueue_skb_tso - segment and transmit a TSO socket buffer * @tx_queue: Efx TX queue * @skb: Socket buffer * * Context: You must hold netif_tx_lock() to call this function. * * Add socket buffer @skb to @tx_queue, doing TSO or return != 0 if * @skb was not enqueued. In all cases @skb is consumed. Return * %NETDEV_TX_OK or %NETDEV_TX_BUSY. */ static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue, struct sk_buff *skb) { struct efx_nic *efx = tx_queue->efx; int frag_i, rc, rc2 = NETDEV_TX_OK; struct tso_state state; /* Since the stack does not limit the number of segments per * skb, we must do so. Otherwise an attacker may be able to * make the TCP produce skbs that will never fit in our TX * queue, causing repeated resets. */ if (unlikely(skb_shinfo(skb)->gso_segs > EFX_TSO_MAX_SEGS)) { unsigned int excess = (skb_shinfo(skb)->gso_segs - EFX_TSO_MAX_SEGS) * skb_shinfo(skb)->gso_size; if (__pskb_trim(skb, skb->len - excess)) { dev_kfree_skb_any(skb); return NETDEV_TX_OK; } } /* Find the packet protocol and sanity-check it */ state.protocol = efx_tso_check_protocol(skb); EFX_BUG_ON_PARANOID(tx_queue->write_count != tx_queue->insert_count); tso_start(&state, skb); /* Assume that skb header area contains exactly the headers, and * all payload is in the frag list. */ if (skb_headlen(skb) == state.header_len) { /* Grab the first payload fragment. */ EFX_BUG_ON_PARANOID(skb_shinfo(skb)->nr_frags < 1); frag_i = 0; rc = tso_get_fragment(&state, efx, skb_shinfo(skb)->frags + frag_i); if (rc) goto mem_err; } else { rc = tso_get_head_fragment(&state, efx, skb); if (rc) goto mem_err; frag_i = -1; } if (tso_start_new_packet(tx_queue, skb, &state) < 0) goto mem_err; while (1) { rc = tso_fill_packet_with_fragment(tx_queue, skb, &state); if (unlikely(rc)) { rc2 = NETDEV_TX_BUSY; goto unwind; } /* Move onto the next fragment? */ if (state.in_len == 0) { if (++frag_i >= skb_shinfo(skb)->nr_frags) /* End of payload reached. */ break; rc = tso_get_fragment(&state, efx, skb_shinfo(skb)->frags + frag_i); if (rc) goto mem_err; } /* Start at new packet? */ if (state.packet_space == 0 && tso_start_new_packet(tx_queue, skb, &state) < 0) goto mem_err; } /* Pass off to hardware */ efx_nic_push_buffers(tx_queue); tx_queue->tso_bursts++; return NETDEV_TX_OK; mem_err: netif_err(efx, tx_err, efx->net_dev, "Out of memory for TSO headers, or PCI mapping error\n"); dev_kfree_skb_any(skb); unwind: /* Free the DMA mapping we were in the process of writing out */ if (state.unmap_len) { if (state.unmap_single) pci_unmap_single(efx->pci_dev, state.unmap_addr, state.unmap_len, PCI_DMA_TODEVICE); else pci_unmap_page(efx->pci_dev, state.unmap_addr, state.unmap_len, PCI_DMA_TODEVICE); } efx_enqueue_unwind(tx_queue); return rc2; }