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;

}

 

你可能感兴趣的:(socket)