數據鏈路層主要的功能
- 把網絡層的包封裝成幀
- 對幀的校驗和確認
- 流量的控制
數據鏈路層生成以太網幀,以太網幀的主要格式如下。
太網幀的傳輸大小是由傳輸媒介決定的,數據幀的大小是64—1518。幀頭14個字節,分別是目標MAC地址
(6個字節)+源MAC地址(6個字節)+協議類型(2個字節),幀尾是32位的CRC冗余校驗。對于兩個字
節協議字段,0×0800主要用于IP協議,還有一些其他的網絡協議,比如Novell IPX等。
這里先介紹以太網幀頭格式,用libcap抓出來的包最后的CRC冗余校驗已經在物理網卡上完成。下面是代碼
#include <pcap.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <net/ethernet.h>
#include <netinet/ip_icmp.h> //Provides declarations for icmp header
#include <netinet/udp.h> //Provides declarations for udp header
#include <netinet/tcp.h> //Provides declarations for tcp header
#include <netinet/ip.h> //Provides declarations for ip header
#define BUFFER_SIZE 2048
#define HIGH4(a) (((a&0xf0))>>4)
#define LOW4(a) (a&0x0f)
int size ;
void process_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *buffer);
void print_mac(const u_char *packet_buffer);
void mac_to_str(char *szMac, unsigned char mac[6]);
int main(int argc,char *argv[])
{
pcap_if_t *alldevsp , *device;
pcap_t *handle; //Handle of the device that shall be sniffed
char errbuf[100] , *devname , devs[100][100];
int count = 1 , n;
//First get the list of available devices
printf("Finding available devices ... ");
if( pcap_findalldevs( &alldevsp , errbuf) )
{
printf("Error finding devices : %s" , errbuf);
exit(1);
}
printf("Done");
//Print the available devices
printf("\nAvailable Devices are :\n");
for(device = alldevsp ; device != NULL ; device = device->next)
{
printf("%d. %s - %s\n" , count , device->name , device->description);
if(device->name != NULL)
{
strcpy(devs[count] , device->name);
}
count++;
}
//Ask user which device to sniff
printf("Enter the number of the device you want to sniff : ");
scanf("%d" , &n);
devname = devs[n];
//Open the device for sniffing
printf("Opening device %s for sniffing ... " , devname);
handle = pcap_open_live(devname , 65536 , 1 , 0 , errbuf);
if (handle == NULL)
{
fprintf(stderr, "Couldn't open device %s : %s\n" , devname , errbuf);
exit(1);
}
printf("Done\n");
//Put the device in sniff loop
pcap_loop(handle , -1 , process_packet , NULL);
return 0;
}
void process_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *buffer)
{
size = header->len;
print_mac(buffer);
}
void print_mac(const u_char *packet_buffer)
{
struct ethhdr *ethernet_header = NULL; //ether header
char sour_mac[40] = {'\0'}; //<linux/if_ether.h>
char des_mac[40] = {'\0'}; //#define ETH_ALEN 6
ethernet_header = (struct ethhdr *)packet_buffer;
mac_to_str(sour_mac,ethernet_header->h_source);
mac_to_str(des_mac,ethernet_header->h_dest);
printf("length of ethernet_head : %d \n",sizeof(struct ethhdr));
printf("des_MAC : %s\n",des_mac);
printf("sour_MAC : %s\n",sour_mac);
printf("Protocal : %x\n",ntohs(ethernet_header->h_proto));
}
//MAC地址翻譯
void mac_to_str(char *szMac, unsigned char mac[6])
{
sprintf(szMac, "%X%X:%X%X:%X%X:%X%X:%X%X:%X%X"
, HIGH4(mac[0]), LOW4(mac[0])
, HIGH4(mac[1]), LOW4(mac[1])
, HIGH4(mac[2]), LOW4(mac[2])
, HIGH4(mac[3]), LOW4(mac[3])
, HIGH4(mac[4]), LOW4(mac[4])
, HIGH4(mac[5]), LOW4(mac[5])
);
}
$ gcc get_mac.c -o get_mac -lpcap
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

