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; }
转载请注明出处
浙公网安备 33010602011771号