struct dns_packet * get_next_packet(struct dns_packet *decoded, pcap_parser_file * input) { /* Misc. variables */ char fqdn[MAX_NAME + 1]; unsigned int fqdn_length; /* pcap-related variables */ const uint8_t *packet; /* The actual packet */ struct pcap_pkthdr header; /* The header that pcap gives us */ const struct sniff_ethernet *ethernet; /* The ethernet header */ unsigned short ethertype; const struct sniff_ipv4 *ipv4; /* The IP header */ const struct sniff_ipv6 *ipv6; const struct sniff_udp *udp; /* The UDP header */ const struct sniff_dns *dns; u_int size_ip; u_int size_layer2; unsigned short ip_version; uint32_t family; const uint8_t *qsection; uint8_t labelsize; uint16_t add_type; uint16_t edns_size; uint16_t extended_rcode_and_version; uint16_t zpart; const uint8_t *sectionptr; const uint8_t *where_am_i; /* Cursor in packet */ bool end_of_name; unsigned int size_header; bool end_of_headers, fragmented; uint8_t next_v6_header; const struct sniff_eh *eh; /* The IPv6 extension header, if present */ const struct sniff_frag *frag; assert(decoded->qname != NULL); /* Grab next packet */ decoded->rank = input->packetnum; next_packet: packet = (uint8_t *) pcap_next(input->handle, &header); if (packet == NULL) { /* End of file */ return NULL; } input->packetnum++; decoded->length = header.len; decoded->captured_length = header.caplen; decoded->date = header.ts; if (input->firstpacket.tv_sec == 0 && input->firstpacket.tv_usec == 0) { input->firstpacket = header.ts; } input->lastpacket = header.ts; if (input->datalink == DLT_EN10MB) { size_layer2 = SIZE_ETHERNET; ethernet = (struct sniff_ethernet *) (packet); ethertype = ntohs(ethernet->ether_type); if (ethertype == VLAN_ETHERTYPE) { packet += 4; ethernet = (struct sniff_ethernet *) (packet); ethertype = ntohs(ethernet->ether_type); } if (ethertype == IPv6_ETHERTYPE) { ip_version = 6; } else if (ethertype == IPv4_ETHERTYPE) { ip_version = 4; } else { /* Ignore other Ethernet types */ goto next_packet; } } else if (input->datalink == DLT_LOOP) { size_layer2 = SIZE_LOOP; family = (ntohl(*((uint32_t *) packet))); if (family == PF_INET6) { ip_version = 6; } else if (family == PF_INET) { ip_version = 4; } else { /* Ignore other packet types */ goto next_packet; } } else { fatal("Unsupported data link type %s (%i)\n", pcap_datalink_val_to_description(input->datalink), input->datalink); } if (ip_version == 6) { ipv6 = (struct sniff_ipv6 *) (packet + size_layer2); size_ip = SIZE_IPv6; assert(IPV6_VERSION(ipv6) == 6); next_v6_header = ipv6->ip_nxt; size_header = 0; where_am_i = where_am_i + SIZE_IPv6; end_of_headers = false; fragmented = false; while (!end_of_headers) { /* Extension headers defined in RFC 2460, section 4 */ if (next_v6_header == 0 || next_v6_header == 43 || next_v6_header == 50 || next_v6_header == 51 || next_v6_header == 60) { eh = (struct sniff_eh *) (where_am_i); next_v6_header = eh->eh_next; size_header = eh->eh_length; } /* Fragment */ else if (next_v6_header == 44) { fragmented = 1; frag = (struct sniff_frag *) (where_am_i); next_v6_header = frag->frag_next; size_header = SIZE_FRAGMENT_HDR; } else { end_of_headers = true; } where_am_i = where_am_i + size_header; size_ip += size_header; if ((size_layer2 + size_ip) > decoded->captured_length) { if (verbose) { fprintf(stdout, "Warning: ignoring packet #%li because IPv6 headers too large\n", input->packetnum); } goto next_packet; } } if (fragmented && FRAG_OFFSET(frag) == 0) { goto next_packet; } } else if (ip_version == 4) { ipv4 = (struct sniff_ipv4 *) (packet + size_layer2); size_ip = IP_HL(ipv4) * 4; assert(IPV4_VERSION(ipv4) == 4); } else { /* Should never happen */ assert(0); } if ((ip_version == 6 && next_v6_header == UDP) || (ip_version == 4 && ipv4->ip_p == UDP)) { if (ip_version == 6) { assert(decoded->src != NULL); assert(decoded->dst != NULL); inet_ntop(AF_INET6, &ipv6->ip_src, decoded->src, INET6_ADDRSTRLEN); inet_ntop(AF_INET6, &ipv6->ip_dst, decoded->dst, INET6_ADDRSTRLEN); } else if (ip_version == 4) { assert(decoded->src != NULL); assert(decoded->dst != NULL); inet_ntop(AF_INET, &ipv4->ip_src, decoded->src, INET_ADDRSTRLEN); inet_ntop(AF_INET, &ipv4->ip_dst, decoded->dst, INET_ADDRSTRLEN); } else { goto next_packet; } udp = (struct sniff_udp *) (packet + size_layer2 + size_ip); decoded->src_port = (u_short) ntohs(udp->sport); decoded->dst_port = (u_short) ntohs(udp->dport); if (decoded->src_port == DNS_PORT || decoded->dst_port == DNS_PORT) { if (maxpackets > 0 && input->dnspacketnum >= maxpackets) { return NULL; } dns = (struct sniff_dns *) (packet + size_layer2 + size_ip + SIZE_UDP); decoded->query = DNS_QR(dns) == 0 ? true : false; decoded->query_id = dns->query_id; decoded->opcode = DNS_OPCODE(dns); decoded->returncode = DNS_RCODE(dns); decoded->aa = DNS_AA(dns) ? true : false; decoded->tc = DNS_TC(dns) ? true : false; decoded->rd = DNS_RD(dns) ? true : false; decoded->ra = DNS_RA(dns) ? true : false; decoded->ancount = ntohs(dns->ancount); decoded->nscount = ntohs(dns->nscount); decoded->arcount = ntohs(dns->arcount); qsection = (uint8_t *) (packet + size_layer2 + size_ip + SIZE_UDP + SIZE_DNS); fqdn[0] = '\0'; end_of_name = false; for (sectionptr = qsection; !end_of_name;) { CHECK_SECTIONPTR(1); labelsize = (uint8_t) * sectionptr; if (labelsize == 0) { sectionptr++; end_of_name = true; } else if (labelsize > 63) { /* It can be an error/attack or it can be compression (RFC 1035, * section 4.1.4). Today, we ignore packets with compression (we * just parse the question section, anyway). * * * * * * * * * TODO */ if (verbose) { fprintf(stdout, "Warning: ignoring packet #%li because labelsize > 63\n", input->packetnum); } goto next_packet; } else { CHECK_SECTIONPTR(labelsize); if (strlen(fqdn) == 0) { strncpy(fqdn, (char *) sectionptr + 1, labelsize); fqdn_length = labelsize; } else { fqdn_length = strlen(fqdn); if (fqdn_length + labelsize > MAX_NAME) { if (verbose) { fprintf(stdout, "Warning: ignoring packet #%li because malformed (FQDN length is already %i and label size is %i bytes)\n", input->packetnum, fqdn_length, labelsize); }; goto next_packet; } strncat(fqdn, ".", 1); strncat(fqdn, (char *) sectionptr + 1, labelsize); fqdn_length += (labelsize + 1); } if (fqdn_length > MAX_NAME) { if (verbose) { fprintf(stdout, "Warning: ignoring packet #%li because FQDN length > %i\n", input->packetnum, MAX_NAME); } goto next_packet; } fqdn[fqdn_length] = '\0'; sectionptr = sectionptr + labelsize + 1; CHECK_SECTIONPTR(0); } } CHECK_SECTIONPTR(2); strcpy(decoded->qname, fqdn); #ifdef PICKY_WITH_ALIGNMENT decoded->qtype = unaligned_uint16(sectionptr); #else decoded->qtype = ntohs(*((uint16_t *) sectionptr)); #endif sectionptr += 2; CHECK_SECTIONPTR(2); #ifdef PICKY_WITH_ALIGNMENT decoded->qclass = unaligned_uint16(sectionptr); #else decoded->qclass = ntohs(*((uint16_t *) sectionptr)); #endif sectionptr += 2; decoded->edns0 = false; if (decoded->query) { edns_size = 0; if (dns->ancount == 0 && dns->nscount == 0) { /* Probably by far the most common case in queries... */ if (dns->arcount != 0) { /* There is an additional section. * Probably the OPT * * * * * * * * * * * * * of EDNS */ CHECK_SECTIONPTR(1); labelsize = (uint8_t) * sectionptr; if (labelsize == 0) { /* Yes, EDNS0 */ sectionptr += 1; CHECK_SECTIONPTR(2); #ifdef PICKY_WITH_ALIGNMENT add_type = unaligned_uint16(sectionptr); #else add_type = ntohs(*((uint16_t *) sectionptr)); #endif sectionptr += 2; CHECK_SECTIONPTR(2); if (add_type == OPT) { #ifdef PICKY_WITH_ALIGNMENT edns_size = unaligned_uint16(sectionptr); #else edns_size = ntohs(*((uint16_t *) sectionptr)); #endif decoded->edns0 = true; /* RFC 2671 */ sectionptr += 2; CHECK_SECTIONPTR(2); #ifdef PICKY_WITH_ALIGNMENT extended_rcode_and_version = unaligned_uint16(sectionptr); #else extended_rcode_and_version = ntohs(*((uint16_t *) sectionptr)); #endif sectionptr += 2; CHECK_SECTIONPTR(2); #ifdef PICKY_WITH_ALIGNMENT zpart = unaligned_uint16(sectionptr); #else zpart = ntohs(*((uint16_t *) sectionptr)); #endif /* RFC 3225 */ decoded->do_dnssec = DNS_DO_DNSSEC(zpart) ? true : false; } sectionptr += 2; /* TODO: dissect the RDATA to find things like the option code (such as 3 for NSID) http://www.iana.org/assignments/dns-parameters */ } } } } if (decoded->edns0) { decoded->edns0_size = (unsigned int) edns_size; } input->dnspacketnum++; return decoded; } } goto next_packet; }
struct rte_mbuf * rte_ipv6_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl, struct rte_ip_frag_death_row *dr, struct rte_mbuf *mb, uint64_t tms, struct ipv6_hdr *ip_hdr, struct ipv6_extension_fragment *frag_hdr) { struct ip_frag_pkt *fp; struct ip_frag_key key; uint16_t ip_len, ip_ofs; rte_memcpy(&key.src_dst[0], ip_hdr->src_addr, 16); rte_memcpy(&key.src_dst[2], ip_hdr->dst_addr, 16); key.id = frag_hdr->id; key.key_len = IPV6_KEYLEN; ip_ofs = FRAG_OFFSET(frag_hdr->frag_data) * 8; /* * as per RFC2460, payload length contains all extension headers as well. * since we don't support anything but frag headers, this is what we remove * from the payload len. */ ip_len = rte_be_to_cpu_16(ip_hdr->payload_len) - sizeof(*frag_hdr); IP_FRAG_LOG(DEBUG, "%s:%d:\n" "mbuf: %p, tms: %" PRIu64 ", key: <" IPv6_KEY_BYTES_FMT ", %#x>, ofs: %u, len: %u, flags: %#x\n" "tbl: %p, max_cycles: %" PRIu64 ", entry_mask: %#x, " "max_entries: %u, use_entries: %u\n\n", __func__, __LINE__, mb, tms, IPv6_KEY_BYTES(key.src_dst), key.id, ip_ofs, ip_len, frag_hdr->more_frags, tbl, tbl->max_cycles, tbl->entry_mask, tbl->max_entries, tbl->use_entries); /* try to find/add entry into the fragment's table. */ fp = ip_frag_find(tbl, dr, &key, tms); if (fp == NULL) { IP_FRAG_MBUF2DR(dr, mb); return NULL; } IP_FRAG_LOG(DEBUG, "%s:%d:\n" "tbl: %p, max_entries: %u, use_entries: %u\n" "ipv6_frag_pkt: %p, key: <" IPv6_KEY_BYTES_FMT ", %#x>, start: %" PRIu64 ", total_size: %u, frag_size: %u, last_idx: %u\n\n", __func__, __LINE__, tbl, tbl->max_entries, tbl->use_entries, fp, IPv6_KEY_BYTES(fp->key.src_dst), fp->key.id, fp->start, fp->total_size, fp->frag_size, fp->last_idx); /* process the fragmented packet. */ mb = ip_frag_process(fp, dr, mb, ip_ofs, ip_len, MORE_FRAGS(frag_hdr->frag_data)); ip_frag_inuse(tbl, fp); IP_FRAG_LOG(DEBUG, "%s:%d:\n" "mbuf: %p\n" "tbl: %p, max_entries: %u, use_entries: %u\n" "ipv6_frag_pkt: %p, key: <" IPv6_KEY_BYTES_FMT ", %#x>, start: %" PRIu64 ", total_size: %u, frag_size: %u, last_idx: %u\n\n", __func__, __LINE__, mb, tbl, tbl->max_entries, tbl->use_entries, fp, IPv6_KEY_BYTES(fp->key.src_dst), fp->key.id, fp->start, fp->total_size, fp->frag_size, fp->last_idx); return mb; }
#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; }