linux socket使用ARP判断局域网指定IP是否被占用

本文介绍了一种在Linux系统下,通过C/C++编程实现利用socket ARP检查局域网内IP是否被占用的方法。由于ping命令无法判断跨网段IP,而arping可能在某些嵌入式系统中不可用,因此采用socket ARP实现,能够区分6种不同的IP状态,并提供了详细的使用流程和示例代码。

项目中需要判断局域网内某个IP是否被占用,一开始想到的是ping命令,但是ping只能判断同一网段的IP。后来发现linux使用arping命令可以判断,如使用arping -D -f -w 1 x.x.x.x

但是对于经过裁剪的嵌入式linux,busybox中不一定还保留arping命令,而且C代码中调用shell命令需要临时创建一个子进程来执行,频繁操作会浪费资源。于是决定参考busybox源码中的arping.c自己实现C代码socket的ARP,以下代码是从busybox的arping.c中提取的。

需要能区分出以下6种情况:

  • 同网段本IP且IP不冲突
  • 同网段本IP且IP冲突
  • 同网段其他IP且IP存在
  • 同网段其他IP且IP不存在
  • 跨网段IP存在
  • 跨网段IP不存在

如何使用

调用函数arp_get_mac即可,参数if_name 是网卡名称,嵌入式中经常是eth0,str_src_ip是本设备的IP,str_dst_ip是需要判断的目标IP,dst_mac返回目标IP对应设备的MAC,timeout_ms指定超时时间,单位是ms。

返回值中,对于str_src_ip与str_dst_ip不相同的情况下,该IP正被占用返回1,未被占用返回0.对于str_src_ip与str_dst_ip相同的情况,该IP只有本设备在使用则返回2,本设备的IP与别的设备IP冲突,且该IP正被别的设备占用则返回1。

/**

返回值:        -1  错误
            0   不存在
            1   存在
            2   请求IP是本设备IP,且IP可用
*/
int arp_get_mac(char *if_name,char *str_src_ip,char *str_dst_ip,unsigned char *dst_mac,int timeout_ms) 

流程解释

先按需求设置好socket,封装好struct sockaddr以及需要发送的数据,以UDP广播的方式发送出去,然后接收广播包,在接收到的数据包中分析提取需要的信息,如果能提取到则说明该IP正在被占用。

实例代码:

/**
根据指定IP地址获取MAC地址,可用于判断IP是否被占用
*/

#include <stdlib.h>
#include <sys/param.h>  
#include <sys/socket.h>
#include <linux/sockios.h> 
#include <sys/file.h>  
#include <sys/time.h>  
#include <sys/signal.h>  
#include <sys/ioctl.h>  
#include <linux/if.h>  
#include <linux/if_arp.h>  
#include <sys/uio.h>  

#include <netdb.h>  
#include <unistd.h>  
#include <stdio.h>  
#include <ctype.h>  
#include <errno.h>  
#include <string.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>  

#include <debug_util.h>
#include "arp_get_mac.h"    

#define MS_TDIFF(tv1,tv2) ( ((tv1).tv_sec-(tv2).tv_sec)*1000 + ((tv1).tv_usec-(tv2).tv_usec)/1000 )    

int send_pack(int fd, struct in_addr src, struct in_addr dst,  
              struct sockaddr_ll *ME, struct sockaddr_ll *HE)  
{
        int advert=0;

        int err;  
        struct timeval now;  
        unsigned char buf[256];  
        struct arphdr *ah = (struct arphdr*)buf;  
        unsigned char *p = (unsigned char *)(ah+1);  

        ah->ar_hrd = htons(ME->sll_hatype);        /* 硬件地址类型*/  
        if (ah->ar_hrd == htons(ARPHRD_FDDI))  
                ah->ar_hrd = htons(ARPHRD_ETHER);  
        ah->ar_pro = htons(ETH_P_IP);                /* 协议地址类型   */  
        ah->ar_hln = ME->sll_halen;                /* 硬件地址长度   */  
        ah->ar_pln = 4;                                /* 协议地址长度 */  
        a
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值