博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux下PF_PACKET的使用,RARP的server和client程序
阅读量:7065 次
发布时间:2019-06-28

本文共 10279 字,大约阅读时间需要 34 分钟。

1.介绍
在linux中提供了PF_PACKET接口可以操作链路层的数据。
2.使用方法
定义一个pf_packet = socket(PF_SOCKET, SOCK_RAW, htons(ETH_P_RARP));
就可以利用函数sendto和recefrom来读取和发送链路层的数据包了(当然,发送ARP包,上面第三个参数要变为htons(ETH_P_ARP),或者IP的包为ETH_P_IP,可查看文件/usr/include/linux/if_ether.h文件看到所有支持的协议)。
3.在使用SOCK_RAW, SOCK_DGRAM和SOCK_PACKET的区别
在socket的第一个参数使用PF_PACKET的时候,上述三种socket的类型都可以使用。但是有区别。
(1)使用SOCK_RAW发送的数据必须包含链路层的协议头,接受得到的数据包,包含链路层协议头。而使用SOCK_DGRAM则都不含链路层的协议头。
(2)SOCK_PACKET也是可以使用的,但是已经废弃,以后不保证还能支持,不推荐使用。
(3)在使用SOCK_RAW或SOCK_DGRAM和SOCK_PACKET时,在sendto和recvfrom中使用的地址类型不同,前两者使用sockaddr_ll类型的地址,而后者使用sockaddr类型的地址。
(4)如socket的第一个参数使用PF_INET,第二个参数使用SOCK_RAW,则可以得到原始的IP包。
4.下面的例子是一个简单的rarp协议的server程序和client程序
server程序一开始获得除lo接口以外接口的mac地址,等待rarp request请求的到来,如果请求的是自己的mac地址,则向客户端发送rarp reply,回送自己的ip地址。应我使用的地方,一台机器的ip地址每次dhcp以后都会变。所以该程序还是有一些用处。
注意:本程序只为演示packet socket的工作原理,所以没有进行任何的错误处理,并假设工作的机器上只有ethernet接口。但是本程序有个缺点,就是两个程序工作在同一台机器上的时候,server无法接收到client的rarp request。请知道的朋友赐教,谢谢!
//File Name : rarp_server.cpp
extern "C"{ #include #include #include #include #include #include #include #include #include #include #include #include#include #include #include #include #include #include#include }#include/* args: yiaddr - what IP to ping* ip - our ip* mac - our arp address* interface - interface to use* retn: 1 addr free* 0 addr used* -1 error *//* FIXME: match response against chaddr */struct arpMsg {struct ethhdr ethhdr; /* Ethernet header */u_short htype; /* hardware type (must be ARPHRD_ETHER) */u_short ptype; /* protocol type (must be ETH_P_IP) */u_char hlen; /* hardware address length (must be 6) */u_char plen; /* protocol address length (must be 4) */u_short operation; /* ARP opcode */u_char sHaddr[6]; /* sender's hardware address */u_char sInaddr[4]; /* sender's IP address */u_char tHaddr[6]; /* target's hardware address */u_char tInaddr[4]; /* target's IP address */u_char pad[18]; /* pad for min. Ethernet payload (60 bytes) */};/* miscellaneous defines */#define MAC_BCAST_ADDR (uint8_t *) "\xff\xff\xff\xff\xff\xff"#define OPT_CODE 0#define OPT_LEN 1#define OPT_DATA 2struct interface_info{char ifname[64];unsigned char ip[4];unsigned char mac[6]; };struct interface_info if_info[10];int eth_num = 0;void print_mac(unsigned char * mac_addr){for (int i =0; i < 6; ++i){printf("%02X", mac_addr[i]);if (i != 5) printf(":");} printf("\n");}void print_ip(unsigned char * ip_addr){for (int i =0; i < 4; ++i){printf("%d", ip_addr[i]);if (i != 3) printf(".");} printf("\n");}int get_iface_index(int fd, const char* interface_name){struct ifreq ifr;memset(&ifr, 0, sizeof(ifr));strcpy (ifr.ifr_name, interface_name);if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1){return (-1);}return ifr.ifr_ifindex;}int get_interfaces(){int sock;int len = 64;int last_len = 0;char *pBuff = NULL;int interface_num = 0;struct ifconf interface_conf;struct ifreq ifreq1;struct sockaddr_in *psockaddr_in = NULL;if ( (sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0){perror("Could not create socket for geting interface info");exit(1);}while(1){pBuff = (char*)malloc(len);interface_conf.ifc_len = len;interface_conf.ifc_buf = pBuff;if (ioctl(sock, SIOCGIFCONF, &interface_conf) < 0){perror("ioctl error");}else{if (interface_conf.ifc_len == last_len){break;}else{last_len = interface_conf.ifc_len; } }len += 2*sizeof(struct ifreq);free(pBuff); }interface_num = last_len / sizeof(struct ifreq);for (int i =0; i < interface_num; ++i){strcpy(ifreq1.ifr_name, interface_conf.ifc_ifcu.ifcu_req[i].ifr_name);if (strcmp(ifreq1.ifr_name, "lo") == 0){continue;} if (ioctl(sock, SIOCGIFHWADDR, &ifreq1) < 0){continue; } memcpy(if_info[eth_num].mac, ifreq1.ifr_hwaddr.sa_data, 6); strcpy(if_info[eth_num].ifname, ifreq1.ifr_name);psockaddr_in = (struct sockaddr_in*)&interface_conf.ifc_req[i].ifr_addr;memcpy(if_info[eth_num].ip, &(psockaddr_in->sin_addr.s_addr), 4);printf("Interface name: %s", if_info[eth_num].ifname);printf(" ip address: ");print_ip(if_info[eth_num].ip);printf(" mac address:");print_mac(if_info[eth_num].mac); eth_num++;} free(pBuff); close(sock); }int equal_mac(unsigned char* mac1, unsigned char* mac2){for (int i =0; i < 6; ++i){if (mac1[i] != mac2[i]) return 0;}return 1; } int main(){int timeout = 2;int optval = 1;int s; /* socket */int rv = 1; /* return value */struct sockaddr_ll addr; /* for interface name */struct arpMsg arp;struct arpMsg *parp;fd_set fdset;struct timeval tm;time_t prevTime;u_int32_t ip;u_int32_t yiaddr;struct in_addr my_ip;struct in_addr dst_ip;char buff[2000];int nLen;char szBuffer[4096];if ((s = socket (PF_PACKET, SOCK_RAW, htons(ETH_P_RARP))) == -1) {printf("Could not open raw socket\n");return -1;}if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) == -1) {printf("Could not setsocketopt on raw socket\n");close(s);return -1;} memset(&addr, 0, sizeof(addr));addr.sll_family = AF_PACKET;addr.sll_ifindex = get_iface_index(s, "eth0");addr.sll_protocol = htons(ETH_P_ARP);get_interfaces();memset(szBuffer, 0, sizeof(szBuffer)); while ((nLen = recvfrom(s, szBuffer, sizeof(szBuffer), MSG_TRUNC, NULL, NULL)) > 0){parp = (struct arpMsg*)szBuffer;printf("The request is from ");print_ip(parp->sInaddr);for (int i = 0; i < eth_num; ++i){if (equal_mac(if_info[i].mac, parp->tHaddr)){/* send arp request */memset(&arp, 0, sizeof(arp));memcpy(arp.ethhdr.h_dest, parp->sHaddr, 6); // MAC DAmemcpy(arp.ethhdr.h_source, parp->tHaddr, 6); // MAC SAarp.ethhdr.h_proto = htons(ETH_P_RARP); // protocol type (Ethernet)arp.htype = htons(ARPHRD_ETHER); // hardware typearp.ptype = htons(ETH_P_IP); // protocol type (ARP message)arp.hlen = 6; // hardware address lengtharp.plen = 4; // protocol address lengtharp.operation = htons(4); // RARP reply codememcpy(arp.sInaddr, if_info[i].ip, 4); // source IP address memcpy(arp.sHaddr, parp->tHaddr, 6); // source hardware addressmemcpy(arp.tInaddr, parp->sInaddr, 4); // target IP addressmemcpy(arp.tHaddr, parp->sHaddr, 6);if (sendto(s, &arp, sizeof(arp), 0, (struct sockaddr*)&addr, sizeof(addr)) < 0){perror("Unabele to send arp request");return 0; }elseprintf("send reply\n"); } } }close(s);return 0;}////File Name : get_ip_by_mac.cpp#include #include #include #include #include #include #include #include #include #include #include #include#include #include #include #include #include #include#includestruct arpMsg {struct ethhdr ethhdr; /* Ethernet header */u_short htype; /* hardware type (must be ARPHRD_ETHER) */u_short ptype; /* protocol type (must be ETH_P_IP) */u_char hlen; /* hardware address length (must be 6) */u_char plen; /* protocol address length (must be 4) */u_short operation; /* ARP opcode */u_char sHaddr[6]; /* sender's hardware address */u_char sInaddr[4]; /* sender's IP address */u_char tHaddr[6]; /* target's hardware address */u_char tInaddr[4]; /* target's IP address */u_char pad[18]; /* pad for min. Ethernet payload (60 bytes) */};/* miscellaneous defines */#define MAC_BCAST_ADDR (uint8_t *) "\xff\xff\xff\xff\xff\xff"#define OPT_CODE 0#define OPT_LEN 1#define OPT_DATA 2void print_mac(unsigned char * mac_addr){for (int i =0; i < 6; ++i){printf("%02X", mac_addr[i]);if (i != 5) printf(":");} printf("\n");}void print_ip(unsigned char * ip_addr){for (int i =0; i < 4; ++i){printf("%d", ip_addr[i]);if (i != 3) printf(".");} printf("\n");}void get_local_addr(unsigned char* mac, u_int32_t &ip){struct ifconf interface_conf;struct ifreq ifreq1;int sock;struct sockaddr_in* psockaddr_in = NULL;if ( (sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0){perror("Unable to create socket for geting the mac address");exit(1);} strcpy(ifreq1.ifr_name, "eth0");if (ioctl(sock, SIOCGIFHWADDR, &ifreq1) < 0){perror("Unable to get the mac address");exit(1); } memcpy(mac, ifreq1.ifr_hwaddr.sa_data, 6); if (ioctl(sock, SIOCGIFADDR, &ifreq1) < 0){perror("Unable to get the ip address");exit(1); } psockaddr_in = (struct sockaddr_in*)&ifreq1.ifr_addr; ip = psockaddr_in->sin_addr.s_addr;//print_ip((unsigned char*)ip);} int main(int argc, char* argv[]){int timeout = 2;int optval = 1;int s; /* socket */int rv = 1; /* return value */struct sockaddr addr; /* for interface name */struct arpMsg arp;fd_set fdset;struct timeval tm;time_t prevTime;u_int32_t ip;struct in_addr my_ip;struct in_addr dst_ip;char buff[2000];unsigned char mac[6];unsigned char dmac[6];char interface[] = "eth0";if (argc != 2){printf("Usage: get_ip_by_mac dst_mac\n");printf("For example: get_ip_by_mac 00:0F:EA:40:0D:04\n");return 0; }get_local_addr(mac, ip);for (int i = 0; i < 6; ++i){strncpy(buff, argv[1]+3*i, 2);buff[3] = '\0';dmac[i] = strtol(buff, (char**)NULL, 16);}if ((s = socket (PF_PACKET, SOCK_PACKET, htons(ETH_P_RARP))) == -1) {printf("Could not open raw socket\n");return -1;}if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) == -1) {printf("Could not setsocketopt on raw socket\n");close(s);return -1;}memset(&addr, 0, sizeof(addr));strcpy(addr.sa_data, interface);/* send rarp request */memset(&arp, 0, sizeof(arp));memcpy(arp.ethhdr.h_dest, MAC_BCAST_ADDR, 6); /* MAC DA */memcpy(arp.ethhdr.h_source, mac, 6); /* MAC SA */arp.ethhdr.h_proto = htons(ETH_P_RARP); /* protocol type (Ethernet) */arp.htype = htons(ARPHRD_ETHER); /* hardware type */arp.ptype = htons(ETH_P_IP); /* protocol type (ARP message) */arp.hlen = 6; /* hardware address length */arp.plen = 4; /* protocol address length */arp.operation = htons(3); /* RARP request code */*((u_int *) arp.sInaddr) = ip; /* source IP address */memcpy(arp.sHaddr, mac, 6); /* source hardware address */ memcpy(arp.tHaddr, dmac, 6);if (sendto(s, &arp, sizeof(arp), 0, &addr, sizeof(addr)) < 0){perror("Unabele to send arp request");return 0; }rv = 0;/* wait arp reply, and check it */tm.tv_usec = 0;time(&prevTime);while (timeout > 0) {FD_ZERO(&fdset);FD_SET(s, &fdset);tm.tv_sec = timeout;if (select(s + 1, &fdset, (fd_set *) NULL, (fd_set *) NULL, &tm) < 0) {printf("Error on ARPING request:");if (errno != EINTR) rv = 0;} else if (FD_ISSET(s, &fdset)) {if (recv(s, &arp, sizeof(arp), 0) < 0 ) {perror("Unable get valid rarp response");rv = 0;} if (arp.operation == htons(4) && bcmp(arp.tHaddr, mac, 6) == 0 ) {printf("Valid rarp reply receved for this address\n");//print_mac(arp.sHaddr);print_ip(arp.sInaddr);rv = 0;break;}}timeout -= time(NULL) - prevTime;time(&prevTime);}close(s);return 0;}
转载自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=686647&id=1745799
你可能感兴趣的文章
c库和嵌入式开发
查看>>
我的友情链接
查看>>
大端与小端
查看>>
.关于oracle latch和lock的一点点
查看>>
我的友情链接
查看>>
小软件解决大问题之数码相机存储卡的数据恢复
查看>>
linux-lsof
查看>>
Python学习笔记(3)-Python基础
查看>>
我的友情链接
查看>>
Iptables中SNAT和MASQUERADE的区别
查看>>
fourinone分布式协调设计解析
查看>>
年休假、婚丧假、产假、病假、事假分别有多少天?你必须懂!
查看>>
我的友情链接
查看>>
Docker Swarm Mode 的容器资源回收问题
查看>>
汇编指令速查
查看>>
自由软件不完全手册
查看>>
转移Wise Folder Hider的文件
查看>>
《游戏程序设计模式》 0 - 目录
查看>>
甲状腺超声要点
查看>>
模拟实现getch()
查看>>