diff --git a/scapy/arch/linux.py b/scapy/arch/linux.py index 614adbde84fe3280dcd667c046a3a0ea0c42de33..28e5db9b686502dee9130ebde94b77e29b431ef1 100644 --- a/scapy/arch/linux.py +++ b/scapy/arch/linux.py @@ -10,6 +10,7 @@ Linux specific functions. import sys,os,struct,socket,time from select import select from fcntl import ioctl +import array from scapy.consts import LOOPBACK_NAME, IS_64BITS import scapy.utils @@ -161,6 +162,55 @@ def set_promisc(s,iff,val=1): s.setsockopt(SOL_PACKET, cmd, mreq) +def get_alias_address(iface_name, ip_mask): + """ + Get the correct source IP address of an interface alias + """ + + # Detect the architecture + if scapy.consts.IS_64BITS: + offset, name_len = 16, 40 + else: + offset, name_len = 32, 32 + + # Retrieve interfaces structures + sck = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + names = array.array('B', '\0' * 4096) + ifreq = ioctl(sck.fileno(), SIOCGIFCONF, + struct.pack("iL", len(names), names.buffer_info()[0])) + + # Extract interfaces names + out = struct.unpack("iL", ifreq)[0] + names = names.tostring() + names = [names[i:i+offset].split('\0', 1)[0] for i in xrange(0, out, name_len)] + + # Look for the IP address + for ifname in names: + # Only look for a matching interface name + if not ifname.startswith(iface_name): + continue + + # Retrieve and convert addresses + ifreq = ioctl(sck, SIOCGIFADDR, struct.pack("16s16x", ifname)) + ifaddr = struct.unpack(">I", ifreq[20:24])[0] + ifreq = ioctl(sck, SIOCGIFNETMASK, struct.pack("16s16x", ifname)) + msk = struct.unpack(">I", ifreq[20:24])[0] + + # Get the full interface name + if ':' in ifname: + ifname = ifname[:ifname.index(':')] + else: + continue + + # Check if the source address is included in the network + if (ifaddr & msk) == ip_mask: + sck.close() + return (ifaddr & msk, msk, "0.0.0.0", ifname, + scapy.utils.ltoa(ifaddr)) + + sck.close() + return + def read_routes(): try: @@ -199,10 +249,19 @@ def read_routes(): else: warning("Interface %s: unkown address family (%i)"%(iff, addrfamily)) continue - routes.append((socket.htonl(long(dst,16))&0xffffffffL, - socket.htonl(long(msk,16))&0xffffffffL, - scapy.utils.inet_ntoa(struct.pack("I",long(gw,16))), - iff, ifaddr)) + + # Attempt to detect an interface alias based on addresses inconsistencies + dst_int = socket.htonl(int(dst, 16)) & 0xffffffff + msk_int = socket.htonl(int(msk, 16)) & 0xffffffff + ifaddr_int = struct.unpack("!I", ifreq[20:24])[0] + if ifaddr_int & msk_int != dst_int: + tmp_route = get_alias_address(iff, dst_int) + if tmp_route: + routes.append(tmp_route) + else: + routes.append((dst_int, msk_int, + scapy.utils.inet_ntoa(struct.pack("I", int(gw, 16))), + iff, ifaddr)) f.close() return routes