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;
}
复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值