#include #include #include #include #include #include #include #include #include static volatile uint64_t g_rand_seed = 0x013579ABCDEF; #define SENDPACKET_CKSUM_CARRY(x) (x = (x >> 16) + (x & 0xffff), (~(x + (x >> 16)) & 0xffff)) unsigned int deliver_rand(void) { return g_rand_seed ^ (unsigned int)random(); } unsigned int deliver_rand_range(unsigned int start, unsigned int end) { unsigned int rand_num = deliver_rand(); if(start > end) { return end + rand_num % (start - end + 1); } return start + rand_num % (end - start + 1); } /* ascii字符转16进制 */ char MESA_ascii_to_hex(char ascii) { char c = 0; switch(ascii) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': c = ascii - 0x30; break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': c = 10 + ascii - 0x61; break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': c = 10 + ascii - 0x41; break; } return c; } /* 2012-04-10 LiJia add, 获取网卡MAC地址 参数: device: 网卡名称 mac: 存储MAC地址的数组,结果为网络序, 如网卡MAC地址为11:22:33:44:55:66,则mac[0]为0x11,mac[5]为0x66. 返回值: 0: 正常 -1:错误 */ int deliver_get_dev_mac(const char *device, unsigned char mac[6]) { struct ifreq ifr; int fd; fd = socket(AF_INET, SOCK_DGRAM, 0); if(fd < 0) { return -1; } memset(ifr.ifr_ifrn.ifrn_name, 0, sizeof(ifr.ifr_ifrn.ifrn_name)); strncpy(ifr.ifr_ifrn.ifrn_name, device, sizeof(ifr.ifr_ifrn.ifrn_name)); if(ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) { printf("Cann't get hwaddr of %s:%s\n", device, strerror(errno)); goto err_exit; } if(ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) { printf("'%s' is not ethernet interface!\n", device); goto err_exit; } memcpy(mac, ifr.ifr_ifru.ifru_addr.sa_data, 6); close(fd); return 0; err_exit: close(fd); return -1; } /* 2012-04-11 LiJia add,将MAC字符串形式转换为16进制MAC地址. 参数: str: MAC地址字符串 delim: 字符串分隔符,常见为':', '-'等,如: xx:xx:xx:xx:xx:xx 如果字符串无分隔符,delim设为-1. mac: 存储MAC地址的数组(指针),结果为网络序, 如网卡MAC地址为11:22:33:44:55:66,则mac[0]为0x11,mac[5]为0x66. 返回值: 0: 正常 -1:错误 */ int deliver_mac_pton(const char *str, int delim, char *mac) { #define MAC_STR_LEN_DELIM (17) /* length of "11:22:33:44:55:66" */ #define MAC_STR_LEN_NODELIM (12) /* length of "112233445566" */ const char *s = str; int i; /* 检查输入合法性 */ if(delim != -1) { if(strlen(str) != MAC_STR_LEN_DELIM) { printf("MAC string length error!\n"); return -1; } } else { if(strlen(str) != MAC_STR_LEN_NODELIM) { printf("MAC string length error!\n"); return -1; } } /* 检查输入合法性,同时转换成16进制值 */ for(i = 0; i < 6; i++) { mac[i] = 0; /* 先清零,赋值语句都是或操作 */ if(isxdigit(*s)==0) { printf("MAC string type error!\n"); return -1; } mac[i] |= MESA_ascii_to_hex(*s) << 4; s++; if(isxdigit(*s)==0) { printf("MAC string type error!\n"); return -1; } mac[i] |= MESA_ascii_to_hex(*s); s++; if((delim != -1) && i<5 && (*s++ != (char)delim)) { printf("MAC string type error!\n"); return -1; } } return 0; } int sendpacket_in_cksum(unsigned short *addr, int len) { int sum; int nleft; unsigned short ans; unsigned short *w; sum = 0; ans = 0; nleft = len; w = addr; while (nleft > 1) { sum += *w++; nleft -= 2; } if (nleft == 1) { *(char *)(&ans) = *(char *)w; sum += ans; } return (sum); } int deliver_do_checksum(unsigned char *buf, int protocol, int len) { struct mesa_ip4_hdr *iph_p; struct mesa_ip6_hdr *ip6h_p; int ip_hl; int sum; int is_ipv6 = 0; sum = 0; iph_p = (struct mesa_ip4_hdr *)buf; if(4 == iph_p->ip_v) /* IP版本号字段,IPv4和IPv6格式是相同的 */ { ip_hl = iph_p->ip_hl << 2; ip6h_p = NULL; } else if(6 == iph_p->ip_v) { ip6h_p = (struct mesa_ip6_hdr *)buf; iph_p = NULL; ip_hl = sizeof(struct mesa_ip6_hdr); is_ipv6 = 1; } else { return (-1); } switch (protocol) { case IPPROTO_TCP: { struct mesa_tcp_hdr *tcph_p = (struct mesa_tcp_hdr *)(buf + ip_hl); tcph_p->th_sum = 0; if(is_ipv6) { sum = sendpacket_in_cksum((unsigned short*)&ip6h_p->ip6_src, 32); } else { sum = sendpacket_in_cksum((unsigned short *)&iph_p->ip_src, 8); } sum += ntohs(IPPROTO_TCP + len); sum += sendpacket_in_cksum((unsigned short *)tcph_p, len); tcph_p->th_sum = SENDPACKET_CKSUM_CARRY(sum); break; } case IPPROTO_UDP: { struct mesa_udp_hdr *udph_p =(struct mesa_udp_hdr *)(buf + ip_hl); udph_p->uh_sum = 0; if(is_ipv6) { sum = sendpacket_in_cksum((unsigned short*)&ip6h_p->ip6_src, 32); } else { sum = sendpacket_in_cksum((unsigned short*)&iph_p->ip_src, 8); } sum += ntohs(IPPROTO_UDP + len); sum += sendpacket_in_cksum((unsigned short*)udph_p, len); udph_p->uh_sum = SENDPACKET_CKSUM_CARRY(sum); break; } case IPPROTO_IP: { iph_p->ip_sum = 0; sum = sendpacket_in_cksum((unsigned short*)iph_p, len); iph_p->ip_sum = SENDPACKET_CKSUM_CARRY(sum); break; } default: { return (-1); } } return (1); } /* if playload2 is not NULL, it means that there is ip spice, it must be copied first, then playload is copied otherwise, only payload is copied and it includes ip header */ int deliver_build_ethhdr(unsigned char *dst, unsigned char *src, unsigned short type,unsigned char *buf) { struct mesa_ethernet_hdr eth_hdr; if (!buf) { return (-1); } memcpy(eth_hdr.ether_dhost, dst, ETHER_ADDR_LEN); /* destination address */ memcpy(eth_hdr.ether_shost, src, ETHER_ADDR_LEN); /* source address */ eth_hdr.ether_type = htons(type); /* packet type */ memcpy(buf, ð_hdr, sizeof(eth_hdr)); return (0); } /* if playload2 is not NULL, it means that there is ip spice, it must be copied first, then playload is copied otherwise, only payload is copied and it includes ip header */ int deliver_build_ethernet(unsigned char *dst, unsigned char *src, unsigned short type, const unsigned char *payload, int payload_s, unsigned char *buf) { struct mesa_ethernet_hdr eth_hdr; if (!buf) { return (-1); } memcpy(eth_hdr.ether_dhost, dst, ETHER_ADDR_LEN); /* destination address */ memcpy(eth_hdr.ether_shost, src, ETHER_ADDR_LEN); /* source address */ eth_hdr.ether_type = htons(type); /* packet type */ if (payload && payload_s) { memcpy(buf + SENDPACKET_ETH_H, payload, payload_s); } memcpy(buf, ð_hdr, sizeof(eth_hdr)); return (0); } int deliver_build_ipv6(unsigned char traffic_class, unsigned int flow_lable, unsigned short len, unsigned char next_header, unsigned char hop, const struct in6_addr *src, const struct in6_addr *dst, const char *payload, int payload_s, unsigned char *buf) { struct mesa_ip6_hdr *ip6_h; if(!buf){ return -1; } ip6_h = (struct mesa_ip6_hdr *)buf; memset(ip6_h, 0, sizeof(struct mesa_ip6_hdr)); ip6_h->ip6_flags[0] = 0x60 | ((traffic_class & 0xF0) >> 4); ip6_h->ip6_flags[1] = ((traffic_class & 0x0F) << 4) | ((flow_lable & 0xF0000) >> 16); ip6_h->ip6_flags[2] = flow_lable & 0x0FF00 >> 8; ip6_h->ip6_flags[3] = flow_lable & 0x000FF; ip6_h->ip6_payload_len = htons(len); ip6_h->ip6_nxt_hdr = next_header; ip6_h->ip6_hop = hop; memcpy(&ip6_h->ip6_src, src, sizeof(struct in6_addr)); memcpy(&ip6_h->ip6_dst, dst, sizeof(struct in6_addr)); if(payload && payload_s) { memcpy(buf + sizeof(struct mesa_ip6_hdr), payload, payload_s); } return 0; } int deliver_build_ipv4(unsigned short carry_layer_len, unsigned char tos, unsigned short id, unsigned short frag, unsigned char ttl, unsigned char prot, unsigned int src, unsigned int dst, const char *payload,int payload_s, unsigned char *buf) { struct mesa_ip4_hdr *ip_hdr; if (!buf) { return (-1); } ip_hdr = (struct mesa_ip4_hdr *)buf; ip_hdr->ip_v = 4; /* version 4 */ ip_hdr->ip_hl = 5; /* 20 byte header */ ip_hdr->ip_tos = tos; /* IP tos */ ip_hdr->ip_len = htons(SENDPACKET_IP_H + carry_layer_len); /* total length */ ip_hdr->ip_id = htons(id); /* IP ID */ ip_hdr->ip_off = htons(frag); /* fragmentation flags */ ip_hdr->ip_ttl = ttl; /* time to live */ ip_hdr->ip_p = prot; /* transport protocol */ ip_hdr->ip_sum = 0; /* do this later */ ip_hdr->ip_src.s_addr = src; /* 为什么地址用网络序? 历史遗留原因, 改动太多,只能这么继续了 */ ip_hdr->ip_dst.s_addr = dst; /* 为什么地址用网络序? 历史遗留原因, 改动太多,只能这么继续了 */ if (payload && payload_s) { memcpy(buf + SENDPACKET_IP_H, payload, payload_s); } return (0); } int deliver_build_tcp(unsigned short sp, unsigned short dp, unsigned int seq, unsigned int ack, unsigned char th_flags, unsigned short win, unsigned short urg, const char *payload, int payload_s, unsigned char *buf) { struct mesa_tcp_hdr *tcp_hdr; if (!buf) { return (-1); } tcp_hdr = (struct mesa_tcp_hdr *)buf; tcp_hdr->th_sport = htons(sp); /* source port */ tcp_hdr->th_dport = htons(dp); /* destination port */ tcp_hdr->th_seq = htonl(seq); /* sequence number */ tcp_hdr->th_ack = htonl(ack); /* acknowledgement number */ tcp_hdr->th_flags = th_flags; /* control flags */ tcp_hdr->th_x2 = 0; /* UNUSED */ tcp_hdr->th_off = 5; /* 20 byte header */ tcp_hdr->th_win = htons(win); /* window size */ tcp_hdr->th_sum = 0; /* checksum done in userland */ tcp_hdr->th_urp = urg; /* urgent pointer */ if (payload && payload_s) { // memcpy(buf + SENDPACKET_TCP_H, payload, payload_s); memcpy(buf + sizeof(struct mesa_tcp_hdr), payload, payload_s); } return (0); }