前几天做了一个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; }