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