cornsea

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;
}

 

posted on 2013-01-07 11:29  cornsea  阅读(4462)  评论(0编辑  收藏  举报

导航