void gen_ip_frag_proc(int it, TPTD_Token * token) { //fprintf(stderr, "gen_ip_frag_proc\n"); struct proc_node *i; u_char *data = token->data; //fprintf(stderr, "f**k f**k id %d\n", it); struct ip *iph = (struct ip *) data; int need_free = 0; int skblen; void (*glibc_syslog_h_workaround)(int, int, struct ip *, void*)= nids_params.syslog; ip_fast_csum((unsigned char *) iph, iph->ip_hl); if (token->caplen < (int)sizeof(struct ip) || iph->ip_hl < 5 || iph->ip_v != 4 || (u_short)ip_fast_csum((unsigned char *) iph, iph->ip_hl) != 0 || token->caplen < ntohs(iph->ip_len) || ntohs(iph->ip_len) < iph->ip_hl << 2) { glibc_syslog_h_workaround(NIDS_WARN_IP, NIDS_WARN_IP_HDR, iph, 0); token->token_state = TOKEN_STATE_END; // fprintf(stderr, "break on ipfragment 1\n"); return; } if (iph->ip_hl > 5 && ip_options_compile((unsigned char *)data)) { glibc_syslog_h_workaround(NIDS_WARN_IP, NIDS_WARN_IP_SRR, iph, 0); token->token_state = TOKEN_STATE_END; //fprintf(stderr, "break on ipfragment 2\n"); return; } switch (ip_defrag_stub((struct ip *) data, &iph)) { case IPF_ISF: //fprintf(stderr, "IPF_ISF\n"); token->token_state = TOKEN_STATE_ALIVE; //fprintf(stderr, "break on ipfragment 2\n"); return; case IPF_NOTF: need_free = 0; iph = (struct ip *) data; break; case IPF_NEW: need_free = 1; break; default:; } skblen = ntohs(iph->ip_len) + 16; if (!need_free) skblen += nids_params.dev_addon; skblen = (skblen + 15) & ~15; skblen += nids_params.sk_buff_size; if (need_free) free(iph); token->token_state = TOKEN_STATE_GOON; return; }
/* Generate a checksum for an outgoing IP datagram. */ __inline__ void ip_send_check(struct iphdr *iph) { iph->check = 0; #ifndef CONFIG_CSUM_UNNECESSARY iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); #endif }
static int CUSTOM_check_IP_checksum(struct sk_buff *skb, unsigned int offset){ __sum16 ck; struct iphdr *iph; int ok; skb_pull(skb, offset); iph = get_IP_header(skb); //printk(" ---> checksum: %u\n", iph->check); if(iph->check == 0) return -1; ck = iph->check; iph->check = 0; iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); if(iph->check != ck){ //printk("\n NO CHECK %u | %u \n", iph->check, ck); ok = -1; iph->check = ck; } else{ //printk("\n YES CHECK %u | %u \n", iph->check, ck); ok = 0; } skb_push(skb, offset); return ok; }
void skb_updateChecksumIP_UDP(struct sk_buff *skb) { struct udphdr *uh; struct iphdr *iph; unsigned long len; // retrieve IP header iph = ip_hdr(skb); // retrieve UDP header uh = (struct udphdr*)(skb->data+(iph->ihl<<2)); //update IP header iph->check = 0; iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); // update UDP header len = skb->len - (iph->ihl<<2); skb->csum = csum_partial((char*)uh + sizeof(struct udphdr),len-sizeof(struct udphdr),0); //skb_checksum(skb, offset, skb->len-offset, 0); uh->check =0; uh->check = csum_tcpudp_magic(iph->saddr,iph->daddr,len,IPPROTO_UDP, csum_partial((char*)uh,sizeof(struct udphdr),skb->csum)); }
int32_t fio_icmp_gen_resp(struct fio_nic *nic, struct icmp_packet *icmp_from, struct icmp_packet *icmp_to, struct fio_rxdata *rxd, int realtime) { if (TXDATA_TYPE_REALTIME != realtime) memcpy(icmp_to, icmp_from, rxd->size); memcpy(&icmp_to->eh.ether_dhost, &rxd->smac, ETH_ALEN); memcpy(&icmp_to->eh.ether_shost, &nic->if_mac, ETH_ALEN); struct ip *ip = &icmp_to->ip; ip->ip_len = ntohs(rxd->size - sizeof(struct ether_header)); ip->ip_dst.s_addr = rxd->sip; ip->ip_src.s_addr = rxd->dip; ip->ip_sum = 0; ip->ip_sum = ip_fast_csum((char*)ip, ip->ip_hl); struct icmp *icmp = &icmp_to->icmp; OD( "icmp_type = %x", icmp->icmp_type); icmp->icmp_type = ICMP_ECHOREPLY;//0 uint8_t *ptr = (uint8_t*)&icmp->icmp_cksum; if (*ptr > (0xff-0x08)) (*(ptr+1))++; *ptr += 0x08; //snprintf((char*)icmp_to->padding, 100, "%s", nic->alise); return 0; }
static int raw_getrawfrag(const void *p, char *to, unsigned int offset, unsigned int fraglen, struct sk_buff *skb) { struct rawfakehdr *rfh = (struct rawfakehdr *) p; if (memcpy_fromiovecend(to, rfh->iov, offset, fraglen)) return -EFAULT; if (!offset) { struct iphdr *iph = (struct iphdr *)to; if (!iph->saddr) iph->saddr = rfh->saddr; iph->check = 0; iph->tot_len = htons(fraglen); /* This is right as you can't frag RAW packets */ /* * Deliberate breach of modularity to keep * ip_build_xmit clean (well less messy). */ if (!iph->id) ip_select_ident(iph, rfh->dst, NULL); iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); } return 0; }
void netpoll_send_udp(struct netpoll *np, const char *msg, int len) { int total_len, eth_len, ip_len, udp_len; struct sk_buff *skb; struct udphdr *udph; struct iphdr *iph; struct ethhdr *eth; udp_len = len + sizeof(*udph); ip_len = eth_len = udp_len + sizeof(*iph); total_len = eth_len + ETH_HLEN + NET_IP_ALIGN; skb = find_skb(np, total_len, total_len - len); if (!skb) return; skb_copy_to_linear_data(skb, msg, len); skb->len += len; skb_push(skb, sizeof(*udph)); skb_reset_transport_header(skb); udph = udp_hdr(skb); udph->source = htons(np->local_port); udph->dest = htons(np->remote_port); udph->len = htons(udp_len); udph->check = 0; udph->check = csum_tcpudp_magic(htonl(np->local_ip), htonl(np->remote_ip), udp_len, IPPROTO_UDP, csum_partial((unsigned char *)udph, udp_len, 0)); if (udph->check == 0) udph->check = CSUM_MANGLED_0; skb_push(skb, sizeof(*iph)); skb_reset_network_header(skb); iph = ip_hdr(skb); /* iph->version = 4; iph->ihl = 5; */ put_unaligned(0x45, (unsigned char *)iph); iph->tos = 0; put_unaligned(htons(ip_len), &(iph->tot_len)); iph->id = 0; iph->frag_off = 0; iph->ttl = 64; iph->protocol = IPPROTO_UDP; iph->check = 0; put_unaligned(htonl(np->local_ip), &(iph->saddr)); put_unaligned(htonl(np->remote_ip), &(iph->daddr)); iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); eth = (struct ethhdr *) skb_push(skb, ETH_HLEN); skb_reset_mac_header(skb); skb->protocol = eth->h_proto = htons(ETH_P_IP); memcpy(eth->h_source, np->local_mac, 6); memcpy(eth->h_dest, np->remote_mac, 6); skb->dev = np->dev; netpoll_send_skb(np, skb); }
static void lro_update_tcp_ip_header(struct net_lro_desc *lro_desc) { struct iphdr *iph = lro_desc->iph; struct tcphdr *tcph = lro_desc->tcph; __be32 *p; __wsum tcp_hdr_csum; tcph->ack_seq = lro_desc->tcp_ack; tcph->window = lro_desc->tcp_window; if (lro_desc->tcp_saw_tstamp) { p = (__be32 *)(tcph + 1); *(p+2) = lro_desc->tcp_rcv_tsecr; } iph->tot_len = htons(lro_desc->ip_tot_len); iph->check = 0; iph->check = ip_fast_csum((u8 *)lro_desc->iph, iph->ihl); tcph->check = 0; tcp_hdr_csum = csum_partial((u8 *)tcph, TCP_HDR_LEN(tcph), 0); lro_desc->data_csum = csum_add(lro_desc->data_csum, tcp_hdr_csum); tcph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, lro_desc->ip_tot_len - IP_HDR_LEN(iph), IPPROTO_TCP, lro_desc->data_csum); }
void denat_packet(struct sk_buff *skb){ struct in_device *pin_dev; struct iphdr *iph; //u32 naddr; iph = get_IP_header(skb); pin_dev = (struct in_device *) upmt_dev->ip_ptr; if(pin_dev == NULL){ dmesge("denat_packet - pin_dev = NULL"); return; } if(pin_dev->ifa_list == NULL){ dmesge("denat_packet - pin_dev->ifa_list = NULL"); return; } /*if(pin_dev->ifa_list->ifa_address == NULL){ dmesg("denat_packet - error - pin_dev->ifa_list->ifa_address ---> NULL"); return; }*/ //dmesg("IP of upmt_dev: %u ---> ", pin_dev->ifa_list->ifa_address); //print_ip_address(pin_dev->ifa_list->ifa_address); iph->daddr = pin_dev->ifa_list->ifa_address; //naddr = get_dev_ip_address(upmt_dev, NULL, 0); //iph->daddr = naddr; iph->check = 0; iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); compute_TRANSPORT_checksum(skb); }
static int br_parse_ip_options(struct sk_buff *skb) { struct ip_options *opt; struct iphdr *iph; struct net_device *dev = skb->dev; u32 len; iph = ip_hdr(skb); opt = &(IPCB(skb)->opt); /* Basic sanity checks */ if (iph->ihl < 5 || iph->version != 4) goto inhdr_error; if (!pskb_may_pull(skb, iph->ihl*4)) goto inhdr_error; iph = ip_hdr(skb); if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl))) goto inhdr_error; len = ntohs(iph->tot_len); if (skb->len < len) { IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INTRUNCATEDPKTS); goto drop; } else if (len < (iph->ihl*4)) goto inhdr_error; if (pskb_trim_rcsum(skb, len)) { IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INDISCARDS); goto drop; } /* Zero out the CB buffer if no options present */ if (iph->ihl == 5) { memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); return 0; } opt->optlen = iph->ihl*4 - sizeof(struct iphdr); if (ip_options_compile(dev_net(dev), opt, skb)) goto inhdr_error; /* Check correct handling of SRR option */ if (unlikely(opt->srr)) { struct in_device *in_dev = __in_dev_get_rcu(dev); if (in_dev && !IN_DEV_SOURCE_ROUTE(in_dev)) goto drop; if (ip_options_rcv_srr(skb)) goto drop; } return 0; inhdr_error: IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_INHDRERRORS); drop: return -1; }
static int ib_get_header_version(const union rdma_network_hdr *hdr) { const struct iphdr *ip4h = (struct iphdr *)&hdr->roce4grh; struct iphdr ip4h_checked; const struct ipv6hdr *ip6h = (struct ipv6hdr *)&hdr->ibgrh; /* If it's IPv6, the version must be 6, otherwise, the first * 20 bytes (before the IPv4 header) are garbled. */ if (ip6h->version != 6) return (ip4h->version == 4) ? 4 : 0; /* version may be 6 or 4 because the first 20 bytes could be garbled */ /* RoCE v2 requires no options, thus header length * must be 5 words */ if (ip4h->ihl != 5) return 6; /* Verify checksum. * We can't write on scattered buffers so we need to copy to * temp buffer. */ memcpy(&ip4h_checked, ip4h, sizeof(ip4h_checked)); ip4h_checked.check = 0; ip4h_checked.check = ip_fast_csum((u8 *)&ip4h_checked, 5); /* if IPv4 header checksum is OK, believe it */ if (ip4h->check == ip4h_checked.check) return 4; return 6; }
static int vnet_start_xmit(struct sk_buff *skb, struct net_device *net) { struct pdp_info *dev = (struct pdp_info *)net->ml_priv; #ifdef USE_LOOPBACK_PING int ret; struct sk_buff *skb2; struct icmphdr *icmph; struct iphdr *iph; #endif DPRINTK(2, "BEGIN\n"); #ifdef USE_LOOPBACK_PING dev->vn_dev.stats.tx_bytes += skb->len; dev->vn_dev.stats.tx_packets++; skb2 = alloc_skb(skb->len, GFP_ATOMIC); if (skb2 == NULL) { DPRINTK(1, "alloc_skb() failed\n"); dev_kfree_skb_any(skb); return -ENOMEM; } memcpy(skb2->data, skb->data, skb->len); skb_put(skb2, skb->len); dev_kfree_skb_any(skb); icmph = (struct icmphdr *)(skb2->data + sizeof(struct iphdr)); iph = (struct iphdr *)skb2->data; icmph->type = __constant_htons(ICMP_ECHOREPLY); ret = iph->daddr; iph->daddr = iph->saddr; iph->saddr = ret; iph->check = 0; iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); skb2->dev = net; skb2->protocol = __constant_htons(ETH_P_IP); netif_rx(skb2); dev->vn_dev.stats.rx_packets++; dev->vn_dev.stats.rx_bytes += skb->len; #else if (vnet_start_xmit_flag != 0) { return NETDEV_TX_BUSY; } vnet_start_xmit_flag = 1; workqueue_data = (unsigned long)skb; PREPARE_WORK(&dev->vn_dev.xmit_task,vnet_defer_xmit); schedule_work(&dev->vn_dev.xmit_task); netif_stop_queue(net); #endif DPRINTK(2, "END\n"); return NETDEV_TX_OK; }
static void flush_session(struct mlx4_en_priv *priv, struct mlx4_en_ipfrag *session, u16 more) { struct sk_buff *skb = session->fragments; struct iphdr *iph = ip_hdr(skb); struct net_device *dev = skb->dev; /* Update IP length and checksum */ iph->tot_len = htons(session->total_len); iph->frag_off = htons(more | (session->offset >> 3)); iph->check = 0; iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); if (session->vlan) { if (priv->mdev->profile.use_napi) vlan_hwaccel_receive_skb(skb, priv->vlgrp, be16_to_cpu(session->sl_vid)); else vlan_hwaccel_rx(skb, priv->vlgrp, be16_to_cpu(session->sl_vid)); } else { if (priv->mdev->profile.use_napi) netif_receive_skb(skb); else netif_rx(skb); } dev->last_rx = jiffies; session->fragments = NULL; session->last = NULL; }
u16 bpf_checksum(const u8 *buf, u32 len) { /* if 'buf' points to BPF program stack, bpf_check() * verified that 'len' bytes of it are valid * len/4 rounds the length down, so that memory is safe to access */ return ip_fast_csum(buf, len/4); }
/*----------------------------------------------------------------------------*/ inline int ProcessInIPv4Packet(mtcp_manager_t mtcp, struct pkt_ctx *pctx) { bool release = false; int ret; struct mon_listener *walk; /* check and process IPv4 packets */ struct iphdr* iph = (struct iphdr *)((char *)pctx->p.ethh + sizeof(struct ethhdr)); int ip_len = ntohs(iph->tot_len); /* drop the packet shorter than ip header */ if (ip_len < sizeof(struct iphdr)) { ret = ERROR; goto __return; } if (ip_fast_csum(iph, iph->ihl)) { ret = ERROR; goto __return; } if (iph->version != IPVERSION ) { release = true; ret = FALSE; goto __return; } FillInPacketIPContext(pctx, iph, ip_len); switch (iph->protocol) { case IPPROTO_TCP: return ProcessInTCPPacket(mtcp, pctx); case IPPROTO_ICMP: if (ProcessICMPPacket(mtcp, pctx)) return TRUE; default: /* forward other protocols without any processing */ if (!mtcp->num_msp || !pctx->forward) release = true; else ForwardIPPacket(mtcp, pctx); ret = FALSE; goto __return; } __return: /* callback for monitor raw socket */ TAILQ_FOREACH(walk, &mtcp->monitors, link) if (walk->socket->socktype == MOS_SOCK_MONITOR_RAW) HandleCallback(mtcp, MOS_NULL, walk->socket, MOS_SIDE_BOTH, pctx, MOS_ON_PKT_IN); if (release && mtcp->iom->release_pkt) mtcp->iom->release_pkt(mtcp->ctx, pctx->in_ifidx, (unsigned char *)pctx->p.ethh, pctx->p.eth_len); return ret; }
static void construct_rxpack(struct sk_buff *skb, struct net_device *dev) { unsigned char *type; struct iphdr *ih; __be32 *saddr, *daddr, tmp; unsigned char tmp_dev_addr[ETH_ALEN]; struct ethhdr *ethhdr; struct sk_buff *rx_skb; /* * Read and save the data from hardware * Switch the source/destination of the MAC address */ ethhdr = (struct ethhdr *)skb->data; memcpy(tmp_dev_addr, ethhdr->h_dest, ETH_ALEN); memcpy(ethhdr->h_dest, ethhdr->h_source, ETH_ALEN); memcpy(ethhdr->h_source, tmp_dev_addr, ETH_ALEN); /* * Switch the source/destination of the IP address */ ih = (struct iphdr *)(skb->data + sizeof(struct ethhdr)); saddr = &ih->saddr; daddr = &ih->daddr; tmp = *saddr; *saddr = *daddr; *daddr = tmp; //((u8 *)saddr)[2] ^= 1; /* change the third octet (class C) */ //((u8 *)daddr)[2] ^= 1; type = skb->data + sizeof(struct ethhdr) + sizeof(struct iphdr); //printk("tx package type = %02x\n", *type); /* * Modify the type, 0x8 means ping */ *type = 0; /* 0 means reply */ ih->check = 0; /* and rebuild the checksum (ip needs it) */ ih->check = ip_fast_csum((unsigned char *)ih,ih->ihl); /* Construct a sk_buff structure */ rx_skb = dev_alloc_skb(skb->len + 2); skb_reserve(rx_skb, 2); /* align IP on 16B boundary */ memcpy(skb_put(rx_skb, skb->len), skb->data, skb->len); /* Write metadata, and then pass to the receive level */ rx_skb->dev = dev; rx_skb->protocol = eth_type_trans(rx_skb, dev); rx_skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */ dev->stats.rx_packets++; dev->stats.rx_bytes += skb->len; /* Submit sk_buff */ netif_rx(rx_skb); }
/*----------------------------------------------------------------------------*/ void DumpIPPacketToFile(FILE *fout, const struct iphdr *iph, int len) { struct udphdr *udph; struct tcphdr *tcph; uint8_t *t; udph = (struct udphdr *)((uint32_t *)iph + iph->ihl); tcph = (struct tcphdr *)((uint32_t *)iph + iph->ihl); t = (uint8_t *)&iph->saddr; fprintf(fout, "%u.%u.%u.%u", t[0], t[1], t[2], t[3]); if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) fprintf(fout, "(%d)", ntohs(udph->source)); fprintf(fout, " -> "); t = (uint8_t *)&iph->daddr; fprintf(fout, "%u.%u.%u.%u", t[0], t[1], t[2], t[3]); if (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) fprintf(fout, "(%d)", ntohs(udph->dest)); fprintf(fout, " IP_ID=%d", ntohs(iph->id)); fprintf(fout, " TTL=%d ", iph->ttl); if (ip_fast_csum(iph, iph->ihl)) { fprintf(fout, "(bad checksum) "); } switch (iph->protocol) { case IPPROTO_TCP: fprintf(fout, "TCP "); if (tcph->syn) fprintf(fout, "S "); if (tcph->fin) fprintf(fout, "F "); if (tcph->ack) fprintf(fout, "A "); if (tcph->rst) fprintf(fout, "R "); fprintf(fout, "seq %u ", ntohl(tcph->seq)); if (tcph->ack) fprintf(fout, "ack %u ", ntohl(tcph->ack_seq)); fprintf(fout, "WDW=%u ", ntohs(tcph->window)); break; case IPPROTO_UDP: fprintf(fout, "UDP "); break; default: fprintf(fout, "protocol %d ", iph->protocol); goto done; } done: fprintf(fout, "len=%d\n", len); }
s32 dp_bfd_echo_packet_rebound(struct sk_buff *skb) { u32 l2_len; u32 data_off = (u32)((skb->nh.raw - skb->data) + skb->nh.iph->ihl*4); u32 udp_data_len; struct sk_buff *skb_new; struct ethhdr *eth; struct iphdr *iph; struct udphdr *udph; struct udphdr _hdr, *hdr; skb_new = alloc_skb(1500, GFP_ATOMIC); if(NULL == skb_new) { return ERROR_FAIL; } skb_new->in_if = skb->out_if; skb_new->out_if = skb->in_if; skb_new->forward_flag = 0; skb_new->dev = skb->dev; l2_len = (u32)((u8*)skb->nh.iph - (u8*)skb->mac.raw); eth = (struct ethhdr*)skb_put(skb_new, l2_len); memcpy(eth, skb->mac.raw, l2_len); skb_new->mac.raw = (u8 *)eth; memcpy(eth->h_dest, eth_hdr(skb)->h_source, ETH_ALEN); memcpy(eth->h_source, eth_hdr(skb)->h_dest, ETH_ALEN); eth->h_proto = 0x0800; iph = (struct iphdr*)skb_put(skb_new, sizeof(struct iphdr)); memcpy(iph, skb->nh.iph, sizeof(struct iphdr)); skb_new->nh.iph = iph; iph->daddr = skb_get_src_ip(skb); iph->saddr = skb_get_dst_ip(skb); iph->id = skb->nh.iph->id; udph = (struct udphdr*)skb_put(skb_new, sizeof(struct udphdr)); hdr = skb_header_pointer(skb, (s32)data_off, sizeof(_hdr), &_hdr); memcpy(udph, hdr, sizeof(struct udphdr)); skb_new->h.uh = udph; udph->dest = hdr->source; udph->source = hdr->dest; udp_data_len = hdr->len - sizeof(struct udphdr); skb_put(skb_new, udp_data_len); memcpy((u8 *)udph + sizeof(struct udphdr), (u8 *)hdr + sizeof(struct udphdr), udp_data_len); udph->check = 0; udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, (u16)(sizeof(struct udphdr) + udp_data_len), IPPROTO_UDP, csum_partial((u8*)udph, (int)(sizeof(struct udphdr)+udp_data_len), 0)); iph->check = 0; iph->check = ip_fast_csum((u8*)iph, iph->ihl); skb_xmit_for_bfd(skb_new ,skb->dev->ifindex); return ERROR_SUCCESS; }
void inat_packet(struct sk_buff *skb, const struct tun_param *tp){ struct iphdr *iph; iph = get_IP_header(skb); iph->saddr = tp->in.local; iph->check = 0; iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); compute_TRANSPORT_checksum(skb); }
/** * Netfilter is nice enough to defragment the packet for us and store * details about the fragments in skb->data_len and skb_shinfo(skb)->frag_list * All the fragments are there, we just have to add them all up by * traversing the frag_list linked list. * **/ void calc_checksum(struct sk_buff *skb) { struct iphdr *iph = NULL; struct tcphdr *th = NULL; struct udphdr *uh = NULL; uint16_t l4len = 0; uint16_t iph_len = 0; uint16_t tcpdata_len = 0; uint16_t tcph_len = 0; uint16_t tcp_len = 0; uint16_t l3len = 0; void *l4ptr = NULL; iph = ip_hdr(skb); if(!iph){ return; } l3len = iph->ihl << 2; if(iph->protocol == IPPROTO_UDP){ uh = (struct udphdr *)((unsigned char *)iph + (iph->ihl<<2)); iph_len = l3len; l4ptr = uh; l4len = ntohs(uh->len); uh->check = 0x0000; } if(iph->protocol == IPPROTO_TCP){ th = (struct tcphdr *)((unsigned char *)iph + (iph->ihl<<2)); tcph_len = th->doff << 2; iph_len = l3len; tcpdata_len = ntohs(iph->tot_len) - iph_len - tcph_len; tcp_len = tcph_len + tcpdata_len; l4ptr = th; l4len = tcp_len; th->check = 0x0000; } if(th){ th->check = csum_tcpudp_magic(iph->saddr, iph->daddr, l4len, IPPROTO_TCP, skb_checksum(skb, iph_len, l4len, 0)); } if(uh){ uh->check = csum_tcpudp_magic(iph->saddr, iph->daddr, l4len, IPPROTO_UDP, skb_checksum(skb, iph_len, l4len, 0)); } iph->check = 0; iph->check = ip_fast_csum((void *)iph, iph->ihl); }
void build_packet(char *buf, int size, uint64_t *seed) { struct ethhdr *eth; struct iphdr *ip; struct udphdr *udp; uint32_t rand_val; //memset(buf, 0, size); /* build an ethernet header */ eth = (struct ethhdr *)buf; eth->h_dest[0] = 0x00; eth->h_dest[1] = 0x00; eth->h_dest[2] = 0x00; eth->h_dest[3] = 0x00; eth->h_dest[4] = 0x00; eth->h_dest[5] = 0x02; eth->h_source[0] = 0x00; eth->h_source[1] = 0x00; eth->h_source[2] = 0x00; eth->h_source[3] = 0x00; eth->h_source[4] = 0x00; eth->h_source[5] = 0x01; eth->h_proto = HTONS(0x0800); /* build an IP header */ ip = (struct iphdr *)(buf + sizeof(*eth)); ip->version = 4; ip->ihl = 5; ip->tos = 0; ip->tot_len = HTONS(size - sizeof(*eth)); ip->id = 0; ip->frag_off = 0; ip->ttl = 32; ip->protocol = IPPROTO_UDP; ip->saddr = HTONL(0x0A000001); ip->daddr = HTONL(myrand(seed)); ip->check = 0; ip->check = ip_fast_csum(ip, ip->ihl); udp = (struct udphdr *)((char *)ip + sizeof(*ip)); rand_val = myrand(seed); udp->source = HTONS(rand_val & 0xFFFF); udp->dest = HTONS((rand_val >> 16) & 0xFFFF); udp->len = HTONS(size - sizeof(*eth) - sizeof(*ip)); udp->check = 0; }
static bool parse_udp_packet(struct sk_buff *skb, struct iphdr **piph, struct udphdr **puh, int *pulen) { int proto, len, ulen; struct iphdr *iph; struct udphdr *uh; proto = ntohs(eth_hdr(skb)->h_proto); if (proto != ETH_P_IP) return false; if (skb->pkt_type == PACKET_OTHERHOST) return false; if (skb_shared(skb)) return false; if (!pskb_may_pull(skb, sizeof(struct iphdr))) return false; iph = (struct iphdr *)skb->data; if (iph->ihl < 5 || iph->version != 4) return false; if (!pskb_may_pull(skb, iph->ihl * 4)) return false; iph = (struct iphdr *)skb->data; if (ip_fast_csum((u8 *)iph, iph->ihl) != 0) return false; len = ntohs(iph->tot_len); if (skb->len < len || len < iph->ihl * 4) return false; /* * Our transport medium may have padded the buffer out. * Now We trim to the true length of the frame. */ if (pskb_trim_rcsum(skb, len)) return false; iph = (struct iphdr *)skb->data; if (iph->protocol != IPPROTO_UDP) return false; len -= iph->ihl * 4; uh = (struct udphdr *)(((char *)iph) + iph->ihl * 4); ulen = ntohs(uh->len); if (ulen != len) return false; *piph = iph; *puh = uh; *pulen = ulen; return true; }
/** * @brief this adds a IP ckecksum in the IP header of the packet * @param skb */ static void __adf_net_ip_cksum(struct sk_buff *skb) { struct iphdr *ih = {0}; struct skb_shared_info *sh = skb_shinfo(skb); adf_os_assert(sh->nr_frags == 0); ih = (struct iphdr *)(skb->data + sizeof(struct ethhdr)); ih->check = 0; ih->check = ip_fast_csum((unsigned char *)ih, ih->ihl); }
static void emulator_rx_packet(struct sk_buff *skb, struct net_device *dev) { /* 参考LDD3 */ unsigned char *type; struct iphdr *ih; __be32 *saddr, *daddr, tmp; unsigned char tmp_dev_addr[ETH_ALEN]; struct ethhdr *ethhdr; struct sk_buff *rx_skb; // 从硬件读出/保存数据 /* 对调"源/目的"的mac地址 */ ethhdr = (struct ethhdr *)skb->data; memcpy(tmp_dev_addr, ethhdr->h_dest, ETH_ALEN); memcpy(ethhdr->h_dest, ethhdr->h_source, ETH_ALEN); memcpy(ethhdr->h_source, tmp_dev_addr, ETH_ALEN); /* 对调"源/目的"的ip地址 */ ih = (struct iphdr *)(skb->data + sizeof(struct ethhdr)); saddr = &ih->saddr; daddr = &ih->daddr; tmp = *saddr; *saddr = *daddr; *daddr = tmp; //((u8 *)saddr)[2] ^= 1; /* change the third octet (class C) */ //((u8 *)daddr)[2] ^= 1; type = skb->data + sizeof(struct ethhdr) + sizeof(struct iphdr); //printk("tx package type = %02x\n", *type); // 修改类型, 原来0x8表示ping *type = 0; /* 0表示reply */ ih->check = 0; /* and rebuild the checksum (ip needs it) */ ih->check = ip_fast_csum((unsigned char *)ih,ih->ihl); // 构造一个sk_buff rx_skb = dev_alloc_skb(skb->len + 2); skb_reserve(rx_skb, 2); /* align IP on 16B boundary */ memcpy(skb_put(rx_skb, skb->len), skb->data, skb->len); /* Write metadata, and then pass to the receive level */ rx_skb->dev = dev; rx_skb->protocol = eth_type_trans(rx_skb, dev); rx_skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */ dev->stats.rx_packets++; dev->stats.rx_bytes += skb->len; // 提交sk_buff netif_rx(rx_skb); }
/*** * rt_ip_rcv */ int rt_ip_rcv(struct rtskb *skb, struct rtnet_device *rtdev, struct rtpacket_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; 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 drop; if ( ip_fast_csum((u8 *)iph, iph->ihl)!=0 ) goto drop; { __u32 len = ntohs(iph->tot_len); if ( (skb->len<len) || (len<(iph->ihl<<2)) ) goto drop; rtskb_trim(skb, len); } if (skb->dst == NULL) if ( rt_ip_route_input(skb, iph->daddr, iph->saddr, skb->rtdev) ) goto drop; /* ip_local_deliver */ if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) { skb = rt_ip_defrag(skb); if (!skb) return 0; } return rt_ip_local_deliver_finish(skb); drop: kfree_rtskb(skb); return NET_RX_DROP; }
static void nic_hw_xmit(struct net_device *netdev) { struct nic_priv *priv = netdev_priv(netdev); struct iphdr *iph; u32 *saddr, *daddr; struct in_device* in_dev; struct in_ifaddr* if_info; if (priv->tx_len < sizeof(struct ethhdr) + sizeof(struct iphdr)) { netif_info(priv, hw, netdev, "%s(#%d), too short\n", __func__, __LINE__); return; } dump(priv->tx_buf); iph = (struct iphdr *)(priv->tx_buf + sizeof(struct ethhdr)); saddr = &iph->saddr; daddr = &iph->daddr; netif_info(priv, hw, netdev, "%s(#%d), orig, src:%pI4, dst:%pI4, len:%d\n", __func__, __LINE__, saddr, daddr, priv->tx_len); in_dev = nic_dev[(netdev == nic_dev[0] ? 1 : 0)]->ip_ptr; if (in_dev) { if_info = in_dev->ifa_list; for (if_info = in_dev->ifa_list; if_info; if_info=if_info->ifa_next) { #if 0 printk("label:%s, address=%pI4\n", if_info->ifa_label, &if_info->ifa_address); #endif *saddr = *daddr = if_info->ifa_address; ((u8 *)saddr)[3]++; netif_info(priv, hw, netdev, "%s(#%d), new, src:%pI4, dst:%pI4\n", __func__, __LINE__, saddr, daddr); break; } if (!if_info) { /* drop packet */ netdev->stats.tx_dropped++; netif_info(priv, hw, netdev, "%s(#%d), drop packet\n", __func__, __LINE__); return; } } iph->check = 0; /* and rebuild the checksum (ip needs it) */ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); netdev->stats.tx_packets++; netdev->stats.tx_bytes += priv->tx_len; nic_rx(nic_dev[(netdev == nic_dev[0] ? 1 : 0)], priv->tx_len, priv->tx_buf); }
static void emulate_large_send_offload(struct sk_buff *skb) { struct iphdr *iph = skb->nh.iph; struct tcphdr *th = (struct tcphdr*)(skb->nh.raw + (iph->ihl * 4)); unsigned int doffset = (iph->ihl + th->doff) * 4; unsigned int mtu = skb_shinfo(skb)->tso_size + doffset; unsigned int offset = 0; u32 seq = ntohl(th->seq); u16 id = ntohs(iph->id); while (offset + doffset < skb->len) { unsigned int frag_size = min(mtu, skb->len - offset) - doffset; struct sk_buff *nskb = alloc_skb(mtu + 32, GFP_ATOMIC); if (!nskb) break; skb_reserve(nskb, 32); nskb->mac.raw = nskb->data - 14; nskb->nh.raw = nskb->data; iph = nskb->nh.iph; memcpy(nskb->data, skb->nh.raw, doffset); if (skb_copy_bits(skb, doffset + offset, nskb->data + doffset, frag_size)) BUG(); skb_put(nskb, doffset + frag_size); nskb->ip_summed = CHECKSUM_UNNECESSARY; nskb->dev = skb->dev; nskb->priority = skb->priority; nskb->protocol = skb->protocol; nskb->dst = dst_clone(skb->dst); memcpy(nskb->cb, skb->cb, sizeof(skb->cb)); nskb->pkt_type = skb->pkt_type; th = (struct tcphdr*)(nskb->nh.raw + iph->ihl*4); iph->tot_len = htons(frag_size + doffset); iph->id = htons(id); iph->check = 0; iph->check = ip_fast_csum((unsigned char *) iph, iph->ihl); th->seq = htonl(seq); if (offset + doffset + frag_size < skb->len) th->fin = th->psh = 0; netif_rx(nskb); offset += frag_size; seq += frag_size; id++; } dev_kfree_skb(skb); }
/*----------------------------------------------------------------------------*/ uint8_t * IPOutput(struct mtcp_manager *mtcp, tcp_stream *stream, uint16_t tcplen) { struct iphdr *iph; int nif; unsigned char *haddr; if (stream->sndvar->nif_out >= 0) { nif = stream->sndvar->nif_out; } else { nif = GetOutputInterface(stream->daddr); stream->sndvar->nif_out = nif; } haddr = GetDestinationHWaddr(stream->daddr); if (!haddr) { #if 0 uint8_t *da = (uint8_t *)&stream->daddr; TRACE_INFO("[WARNING] The destination IP %u.%u.%u.%u " "is not in ARP table!\n", da[0], da[1], da[2], da[3]); #endif /* if not found in the arp table, send arp request and return NULL */ /* tcp will retry sending the packet later */ RequestARP(mtcp, stream->daddr, stream->sndvar->nif_out, mtcp->cur_ts); return NULL; } iph = (struct iphdr *)EthernetOutput(mtcp, ETH_P_IP, stream->sndvar->nif_out, haddr, tcplen + IP_HEADER_LEN); if (!iph) { return NULL; } iph->ihl = IP_HEADER_LEN >> 2; iph->version = 4; iph->tos = 0; iph->tot_len = htons(IP_HEADER_LEN + tcplen); iph->id = htons(stream->sndvar->ip_id++); iph->frag_off = htons(0x4000); // no fragmentation iph->ttl = 64; iph->protocol = IPPROTO_TCP; iph->saddr = stream->saddr; iph->daddr = stream->daddr; iph->check = 0; iph->check = ip_fast_csum(iph, iph->ihl); return (uint8_t *)(iph + 1); }
static void gen_ip_frag_proc(u_char * data, int len) { struct proc_node *i; struct ip *iph = (struct ip *) data; int need_free = 0; int skblen; void (*glibc_syslog_h_workaround)(int, int, struct ip *, void*)= nids_params.syslog; if (!nids_params.ip_filter(iph, len)) return; #if 0 if (len < (int)sizeof(struct ip) || iph->ip_hl < 5 || iph->ip_v != 4 || ip_fast_csum((unsigned char *) iph, iph->ip_hl) != 0 || len < ntohs(iph->ip_len) || ntohs(iph->ip_len) < iph->ip_hl << 2) { glibc_syslog_h_workaround(NIDS_WARN_IP, NIDS_WARN_IP_HDR, iph, 0); return; } #endif if (iph->ip_hl > 5 && ip_options_compile((unsigned char *)data)) { glibc_syslog_h_workaround(NIDS_WARN_IP, NIDS_WARN_IP_SRR, iph, 0); return; } switch (ip_defrag_stub((struct ip *) data, &iph)) { case IPF_ISF: return; case IPF_NOTF: need_free = 0; iph = (struct ip *) data; break; case IPF_NEW: need_free = 1; break; default: ; } skblen = ntohs(iph->ip_len) + 16; if (!need_free) skblen += nids_params.dev_addon; skblen = (skblen + 15) & ~15; skblen += nids_params.sk_buff_size; for (i = ip_procs; i; i = i->next) (i->item) (iph, skblen); if (need_free) free(iph); }
int ipsec_tunnel_udp_encap(struct sk_buff *skb, uint8_t natt_type, uint8_t natt_head, uint16_t natt_sport, uint16_t natt_dport) { struct iphdr *ipp = skb->nh.iph; struct udphdr *udp; int iphlen; KLIPS_PRINT(debug_tunnel & DB_TN_XMIT, "klips_debug:ipsec_tunnel_udp_encap: " "encapsuling packet into UDP (NAT-Traversal) (%d %d)\n", natt_type, natt_head); iphlen = ipp->ihl << 2; ipp->tot_len = htons(ntohs(ipp->tot_len) + natt_head); if(skb_tailroom(skb) < natt_head) { printk(KERN_WARNING "klips_error:ipsec_tunnel_udp_encap: " "tried to skb_put %d, %d available. " "This should never happen, please report.\n", natt_head, skb_tailroom(skb)); return -1; } skb_put(skb, natt_head); udp = (struct udphdr *)((char *)ipp + iphlen); /* move ESP hdr after UDP hdr */ memmove((void *)((char *)udp + natt_head), (void *)(udp), ntohs(ipp->tot_len) - iphlen - natt_head); /* clear UDP & Non-IKE Markers (if any) */ memset(udp, 0, natt_head); /* fill UDP with usefull informations ;-) */ udp->source = htons(natt_sport); udp->dest = htons(natt_dport); udp->len = htons(ntohs(ipp->tot_len) - iphlen); /* set protocol */ ipp->protocol = IPPROTO_UDP; /* fix IP checksum */ ipp->check = 0; ipp->check = ip_fast_csum((unsigned char *)ipp, ipp->ihl); return 0; }