raw socket收发数据

raw socket发数据信息

/******************************************************************************
* Filename: raw_socket2.c
*
* Description: 发送raw 网卡数据
*
* Version: 2.0
* Created: 2021年07月07日 20时27分51秒
* Revision: none
* Compiler: gcc
*
* Author: yangkun (yk)
* Email: xyyangkun@163.com
* Company: yangkun.com
*
*****************************************************************************/
#include <net/ethernet.h> /* the L2 protocols */// ETH_P_ALL
#include <linux/if_packet.h>
#include <linux/if.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <netinet/ip.h> // ip head
#include <netinet/udp.h> // udp head
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
// 校验和函数
unsigned short csum(unsigned short *buf, int nwords)
{
unsigned long sum;
for(sum=0; nwords>0; nwords--)
sum += *buf++;
sum = (sum >> 16) + (sum &0xffff);
sum += (sum >> 16);
return (unsigned short)(~sum);
}
// 发送mac层数据
int main()
{
struct sockaddr_ll stTagAddr;
memset(&stTagAddr, 0 , sizeof(stTagAddr));
stTagAddr.sll_family = AF_PACKET;//填写AF_PACKET,不再经协议层处理
stTagAddr.sll_protocol = htons(ETH_P_ALL);
int ret;
struct ifreq req;
int sd;
sd = socket(PF_INET, SOCK_DGRAM, 0);//这个sd就是用来获取eth0的index,完了就关闭
if(sd == -1)
{
printf("error to create socket pf_inet:%s\n", strerror(errno));
return -1;
}
// todo 此处需要更改为你使用的网卡名称
char *eth_name = "enp3s0";
memset(&req, 0, sizeof(req));
strncpy(req.ifr_name, eth_name, strlen(eth_name));//通过设备名称获取index
ret=ioctl(sd, SIOCGIFINDEX, &req);
if(ret <0)
{
perror("SIOCGIFHWADDR");
return -1;
}
// 获取mac地址
struct ifreq if_mac;
memset(&if_mac, 0, sizeof(struct ifreq));
strncpy(if_mac.ifr_name, eth_name, strlen(eth_name));
if (ioctl(sd, SIOCGIFHWADDR, &if_mac) < 0)
{
perror("SIOCGIFHWADDR");
return -1;
}
close(sd);
if (ret==-1)
{
printf("Get eth0 index err:%d=>%s \n", errno, strerror(errno));
return -1;
}

// int SockFd = socket(PF_PACKET, SOCK_RAW, htons(VSTRONG_PROTOCOL));
int SockFd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (-1 == SockFd)
{
printf("create socket error:%d.\n",errno);
return -11;
}
stTagAddr.sll_ifindex = req.ifr_ifindex;//网卡eth0的index,非常重要,系统把数据往哪张网卡上发,就靠这个标识
stTagAddr.sll_pkttype = PACKET_OUTGOING;//标识包的类型为发出去的包
stTagAddr.sll_halen = 6; //目标MAC地址长度为6
//填写目标MAC地址
stTagAddr.sll_addr[0] = 0x2c;
stTagAddr.sll_addr[1] = 0xf0;
stTagAddr.sll_addr[2] = 0x5d;
stTagAddr.sll_addr[3] = 0x6e;
stTagAddr.sll_addr[4] = 0x3e;
stTagAddr.sll_addr[5] = 0xa6;
//填充帧头和内容
// 构造ethernet header
int tx_len = 0;
char sendbuf[1024];
struct ether_header *eh = (struct ether_header *) sendbuf;
memset(sendbuf, 0, 1024);
/* Ethernet header */
// 此处应该根据源mac 和 目的mac做更改
eh->ether_shost[0] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[0];
eh->ether_shost[1] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[1];
eh->ether_shost[2] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[2];
eh->ether_shost[3] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[3];
eh->ether_shost[4] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[4];
eh->ether_shost[5] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[5];
eh->ether_dhost[0] = 0x2c;
eh->ether_dhost[1] = 0xf0;
eh->ether_dhost[2] = 0x5d;
eh->ether_dhost[3] = 0x6e;
eh->ether_dhost[4] = 0x3e;
eh->ether_dhost[5] = 0xa6;
eh->ether_type = htons(ETH_P_IP);
tx_len += sizeof(struct ether_header);
// 构造ip 头
struct iphdr *iph = (struct iphdr *) (sendbuf + sizeof(struct ether_header));
int ttl = 20;
/* IP Header */
iph->ihl = 5;
iph->version = 4;
iph->tos = 16; // Low delay
iph->id = htons(54321);
iph->ttl = ttl; // hops
iph->protocol = 17; // UDP
/* Source IP address, can be spoofed */
//iph->saddr = inet_addr(inet_ntoa(((struct sockaddr_in *)&if_ip.ifr_addr)->sin_addr));
// 此处要更改源ip和目的ip
iph->saddr = inet_addr("172.20.2.7");
/* Destination IP address */
iph->daddr = inet_addr("172.20.2.76");
tx_len += sizeof(struct iphdr);

// 构建udp 数据头
struct udphdr *udph = (struct udphdr *) (sendbuf + sizeof(struct iphdr) + sizeof(struct ether_header));
/* UDP Header */
// 源端口, 目的端口
udph->source = htons(3423);
udph->dest = htons(5342);
udph->check = 0; // skip
tx_len += sizeof(struct udphdr);

//udp 数据
/* Packet data */
sendbuf[tx_len++] = 0xde;
sendbuf[tx_len++] = 0xad;
sendbuf[tx_len++] = 0xbe;
sendbuf[tx_len++] = 0xef;

// 填充头校验信息
/* Length of UDP payload and header */
udph->len = htons(tx_len - sizeof(struct ether_header) - sizeof(struct iphdr));
/* Length of IP payload and header */
iph->tot_len = htons(tx_len - sizeof(struct ether_header));
/* Calculate IP checksum on completed header */
iph->check = csum((unsigned short *)(sendbuf+sizeof(struct ether_header)), sizeof(struct iphdr)/2);

// 这样网卡会把sebuff中的内容发送出去

int i32Len = sendto(SockFd, (char *)sendbuf, tx_len, 0, (const struct sockaddr *)&stTagAddr, sizeof(stTagAddr));
if(-1 == i32Len)
{
printf("error to send data:errno=%d=>%s\n", errno, strerror(errno));
return -1;
}
}

raw socket recv所有网口信息

int aaa(char *recv_machine)
{
    int rawsock;
    
    int n;
    int count = 0;
    unsigned char buff[BUFFSIZE];
    struct sockaddr_ll sll;
    rawsock = socket(AF_PACKET,SOCK_RAW,htons(ETH_P_IP));
    if(rawsock < 0){
        printf("raw socket error!\n");
        exit(1);
    }
    while(1){    
    n = recvfrom(rawsock,buff,BUFFSIZE,0,NULL,NULL);
    if(n<0){
        printf("receive error!\n");
        exit(1);
    }
    else
    {
        if((buff[30] == 0xFF)&&(buff[31] == 0xFF)&&(buff[32] == 0xFF)&&(buff[33] == 0xFF))
        {
            memcpy(recv_machine,buff,n);
            printf("recv:\n");
            for(int i=0;i<n;i++)
            {
                printf("%x ",recv_machine[i]);
            }  
            printf("\n");
            printf("aa==%d\n",n);
            return n;
        }
    }
  }
}

raw socket recv指定网卡信息

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<netinet/ip_icmp.h>
#include<netinet/tcp.h>
#include<netinet/udp.h>
#include<netinet/if_ether.h>
#include<net/if.h>
#include <net/ethernet.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<sys/ioctl.h>
#include <linux/if_packet.h>
#include <unistd.h>
#define BUFFSIZE 1024
const char* device = "virbr0";
const unsigned char dst_mac[6] = {0x00,0x0c,0x29,0x87,0x16, 0x37};
struct ker_arphdr
  {
    unsigned short int ar_hrd;          /* Format of hardware address.  */
    unsigned short int ar_pro;          /* Format of protocol address.  */
    unsigned char ar_hln;               /* Length of hardware address.  */
    unsigned char ar_pln;               /* Length of protocol address.  */
    unsigned short int ar_op;           /* ARP opcode (command).  */
#if 1
    /* Ethernet looks like this : This bit is variable sized
       however...  */
    unsigned char __ar_sha[ETH_ALEN];   /* Sender hardware address.  */
    unsigned char __ar_sip[4];          /* Sender IP address.  */
    unsigned char __ar_tha[ETH_ALEN];   /* Target hardware address.  */
    unsigned char __ar_tip[4];          /* Target IP address.  */
#endif
  };
typedef struct {
    /* Source/destination address. */
    unsigned char dst_address[6];
    unsigned char src_address[6];
    /* Ethernet type. */
    unsigned short type;
} eth_header_t;
int main(){
    int rawsock;
    unsigned char rbuf[BUFFSIZE];
    int n, count = 0;
    eth_header_t* eth;
    
        rawsock = socket(AF_PACKET, SOCK_RAW, ntohs(ETH_P_IP));
        if(rawsock < 0){
                printf("raw socket error!\n");
                exit(1);
        }
    struct ifreq ifr_re;
    strcpy(ifr_re.ifr_name, device);
    // 获取接口index
    if(ioctl(rawsock, SIOCGIFINDEX, (char*)&ifr_re))
    {
        return -1;
    }
    // 赋值socket属性
    struct sockaddr_ll hwaddr;
    memset(&hwaddr, 0, sizeof(hwaddr));
    hwaddr.sll_ifindex   = ifr_re.ifr_ifindex;
    hwaddr.sll_family    = AF_PACKET;
    hwaddr.sll_protocol  = htons(ETH_P_IP);
    hwaddr.sll_hatype    = 0;
    hwaddr.sll_pkttype   = PACKET_HOST;
    hwaddr.sll_halen     = ETH_ALEN;
    // 绑定socket至接口
    if(bind(rawsock, (struct sockaddr*)&hwaddr, sizeof(hwaddr)))
    {
        printf("raw socket bind error!\n");
        return -1;
    }
    // 获取接口MAC地址
    if(ioctl(rawsock, SIOCGIFHWADDR, (char*)&ifr_re))
    {
        printf("raw socket get mac address failed!\n");
        return -2;
    }
    printf("Local mac: %02x:%02x:%02x:%02x:%02x:%02x\n",
                    ifr_re.ifr_hwaddr.sa_data[0],
                    ifr_re.ifr_hwaddr.sa_data[1],
                    ifr_re.ifr_hwaddr.sa_data[2],
                    ifr_re.ifr_hwaddr.sa_data[3],
                    ifr_re.ifr_hwaddr.sa_data[4],
                    ifr_re.ifr_hwaddr.sa_data[5]);
    // send pkt
    //write(rawsock, wbuf,  12);
    while (1) {
        n = recvfrom(rawsock,rbuf,BUFFSIZE,0,NULL,NULL);
        if(n<0){
            printf("receive error!\n");
            exit(1);
        }
    
        printf("recv%d: ",n);
        for(int i = 0;i < n;i++)
        {
            printf("%02X ",rbuf[i]);
        }
        printf("\n");
       /*
        count++;
        eth = (eth_header_t*)rbuf;
         if (eth->type == htons(ETH_P_IP)){
            printf("Recved IP  pkt dst mac: %02x:%02x:%02x:%02x:%02x:%02x  ", eth->dst_address[0]
                , eth->dst_address[1]
                , eth->dst_address[2]
                , eth->dst_address[3]
                , eth->dst_address[4]
                , eth->dst_address[5]);
                struct ip *ip = (struct ip*)(eth + 1);
                printf("%3d     %15s",count,inet_ntoa(ip->ip_src));
                printf("%15s    %5d     %5d\n",inet_ntoa(ip->ip_dst),ip->ip_p,ntohs(ip->ip_len));
        }
        else if (eth->type == htons(ETH_P_ARP)) {
                printf("Recved ARP pkt src mac: %02x:%02x:%02x:%02x:%02x:%02x  ", eth->src_address[0]
                                , eth->src_address[1]
                                , eth->src_address[2]
                                , eth->src_address[3]
                                , eth->src_address[4]
                                , eth->src_address[5]);
                struct ker_arphdr* ah =  (struct ker_arphdr*)(eth + 1);
                printf("%3d          %u.%u.%u.%u\n",count, ah->__ar_sip[3],ah->__ar_sip[2],ah->__ar_sip[1],ah->__ar_sip[0]);
        }
        memset(rbuf, 0, sizeof(rbuf));
        */
    }
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值