linux RAW SOCKET加Packet af定制2层报文
前几天做了一个feature,使用raw socket加AF_PACKET。选择了一部分,修改了下,变成一个简单的例子,分享出来。用这个只要你能接入网络,你想发什么就发什么,别干坏事就好:-)。AF_PACKET和AF_INET区别就是一个可以脱光到2层,一个只能到3层。直接把代码贴出来,希望感兴趣的人可以参考。
客户端:
#include <stdio.h> #include<errno.h> #include<stdlib.h> #include<unistd.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include<netdb.h> #include<linux/if.h> #include<linux/if_packet.h> #include<linux/sockios.h> #include<linux/if_ether.h> #include<string.h> struct socks { int fd; struct sockaddr_ll addr; } dp_socket[2]; int create_sockets(void) { struct ifreq ifr; struct sockaddr_ll addr; int retval; int s; __u16 type; int dev, num_devs=2; type = htons(0x8d8d); for (dev = 0 ; dev <num_devs; ++dev) { type = htons(0x8d8d + dev); dp_socket[dev].fd = -1; s = socket (PF_PACKET, SOCK_RAW, type); if (s < 0) { return (s); } memset ((void*)&ifr, 0, sizeof (ifr)); snprintf (ifr.ifr_name, sizeof (ifr.ifr_name), "eth0"); retval = ioctl (s, SIOCGIFINDEX, &ifr); if (retval < 0) { close (s); return (retval); } memset (&addr, 0, sizeof (addr)); addr.sll_family = AF_PACKET; addr.sll_ifindex = ifr.ifr_ifindex; addr.sll_protocol = type; retval = bind (s, (struct sockaddr *) &addr, sizeof (addr)); if (retval < 0) { close (s); return (retval); } dp_socket[dev].fd = s; memset(&dp_socket[dev].addr, 0, sizeof(dp_socket[dev].addr)); dp_socket[dev].addr.sll_family = AF_PACKET; dp_socket[dev].addr.sll_ifindex = ifr.ifr_ifindex; dp_socket[dev].addr.sll_protocol = type; } return 0; } int main(void) { fd_set rfd_set, wfd_set; int i; char rbuf[512]; int ret; char wbuf[512]; struct ethhdr *rhdr = (struct ethhdr *)rbuf; struct ethhdr *whdr = (struct ethhdr *)wbuf; FD_ZERO(&rfd_set); FD_ZERO(&wfd_set); create_sockets(); FD_SET(dp_socket[1].fd, &rfd_set); memset(wbuf + sizeof(*whdr), 0, 512 - sizeof(*whdr)); memcpy(wbuf + sizeof(*whdr), "coming", 7); whdr->h_dest[0] = 0x00; whdr->h_dest[1] = 0x22; whdr->h_dest[2] = 0x68; whdr->h_dest[3] = 0x14; whdr->h_dest[4] = 0xe1; whdr->h_dest[5] = 0xb1; whdr->h_proto = htons(0x8d8d); rhdr->h_proto = htons(0x8d8e); while (1) { ret = write(dp_socket[0].fd, wbuf, 7 + sizeof(*whdr)); if (select(FD_SETSIZE, &rfd_set, NULL, NULL, NULL) < 0) { printf("select error\n"); exit(-1); } memset(rbuf + sizeof(*rhdr), 0, 512 - sizeof(*rhdr)); if(FD_ISSET(dp_socket[1].fd, &rfd_set)) { ret = read(dp_socket[1].fd, rbuf, 512); if (ret > 0) { printf("%s\n",rbuf+sizeof(*rhdr)); } ret = write(dp_socket[0].fd, wbuf, 7 + sizeof(*whdr)); if (ret <=0) { printf("error write\n"); } sleep(1); } } return 0; }
服务端:
#include <stdio.h> #include<errno.h> #include<stdlib.h> #include<unistd.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include<netdb.h> #include<linux/if.h> #include<linux/if_packet.h> #include<linux/if_ether.h> #include<linux/sockios.h> #include<string.h> struct socks { int fd; struct sockaddr_ll addr; } dp_socket[2]; int create_sockets(void) { struct ifreq ifr; struct sockaddr_ll addr; int retval; int s; __u16 type; int dev, num_devs=2; type = htons(0x8d8d); for (dev = 0 ; dev < num_devs; ++dev) { type = htons(0x8d8d + dev); dp_socket[dev].fd = -1; s = socket (PF_PACKET, SOCK_RAW, type); if (s < 0) { return (s); } memset ((void*)&ifr, 0, sizeof (ifr)); snprintf (ifr.ifr_name, sizeof (ifr.ifr_name), "eth0"); retval = ioctl (s, SIOCGIFINDEX, &ifr); if (retval < 0) { close (s); return (retval); } memset (&addr, 0, sizeof (addr)); addr.sll_family = AF_PACKET; addr.sll_ifindex = ifr.ifr_ifindex; addr.sll_protocol = type; retval = bind (s, (struct sockaddr *) &addr, sizeof (addr)); if (retval < 0) { close (s); return (retval); } dp_socket[dev].fd = s; memset(&dp_socket[dev].addr, 0, sizeof(dp_socket[dev].addr)); dp_socket[dev].addr.sll_family = AF_PACKET; dp_socket[dev].addr.sll_ifindex = ifr.ifr_ifindex; dp_socket[dev].addr.sll_protocol = type; } return 0; } int main(void) { fd_set rfd_set, wfd_set; int i; unsigned char rbuf[512]; char wbuf[512]; struct ethhdr *hdr = (struct ethhdr *)rbuf; struct ethhdr *whdr = (struct ethhdr *)wbuf; hdr->h_proto = htons(0x8d8d); whdr->h_proto = htons(0x8d8e); FD_ZERO(&rfd_set); FD_ZERO(&wfd_set); create_sockets(); FD_SET(dp_socket[0].fd, &rfd_set); //FD_SET(dp_socket[1].fd, &wfd_set); while (1) { if (select(FD_SETSIZE, &rfd_set, NULL, NULL, NULL) < 0) { printf("select error\n"); exit(-1); } memset(rbuf + sizeof(*hdr), 0, 512 - sizeof(*hdr)); memset(wbuf + sizeof(*hdr), 0, 512 - sizeof(*hdr)); memcpy(wbuf + sizeof(*hdr), "got it", 7); if(FD_ISSET(dp_socket[0].fd, &rfd_set)) { int ret; ret = read(dp_socket[0].fd, rbuf, 511); if (ret > 0) { //printf("%02x %02x %02x %02x %02x %02x\n",rbuf[0],rbuf[1],rbuf[2],rbuf[3], rbuf[4], rbuf[5]); printf("%s\n",rbuf + sizeof(*hdr)); } ret = write(dp_socket[1].fd, wbuf, sizeof(*hdr) + 7); if (ret <=0) { printf("error write\n"); } } } return 0; }
转载请注明出处