Send a raw Ethernet frame in Linux (zz)
来源:互联网 发布:amt emulator mac 编辑:程序博客网 时间:2024/06/06 09:24
From here:
Send a raw Ethernet frame in Linux (GitHub)
Explanation is here
Sending raw Ethernet packets from a specific interface in C on Linux
packet, AF_PACKET - packet interface on device levelIn additionNote that this works only for some socket types, particularly AF_INET sockets. It is not supported for packet sockets (use normal bind(2) there)Raw socket with device bind using setsockopt() system is not workingMore for UDPProgramming raw udp sockets in C on Linux
/** This program is free software: you can redistribute it and/or modify* it under the terms of the GNU General Public License as published by* the Free Software Foundation, either version 3 of the License, or* (at your option) any later version.*/ #include <arpa/inet.h>#include <linux/if_packet.h>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <net/if.h>#include <netinet/ether.h> #define MY_DEST_MAC0 0x00#define MY_DEST_MAC1 0x00#define MY_DEST_MAC2 0x00#define MY_DEST_MAC3 0x00#define MY_DEST_MAC4 0x00#define MY_DEST_MAC5 0x00 #define DEFAULT_IF "eth0"#define BUF_SIZ 1024 int main(int argc, char *argv[]){int sockfd;struct ifreq if_idx;struct ifreq if_mac;int tx_len = 0;char sendbuf[BUF_SIZ];struct ether_header *eh = (struct ether_header *) sendbuf;struct iphdr *iph = (struct iphdr *) (sendbuf + sizeof(struct ether_header));struct sockaddr_ll socket_address;char ifName[IFNAMSIZ];/* Get interface name */if (argc > 1)strcpy(ifName, argv[1]);elsestrcpy(ifName, DEFAULT_IF); /* Open RAW socket to send on */if ((sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) == -1) {perror("socket");} /* Get the index of the interface to send on */memset(&if_idx, 0, sizeof(struct ifreq));strncpy(if_idx.ifr_name, ifName, IFNAMSIZ-1);if (ioctl(sockfd, SIOCGIFINDEX, &if_idx) < 0)perror("SIOCGIFINDEX");/* Get the MAC address of the interface to send on */memset(&if_mac, 0, sizeof(struct ifreq));strncpy(if_mac.ifr_name, ifName, IFNAMSIZ-1);if (ioctl(sockfd, SIOCGIFHWADDR, &if_mac) < 0)perror("SIOCGIFHWADDR"); /* Construct the Ethernet header */memset(sendbuf, 0, BUF_SIZ);/* Ethernet header */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] = MY_DEST_MAC0;eh->ether_dhost[1] = MY_DEST_MAC1;eh->ether_dhost[2] = MY_DEST_MAC2;eh->ether_dhost[3] = MY_DEST_MAC3;eh->ether_dhost[4] = MY_DEST_MAC4;eh->ether_dhost[5] = MY_DEST_MAC5;/* Ethertype field */eh->ether_type = htons(ETH_P_IP);tx_len += sizeof(struct ether_header); /* Packet data */sendbuf[tx_len++] = 0xde;sendbuf[tx_len++] = 0xad;sendbuf[tx_len++] = 0xbe;sendbuf[tx_len++] = 0xef; /* Index of the network device */socket_address.sll_ifindex = if_idx.ifr_ifindex;/* Address length*/socket_address.sll_halen = ETH_ALEN;/* Destination MAC */socket_address.sll_addr[0] = MY_DEST_MAC0;socket_address.sll_addr[1] = MY_DEST_MAC1;socket_address.sll_addr[2] = MY_DEST_MAC2;socket_address.sll_addr[3] = MY_DEST_MAC3;socket_address.sll_addr[4] = MY_DEST_MAC4;socket_address.sll_addr[5] = MY_DEST_MAC5; /* Send packet */if (sendto(sockfd, sendbuf, tx_len, 0, (struct sockaddr*)&socket_address, sizeof(struct sockaddr_ll)) < 0)printf("Send failed\n"); return 0;}
=======================
Lately I’ve been writing some code to send packets to a specific MAC address from a specific interface. I’m sure this will come in handy again so here is how it goes:
Includes:
(might not need all of these)
#include <netinet/in.h>#include <sys/socket.h>#include <arpa/inet.h>#include <net/if.h>#include <netinet/ip.h>#include <netinet/udp.h>#include <netinet/ether.h>#include <linux/if_packet.h>
Open the raw socket:
int sockfd;.../* Open RAW socket to send on */if ((sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) == -1) { perror("socket");}
Get the index of the interface to send on:
struct ifreq if_idx;...memset(&if_idx, 0, sizeof(struct ifreq));strncpy(if_idx.ifr_name, "eth0", IFNAMSIZ-1);if (ioctl(sock, SIOCGIFINDEX, &if_idx) < 0) perror("SIOCGIFINDEX");
Get the MAC address of the interface to send on:
struct ifreq if_mac;...memset(&if_mac, 0, sizeof(struct ifreq));strncpy(if_mac.ifr_name, "eth0", IFNAMSIZ-1);if (ioctl(sock, SIOCGIFHWADDR, &if_mac) < 0) perror("SIOCGIFHWADDR");
Get the IP address of the interface to send on:
struct ifreq if_ip;...memset(&if_ip, 0, sizeof(struct ifreq));strncpy(if_ip.ifr_name, "eth0", IFNAMSIZ-1);if (ioctl(sock, SIOCGIFADDR, &if_ip) < 0) perror("SIOCGIFADDR");
Construct the Ethernet header:
int tx_len = 0;char sendbuf[1024];struct ether_header *eh = (struct ether_header *) sendbuf;...memset(sendbuf, 0, 1024);/* Ethernet header */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] = MY_DEST_MAC0;eh->ether_dhost[1] = MY_DEST_MAC1;eh->ether_dhost[2] = MY_DEST_MAC2;eh->ether_dhost[3] = MY_DEST_MAC3;eh->ether_dhost[4] = MY_DEST_MAC4;eh->ether_dhost[5] = MY_DEST_MAC5;eh->ether_type = htons(ETH_P_IP);tx_len += sizeof(struct ether_header);
Construct the IP header:
struct iphdr *iph = (struct iphdr *) (sendbuf + sizeof(struct ether_header));.../* IP Header */iph->ihl = 5;iph->version = 4;iph->tos = 16; // Low delayiph->id = htons(54321);iph->ttl = ttl; // hopsiph->protocol = 17; // UDP/* Source IP address, can be spoofed */iph->saddr = inet_addr(inet_ntoa(((struct sockaddr_in *)&if_ip.ifr_addr)->sin_addr));// iph->saddr = inet_addr("192.168.0.112");/* Destination IP address */iph->daddr = inet_addr("192.168.0.111");tx_len += sizeof(struct iphdr);
Construct the UDP header:
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; // skiptx_len += sizeof(struct udphdr);
Fill in UDP payload:
/* Packet data */sendbuf[tx_len++] = 0xde;sendbuf[tx_len++] = 0xad;sendbuf[tx_len++] = 0xbe;sendbuf[tx_len++] = 0xef;
Fill in remaining header info:
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);}.../* 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);
Send the raw Ethernet packet:
/* Destination address */struct sockaddr_ll socket_address;.../* Index of the network device */socket_address.sll_ifindex = if_idx.ifr_ifindex;/* Address length*/socket_address.sll_halen = ETH_ALEN;/* Destination MAC */socket_address.sll_addr[0] = MY_DEST_MAC0;socket_address.sll_addr[1] = MY_DEST_MAC1;socket_address.sll_addr[2] = MY_DEST_MAC2;socket_address.sll_addr[3] = MY_DEST_MAC3;socket_address.sll_addr[4] = MY_DEST_MAC4;socket_address.sll_addr[5] = MY_DEST_MAC5;/* Send packet */if (sendto(sock, sendbuf, tx_len, 0, (struct sockaddr*)&socket_address, sizeof(struct sockaddr_ll)) < 0) printf("Send failed\n");
Update:
As in the comments, I’ve written a working example that can be found here: https://gist.github.com/1922600
Change the destination MAC address (e.g. 00:11:22:33:44:55) and compile:
gcc sendRawEth.c -o sendRawEth
In one terminal run tcpdump to observe the packets:
sudo tcpdump -nettti eth0 '(ether dst host 00:11:22:33:44:55)'
And in another run the program as root:
sudo ./sendRawEth eth0
References:
http://aschauf.landshut.org/fh/linux/udp_vs_raw/ch01s03.html
http://www.tenouk.com/Module43a.html
http://linux.die.net/man/3/sendto
=====================================
void BindToInterface(int raw , char *device , int protocol) { struct sockaddr_ll sll; struct ifreq ifr; bzero(&sll , sizeof(sll)); bzero(&ifr , sizeof(ifr)); strncpy((char *)ifr.ifr_name ,device , IFNAMSIZ); //copy device name to ifr if((ioctl(raw , SIOCGIFINDEX , &ifr)) == -1) { perror("Unable to find interface index"); exit(-1); } sll.sll_family = AF_PACKET; sll.sll_ifindex = ifr.ifr_ifindex; sll.sll_protocol = htons(protocol); if((bind(raw , (struct sockaddr *)&sll , sizeof(sll))) ==-1) { perror("bind: "); exit(-1); } return 0;}
- Send a raw Ethernet frame in Linux (zz)
- Ethernet frame
- ethernet frame
- Ethernet frame
- Ethernet frame
- use AT command to send a sms in linux system
- raw socket in linux
- how to send raw data to printer in java
- Ethernet frame check sequence incorrect
- [ZZ]CSS FRAME WORK – A SURVEY AND INTRODUCTION
- Setting JAVA_HOME in Linux [zz]
- usb to ethernet adapter (moshi) work in linux kernel
- Send Raw Data to a Printer by Using the Win32 API
- How to send raw data to a printer by using Visual C# .NET
- HowTo: Linux Send a Gratuitous ARPs Requests
- Setting a raw device in RHEL5/OEL5 - Oracle Cluster
- ebtables - Ethernet bridge frame table administration
- A quite easy way to send email in ABAP
- [锋客计划]Android Design 翻译计划
- android中The connection to adb is down,问题和解决
- 大圣闹海、金蝉捕鱼0x000003e8指令引用的0x000003e8内存。改内存不能为read
- 网狐登录提示,服务器连接失败,请检查网络配置以及网络连接状况
- 网狐6603解决平台脚本生成标识ID到335停止不动
- Send a raw Ethernet frame in Linux (zz)
- 网狐6603机器人不进房间
- 网狐、6878、EWIN后台管理员帐号密码 对应数据库表
- 网狐棋牌更换服务器,客户端大厅要更换的文件
- 网狐6603客户端 ServerInfo.INI 详解
- Call for papers-Special Issue on View-Based 3D Representation, Learning, and Understanding
- 网狐6603真钱梦成EWIN启动大厅不能进游戏房间
- 数据库异常:形参@strCompellation 未声明为OUTPUT参数 但传递经理的实参请求输出
- 莱恩棋牌版本网络引擎监听端口被占用,端口绑定失败