当一台嵌入式设备连接到PC或多个设备通过交换机与PC相连时,由于设备的IP地址可能未知,那么就需要通过工具进行设备探测,来获取设备的IP地址和网络掩码,获取到的参数可以由PC来参考设备本地的网络参数和PC程序中用来打开设备的参数。
注意事项:
(1)广播的目的mac地址为FF:FF:FF:FF:FF:FF
(2)发送数据需要先绑定网卡
struct sockaddr_ll saddr_ll;
struct ifreq ifr;
bzero(&saddr_ll, sizeof(struct sockaddr_ll));
bzero(&ifr, sizeof(struct ifreq));
/* 网卡接口名 */
memcpy(ifr.ifr_name, Network_Name, strlen(Network_Name));
/* 获取网卡接口索引 */
if (ioctl(skfd, SIOCGIFINDEX, &ifr) == -1)
perror("ioctl() get ifindex");
saddr_ll.sll_ifindex = ifr.ifr_ifindex;
saddr_ll.sll_family = PF_PACKET;
(3)需要构建原始套接字raw_socket;
socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL))
(4)ioctl函数的应用获取IP,Mask,Mac地址;
实现广播程序如下:
#include "api.h"
int send_broadcast(const char* Network_Name/*in*/)
{
int skfd,n;
char buf[BUFLEN]={0};
char r_buf[BUFLEN]={0};
struct ethhdr *eth0;
struct ether_header *eth;
Tbroadcast *broadcast;
Tack *iph;
struct sockaddr_ll saddr_ll;
struct ifreq ifr;
struct sockaddr_in *sin;
char ip[16] ;
char netmask[16];
char mac[16];
//struct sockaddr_in clientaddr;
//bzero(&clientaddr, sizeof(clientaddr));
//clientaddr.sin_family = AF_INET;
//inet_pton(AF_INET, BROADCAST_IP, &clientaddr.sin_addr.s_addr);
//clientaddr.sin_port = htons(CLIENT_PORT);
unsigned char src_mac[ETH_ALEN]={0};
unsigned char dst_mac[ETH_ALEN]={0xff,0xff,0xff,0xff,0xff,0xff}; //全网广播
bzero(&saddr_ll, sizeof(struct sockaddr_ll));
bzero(&ifr, sizeof(struct ifreq));
/* 网卡接口名 */
memcpy(ifr.ifr_name, Network_Name, strlen(Network_Name));
if(0>(skfd=socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL))))
{
perror("Create Error");
exit(1);
}
/* 获取网卡接口索引 */
if (ioctl(skfd, SIOCGIFINDEX, &ifr) == -1)
perror("ioctl() get ifindex");
saddr_ll.sll_ifindex = ifr.ifr_ifindex;
saddr_ll.sll_family = PF_PACKET;
int flag = 1;
setsockopt(skfd, SOL_SOCKET, SO_BROADCAST, &flag, sizeof(flag));
//获取接口IP地址
//strcpy(ifr.ifr_name,argv[1]);
memset(&sin, 0, sizeof(sin));
if(ioctl(skfd, SIOCGIFADDR, &ifr) != -1)
{
sin = (struct sockaddr_in *)&ifr.ifr_addr;
strcpy(ip, inet_ntoa(sin->sin_addr));
printf("IP address is %s\n", ip);
}
//获取接口的子网掩码
if(ioctl(skfd, SIOCGIFNETMASK, &ifr) != -1)
{
sin = (struct sockaddr_in *)&ifr.ifr_netmask;
strcpy(netmask, inet_ntoa(sin->sin_addr));
printf("Net-mask is %s\n", netmask);
}
//获取接口的MAC地址
if(ioctl(skfd, SIOCGIFHWADDR, &ifr) != -1)
{
sprintf(mac, "%02x:%02x:%02x:%02x:%02x:%02x",
(unsigned char)ifr.ifr_hwaddr.sa_data[0],
(unsigned char)ifr.ifr_hwaddr.sa_data[1],
(unsigned char)ifr.ifr_hwaddr.sa_data[2],
(unsigned char)ifr.ifr_hwaddr.sa_data[3],
(unsigned char)ifr.ifr_hwaddr.sa_data[4],
(unsigned char)ifr.ifr_hwaddr.sa_data[5]);
printf("Mac address is %s\n", mac);
}
memcpy(src_mac,ifr.ifr_hwaddr.sa_data,ETH_ALEN);
//开始填充,构造以太头部
eth=(struct ether_header*)buf;
memcpy(eth->ether_dhost,dst_mac,ETH_ALEN);
memcpy(eth->ether_shost,src_mac,ETH_ALEN);
eth->ether_type = htons(BROADCAST);
//手动开始广播帧结构
broadcast=(struct _Tbroadcast*)(buf+sizeof(struct ether_header));
broadcast->header=0xdeadbeef; //帧头(帧头固定为0xdeadbeef)
broadcast->length=sizeof(struct _Tbroadcast); //广播帧长度
broadcast->version=0x00; //广播帧版本
broadcast->contNum=1; //控制字
if(ioctl(skfd, SIOCGIFADDR, &ifr) != -1)
memcpy(&broadcast->dev_ip,&(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr),4); //网络参数 设备IP地址
else
perror("broadcast->dev_ip error");
if(ioctl(skfd, SIOCGIFNETMASK, &ifr) != -1)
memcpy(&broadcast->dev_mask,&(((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr),4); //网络参数 设备子网掩码
else
perror("broadcast->dev_mask error");
if(ioctl(skfd, SIOCGIFHWADDR, &ifr)!= -1 )
memcpy(&broadcast->dev_mac,ifr.ifr_hwaddr.sa_data,6); //网络参数 设备MAC地址
else
perror("broadcast->dev_mac error");
//发送广播数据
while(1)
{
if(n=sendto(skfd,buf,BUFLEN,0, (struct sockaddr *)&saddr_ll, sizeof(struct sockaddr_ll))<0)
{
perror("Send error:");
continue;
}
else
{
n=recvfrom(skfd,r_buf,BUFLEN,0,NULL,0);
if(n <=0)
{
perror("Receive error:");
continue;
}
else
{
iph=(struct _Tack*)(r_buf+sizeof(struct ether_header));
if(iph->header == 0xdeadbeef)
{
printf("\n %d Bytes Receive\n",n);
char strIP[16];
char strMask[16];
printf("Client IP:%s\n",inet_ntop(AF_INET,&iph->dev_ip,strIP,sizeof(strIP)));
printf("Client Mask:%s\n",inet_ntop(AF_INET,&iph->dev_mask,strMask,sizeof(strMask)));
sprintf(mac, "%02x:%02x:%02x:%02x:%02x:%02x",
(unsigned char)iph->dev_mac[0],
(unsigned char)iph->dev_mac[1],
(unsigned char)iph->dev_mac[2],
(unsigned char)iph->dev_mac[3],
(unsigned char)iph->dev_mac[4],
(unsigned char)iph->dev_mac[5]);
printf("Mac address is %s\n", mac);
return 0;
}
}
}
}
close(skfd);
return 0;
}