16ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti#!/usr/bin/python 2334a05a24a5e4c27d9318967987fb181530deaffLorenzo Colitti# 3334a05a24a5e4c27d9318967987fb181530deaffLorenzo Colitti# Copyright 2014 The Android Open Source Project 4334a05a24a5e4c27d9318967987fb181530deaffLorenzo Colitti# 5334a05a24a5e4c27d9318967987fb181530deaffLorenzo Colitti# Licensed under the Apache License, Version 2.0 (the "License"); 6334a05a24a5e4c27d9318967987fb181530deaffLorenzo Colitti# you may not use this file except in compliance with the License. 7334a05a24a5e4c27d9318967987fb181530deaffLorenzo Colitti# You may obtain a copy of the License at 8334a05a24a5e4c27d9318967987fb181530deaffLorenzo Colitti# 9334a05a24a5e4c27d9318967987fb181530deaffLorenzo Colitti# http://www.apache.org/licenses/LICENSE-2.0 10334a05a24a5e4c27d9318967987fb181530deaffLorenzo Colitti# 11334a05a24a5e4c27d9318967987fb181530deaffLorenzo Colitti# Unless required by applicable law or agreed to in writing, software 12334a05a24a5e4c27d9318967987fb181530deaffLorenzo Colitti# distributed under the License is distributed on an "AS IS" BASIS, 13334a05a24a5e4c27d9318967987fb181530deaffLorenzo Colitti# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14334a05a24a5e4c27d9318967987fb181530deaffLorenzo Colitti# See the License for the specific language governing permissions and 15334a05a24a5e4c27d9318967987fb181530deaffLorenzo Colitti# limitations under the License. 166ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 176ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colittiimport fcntl 186ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colittiimport os 198236c75d0492e37a2925fdcb2b3d3636a9c615dfLorenzo Colittiimport random 20d2344168138814630764df3da6b23dc839b4890dLorenzo Colittiimport re 21124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colittifrom socket import * # pylint: disable=wildcard-import 226ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colittiimport struct 236ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colittiimport unittest 246ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 256ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colittifrom scapy import all as scapy 266ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 276ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo ColittiSOL_IPV6 = 41 286ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo ColittiIP_RECVERR = 11 296ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo ColittiIPV6_RECVERR = 25 30a25ebd97dd121c7f89e59fa440b86ffc9822d012Lorenzo ColittiIP_TRANSPARENT = 19 31a25ebd97dd121c7f89e59fa440b86ffc9822d012Lorenzo ColittiIPV6_TRANSPARENT = 75 32a25ebd97dd121c7f89e59fa440b86ffc9822d012Lorenzo ColittiIPV6_TCLASS = 67 336ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo ColittiIPV6_FLOWLABEL_MGR = 32 346ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo ColittiIPV6_FLOWINFO_SEND = 33 356ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 36a213cb48c593f34544da80d0462572b2410e36b1Lorenzo ColittiSO_BINDTODEVICE = 25 37a213cb48c593f34544da80d0462572b2410e36b1Lorenzo ColittiSO_MARK = 36 38a213cb48c593f34544da80d0462572b2410e36b1Lorenzo ColittiSO_PROTOCOL = 38 39a213cb48c593f34544da80d0462572b2410e36b1Lorenzo ColittiSO_DOMAIN = 39 40a213cb48c593f34544da80d0462572b2410e36b1Lorenzo Colitti 4171f0b6211d9550ae267af2603a61789aa680cd28Lorenzo ColittiETH_P_IP = 0x0800 426ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo ColittiETH_P_IPV6 = 0x86dd 436ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 44610743878821c018ac1918b280ecfa097b77d6f0Lorenzo ColittiIPPROTO_GRE = 47 45610743878821c018ac1918b280ecfa097b77d6f0Lorenzo Colitti 466ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo ColittiSIOCSIFHWADDR = 0x8924 476ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 486ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo ColittiIPV6_FL_A_GET = 0 496ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo ColittiIPV6_FL_A_PUT = 1 506ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo ColittiIPV6_FL_A_RENEW = 1 516ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 526ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo ColittiIPV6_FL_F_CREATE = 1 536ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo ColittiIPV6_FL_F_EXCL = 2 546ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 556ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo ColittiIPV6_FL_S_NONE = 0 566ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo ColittiIPV6_FL_S_EXCL = 1 576ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo ColittiIPV6_FL_S_ANY = 255 586ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 59da3aa4c1e092b6cddc2e3b64ddde24777fedd931Lorenzo ColittiIFNAMSIZ = 16 60da3aa4c1e092b6cddc2e3b64ddde24777fedd931Lorenzo Colitti 616ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo ColittiIPV4_PING = "\x08\x00\x00\x00\x0a\xce\x00\x03" 626ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo ColittiIPV6_PING = "\x80\x00\x00\x00\x0a\xce\x00\x03" 636ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 646ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo ColittiIPV4_ADDR = "8.8.8.8" 656ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo ColittiIPV6_ADDR = "2001:4860:4860::8888" 666ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 676ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo ColittiIPV6_SEQ_DGRAM_HEADER = (" sl " 68124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti "local_address " 69124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti "remote_address " 70124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti "st tx_queue rx_queue tr tm->when retrnsmt" 71124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti " uid timeout inode ref pointer drops\n") 726ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 738236c75d0492e37a2925fdcb2b3d3636a9c615dfLorenzo Colitti# Arbitrary packet payload. 748236c75d0492e37a2925fdcb2b3d3636a9c615dfLorenzo ColittiUDP_PAYLOAD = str(scapy.DNS(rd=1, 758236c75d0492e37a2925fdcb2b3d3636a9c615dfLorenzo Colitti id=random.randint(0, 65535), 768236c75d0492e37a2925fdcb2b3d3636a9c615dfLorenzo Colitti qd=scapy.DNSQR(qname="wWW.GoOGle.CoM", 778236c75d0492e37a2925fdcb2b3d3636a9c615dfLorenzo Colitti qtype="AAAA"))) 788236c75d0492e37a2925fdcb2b3d3636a9c615dfLorenzo Colitti 79610743878821c018ac1918b280ecfa097b77d6f0Lorenzo Colitti# Unix group to use if we want to open sockets as non-root. 80610743878821c018ac1918b280ecfa097b77d6f0Lorenzo ColittiAID_INET = 3003 8171f0b6211d9550ae267af2603a61789aa680cd28Lorenzo Colitti 826ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 83105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colittidef LinuxVersion(): 84105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti # Example: "3.4.67-00753-gb7a556f". 85105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti # Get the part before the dash. 86105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti version = os.uname()[2].split("-")[0] 87105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti # Convert it into a tuple such as (3, 4, 67). That allows comparing versions 88105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti # using < and >, since tuples are compared lexicographically. 89105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti version = tuple(int(i) for i in version.split(".")) 90105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti return version 91105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti 92105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti 93105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo ColittiLINUX_VERSION = LinuxVersion() 94105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti 95105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti 966ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colittidef SetSocketTimeout(sock, ms): 976ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti s = ms / 1000 986ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti us = (ms % 1000) * 1000 996ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti sock.setsockopt(SOL_SOCKET, SO_RCVTIMEO, struct.pack("LL", s, us)) 1006ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 101124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti 102a25ebd97dd121c7f89e59fa440b86ffc9822d012Lorenzo Colittidef SetSocketTos(s, tos): 103a25ebd97dd121c7f89e59fa440b86ffc9822d012Lorenzo Colitti level = {AF_INET: SOL_IP, AF_INET6: SOL_IPV6}[s.family] 104a25ebd97dd121c7f89e59fa440b86ffc9822d012Lorenzo Colitti option = {AF_INET: IP_TOS, AF_INET6: IPV6_TCLASS}[s.family] 105a25ebd97dd121c7f89e59fa440b86ffc9822d012Lorenzo Colitti s.setsockopt(level, option, tos) 106a25ebd97dd121c7f89e59fa440b86ffc9822d012Lorenzo Colitti 107124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti 108717357af1ea56f3474a17fb909efc0f86db31e15Lorenzo Colittidef SetNonBlocking(fd): 109717357af1ea56f3474a17fb909efc0f86db31e15Lorenzo Colitti flags = fcntl.fcntl(fd, fcntl.F_GETFL, 0) 110717357af1ea56f3474a17fb909efc0f86db31e15Lorenzo Colitti fcntl.fcntl(fd, fcntl.F_SETFL, flags | os.O_NONBLOCK) 111717357af1ea56f3474a17fb909efc0f86db31e15Lorenzo Colitti 112124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti 113717357af1ea56f3474a17fb909efc0f86db31e15Lorenzo Colitti# Convenience functions to create sockets. 1146ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colittidef Socket(family, sock_type, protocol): 1156ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti s = socket(family, sock_type, protocol) 1166ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti SetSocketTimeout(s, 1000) 1176ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti return s 1186ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 119124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti 120717357af1ea56f3474a17fb909efc0f86db31e15Lorenzo Colittidef PingSocket(family): 121717357af1ea56f3474a17fb909efc0f86db31e15Lorenzo Colitti proto = {AF_INET: IPPROTO_ICMP, AF_INET6: IPPROTO_ICMPV6}[family] 122717357af1ea56f3474a17fb909efc0f86db31e15Lorenzo Colitti return Socket(family, SOCK_DGRAM, proto) 123717357af1ea56f3474a17fb909efc0f86db31e15Lorenzo Colitti 124124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti 1256ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colittidef IPv4PingSocket(): 126717357af1ea56f3474a17fb909efc0f86db31e15Lorenzo Colitti return PingSocket(AF_INET) 1276ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 128124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti 1296ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colittidef IPv6PingSocket(): 130717357af1ea56f3474a17fb909efc0f86db31e15Lorenzo Colitti return PingSocket(AF_INET6) 131717357af1ea56f3474a17fb909efc0f86db31e15Lorenzo Colitti 132124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti 133717357af1ea56f3474a17fb909efc0f86db31e15Lorenzo Colittidef TCPSocket(family): 134717357af1ea56f3474a17fb909efc0f86db31e15Lorenzo Colitti s = Socket(family, SOCK_STREAM, IPPROTO_TCP) 135717357af1ea56f3474a17fb909efc0f86db31e15Lorenzo Colitti SetNonBlocking(s.fileno()) 136717357af1ea56f3474a17fb909efc0f86db31e15Lorenzo Colitti return s 1376ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 138124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti 1396ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colittidef IPv4TCPSocket(): 140717357af1ea56f3474a17fb909efc0f86db31e15Lorenzo Colitti return TCPSocket(AF_INET) 1416ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 142124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti 1436ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colittidef IPv6TCPSocket(): 144717357af1ea56f3474a17fb909efc0f86db31e15Lorenzo Colitti return TCPSocket(AF_INET6) 145717357af1ea56f3474a17fb909efc0f86db31e15Lorenzo Colitti 146124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti 147717357af1ea56f3474a17fb909efc0f86db31e15Lorenzo Colittidef UDPSocket(family): 148717357af1ea56f3474a17fb909efc0f86db31e15Lorenzo Colitti return Socket(family, SOCK_DGRAM, IPPROTO_UDP) 1496ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 150124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti 15171f0b6211d9550ae267af2603a61789aa680cd28Lorenzo Colittidef RawGRESocket(family): 15271f0b6211d9550ae267af2603a61789aa680cd28Lorenzo Colitti s = Socket(family, SOCK_RAW, IPPROTO_GRE) 1536ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti return s 1546ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 155124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti 156f2dffc46c435e1260185eb525f237e862525c2beLorenzo Colittidef DisableLinger(sock): 157f2dffc46c435e1260185eb525f237e862525c2beLorenzo Colitti sock.setsockopt(SOL_SOCKET, SO_LINGER, struct.pack("ii", 1, 0)) 158f2dffc46c435e1260185eb525f237e862525c2beLorenzo Colitti 159f2dffc46c435e1260185eb525f237e862525c2beLorenzo Colitti 16068e30d38f69f0a94df886a57b334e836cc48050eLorenzo Colittidef CreateSocketPair(family, socktype, addr): 16168e30d38f69f0a94df886a57b334e836cc48050eLorenzo Colitti clientsock = socket(family, socktype, 0) 16268e30d38f69f0a94df886a57b334e836cc48050eLorenzo Colitti listensock = socket(family, socktype, 0) 16368e30d38f69f0a94df886a57b334e836cc48050eLorenzo Colitti listensock.bind((addr, 0)) 16468e30d38f69f0a94df886a57b334e836cc48050eLorenzo Colitti addr = listensock.getsockname() 16568e30d38f69f0a94df886a57b334e836cc48050eLorenzo Colitti listensock.listen(1) 16668e30d38f69f0a94df886a57b334e836cc48050eLorenzo Colitti clientsock.connect(addr) 16768e30d38f69f0a94df886a57b334e836cc48050eLorenzo Colitti acceptedsock, _ = listensock.accept() 168f2dffc46c435e1260185eb525f237e862525c2beLorenzo Colitti DisableLinger(clientsock) 169f2dffc46c435e1260185eb525f237e862525c2beLorenzo Colitti DisableLinger(acceptedsock) 170f2dffc46c435e1260185eb525f237e862525c2beLorenzo Colitti listensock.close() 17168e30d38f69f0a94df886a57b334e836cc48050eLorenzo Colitti return clientsock, acceptedsock 17268e30d38f69f0a94df886a57b334e836cc48050eLorenzo Colitti 17368e30d38f69f0a94df886a57b334e836cc48050eLorenzo Colitti 1746ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colittidef GetInterfaceIndex(ifname): 1756ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti s = IPv4PingSocket() 176da3aa4c1e092b6cddc2e3b64ddde24777fedd931Lorenzo Colitti ifr = struct.pack("%dsi" % IFNAMSIZ, ifname, 0) 1776ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti ifr = fcntl.ioctl(s, scapy.SIOCGIFINDEX, ifr) 178da3aa4c1e092b6cddc2e3b64ddde24777fedd931Lorenzo Colitti return struct.unpack("%dsi" % IFNAMSIZ, ifr)[1] 1796ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 180124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti 1816ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colittidef SetInterfaceHWAddr(ifname, hwaddr): 182717357af1ea56f3474a17fb909efc0f86db31e15Lorenzo Colitti s = IPv4PingSocket() 1836ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti hwaddr = hwaddr.replace(":", "") 1846ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti hwaddr = hwaddr.decode("hex") 1856ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti if len(hwaddr) != 6: 1866ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti raise ValueError("Unknown hardware address length %d" % len(hwaddr)) 187da3aa4c1e092b6cddc2e3b64ddde24777fedd931Lorenzo Colitti ifr = struct.pack("%dsH6s" % IFNAMSIZ, ifname, scapy.ARPHDR_ETHER, hwaddr) 188124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti fcntl.ioctl(s, SIOCSIFHWADDR, ifr) 189124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti 1906ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 1916ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colittidef SetInterfaceState(ifname, up): 1926ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti s = IPv4PingSocket() 193da3aa4c1e092b6cddc2e3b64ddde24777fedd931Lorenzo Colitti ifr = struct.pack("%dsH" % IFNAMSIZ, ifname, 0) 1946ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti ifr = fcntl.ioctl(s, scapy.SIOCGIFFLAGS, ifr) 195da3aa4c1e092b6cddc2e3b64ddde24777fedd931Lorenzo Colitti _, flags = struct.unpack("%dsH" % IFNAMSIZ, ifr) 1966ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti if up: 1976ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti flags |= scapy.IFF_UP 1986ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti else: 1996ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti flags &= ~scapy.IFF_UP 200da3aa4c1e092b6cddc2e3b64ddde24777fedd931Lorenzo Colitti ifr = struct.pack("%dsH" % IFNAMSIZ, ifname, flags) 2016ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti ifr = fcntl.ioctl(s, scapy.SIOCSIFFLAGS, ifr) 2026ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 203124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti 2046ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colittidef SetInterfaceUp(ifname): 2056ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti return SetInterfaceState(ifname, True) 2066ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 207124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti 2086ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colittidef SetInterfaceDown(ifname): 2096ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti return SetInterfaceState(ifname, False) 2106ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 211124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti 2126ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colittidef FormatProcAddress(unformatted): 2136ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti groups = [] 2146ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti for i in xrange(0, len(unformatted), 4): 2156ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti groups.append(unformatted[i:i+4]) 2166ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti formatted = ":".join(groups) 2176ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti # Compress the address. 2186ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti address = inet_ntop(AF_INET6, inet_pton(AF_INET6, formatted)) 2196ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti return address 2206ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 2216ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 2226ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colittidef FormatSockStatAddress(address): 2236ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti if ":" in address: 2246ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti family = AF_INET6 2256ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti else: 2266ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti family = AF_INET 2276ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti binary = inet_pton(family, address) 2286ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti out = "" 2296ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti for i in xrange(0, len(binary), 4): 2306ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti out += "%08X" % struct.unpack("=L", binary[i:i+4]) 2316ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti return out 2326ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 2336ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 2346ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colittidef GetLinkAddress(ifname, linklocal): 2356ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti addresses = open("/proc/net/if_inet6").readlines() 2366ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti for address in addresses: 237124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti address = [s for s in address.strip().split(" ") if s] 2386ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti if address[5] == ifname: 2396ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti if (linklocal and address[0].startswith("fe80") 2406ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti or not linklocal and not address[0].startswith("fe80")): 2416ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti # Convert the address from raw hex to something with colons in it. 2426ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti return FormatProcAddress(address[0]) 2436ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti return None 2446ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 245124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti 2466ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colittidef GetDefaultRoute(version=6): 2476ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti if version == 6: 2486ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti routes = open("/proc/net/ipv6_route").readlines() 2496ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti for route in routes: 250124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti route = [s for s in route.strip().split(" ") if s] 2516ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti if (route[0] == "00000000000000000000000000000000" and route[1] == "00" 2526ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti # Routes in non-default tables end up in /proc/net/ipv6_route!!! 2536ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti and route[9] != "lo" and not route[9].startswith("nettest")): 2546ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti return FormatProcAddress(route[4]), route[9] 2556ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti raise ValueError("No IPv6 default route found") 2566ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti elif version == 4: 2576ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti routes = open("/proc/net/route").readlines() 2586ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti for route in routes: 259124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti route = [s for s in route.strip().split("\t") if s] 260124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti if route[1] == "00000000" and route[7] == "00000000": 2616ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti gw, iface = route[2], route[0] 2626ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti gw = inet_ntop(AF_INET, gw.decode("hex")[::-1]) 2636ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti return gw, iface 2646ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti raise ValueError("No IPv4 default route found") 2656ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti else: 2666ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti raise ValueError("Don't know about IPv%s" % version) 2676ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 268124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti 2696ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colittidef GetDefaultRouteInterface(): 2709c53e8a60125235f0c2263a06ba9a9d2b5419f2cLorenzo Colitti unused_gw, iface = GetDefaultRoute() 2716ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti return iface 2726ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 2736ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 2746ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colittidef MakeFlowLabelOption(addr, label): 2756ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti # struct in6_flowlabel_req { 2766ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti # struct in6_addr flr_dst; 2776ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti # __be32 flr_label; 2786ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti # __u8 flr_action; 2796ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti # __u8 flr_share; 2806ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti # __u16 flr_flags; 2816ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti # __u16 flr_expires; 2826ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti # __u16 flr_linger; 2836ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti # __u32 __flr_pad; 2846ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti # /* Options in format of IPV6_PKTOPTIONS */ 2856ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti # }; 286124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti fmt = "16sIBBHHH4s" 2876ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti assert struct.calcsize(fmt) == 32 2886ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti addr = inet_pton(AF_INET6, addr) 2896ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti assert len(addr) == 16 2906ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti label = htonl(label & 0xfffff) 2916ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti action = IPV6_FL_A_GET 2926ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti share = IPV6_FL_S_ANY 2936ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti flags = IPV6_FL_F_CREATE 294124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti pad = "\x00" * 4 2956ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti return struct.pack(fmt, addr, label, action, share, flags, 0, 0, pad) 2966ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 2976ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 298124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colittidef SetFlowLabel(s, addr, label): 299124b5aae8ca65731b363d898e2da7a543e4b0e3eLorenzo Colitti opt = MakeFlowLabelOption(addr, label) 3006ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti s.setsockopt(SOL_IPV6, IPV6_FLOWLABEL_MGR, opt) 301ac57df5a25e37f9fe2c6ec62d4d6a25f8b39c7ceLorenzo Colitti # Caller also needs to do s.setsockopt(SOL_IPV6, IPV6_FLOWINFO_SEND, 1). 3026ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 3036ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 304cbcbda6d3d8b0c208590cd769bdcf044396ee68aLorenzo Colitti# Determine network configuration. 305cbcbda6d3d8b0c208590cd769bdcf044396ee68aLorenzo Colittitry: 306cbcbda6d3d8b0c208590cd769bdcf044396ee68aLorenzo Colitti GetDefaultRoute(version=4) 307cbcbda6d3d8b0c208590cd769bdcf044396ee68aLorenzo Colitti HAVE_IPV4 = True 308cbcbda6d3d8b0c208590cd769bdcf044396ee68aLorenzo Colittiexcept ValueError: 309cbcbda6d3d8b0c208590cd769bdcf044396ee68aLorenzo Colitti HAVE_IPV4 = False 310cbcbda6d3d8b0c208590cd769bdcf044396ee68aLorenzo Colitti 3116ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colittitry: 3126ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti GetDefaultRoute(version=6) 3136ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti HAVE_IPV6 = True 3146ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colittiexcept ValueError: 3156ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti HAVE_IPV6 = False 3166ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 3176ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 318105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitticlass RunAsUid(object): 319105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti """Context guard to run a code block as a given UID.""" 320105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti 321105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti def __init__(self, uid): 322105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti self.uid = uid 323105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti 324105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti def __enter__(self): 325105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti if self.uid: 326105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti self.saved_uid = os.geteuid() 327105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti self.saved_groups = os.getgroups() 328105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti if self.uid: 329105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti os.setgroups(self.saved_groups + [AID_INET]) 330105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti os.seteuid(self.uid) 331105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti 332105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti def __exit__(self, unused_type, unused_value, unused_traceback): 333105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti if self.uid: 334105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti os.seteuid(self.saved_uid) 335105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti os.setgroups(self.saved_groups) 336105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti 337105bda9ccf001b11ca15ea48863df44ace2f5ba4Lorenzo Colitti 3386ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitticlass NetworkTest(unittest.TestCase): 3396ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 3406ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti def assertRaisesErrno(self, err_num, f, *args): 3416ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti msg = os.strerror(err_num) 3426ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti self.assertRaisesRegexp(EnvironmentError, msg, f, *args) 3436ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 344d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti def ReadProcNetSocket(self, protocol): 345d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti # Read file. 346d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti filename = "/proc/net/%s" % protocol 347d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti lines = open(filename).readlines() 348d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti 349d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti # Possibly check, and strip, header. 350d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti if protocol in ["icmp6", "raw6", "udp6"]: 351d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti self.assertEqual(IPV6_SEQ_DGRAM_HEADER, lines[0]) 352d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti lines = lines[1:] 353d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti 354d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti # Check contents. 355d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti if protocol.endswith("6"): 356d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti addrlen = 32 357d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti else: 358d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti addrlen = 8 359d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti 360d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti if protocol.startswith("tcp"): 361d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti # Real sockets have 5 extra numbers, timewait sockets have none. 362d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti end_regexp = "(| +[0-9]+ [0-9]+ [0-9]+ [0-9]+ -?[0-9]+|)$" 363d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti elif re.match("icmp|udp|raw", protocol): 364d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti # Drops. 365d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti end_regexp = " +([0-9]+) *$" 366d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti else: 367d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti raise ValueError("Don't know how to parse %s" % filename) 368d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti 369d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti regexp = re.compile(r" *(\d+): " # bucket 370d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti "([0-9A-F]{%d}:[0-9A-F]{4}) " # srcaddr, port 371d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti "([0-9A-F]{%d}:[0-9A-F]{4}) " # dstaddr, port 372d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti "([0-9A-F][0-9A-F]) " # state 373d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti "([0-9A-F]{8}:[0-9A-F]{8}) " # mem 374d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti "([0-9A-F]{2}:[0-9A-F]{8}) " # ? 375d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti "([0-9A-F]{8}) +" # ? 376d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti "([0-9]+) +" # uid 377d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti "([0-9]+) +" # timeout 378d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti "([0-9]+) +" # inode 379d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti "([0-9]+) +" # refcnt 380d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti "([0-9a-f]+)" # sp 381d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti "%s" # icmp has spaces 382d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti % (addrlen, addrlen, end_regexp)) 383d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti # Return a list of lists with only source / dest addresses for now. 384d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti # TODO: consider returning a dict or namedtuple instead. 385d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti out = [] 386d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti for line in lines: 387d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti (_, src, dst, state, mem, 388d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti _, _, uid, _, _, refcnt, _, extra) = regexp.match(line).groups() 389d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti out.append([src, dst, state, mem, uid, refcnt, extra]) 390d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti return out 391d2344168138814630764df3da6b23dc839b4890dLorenzo Colitti 3926ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti 3936ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colittiif __name__ == "__main__": 3946ef3e4fdfd823b08aca5ea2c2368e956b5e0eaeaLorenzo Colitti unittest.main() 395