前几天做了一个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; }
本文分享了一个使用AF_PACKET和Raw Socket的简单示例。通过客户端和服务端代码演示如何发送和接收自定义以太网帧,包括设置socket、绑定设备接口、发送数据包等关键步骤。

1759

被折叠的 条评论
为什么被折叠?



