#ifdef __linux__ #define _BSD_SOURCE #endif #include #include #include #include #ifndef USE_NETLIB #include #include #include #include #else #include #endif #include "pktlib.h" #include "pktbuf.h" pktbuf_t pktbuf_make_udp(pktbuf_t pktbuf, struct header_param *param) { struct udphdr *udphdr; int hdrsize, paysize; hdrsize = sizeof(*udphdr); paysize = pktbuf_get_size(pktbuf); udphdr = (struct udphdr *)pktbuf_add_header(pktbuf, hdrsize); memset(udphdr, 0, hdrsize); udphdr->uh_sport = htons(param->udp.src_port); udphdr->uh_dport = htons(param->udp.dst_port); udphdr->uh_ulen = htons(hdrsize + paysize); return pktbuf; } pktbuf_t pktbuf_make_ip(pktbuf_t pktbuf, struct header_param *param) { struct ip *iphdr; int hdrsize, paysize; hdrsize = sizeof(struct ip); paysize = pktbuf_get_size(pktbuf); iphdr = (struct ip *)pktbuf_add_header(pktbuf, hdrsize); memset(iphdr, 0, hdrsize); iphdr->ip_v = 4; iphdr->ip_hl = hdrsize>> 2; iphdr->ip_len = htons(hdrsize + paysize); iphdr->ip_id = htons(param->ip.id); iphdr->ip_ttl = param->ip.ttl; iphdr->ip_p = param->ip.protocol; iphdr->ip_src.s_addr = htonl(param->ip.src_ipaddr); iphdr->ip_dst.s_addr = htonl(param->ip.dst_ipaddr); return pktbuf; } struct vlantag { uint16_t type; uint16_t tag; } vlantag; pktbuf_t pktbuf_insert_vlantag(pktbuf_t pktbuf, int vid) { struct ether_header ether_header; struct ether_header *ehdr; struct vlantag *vtag; if (!vid) return pktbuf; memcpy(ðer_header, pktbuf_get_header(pktbuf), ETHER_HDR_LEN); ehdr = (struct ether_header *)pktbuf_add_header(pktbuf, sizeof(*vtag)); vtag = (struct vlantag *)&ehdr->ether_type; memcpy(ehdr, ðer_header, ETHER_HDR_LEN); vtag->type = htons(ETHERTYPE_VLAN); vtag->tag = htons(vid & 0x0FFF); return pktbuf; } pktbuf_t pktbuf_delete_vlantag(pktbuf_t pktbuf, int *vid) { struct ether_header ether_header; struct ether_header *ehdr; struct vlantag *vtag; ehdr = (struct ether_header *)pktbuf_get_header(pktbuf); if (ntohs(ehdr->ether_type) != ETHERTYPE_VLAN) { if (vid) *vid = 0; return pktbuf; } memcpy(ðer_header, ehdr, ETHER_HDR_LEN); vtag = (struct vlantag *)&ehdr->ether_type; if (vid) *vid = ntohs(vtag->tag) & 0x0FFF; ehdr = (struct ether_header *)pktbuf_delete_header(pktbuf, sizeof(*vtag)); ether_header.ether_type = ehdr->ether_type; memcpy(ehdr, ðer_header, ETHER_HDR_LEN); return pktbuf; } pktbuf_t pktbuf_make_ethernet(pktbuf_t pktbuf, struct header_param *param) { struct ether_header *ehdr; ehdr = (struct ether_header *)pktbuf_add_header(pktbuf, ETHER_HDR_LEN); memcpy(ehdr->ether_dhost, param->ethernet.dst_macaddr, ETHER_ADDR_LEN); memcpy(ehdr->ether_shost, param->ethernet.src_macaddr, ETHER_ADDR_LEN); ehdr->ether_type = htons(param->ethernet.type); pktbuf = pktbuf_insert_vlantag(pktbuf, param->ethernet.vid); return pktbuf; } int pktbuf_analyze_udp(pktbuf_t pktbuf, struct header_param *param) { struct udphdr *udphdr; int r = 0; if (pktbuf_get_size(pktbuf) < sizeof(*udphdr)) return r; udphdr = (struct udphdr *)pktbuf_get_header(pktbuf); if (pktbuf_get_size(pktbuf) < ntohs(udphdr->uh_ulen)) return r; param->udp.header_size = sizeof(*udphdr); param->udp.src_port = ntohs(udphdr->uh_sport); param->udp.dst_port = ntohs(udphdr->uh_dport); r++; return r; } int pktbuf_analyze_ip(pktbuf_t pktbuf, struct header_param *param) { struct ip *iphdr; int r = 0, hdrsize; if (pktbuf_get_size(pktbuf) < sizeof(struct ip)) return r; iphdr = (struct ip *)pktbuf_get_header(pktbuf); if (iphdr->ip_v != 4) return r; hdrsize = iphdr->ip_hl << 2; if (hdrsize < sizeof(struct ip)) return r; if (pktbuf_get_size(pktbuf) < hdrsize) return r; if (pktbuf_get_size(pktbuf) < ntohs(iphdr->ip_len)) return r; param->ip.header_size = hdrsize; param->ip.id = ntohs(iphdr->ip_id); param->ip.ttl = iphdr->ip_ttl; param->ip.protocol = iphdr->ip_p; param->ip.src_ipaddr = ntohl(iphdr->ip_src.s_addr); param->ip.dst_ipaddr = ntohl(iphdr->ip_dst.s_addr); r++; pktbuf_delete_header(pktbuf, hdrsize); switch (param->ip.protocol) { case IPPROTO_UDP: r += pktbuf_analyze_udp(pktbuf, param); break; default: break; } pktbuf_add_header(pktbuf, hdrsize); return r; } int pktbuf_analyze_ethernet(pktbuf_t pktbuf, struct header_param *param) { struct ether_header *ehdr; int r = 0; if (pktbuf_get_size(pktbuf) < ETHER_HDR_LEN) return r; ehdr = (struct ether_header *)pktbuf_get_header(pktbuf); param->ethernet.header_size = ETHER_HDR_LEN; memcpy(param->ethernet.dst_macaddr, ehdr->ether_dhost, ETHER_ADDR_LEN); memcpy(param->ethernet.src_macaddr, ehdr->ether_shost, ETHER_ADDR_LEN); param->ethernet.type = ntohs(ehdr->ether_type); r++; pktbuf_delete_vlantag(pktbuf, ¶m->ethernet.vid); pktbuf_delete_header(pktbuf, ETHER_HDR_LEN); switch (param->ethernet.type) { case ETHERTYPE_IP: r += pktbuf_analyze_ip(pktbuf, param); break; default: break; } pktbuf_add_header(pktbuf, ETHER_HDR_LEN); pktbuf_insert_vlantag(pktbuf, param->ethernet.vid); return r; }

AltStyle によって変換されたページ (->オリジナル) /