GetLocalMac.c
/*============================================================================
Name : GetLocalMac.cpp
Author : Haier
Version : 1.01
Copyright : Copyright (c) 2014
Description : GetLocalMac in C, Compile by Gcc
============================================================================*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <netinet/if_ether.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
typedef struct _Ether_pkg
{
unsigned char ether_dhost[6];
unsigned char ether_shost[6];
unsigned short int ether_type;
unsigned short int ar_hrd;
unsigned short int ar_pro;
unsigned char ar_hln;
unsigned char ar_pln;
unsigned short int ar_op;
unsigned char ar_sha[ETH_ALEN];
unsigned char ar_sip[4];
unsigned char ar_tha[ETH_ALEN];
unsigned char ar_tip[4];
}Ether_pkg;
/*----------------------------------------------------------
; 函數:GetLocalMac()
------------------------------------------------------------*/
int GetLocalMac(const char *device, char *mac, char *ip)
{
int sockfd;
struct ifreq req;
struct sockaddr_in *sin;
if((sockfd=socket(PF_INET,SOCK_DGRAM,0))== -1)
{
fprintf(stderr, "Sock Error:%s\n",strerror(errno));
return -1;
}
memset(&req, 0, sizeof(req));
strcpy(req.ifr_name, device);
if(ioctl(sockfd,SIOCGIFHWADDR, (char*)&req) == -1)
{
fprintf(stderr, "ioctlSIOCGIFHWADDR:%s\n", strerror(errno));
close(sockfd);
return -1;
}
memcpy(mac, req.ifr_hwaddr.sa_data,6);
req.ifr_addr.sa_family = PF_INET;
if(ioctl(sockfd,SIOCGIFADDR, (char*)&req) == -1)
{
fprintf(stderr, "SIOCGIFADDR:%s\n",strerror(errno));
close(sockfd);
return -1;
}
sin = (struct sockaddr_in*)&req.ifr_addr;
memcpy(ip, (char*)&sin->sin_addr,4);
return 0;
}
/*----------------------------------------------------------
; 函數:mac_ntoa()
------------------------------------------------------------*/
char *mac_ntoa(const unsigned char *mac)
{
static char buffer[18];
memset(buffer, 0, sizeof(buffer));
sprintf(buffer, "%02X:%02X:%02X:%02X:%02X:%02X",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
return buffer;
}
/*----------------------------------------------------------
; 函數:parse_ether_package()
------------------------------------------------------------*/
void parse_ether_package(const Ether_pkg *pkg)
{
printf("source IP=[%s] MAC=[%s]\n", inet_ntoa(*(struct in_addr *)pkg->ar_sip),mac_ntoa(pkg->ar_sha));
printf("dest IP=[%s] MAC=[%s]\n", inet_ntoa(*(struct in_addr *)pkg->ar_tip),mac_ntoa(pkg->ar_tha));
}
/*----------------------------------------------------------
; 函數:sendpkg()
------------------------------------------------------------*/
int sendpkg(char *mac, char *broad_mac, char *ip, char *dest)
{
Ether_pkg pkg,*parse;
struct hostent *host = NULL;
struct sockaddr sa;
int sockfd, len;
char buffer[255];
unsigned char temp_ip[5];
memset((char*)&pkg, '0', sizeof(pkg));
memcpy((char*)pkg.ether_shost, (char*)mac, 6);
memcpy((char*)pkg.ether_dhost, (char*)broad_mac, 6);
pkg.ether_type = htons(ETHERTYPE_ARP);
pkg.ar_hrd = htons(ARPHRD_ETHER);
pkg.ar_pro = htons(ETHERTYPE_IP);
pkg.ar_hln = 6;
pkg.ar_pln = 4;
pkg.ar_op = htons(ARPOP_REQUEST);
memcpy((char*)pkg.ar_sha, (char*)mac, 6);
memcpy((char*)pkg.ar_sip, (char*)ip, 4);
memcpy((char*)pkg.ar_tha, (char*)broad_mac, 6);
fflush(stdout);
memset(temp_ip, 0, sizeof(temp_ip));
if(inet_aton(dest, (struct in_addr *)temp_ip) == 0)
{
if((host = gethostbyname(dest)) == NULL)
{
fprintf(stderr, "Fail ! %s\n", hstrerror(h_errno));
return -1;
}
memcpy((char*)temp_ip, host->h_addr, 4);
}
memcpy((char*)pkg.ar_tip, (char*)temp_ip, 4);
if((sockfd=socket(PF_INET, SOCK_PACKET,htons(ETH_P_ALL))) == -1)
{
fprintf(stderr, "Socket Error:%s\n",strerror(errno));
return 0;
}
memset(&sa, '0', sizeof(sa));
strcpy(sa.sa_data,"eth1");
len = sendto(sockfd, &pkg, sizeof(pkg),0,&sa,sizeof(sa));
if(len != sizeof(pkg))
{
fprintf(stderr,"Sendto Error:%s\n",strerror(errno));
close(sockfd);
return 0;
}
fd_set readfds;
struct timeval tv;
while(1)
{
tv.tv_sec = 0;
tv.tv_usec= 500000;
FD_ZERO(&readfds);
FD_SET(sockfd,&readfds);
len = select(sockfd+1, &readfds, 0, 0, &tv);
if(len > -1)
{
memset(buffer,0,sizeof(buffer));
len=recvfrom(sockfd,buffer,sizeof(buffer),0,NULL,&len);
parse = (Ether_pkg*)buffer;
if((ntohs(parse->ether_type) == ETHERTYPE_ARP) && (ntohs(parse->ar_op) == ARPOP_REPLY))
{
parse_ether_package(parse);
break;
}
}
}
close(sockfd);
return 1;
}
/*----------------------------------------------------------
; 函數:main()
------------------------------------------------------------*/
int main(int argc, char **argv)
{
struct timeval tvafter,tvpre;
struct timezone tz;
gettimeofday(&tvpre,&tz);
unsigned char mac[7];
unsigned char ip[5];
char dest[16]={0};
unsigned char broad_mac[7]={0xff,0xff,0xff,0xff,0xff,0xff,0x00};
memset(mac,0,sizeof(mac));
memset(ip,0,sizeof(ip));
if(GetLocalMac("eth1",mac,ip) == -1)
{
return -1;
}
printf("Local Mac=[%s] Ip=[%s]\n", mac_ntoa(mac),inet_ntoa(*(struct in_addr*)ip));
sprintf(dest,"255.255.255.255",16);
sendpkg(mac,broad_mac,ip,dest);
gettimeofday(&tvafter, &tz);
printf("\nfinished:%dms\n",(tvafter.tv_sec-tvpre.tv_sec)*1000 + (tvafter.tv_usec-tvpre.tv_usec)/1000);
return 0;
}
運行示例:
[root@Linux Ping]# ./test.o
Local Mac=[00:0C:29:AC:1B:2C] Ip=[192.168.64.128]
source IP=[192.168.64.254] MAC=[00:50:56:EF:89:0A]
dest IP=[192.168.64.128] MAC=[00:0C:29:AC:1B:2C]