主要应用方向是上位机和嵌软(如stm32单片机)通讯,不在单片机中嵌入web server,即mac层通讯。
一、下面先了解网络数据包组成。
常见数据包的包头长度:
EtherHeader Length: 14 Bytes
TCP Header Length : 20 Bytes
UDP Header Length : 8 Bytes
IP Header Length : 20 Bytes
1.网络封包的整体过程
2.IP 数据包
3.Tcp 数据包
4.UDP 数据包
5、Ethernet Header:
6、ICMP Packet:
7、ARP Packet:
二、程序接收报文示例
*************************UDP Packet******************************
Ethernet Header
|-Source Address : 00-0C-29-64-D9-F5
|-Destination Address : FF-FF-FF-FF-FF-FF
|-Protocol : 8
IP Header
|-Version : 4
|-Internet Header Length : 5 DWORDS or 20 Bytes
|-Type Of Service : 16
|-Total Length : 33 Bytes
|-Identification : 10201
|-Time To Live : 64
|-Protocol : 17
|-Header Checksum : 37369
|-Source IP : 0.0.0.0
|-Destination IP : 192.168.0.66
UDP Header
|-Source Port : 23451
|-Destination Port : 23452
|-UDP Length : 13
|-UDP Checksum : 0
Data
AA BB CC DD EE 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00
*****************************************************************
三、程序示例
程序环境:ubuntu 14.04 send(虚拟机,自定义模式 VMnet1)
Ubuntu 16.04 recv(虚拟机,自定义模式 VMnet1)
1、send
int main()
{
sock_raw=socket(AF_PACKET,SOCK_RAW,IPPROTO_RAW);
if(sock_raw == -1)
printf("error in socket");
// increase in case of large data.Here data is --> AA BB CC DD EE
sendbuff=(unsigned char*)malloc(64);
memset(sendbuff,0,64);
get_eth_index(); // interface number
get_mac();
get_ip();
struct sockaddr_ll sadr_ll;
// sadr_ll.sll_ifindex = ifreq_i.ifr_ifindex;
sadr_ll.sll_ifindex = if_nametoindex("eth0");
sadr_ll.sll_halen = ETH_ALEN;
sadr_ll.sll_addr[0] = DESTMAC0;
sadr_ll.sll_addr[1] = DESTMAC1;
sadr_ll.sll_addr[2] = DESTMAC2;
sadr_ll.sll_addr[3] = DESTMAC3;
sadr_ll.sll_addr[4] = DESTMAC4;
sadr_ll.sll_addr[5] = DESTMAC5;
printf("sending...\n");
while(1)
{
send_len = sendto(sock_raw,sendbuff,64,0,(const struct sockaddr*)&sadr_ll,sizeof(struct sockaddr_ll));
if(send_len<0)
{
printf("error in sending....sendlen=%d....errno=%d\n",send_len,errno);
return -1;
}
}
}
2、recv
/* Note: run this program as root user
* Author:Subodh Saxena
*/
#include<stdio.h>
#include<malloc.h>
#include<string.h>
#include<signal.h>
#include<stdbool.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<linux/if_packet.h>
#include<netinet/in.h>
#include<netinet/if_ether.h> // for ethernet header
#include<netinet/ip.h> // for ip header
#include<netinet/udp.h> // for udp header
#include<netinet/tcp.h>
#include<arpa/inet.h> // to avoid warning at inet_ntoa
FILE* log_txt;
int total,tcp,udp,icmp,igmp,other,iphdrlen;
struct sockaddr saddr;
struct sockaddr_in source,dest;
void ethernet_header(unsigned char* buffer,int buflen)
{
struct ethhdr *eth = (struct ethhdr *)(buffer);
fprintf(log_txt,"\nEthernet Header\n");
fprintf(log_txt,"\t|-Source Address : %.2X-%.2X-%.2X-%.2X-%.2X-%.2X\n",eth->h_source[0],eth->h_source[1],eth->h_source[2],eth->h_source[3],eth->h_source[4],eth->h_source[5]);
fprintf(log_txt,"\t|-Destination Address : %.2X-%.2X-%.2X-%.2X-%.2X-%.2X\n",eth->h_dest[0],eth->h_dest[1],eth->h_dest[2],eth->h_dest[3],eth->h_dest[4],eth->h_dest[5]);
fprintf(log_txt,"\t|-Protocol : %d\n",eth->h_proto);
}
void ip_header(unsigned char* buffer,int buflen)
{
struct iphdr *ip = (struct iphdr*)(buffer + sizeof(struct ethhdr));
iphdrlen =ip->ihl*4;
memset(&source, 0, sizeof(source));
source.sin_addr.s_addr = ip->saddr;
memset(&dest, 0, sizeof(dest));
dest.sin_addr.s_addr = ip->daddr;
fprintf(log_txt , "\nIP Header\n");
fprintf(log_txt , "\t|-Version : %d\n",(unsigned int)ip->version);
fprintf(log_txt , "\t|-Internet Header Length : %d DWORDS or %d Bytes\n",(unsigned int)ip->ihl,((unsigned int)(ip->ihl))*4);
fprintf(log_txt , "\t|-Type Of Service : %d\n",(unsigned int)ip->tos);
fprintf(log_txt , "\t|-Total Length : %d Bytes\n",ntohs(ip->tot_len));
fprintf(log_txt , "\t|-Identification : %d\n",ntohs(ip->id));
fprintf(log_txt , "\t|-Time To Live : %d\n",(unsigned int)ip->ttl);
fprintf(log_txt , "\t|-Protocol : %d\n",(unsigned int)ip->protocol);
fprintf(log_txt , "\t|-Header Checksum : %d\n",ntohs(ip->check));
fprintf(log_txt , "\t|-Source IP : %s\n", inet_ntoa(source.sin_addr));
fprintf(log_txt , "\t|-Destination IP : %s\n",inet_ntoa(dest.sin_addr));
}
void payload(unsigned char* buffer,int buflen)
{
int i=0;
unsigned char * data = (buffer + iphdrlen + sizeof(struct ethhdr) + sizeof(struct udphdr));
fprintf(log_txt,"\nData\n");
int remaining_data = buflen - (iphdrlen + sizeof(struct ethhdr) + sizeof(struct udphdr));
for(i=0;i<remaining_data;i++)
{
if(i!=0 && i%16==0)
fprintf(log_txt,"\n");
fprintf(log_txt," %.2X ",data[i]);
}
fprintf(log_txt,"\n");
}
void tcp_header(unsigned char* buffer,int buflen)
{
fprintf(log_txt,"\n*************************TCP Packet******************************");
ethernet_header(buffer,buflen);
ip_header(buffer,buflen);
struct tcphdr *tcp = (struct tcphdr*)(buffer + iphdrlen + sizeof(struct ethhdr));
fprintf(log_txt , "\nTCP Header\n");
fprintf(log_txt , "\t|-Source Port : %u\n",ntohs(tcp->source));
fprintf(log_txt , "\t|-Destination Port : %u\n",ntohs(tcp->dest));
fprintf(log_txt , "\t|-Sequence Number : %u\n",ntohl(tcp->seq));
fprintf(log_txt , "\t|-Acknowledge Number : %u\n",ntohl(tcp->ack_seq));
fprintf(log_txt , "\t|-Header Length : %d DWORDS or %d BYTES\n" ,(unsigned int)tcp->doff,(unsigned int)tcp->doff*4);
fprintf(log_txt , "\t|----------Flags-----------\n");
fprintf(log_txt , "\t\t|-Urgent Flag : %d\n",(unsigned int)tcp->urg);
fprintf(log_txt , "\t\t|-Acknowledgement Flag : %d\n",(unsigned int)tcp->ack);
fprintf(log_txt , "\t\t|-Push Flag : %d\n",(unsigned int)tcp->psh);
fprintf(log_txt , "\t\t|-Reset Flag : %d\n",(unsigned int)tcp->rst);
fprintf(log_txt , "\t\t|-Synchronise Flag : %d\n",(unsigned int)tcp->syn);
fprintf(log_txt , "\t\t|-Finish Flag : %d\n",(unsigned int)tcp->fin);
fprintf(log_txt , "\t|-Window size : %d\n",ntohs(tcp->window));
fprintf(log_txt , "\t|-Checksum : %d\n",ntohs(tcp->check));
fprintf(log_txt , "\t|-Urgent Pointer : %d\n",tcp->urg_ptr);
payload(buffer,buflen);
fprintf(log_txt,"*****************************************************************\n\n\n");
}
void udp_header(unsigned char* buffer, int buflen)
{
fprintf(log_txt,"\n*************************UDP Packet******************************");
ethernet_header(buffer,buflen);
ip_header(buffer,buflen);
fprintf(log_txt,"\nUDP Header\n");
struct udphdr *udp = (struct udphdr*)(buffer + iphdrlen + sizeof(struct ethhdr));
fprintf(log_txt , "\t|-Source Port : %d\n" , ntohs(udp->source));
fprintf(log_txt , "\t|-Destination Port : %d\n" , ntohs(udp->dest));
fprintf(log_txt , "\t|-UDP Length : %d\n" , ntohs(udp->len));
fprintf(log_txt , "\t|-UDP Checksum : %d\n" , ntohs(udp->check));
payload(buffer,buflen);
fprintf(log_txt,"*****************************************************************\n\n\n");
}
void data_process(unsigned char* buffer,int buflen)
{
struct iphdr *ip = (struct iphdr*)(buffer + sizeof (struct ethhdr));
++total;
/* we will se UDP Protocol only*/
switch (ip->protocol) //see /etc/protocols file
{
case 6:
++tcp;
// tcp_header(buffer,buflen);
break;
case 17:
++udp;
udp_header(buffer,buflen);
break;
default:
++other;
}
printf("TCP: %d UDP: %d Other: %d Toatl: %d \r",tcp,udp,other,total);
}
int main()
{
int sock_r,saddr_len,buflen;
unsigned char* buffer = (unsigned char *)malloc(65536);
memset(buffer,0,65536);
log_txt=fopen("log.txt","w");
if(!log_txt)
{
printf("unable to open log.txt\n");
return -1;
}
printf("starting .... \n");
sock_r=socket(AF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
if(sock_r<0)
{
printf("error in socket\n");
return -1;
}
while(1)
{
saddr_len=sizeof saddr;
buflen=recvfrom(sock_r,buffer,65536,0,&saddr,(socklen_t *)&saddr_len);
if(buflen<0)
{
printf("error in reading recvfrom function\n");
return -1;
}
fflush(log_txt);
data_process(buffer,buflen);
}
close(sock_r);// use signals to close socket
printf("DONE!!!!\n");
}
如需完成发送程序,可关注公众号后,后台留言,说明所需程序。
欢迎关注公众号: