18.3 Socket套接字

18.3  Socket套接字

Socket套接字由远景研究规划局(Advanced Research Projects Agency, ARPA)资助加里福尼亚大学伯克利分校的一个研究组研发。其目的是将TCP/IP协议相关软件移植到UNIX类系统中。设计者开发了一个接口,以便应用程序能简单地调用该接口通信。这个接口不断完善,最终形成了Socket套接字。Linux系统采用了Socket套接字,因此,Socket接口就被广泛使用,到现在已经成为事实上的标准。与套接字相关的函数被包含在头文件sys/socket.h中。

检查以下代码是否有语法错误或者逻辑错误? #include <netinet/if_ether.h> #include <linux/if_packet.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <net/if.h> #include <string.h> #include <arpa/inet.h> #include <net/if_arp.h> #include <stdio.h> #include <netinet/in.h> #include <unistd.h> #include <time.h> #include <errno.h> #define U8 unsigned char #define U16 unsigned short #define U32 unsigned int #define S32 signed int #define STR_MAC_LEN (18) #define STR_IP_LEN (16) #define MAC_ADDR_SIZE (6) #define IP_ADDR_SIZE (4) #define OK (0) #define ERROR (-1) #define DEV_NAME "ens33" #define RAW_DATA_LEN_MAX 1514 typedef struct _ARP_PACKED { /* Ethernet head */ U8 ether_dhost[ETH_ALEN]; /* destination eth addr */ U8 ether_shost[ETH_ALEN]; /* source ether addr */ U16 ether_type; /* packet type ID field */ /* ARP Protocol */ U16 hadrware_type; U16 proto_type; U8 hardware_size; U8 proto_size; U16 op_code; U8 mac_sender[ETH_ALEN]; /* sender mac addr */ U8 ip_sender[4]; /* sender ip addr */ U8 mac_target[ETH_ALEN]; /* target mac addr */ U8 ip_target[4]; /* target ip addr */ U8 pad[18]; }__attribute__ ((__packed__)) ARP_PACKED; S32 mac_to_hex (const char *buffer, U8 *ether) { S32 i, c; if (NULL == buffer || NULL == ether) { return ERROR; } for (i = 0; i < 6; i++) { if (*buffer == &#39;-&#39;) { buffer++; } if (*buffer >= &#39;0&#39; && *buffer <= &#39;9&#39;) { c = (U8)(*buffer++ - &#39;0&#39;); } else if (*buffer >= &#39;a&#39; && *buffer <= &#39;f&#39;) { c = (U8)(*buffer++ - &#39;a&#39;) + 10; } else if (*buffer >= &#39;A&#39; && *buffer <= &#39;F&#39;) { c = (U8)(*buffer++ - &#39;A&#39;) + 10; } else { return ERROR; } c <<= 4; if (*buffer >= &#39;0&#39; && *buffer <= &#39;9&#39;) { c |= (U8) (*buffer++ - &#39;0&#39;); } else if (*buffer >= &#39;a&#39; && *buffer <= &#39;f&#39;) { c |= (U8) (*buffer++ - &#39;a&#39;) + 10; } else if (*buffer >= &#39;A&#39; && *buffer <= &#39;F&#39;) { c |= (U8) (*buffer++ - &#39;A&#39;) + 10; } else { return ERROR; } ether[i] = (U8) c; } return OK; } S32 hex_to_mac(char *buf, S32 len, U8 *mac) { if ((NULL == buf) || (len < 18) || (NULL == mac)) { return ERROR; } snprintf(buf, len, "%02X-%02X-%02X-%02X-%02X-%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); return OK; } /* 接收数据 0没有读取数据 <0出错 >0为接收数据长度*/ S32 rev_raw_data(int raw_sock, U8* buf, U32 len) { int ret; int rev_len = 0; if (NULL == buf) { printf("invalid argument : rawdata buf\n"); return ERROR; } memset(buf, 0, len); while (1) { ret = recv( (raw_sock + rev_len), buf, (len - rev_len), 0); if (ret < 0) { /* 套接字是非阻塞或超时过期 */ if (EAGAIN == errno || EAGAIN == errno) { break; } else { printf("recv raw sock error: %s \n", strerror(errno)); return ERROR; } } /* 对端sock关闭或者读取字数为0 */ else if (0 == ret) { printf("sock %d disconnect\n", raw_sock); break; } rev_len += ret; /* 一包不满,后面没数据了 */ if (ret < RAW_DATA_LEN_MAX) { break; } /* 缓冲区满了 */ if (rev_len >= len) { printf("raw_data buffer is full\n"); break; } } return rev_len; } /* 监听到ARP回应包处理,并添加条目 */ void arp_respond_handle(int sock) { U8 raw_data[RAW_DATA_LEN_MAX]; U8 data_len = 0; char mac_str[STR_MAC_LEN] = {0}; char ip_str[STR_IP_LEN] = {0}; data_len = rev_raw_data (sock, raw_data, RAW_DATA_LEN_MAX); if (data_len < 0) { printf("rev arp raw data %d fail!", sock); return; } ARP_PACKED *arp = (ARP_PACKED *)raw_data; /* 判断是不是合法的arp回复包 */ if ((ntohs(arp->ether_type) != ETH_P_ARP) || (ntohs(arp->op_code) != ARPOP_REPLY)) { return; } hex_to_mac(mac_str, STR_MAC_LEN, arp->mac_sender); inet_ntop(AF_INET, arp->ip_sender, ip_str, STR_IP_LEN); printf("ip: %s --> mac: %s", ip_str, mac_str); } void send_arp(int sock, const char *mac_str, U32 ip_src_nl, U32 ip_des_nl, const char *iface) { struct sockaddr_ll sa; ARP_PACKED arp_pkg; char broadcast_mac_str[STR_MAC_LEN] = "FF-FF-FF-FF-FF-FF"; memset(&sa, 0, sizeof(sa)); sa.sll_family = AF_PACKET; sa.sll_protocol = htons(ETH_P_ARP); sa.sll_ifindex = if_nametoindex(iface); /* ARP请求广播 */ memset(sa.sll_addr, 0xFF, ETH_ALEN); /* arp包内容填充 */ memset(&arp_pkg, 0, sizeof(arp_pkg)); if (-1 == mac_to_hex(broadcast_mac_str, arp_pkg.ether_dhost)) { printf("ther_dhost hex to mac error\n"); } if (-1 == mac_to_hex(mac_str, arp_pkg.ether_shost)) { printf("ther_dhost hex to mac error\n"); } arp_pkg.ether_type = htons(ETH_P_ARP); arp_pkg.hadrware_type = htons(ARPHRD_ETHER); arp_pkg.proto_type = htons(ETH_P_IP); arp_pkg.hardware_size = MAC_ADDR_SIZE; arp_pkg.proto_size = IP_ADDR_SIZE; arp_pkg.op_code = htons(ARPOP_REQUEST); if (-1 == mac_to_hex(mac_str, arp_pkg.mac_sender)) { printf("mac_sender hex to mac error\n"); } memcpy(arp_pkg.ip_sender, &ip_src_nl, IP_ADDR_SIZE); memset(arp_pkg.mac_target, 0, MAC_ADDR_SIZE); memcpy(arp_pkg.ip_target, &ip_des_nl, IP_ADDR_SIZE); sendto(sock, &arp_pkg, sizeof(arp_pkg), 0, (struct sockaddr*)&sa, sizeof(sa)); } S32 get_sock_arp() { int fd = -1; struct sockaddr_ll sa; fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP)); if (fd < 0) { printf("Error on socket ETH_P_ARP.\n"); goto exit_error; } /* bind 套接字到网络接口 */ memset(&sa, 0, sizeof(sa)); sa.sll_family = AF_PACKET; sa.sll_protocol = htons(ETH_P_ARP); sa.sll_ifindex = if_nametoindex(DEV_NAME); int ret = bind( fd, (struct sockaddr*)& sa, sizeof(sa)); if (ret < 0) { printf("bind socket fail! %s \n",strerror(errno)); goto close_socket; } return fd; close_socket: close(fd); exit_error: return ERROR; } int main() { int loop_cnt = 5; S32 sock = get_sock_arp(); if (sock < 0) { printf("error fd \n"); return -1; } struct in_addr start_addr; struct in_addr end_addr; struct in_addr local_addr; inet_pton(AF_INET, "192.168.18.1", &start_addr); inet_pton(AF_INET, "192.168.18.10", &end_addr); inet_pton(AF_INET, "192.168.18.3", &local_addr); /* 主机字节序的IP */ U32 current_ip_h = ntohl(start_addr.s_addr); U32 end_ip_h = ntohl(end_addr.s_addr); S32 count = end_ip_h - current_ip_h; printf("success: need scan %d times\n", count); for (int i=0; i<count; i++) { U32 current_ip_n = htonl(current_ip_h + i); send_arp(sock, "00-0c-29-af-27-24", local_addr.s_addr, current_ip_n, DEV_NAME); usleep(5000); } while (loop_cnt>0) { loop_cnt--; arp_respond_handle(sock); sleep(1); } close(sock); return 0; }
08-28
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值