`
simohayha
  • 浏览: 1386380 次
  • 性别: Icon_minigender_1
  • 来自: 火星
社区版块
存档分类
最新评论

linux下检测ip冲突

阅读更多
原理其实很简单,那就是广播一个arp包,然后recv,如果没有数据(这里要设置延时),那么说明这个ip是可用的,否则就检测这个数据是否为回复我们发出的arp的应答包.如果是则证明ip已被使用,否则继续等待.

这里可以看下busybox的dhcp中的检测程序。
networking/udhcp/arpping.c

/* vi: set sw=4 ts=4: */
/*
 * arpping.c
 *
 * Mostly stolen from: dhcpcd - DHCP client daemon
 * by Yoichi Hariguchi <yoichi@fore.com>
 */

#include <netinet/if_ether.h>
#include <net/if_arp.h>

#include "common.h"
#include "dhcpd.h"

//这里是arp包的格式,其中的数据格式都是宏了,比如uint_8_t为无符char.
struct arpMsg {
	/* Ethernet header */
	uint8_t  h_dest[6];     /* 00 destination ether addr */
	uint8_t  h_source[6];   /* 06 source ether addr */
	uint16_t h_proto;       /* 0c packet type ID field */

	/* ARP packet */
	uint16_t htype;         /* 0e hardware type (must be ARPHRD_ETHER) */
	uint16_t ptype;         /* 10 protocol type (must be ETH_P_IP) */
	uint8_t  hlen;          /* 12 hardware address length (must be 6) */
	uint8_t  plen;          /* 13 protocol address length (must be 4) */
	uint16_t operation;     /* 14 ARP opcode */
	uint8_t  sHaddr[6];     /* 16 sender's hardware address */
	uint8_t  sInaddr[4];    /* 1c sender's IP address */
	uint8_t  tHaddr[6];     /* 20 target's hardware address */
	uint8_t  tInaddr[4];    /* 26 target's IP address */
	uint8_t  pad[18];       /* 2a pad for min. ethernet payload (60 bytes) */
} PACKED;

enum {
	ARP_MSG_SIZE = 0x2a
};


/* Returns 1 if no reply received */

//主程序,如果返回1说明此ip可用
int arpping(uint32_t test_ip, uint32_t from_ip, uint8_t *from_mac, const char *interface)
{

	int timeout_ms;
//这里使用poll来检测句柄。
	struct pollfd pfd[1];
#define s (pfd[0].fd)           /* socket */
	int rv = 1;             /* "no reply received" yet */
	struct sockaddr addr;   /* for interface name */
	struct arpMsg arp;

//建立scoket.由于我们是要直接访问访问链路层并自己组arp包.因此我们使用PF_PACKET协议簇.socket类型为SOCK_PACKET.

	s = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP));
	if (s == -1) {
		bb_perror_msg(bb_msg_can_not_create_raw_socket);
		return -1;
	}

	if (setsockopt_broadcast(s) == -1) {
		bb_perror_msg("cannot enable bcast on raw socket");
		goto ret;
	}
//进行组包,由于是要广播,因此目的mac地址为全0.
	/* send arp request */
	memset(&arp, 0, sizeof(arp));
	memset(arp.h_dest, 0xff, 6);                    /* MAC DA */
	memcpy(arp.h_source, from_mac, 6);              /* MAC SA */
	arp.h_proto = htons(ETH_P_ARP);                 /* protocol type (Ethernet) */
	arp.htype = htons(ARPHRD_ETHER);                /* hardware type */
	arp.ptype = htons(ETH_P_IP);                    /* protocol type (ARP message) */
	arp.hlen = 6;                                   /* hardware address length */
	arp.plen = 4;                                   /* protocol address length */
	arp.operation = htons(ARPOP_REQUEST);           /* ARP op code */
	memcpy(arp.sHaddr, from_mac, 6);                /* source hardware address */
	memcpy(arp.sInaddr, &from_ip, sizeof(from_ip)); /* source IP address */
	/* tHaddr is zero-fiiled */                     /* target hardware address */
	memcpy(arp.tInaddr, &test_ip, sizeof(test_ip)); /* target IP address */

	memset(&addr, 0, sizeof(addr));
	safe_strncpy(addr.sa_data, interface, sizeof(addr.sa_data));
//广播arp包.
	if (sendto(s, &arp, sizeof(arp), 0, &addr, sizeof(addr)) < 0) {
		// TODO: error message? caller didn't expect us to fail,
		// just returning 1 "no reply received" misleads it.
		goto ret;
	}

	/* wait for arp reply, and check it */
//等待时间,超时则认为此ip地址可用
	timeout_ms = 2000;
	do {
		int r;
		unsigned prevTime = monotonic_us();

		pfd[0].events = POLLIN;
//这边他是害怕poll被信号打断,因此加了层循环,其实这边我们还可以使用ppoll的,就可以了。
		r = safe_poll(pfd, 1, timeout_ms);
		if (r < 0)
			break;
		if (r) {
//读取返回数据.
			r = read(s, &arp, sizeof(arp));
			if (r < 0)
				break;
//检测是否为应打包,发送ip是否为我们所请求的ip,这里是为了防止其他的数据包干扰我们检测。
			if (r >= ARP_MSG_SIZE
			 && arp.operation == htons(ARPOP_REPLY)
			 /* don't check it: Linux doesn't return proper tHaddr (fixed in 2.6.24?) */
			 /* && memcmp(arp.tHaddr, from_mac, 6) == 0 */
			 && *((uint32_t *) arp.sInaddr) == test_ip
			) {
//说明ip地址已被使用
				rv = 0;
				break;
			}
		}
		timeout_ms -= ((unsigned)monotonic_us() - prevTime) / 1000;
	} while (timeout_ms > 0);

 ret:
	close(s);
	DEBUG("%srp reply received for this address", rv ? "No a" : "A");
	return rv;
}

3
0
分享到:
评论
1 楼 xiangjie88 2014-03-25  
能否给出setsockopt_broadcast的头文件或函数

相关推荐

    Linux ip冲突检测程序

    Linux下的ip冲突检测的小程序,一起学习吧

    一个IP冲突检测的项目代码linux

    检测IP冲突, 很好的一段代码,下载去看看吧

    IPwatchD:Linux的IP冲突检测工具

    Linux的IP冲突检测工具 IPwatchD是一个简单的守护程序,它分析所有传入的ARP数据包以检测Linux上的IP冲突。 可以将其配置为在主动或被动模式下侦听一个或多个网络接口。 在活动模式下,它通过回答从冲突系统收到的...

    局域网内静态IP地址冲突避免软件设计(Linux-QT版)

    虽然DHCP被广泛应用于动态IP地址分配,但在一些校园或企业的办公室,仍然使用静态IP进行地址分派,因此经常出现IP地址冲突问题。本课题的目的就是开发一个基于Linux操作系统的静态IP地址配置工具,来解决IP地址分配...

    Linux从入门到精通

    E.6.14 我不能在系统的1023柱面下安装Linux, 我该怎么办? E.6.15 我想把LILO从我的机器的MBR中移去, 如何做? E.6.16 我想把Linux从我的硬盘中删除. 我使用DOS的fdisk, 它显示出非DOS分区, 但不能删除. 怎么办? E....

    《Linux从入门到精通》

    E.6.14 我不能在系统的1023柱面下安装Linux, 我该怎么办? E.6.15 我想把LILO从我的机器的MBR中移去, 如何做? E.6.16 我想把Linux从我的硬盘中删除. 我使用DOS的fdisk, 它显示出非DOS分区, 但不能删除. 怎么办? E....

    linux从入门到精通.chm

    E.6.14 我不能在系统的1023柱面下安装Linux, 我该怎么办? E.6.15 我想把LILO从我的机器的MBR中移去, 如何做? E.6.16 我想把Linux从我的硬盘中删除. 我使用DOS的fdisk, 它显示出非DOS分区, 但不能删除. 怎么办? E....

    2005详细介绍Linux从入门到精通

    E.6.14 我不能在系统的1023柱面下安装Linux, 我该怎么办? E.6.15 我想把LILO从我的机器的MBR中移去, 如何做? E.6.16 我想把Linux从我的硬盘中删除. 我使用DOS的fdisk, 它显示出非DOS分区, 但不能删除. 怎么办? E....

    arp-scan-1.9.tar.gz

    linux操作系统下,检测网络中的冲突的ip地址对应的mac地址,本工具为源码包,安装方法如下: tar -xzvf arp-scan-1.9.tar.gz cd arp-scan-1.9 ./autoreconf --install ./configure make && make check && make ...

    入门学习Linux常用必会60个命令实例详解doc/txt

    本文以Mandrake Linux 9.1(Kenrel 2.4.21)为例,介绍Linux下的安装和登录命令。 immortality按:请用ctrl+f在本页中查找某一部分的内容或某一命令的用法。 ----------------------------------------------------...

    kubernetes-vulcanproxy:为通过 Kubernetes 创建的所有 Docker 容器自动创建更新 Vulcanproxy 规则的工具

    Kubernetes 为每个服务分配不同的 IP 地址以避免任何端口冲突,但在过去,无法从外部世界访问这些 IP 地址。 现在,可以使用 Kubernetes 服务,但它们并没有提供 Vulcand 的所有好的负载平衡功能。 Vulcand 是 ...

    网络安全设计方案一.doc

    同时应具备一致性检测机制,防止冲突;在传输层 、应用层(HTTP、FTP、TELNET、SNMP、STMP、POP)提供代理支持;支持网络地址转换(N AT)。 l 防御功能:支持病毒扫描,提供内容过滤,能防御Ping of Death,TCP SYN ...

    KODExplorer 芒果云-资源管理器

    - session key 加入kod_前缀 避免和其他系统key冲突 - 编辑器选中优化 选择鼠标到窗口外事件处理 ####fix bug:(bug解决和程序优化) - backspace后退截获浏览器事件,作为后退前一次访问的文件夹; - 搜索首字母...

    淘客帝国破解版

    加强兼容性,不会和根目录下的站外文件起冲突。 5.02 公测版 改动 列表页的购买链接错误修复 火狐下跳转失效修复。 首页在火狐下变形不兼容修复。 分页代码部分模板出错修复。 不开启伪静态时,分页出错修复。 IE6...

    nServer-v2.1023[FTP + MYSQL + HTTP + PHP(FCGI)]

    - 修正zend路径为linux格式 2011年9月23日 - 运行前先进行网络测试,防止开机网络服务启动慢导致启动失败 - 使用最新汉化版FileZilla Server - MySQL默认使用MYISAM引擎 2011年9月19日 - 更新Nginx版本到1.0.6 - ...

    基于SIP开发软件电话的一些资源(转自YOUTOO)

    并且由于默认LIBC的冲突,需要排除MSVCRT[D]开发库(其中D代表Debug模式下,没有D表示Release模式下),直接使用eXosip的几个主要函数就可以创建一个基本的SIP软电话模型。 其主要流程...

Global site tag (gtag.js) - Google Analytics