向本地网络中广播特定的控制帧,设备端检测到控制帧时,发送自己的网络配置信息,如IP,Mask,Mac地址
2017-09-26 15:45
106 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/idream68/article/details/78096865
当一台嵌入式设备连接到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; }
相关文章推荐
- Linux C 网络编程 - 获取本地 ip 地址,mac,通过域名获取对应的 ip
- 在 TCP 网络上检测出有重复名称,发送消息的计算机的 IP 地址在数据中
- Linux C 网络编程 - 获取本地 ip 地址,mac,通过域名获取对应的 ip 、获取本地主机的名字
- 初学python-获取网络设备配置文件接口IP信息
- Linux C 网络编程 - 获取本地 ip 地址,mac,通过域名获取对应的 ip
- Linux C 网络编程 - 获取本地 ip 地址,mac,通过域名获取对应的 ip
- 网络地址和广播地址也可以用,中间网络设备不会在乎ip是什么地址!
- linux 获取本地网络信息 -ip,mac ,等
- 002 Linux下网络配置、查看ip地址、网关信息,DNS信息(以centos7为例)
- Linux C 网络编程 - 获取本地 ip 地址,mac,通过域名获取对应的 ip
- C# System.Net.NetworkInformation 命名空间学习之NetworkInterface 类获取IP,DNS,Gateway,Mask, MAC等网络相关信息
- java根据本地IP获取mac地址的方法
- 获取本地MAC地址和多IP
- VC++获取系统信息/获取OS/获取MAC/获取本地IP/判断是否为网吧
- linux c 获取本地IP,MAC 子网掩码等信息
- Android中获取设备IP、MAC地址
- 完成一个应用,用户可以根据自己输入的地址下载网络上的图片和网页信息
- 在vb中使用Iphlpapi.dll获取网络信息 第二章 第十三节 获得目的地IP对应的物理地址
- js 检测输入框内容是否为合法IP和MAC地址