向本地网络中广播特定的控制帧,设备端检测到控制帧时,发送自己的网络配置信息,如IP,Mask,Mac地址

        当一台嵌入式设备连接到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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值