struct skbuff * ip_frag(struct net_device *dev, struct skbuff *skb) { __u8 frag_num = 0; __u16 tot_len = ntohs(skb->nh.iph->tot_len); __u8 mtu = dev->mtu; __u8 half_mtu = (mtu+1)/2; frag_num = (tot_len - IPHDR_LEN + half_mtu)/(mtu - IPHDR_LEN - ETH_HLEN);/*计算分片的个数*/ __u16 i = 0; struct skbuff *skb_h = NULL,*skb_t = NULL,*skb_c = NULL; for(i = 0,skb->tail = skb->head; i<frag_num;i++) { if(i ==0){ /*第一个分片*/ skb_t = skb_alloc(mtu); /*申请内存*/ skb_t->phy.raw = skb_put(skb_t, ETH_HLEN); /*物理层*/ skb_t->nh.raw = skb_put(skb_t, IPHDR_LEN); /*网络层*/ memcpy(skb_t->head, skb->head, mtu); /*拷贝数据*/ skb_put(skb,mtu); /*增加数据长度len值*/ skb_t->nh.iph->frag_off = htons(0x2000); /*设置偏移标记值*/ skb_t->nh.iph->tot_len = htons(mtu-ETH_HLEN); /*设置IP头部总长度*/ skb_t->nh.iph->check = 0; /*设置校验和为0*/ skb_t->nh.iph->check = SIP_Chksum(skb_t->nh.raw, IPHDR_LEN);/*计算校验和*/ skb_h = skb_c =skb_t; /*头部分片指针设置*/ }else if(i==frag_num -1){ /*最后一个分片*/ skb_t = skb_alloc(mtu); /*申请内存*/ skb_t->phy.raw = skb_put(skb_t, ETH_HLEN); /*物理层*/ skb_t->nh.raw = skb_put(skb_t, IPHDR_LEN); /*网络层*/ memcpy(skb_t->head, skb->head, ETH_HLEN + IPHDR_LEN); /*拷贝数据*/ memcpy(skb_t->head + ETH_HLEN + IPHDR_LEN, skb->tail, skb->end - skb->tail);/*增加数据长度len值*/ skb_t->nh.iph->frag_off = htons(i*(mtu - ETH_HLEN - IPHDR_LEN) + IPHDR_LEN);/*设置偏移标记值*/ skb_t->nh.iph->tot_len = htons(skb->end - skb->tail + IPHDR_LEN);/*设置IP头部总长度*/ skb_t->nh.iph->check = 0; /*设置校验和为0*/ skb_t->nh.iph->check = SIP_Chksum(skb_t->nh.raw, IPHDR_LEN);/*计算校验和*/ skb_c->next=skb_t; /*挂接此分片*/ }else{ skb_t = skb_alloc(mtu); skb_t->phy.raw = skb_put(skb_t, ETH_HLEN); skb_t->nh.raw = skb_put(skb_t, IPHDR_LEN); memcpy(skb_t->head, skb->head, ETH_HLEN + IPHDR_LEN); memcpy(skb_t->head + ETH_HLEN + IPHDR_LEN, skb->tail, mtu - ETH_HLEN - IPHDR_LEN); skb_put(skb_t, mtu - ETH_HLEN - IPHDR_LEN); skb_t->nh.iph->frag_off = htons((i*(mtu - ETH_HLEN - IPHDR_LEN) + IPHDR_LEN)|0x2000); skb_t->nh.iph->tot_len = htons(mtu - ETH_HLEN); skb_t->nh.iph->check = 0; skb_t->nh.iph->check = SIP_Chksum(skb_t->nh.raw, IPHDR_LEN); skb_c->next=skb_t; skb_c = skb_t; } skb_t->ip_summed = 1; /*已经进行了IP校验和计算*/ } skb_free(skb); /*释放原来的网络数据*/ return skb_h; /*返回分片的头部指针*/ }
static int mipsnet_rx(struct net_device *dev, size_t len) { struct sk_buff *skb; uint8_t *pdata; struct mipsnet_regs *regs; if (!len) return len; regs = (struct mipsnet_regs *)dev->base_addr; skb = skb_alloc(len); if (!skb) { dev->stats.rx_dropped++; return -ENOMEM; } pdata = (uint8_t*) skb->mac.raw; for (; len > 0; len--, pdata++) { *pdata = in32(®s->rxDataBuffer); } show_packet(skb->mac.raw, skb->len, "rx"); skb->dev = dev; netif_rx(skb); dev->stats.rx_packets++; dev->stats.rx_bytes += len; return len; }
static int cs89x0_isr(__u32 irq, void *dev) { int i; __u16 isq_stat; __u16 rx_stat, rx_size; __u16 *buff; struct sock_buff *skb; // struct net_device *ndev = dev; while ((isq_stat = readw(VA(CS8900_IOBASE + CS_ISQ)))) { int regn = isq_stat & 0x3F; if (regn == 4) { rx_stat = readw(VA(CS8900_IOBASE + 0x00)); rx_size = readw(VA(CS8900_IOBASE + 0x00)); DPRINT("isq_stat = 0x%04x, size = 0x%04x (%d)\n", rx_stat, rx_size, rx_size); skb = skb_alloc(0, rx_size); // if NULL buff = (__u16 *)skb->data; for (i = 0; i < rx_size; i += 2) { *buff = readw(VA(CS8900_IOBASE + 0x00)); buff++; } netif_rx(skb); } } return 0; }
static int cs89x0_poll(struct net_device *ndev) { int i; __u16 rx_event; __u16 rx_stat, rx_size; __u16 *buff; struct sock_buff *skb; rx_event = cs8900_inw(0x0124); if (!(rx_event & 0x100)) return 0; // printf("rx event = 0x%04x\n", rx_event); rx_stat = readw(VA(CS8900_IOBASE + 0x00)); rx_size = readw(VA(CS8900_IOBASE + 0x00)); DPRINT("rx_event = 0x%04x, size = 0x%04x (%d)\n", rx_stat, rx_size, rx_size); skb = skb_alloc(0, rx_size); // if NULL buff = (__u16 *)skb->data; for (i = 0; i < rx_size; i += 2) { *buff = readw(VA(CS8900_IOBASE + 0x00)); buff++; } netif_rx(skb); ndev->stat.rx_packets++; return 0; }
int ndp_send(uint8_t type, uint8_t code, const void *body, size_t body_sz, struct net_device *dev) { struct sk_buff *skb; struct in_device *in_dev; struct in6_addr dst_ip6; assert(dev != NULL); skb = skb_alloc(dev->hdr_len + IP6_HEADER_SIZE + ICMP6_MIN_HEADER_SIZE + body_sz); if (skb == NULL) { return -ENOMEM; } skb->dev = dev; skb->nh.raw = skb->mac.raw + dev->hdr_len; skb->h.raw = skb->nh.raw + IP6_HEADER_SIZE; in_dev = inetdev_get_by_dev(dev); assert(in_dev != NULL); inet_pton(AF_INET6, "ff02::1:ff02:10", &dst_ip6); ip6_build(skb->nh.ip6h, ICMP6_MIN_HEADER_SIZE + body_sz, IPPROTO_ICMPV6, 255, &in_dev->ifa6_address, &dst_ip6); icmp6_build(skb->h.icmp6h, type, code, body, body_sz); icmp6_set_check_field(skb->h.icmp6h, skb->nh.ip6h); return ndp_xmit(skb, dev); }
static int send_request(struct net_device *dev, uint16_t pro, uint8_t pln, const void *spa, const void *tpa) { int ret; struct sk_buff *skb; struct net_header_info hdr_info; skb = skb_alloc(dev->hdr_len + ARP_CALC_HEADER_SIZE(dev->addr_len, pln)); if (skb == NULL) { return -ENOMEM; } skb->dev = dev; skb->nh.raw = skb->mac.raw + dev->hdr_len; hdr_info.type = ETH_P_ARP; hdr_info.src_hw = &dev->dev_addr[0]; hdr_info.dst_hw = &dev->broadcast[0]; assert(dev->ops != NULL); assert(dev->ops->build_hdr != NULL); ret = dev->ops->build_hdr(skb, &hdr_info); if (ret != 0) { skb_free(skb); return ret; } arp_build(arp_hdr(skb), dev->type, pro, dev->addr_len, pln, ARP_OP_REQUEST, &dev->dev_addr[0], spa, &dev->broadcast[0], tpa); return net_tx(skb, NULL); }
ssize_t sip_sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) { struct sip_socket *socket; struct in_addr remote_addr; struct sockaddr_in* to_in = (struct sockaddr_in*)to; /*网络数据头部的长度*/ int l_head = sizeof(struct sip_ethhdr) + sizeof(struct sip_iphdr) + sizeof(struct sip_udphdr); int size = l_head + len; /*数据总长度*/ struct skbuff *skb = skb_alloc( size); /*申请空间*/ char* data = skb_put(skb, l_head); /*设置data指针*/ memcpy(data, buf, len); /*将用户数据拷贝到缓冲区*/ remote_addr =to_in->sin_addr; /*设置目的IP地址*/ socket = get_socket(s); if (!socket) return -1; SIP_SockSendTo(socket->sock, skb, &remote_addr, to_in->sin_port);/*发送数据*/ return len; }
struct sk_buff * skb_realloc(size_t size, struct sk_buff *skb) { if (skb == NULL) { return skb_alloc(size); } list_del_init((struct list_head *) skb); skb->dev = NULL; skb->len = size; skb->mac.raw = skb_get_data_pointner(skb->data); skb->nh.raw = skb->h.raw = NULL; return skb; }
struct sk_buff * skb_copy(const struct sk_buff *skb) { struct sk_buff *copied; assert(skb != NULL); copied = skb_alloc(skb->len); if (copied == NULL) { return NULL; /* error: no memory */ } skb_copy_ref(copied, skb); skb_copy_data(copied->data, skb); return copied; }
static size_t tun_dev_write(struct file_desc *desc, void *buf, size_t size) { struct net_device *netdev; struct tun *tun; struct sk_buff *skb; int err; err = tun_netdev_by_desc(desc, &netdev, &tun); if (err) { return err; } skb = skb_alloc(size + ETH_HLEN); if (!skb) { return -ENOMEM; } ethhdr_build(skb->mac.ethh, netdev->dev_addr, NULL, ETH_P_IP); memcpy(skb->mac.raw + ETH_HLEN, buf, size); skb->dev = netdev; netif_rx(skb); return 0; }
#include "sip.h" inline int IP_IS_BROADCAST(struct net_device *dev, __be32 ip) { int retval = 1; if((ip == IP_ADDR_ANY_VALUE) /*IP地址为本地任意IP地址*/ ||(~ip == IP_ADDR_ANY_VALUE)) /*或者为按位取反IP地址*/ { DBGPRINT(DBG_LEVEL_NOTES, "IP is ANY ip\n"); retval = 1; /*是广播地址*/ goto EXITin_addr_isbroadcast; /*退出*/ }else if(ip == dev->ip_host.s_addr) { /*IP地址为本地地址*/ DBGPRINT(DBG_LEVEL_NOTES, "IP is local ip\n"); retval = 0; /*不是广播地址*/ goto EXITin_addr_isbroadcast; /*退出*/ }else if(((ip&dev->ip_netmask.s_addr) /*IP地址为本子网内地址*/ == (dev->ip_host.s_addr &dev->ip_netmask.s_addr)) && ((ip & ~dev->ip_netmask.s_addr) /*与广播地址同网段*/ ==(IP_ADDR_BROADCAST_VALUE & ~dev->ip_netmask.s_addr))){ DBGPRINT(DBG_LEVEL_NOTES, "IP is ANY ip\n"); retval =1; /*是广播地址*/ goto EXITin_addr_isbroadcast; /*退出*/ }else{ /*不是广播IP地址*/ retval = 0; } EXITin_addr_isbroadcast: return retval; } #define IP_FREE_REASS(ipr) \ do{ \ struct skbuff *skb=NULL,*skb_prev=NULL; \ for(skb_prev = skb = ipr->skb; \ skb != NULL; \ skb_prev = skb, \ skb = skb->next, \ skb_free(skb_prev)); \ free(ipr); \ }while(0); #define IPREASS_TIMEOUT 3 /*IP分组重组的超时时间为3秒*/ static struct sip_reass *ip_reass_list = NULL; /*IP重组的链表*/ struct skbuff *sip_reassemble(struct skbuff* skb) { struct sip_iphdr *fraghdr = skb->nh.iph; int retval = 0; __u16 offset, len; int found = 0; offset = (fraghdr->frag_off & 0x1FFF)<<3; /*取得IP分组偏移地址,32位长*/ len = fraghdr->tot_len - fraghdr->ihl<<2; /*IP分组的数据长度*/ struct sip_reass *ipr = NULL,*ipr_prev = NULL; for(ipr_prev = ipr= ip_reass_list; ipr != NULL; ) { if(time(NULL) -ipr->timer > IPREASS_TIMEOUT) /*此分组是超时?*/ { if(ipr_prev == NULL) /*第一个分片?*/ { ipr_prev = ipr; /*更新守护的指针为本分组*/ ip_reass_list->next = ipr = ipr->next; /*将超时的分片从重组链表上取下来*/ ipr = ipr->next; /*更新当前的分组指针*/ IP_FREE_REASS(ipr_prev); /*释放资源*/ ipr_prev->next =NULL; /*重置指针为空*/ continue; /*继续查找合适的分组*/ } else /*不是第一个分组*/ { ipr_prev->next = ipr->next; /*从分片链表上摘除当前链*/ IP_FREE_REASS(ipr); /*释放当前重组链*/ ipr = ipr_prev->next; /*更新当前链的指针*/ continue; /*继续查找*/ } } /*分片是否输入此条链*/ if(ipr->iphdr.daddr == fraghdr->daddr /*目的IP地址匹配*/ &&ipr->iphdr.saddr == fraghdr->saddr /*源IP地址匹配*/ &&ipr->iphdr.id == fraghdr->id) /*分片的ID匹配*/ { found = 1; /*属于这条链*/ break; } } if(!found) /*没有找到合适的分组链?*/ { ipr_prev = NULL; /*初始化为空*/ ipr = (struct sip_reass*)malloc(sizeof(struct sip_reass));/*申请一个分组数据结构*/ if(!ipr) /*申请失败*/ { retval = -1; /*返回值-1*/ goto freeskb; /*退出*/ } memset(ipr, 0, sizeof(struct sip_reass)); /*初始化分组结构*/ ipr->next = ip_reass_list; /*将当前分组结构挂接到分组链的头部*/ ip_reass_list = ipr; memcpy(&ipr->iphdr, skb->nh.raw, sizeof(IPHDR_LEN));/*拷贝IP的数据头部,便于之后的分片匹配*/ }else{ /*找到合适的分组链*/ if(((fraghdr->frag_off & 0x1FFF) == 0) /*当前数据位于分片第一个*/ &&((ipr->iphdr.frag_off & 0x1FFF) != 0)) /*分组链上的头部不是第一个分片*/ { memcpy(&ipr->iphdr, fraghdr, IPHDR_LEN); /*更新重组中的IP头部结构*/ } } /* 检查是否为最后一个分组*/ if( (fraghdr->frag_off & htons(0x2000)) == 0) { /*没有更多分组*/ #define IP_REASS_FLAG_LASTFRAG 0x01 ipr->flags |= IP_REASS_FLAG_LASTFRAG; /*设置最后分组标志*/ ipr->datagram_len = offset + len; /*设置IP数据报文的全长*/ } /*将当前的数据放到重组链上,并更新状态*/ struct skbuff *skb_prev=NULL, *skb_cur=NULL; int finish =0; void *pos = NULL; __u32 length = 0; #define FRAG_OFFSET(iph) (ntohs(iph->frag_off & 0x1FFF)<<3) #define FRAG_LENGTH(iph) (ntohs(iph->tot_len) - IPHDR_LEN) for(skb_prev =NULL, skb_cur=ipr->skb,length = 0,found = 0; skb_cur != NULL && !found; skb_prev=skb_cur,skb_cur = skb_cur->next) { if(skb_prev !=NULL) /*不是第一个分片*/ { if((offset < FRAG_OFFSET(skb_cur->nh.iph)) /*接收数据的偏移值位于前后两个之间*/ &&(offset > FRAG_OFFSET(skb_prev->nh.iph))) { skb->next = skb_cur; /*将接收到的数据放到此位置*/ skb_prev->next = skb; if(offset + len > FRAG_OFFSET(skb_cur->nh.iph)) /*当前数据与后面的分片数据覆盖?*/ { __u16 modify = FRAG_OFFSET(skb_cur->nh.iph) - offset + IPHDR_LEN;/*计算当前链的数据长度修改值*/ skb->nh.iph->tot_len = htons(modify); /*更新当前链长度*/ } if(FRAG_OFFSET(skb_prev->nh.iph) /*前面的分片长度覆盖当前数据?*/ + FRAG_LENGTH(skb_prev->nh.iph) > FRAG_OFFSET(skb_cur->nh.iph)) { __u16 modify = FRAG_OFFSET(skb_prev->nh.iph) - offset + IPHDR_LEN;/*计算前面数据长度的更改之*/ skb_prev->nh.iph->tot_len = htons(modify); /*修改前一片的数据长度*/ } found = 1; /*找到合适的分片插入位置*/ } } else /*为重组链上的头部*/ { if(offset < FRAG_OFFSET(skb_cur->nh.iph)){ /*当前链的偏移量小于第一个分片的偏移长度*/ skb->next = ipr->skb; /*挂接到重组链的头部*/ ipr->skb = skb; if(offset + len + IPHDR_LEN /*查看是否覆盖后面分片的数据*/ > FRAG_OFFSET(skb_cur->nh.iph)) { __u16 modify = FRAG_OFFSET(skb_cur->nh.iph) - offset + IPHDR_LEN;/*修改分片的数据长度*/ if(!offset) /*偏离量为0*/ modify -= IPHDR_LEN; /*包含头部,所以数据段长度需要减去IP头部长度*/ skb->nh.iph->tot_len = htons(modify); /*设置分片中修改后的长度*/ } } } length += skb_cur->nh.iph->tot_len - IPHDR_LEN; /*当前链表中的数据长度*/ } /*重新计算重组链上的总数据长度*/ for(skb_cur=ipr->skb,length = 0; skb_cur != NULL; skb_cur = skb_cur->next) { length += skb_cur->nh.iph->tot_len - IPHDR_LEN; } length += IPHDR_LEN; /*全部的IP分片都已经接收到后进行数据报文的重新组合 数据拷贝到一个新的数据结构中,原来的数据接收都释放掉 并从分组链中取出,将重组后的数据结构指针返回*/ if(length == ipr->datagram_len ) /*分组全部接收到?*/ { ipr->datagram_len += IPHDR_LEN; /*计算数据报文的实际长度长度*/ skb = skb_alloc(ipr->datagram_len + ETH_HLEN); /*申请空间*/ skb->phy.raw = skb_put(skb, ETH_HLEN); /*物理层*/ skb->nh.raw = skb_put(skb, IPHDR_LEN); /*网络层*/ memcpy(skb->nh.raw, & ipr->iphdr, sizeof(ipr->iphdr)); /*向新数据结构中拷贝IP头*/ skb->nh.iph->tot_len = htons(ipr->datagram_len); /*新结构中的tot_len*/ for(skb_prev=skb_cur=ipr->skb;skb_cur != NULL;) /*遍历重组数据链*/ { int size = skb_cur->end - skb_cur->tail; /*计算拷贝数据源的长度*/ pos = skb_put(skb, size); /*计算拷贝目的地址位置*/ memcpy(pos, /*将一个分片拷贝到新结构中*/ skb_cur->tail, skb_cur->nh.iph->tot_len - skb_cur->nh.iph->ihl<<2); } /*一下从重组链中摘除数据并释放,然后设置新结构中的几个IP头部参数*/ ipr_prev->next = ipr->next; /*将此数据报文从重组链中摘除*/ IP_FREE_REASS(ipr); /*释放此报文的重组连*/ skb->nh.iph->check = 0; /*设置校验值为0*/ skb->nh.iph->frag_off = 0; /*偏移值为0*/ skb->nh.iph->check = SIP_Chksum(skb->nh.raw, skb->nh.iph->tot_len);/*计算IP头部校验和*/ } normal: return skb; freeskb: skb_free(skb); return NULL; }