linux RAW SOCKET加Packet af定制2层报文

本文分享了一个使用AF_PACKET和Raw Socket的简单示例。通过客户端和服务端代码演示如何发送和接收自定义以太网帧,包括设置socket、绑定设备接口、发送数据包等关键步骤。

前几天做了一个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;
}
复制代码
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值