1## This file is part of Scapy 2## See http://www.secdev.org/projects/scapy for more informations 3## Copyright (C) Philippe Biondi <phil@secdev.org> 4## This program is published under a GPLv2 license 5 6""" 7Linux specific functions. 8""" 9 10from __future__ import absolute_import 11 12 13import array 14import ctypes 15from fcntl import ioctl 16import os 17from select import select 18import socket 19import struct 20import sys 21import time 22 23 24from scapy.compat import * 25from scapy.consts import LOOPBACK_NAME, IS_64BITS 26import scapy.utils 27import scapy.utils6 28from scapy.packet import Packet, Padding 29from scapy.config import conf 30from scapy.data import * 31from scapy.supersocket import SuperSocket 32import scapy.arch 33from scapy.error import warning, Scapy_Exception, log_interactive, log_loading 34from scapy.arch.common import get_if, get_bpf_pointer 35from scapy.modules.six.moves import range 36 37 38 39# From bits/ioctls.h 40SIOCGIFHWADDR = 0x8927 # Get hardware address 41SIOCGIFADDR = 0x8915 # get PA address 42SIOCGIFNETMASK = 0x891b # get network PA mask 43SIOCGIFNAME = 0x8910 # get iface name 44SIOCSIFLINK = 0x8911 # set iface channel 45SIOCGIFCONF = 0x8912 # get iface list 46SIOCGIFFLAGS = 0x8913 # get flags 47SIOCSIFFLAGS = 0x8914 # set flags 48SIOCGIFINDEX = 0x8933 # name -> if_index mapping 49SIOCGIFCOUNT = 0x8938 # get number of devices 50SIOCGSTAMP = 0x8906 # get packet timestamp (as a timeval) 51 52# From if.h 53IFF_UP = 0x1 # Interface is up. 54IFF_BROADCAST = 0x2 # Broadcast address valid. 55IFF_DEBUG = 0x4 # Turn on debugging. 56IFF_LOOPBACK = 0x8 # Is a loopback net. 57IFF_POINTOPOINT = 0x10 # Interface is point-to-point link. 58IFF_NOTRAILERS = 0x20 # Avoid use of trailers. 59IFF_RUNNING = 0x40 # Resources allocated. 60IFF_NOARP = 0x80 # No address resolution protocol. 61IFF_PROMISC = 0x100 # Receive all packets. 62 63# From netpacket/packet.h 64PACKET_ADD_MEMBERSHIP = 1 65PACKET_DROP_MEMBERSHIP = 2 66PACKET_RECV_OUTPUT = 3 67PACKET_RX_RING = 5 68PACKET_STATISTICS = 6 69PACKET_MR_MULTICAST = 0 70PACKET_MR_PROMISC = 1 71PACKET_MR_ALLMULTI = 2 72 73# From bits/socket.h 74SOL_PACKET = 263 75# From asm/socket.h 76SO_ATTACH_FILTER = 26 77 78# From net/route.h 79RTF_UP = 0x0001 # Route usable 80RTF_REJECT = 0x0200 81 82# From if_packet.h 83PACKET_HOST = 0 # To us 84PACKET_BROADCAST = 1 # To all 85PACKET_MULTICAST = 2 # To group 86PACKET_OTHERHOST = 3 # To someone else 87PACKET_OUTGOING = 4 # Outgoing of any type 88PACKET_LOOPBACK = 5 # MC/BRD frame looped back 89PACKET_USER = 6 # To user space 90PACKET_KERNEL = 7 # To kernel space 91PACKET_FASTROUTE = 6 # Fastrouted frame 92# Unused, PACKET_FASTROUTE and PACKET_LOOPBACK are invisible to user space 93 94 95with os.popen("%s -V 2> /dev/null" % conf.prog.tcpdump) as _f: 96 if _f.close() >> 8 == 0x7f: 97 log_loading.warning("Failed to execute tcpdump. Check it is installed and in the PATH") 98 TCPDUMP=0 99 else: 100 TCPDUMP=1 101del(_f) 102 103 104def get_if_raw_hwaddr(iff): 105 return struct.unpack("16xh6s8x",get_if(iff,SIOCGIFHWADDR)) 106 107def get_if_raw_addr(iff): 108 try: 109 return get_if(iff, SIOCGIFADDR)[20:24] 110 except IOError: 111 return b"\0\0\0\0" 112 113 114def get_if_list(): 115 try: 116 f=open("/proc/net/dev", "rb") 117 except IOError: 118 warning("Can't open /proc/net/dev !") 119 return [] 120 lst = [] 121 f.readline() 122 f.readline() 123 for l in f: 124 l = plain_str(l) 125 lst.append(l.split(":")[0].strip()) 126 return lst 127def get_working_if(): 128 for i in get_if_list(): 129 if i == LOOPBACK_NAME: 130 continue 131 ifflags = struct.unpack("16xH14x",get_if(i,SIOCGIFFLAGS))[0] 132 if ifflags & IFF_UP: 133 return i 134 return LOOPBACK_NAME 135 136def attach_filter(s, bpf_filter, iface): 137 # XXX We generate the filter on the interface conf.iface 138 # because tcpdump open the "any" interface and ppp interfaces 139 # in cooked mode. As we use them in raw mode, the filter will not 140 # work... one solution could be to use "any" interface and translate 141 # the filter from cooked mode to raw mode 142 # mode 143 if not TCPDUMP: 144 return 145 try: 146 f = os.popen("%s -i %s -ddd -s %d '%s'" % ( 147 conf.prog.tcpdump, 148 conf.iface if iface is None else iface, 149 MTU, 150 bpf_filter, 151 )) 152 except OSError: 153 log_interactive.warning("Failed to attach filter.", 154 exc_info=True) 155 return 156 lines = f.readlines() 157 ret = f.close() 158 if ret: 159 log_interactive.warning( 160 "Failed to attach filter: tcpdump returned %d", ret 161 ) 162 return 163 164 bp = get_bpf_pointer(lines) 165 s.setsockopt(socket.SOL_SOCKET, SO_ATTACH_FILTER, bp) 166 167def set_promisc(s,iff,val=1): 168 mreq = struct.pack("IHH8s", get_if_index(iff), PACKET_MR_PROMISC, 0, b"") 169 if val: 170 cmd = PACKET_ADD_MEMBERSHIP 171 else: 172 cmd = PACKET_DROP_MEMBERSHIP 173 s.setsockopt(SOL_PACKET, cmd, mreq) 174 175 176def get_alias_address(iface_name, ip_mask, gw_str, metric): 177 """ 178 Get the correct source IP address of an interface alias 179 """ 180 181 # Detect the architecture 182 if scapy.consts.IS_64BITS: 183 offset, name_len = 16, 40 184 else: 185 offset, name_len = 32, 32 186 187 # Retrieve interfaces structures 188 sck = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 189 names = array.array('B', b'\0' * 4096) 190 ifreq = ioctl(sck.fileno(), SIOCGIFCONF, 191 struct.pack("iL", len(names), names.buffer_info()[0])) 192 193 # Extract interfaces names 194 out = struct.unpack("iL", ifreq)[0] 195 names = names.tostring() 196 names = [names[i:i+offset].split(b'\0', 1)[0] for i in range(0, out, name_len)] 197 198 # Look for the IP address 199 for ifname in names: 200 # Only look for a matching interface name 201 if not ifname.decode("utf8").startswith(iface_name): 202 continue 203 204 # Retrieve and convert addresses 205 ifreq = ioctl(sck, SIOCGIFADDR, struct.pack("16s16x", ifname)) 206 ifaddr = struct.unpack(">I", ifreq[20:24])[0] 207 ifreq = ioctl(sck, SIOCGIFNETMASK, struct.pack("16s16x", ifname)) 208 msk = struct.unpack(">I", ifreq[20:24])[0] 209 210 # Get the full interface name 211 ifname = plain_str(ifname) 212 if ':' in ifname: 213 ifname = ifname[:ifname.index(':')] 214 else: 215 continue 216 217 # Check if the source address is included in the network 218 if (ifaddr & msk) == ip_mask: 219 sck.close() 220 return (ifaddr & msk, msk, gw_str, ifname, 221 scapy.utils.ltoa(ifaddr), metric) 222 223 sck.close() 224 return 225 226 227def read_routes(): 228 try: 229 f=open("/proc/net/route", "rb") 230 except IOError: 231 warning("Can't open /proc/net/route !") 232 return [] 233 routes = [] 234 s=socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 235 ifreq = ioctl(s, SIOCGIFADDR,struct.pack("16s16x", LOOPBACK_NAME.encode("utf8"))) 236 addrfamily = struct.unpack("h",ifreq[16:18])[0] 237 if addrfamily == socket.AF_INET: 238 ifreq2 = ioctl(s, SIOCGIFNETMASK,struct.pack("16s16x", LOOPBACK_NAME.encode("utf8"))) 239 msk = socket.ntohl(struct.unpack("I",ifreq2[20:24])[0]) 240 dst = socket.ntohl(struct.unpack("I",ifreq[20:24])[0]) & msk 241 ifaddr = scapy.utils.inet_ntoa(ifreq[20:24]) 242 routes.append((dst, msk, "0.0.0.0", LOOPBACK_NAME, ifaddr, 1)) 243 else: 244 warning("Interface lo: unkown address family (%i)"% addrfamily) 245 246 for l in f.readlines()[1:]: 247 l = plain_str(l) 248 iff,dst,gw,flags,x,x,metric,msk,x,x,x = l.split() 249 flags = int(flags,16) 250 if flags & RTF_UP == 0: 251 continue 252 if flags & RTF_REJECT: 253 continue 254 try: 255 ifreq = ioctl(s, SIOCGIFADDR,struct.pack("16s16x", iff.encode("utf8"))) 256 except IOError: # interface is present in routing tables but does not have any assigned IP 257 ifaddr="0.0.0.0" 258 else: 259 addrfamily = struct.unpack("h",ifreq[16:18])[0] 260 if addrfamily == socket.AF_INET: 261 ifaddr = scapy.utils.inet_ntoa(ifreq[20:24]) 262 else: 263 warning("Interface %s: unkown address family (%i)", iff, addrfamily) 264 continue 265 266 # Attempt to detect an interface alias based on addresses inconsistencies 267 dst_int = socket.htonl(int(dst, 16)) & 0xffffffff 268 msk_int = socket.htonl(int(msk, 16)) & 0xffffffff 269 ifaddr_int = struct.unpack("!I", ifreq[20:24])[0] 270 gw_str = scapy.utils.inet_ntoa(struct.pack("I", int(gw, 16))) 271 metric = int(metric) 272 273 if ifaddr_int & msk_int != dst_int: 274 tmp_route = get_alias_address(iff, dst_int, gw_str, metric) 275 if tmp_route: 276 routes.append(tmp_route) 277 else: 278 routes.append((dst_int, msk_int, gw_str, iff, ifaddr, metric)) 279 280 else: 281 routes.append((dst_int, msk_int, gw_str, iff, ifaddr, metric)) 282 283 f.close() 284 return routes 285 286############ 287### IPv6 ### 288############ 289 290def in6_getifaddr(): 291 """ 292 Returns a list of 3-tuples of the form (addr, scope, iface) where 293 'addr' is the address of scope 'scope' associated to the interface 294 'ifcace'. 295 296 This is the list of all addresses of all interfaces available on 297 the system. 298 """ 299 ret = [] 300 try: 301 fdesc = open("/proc/net/if_inet6", "rb") 302 except IOError as err: 303 return ret 304 for line in fdesc: 305 # addr, index, plen, scope, flags, ifname 306 tmp = plain_str(line).split() 307 addr = scapy.utils6.in6_ptop( 308 b':'.join( 309 struct.unpack('4s4s4s4s4s4s4s4s', tmp[0].encode()) 310 ).decode() 311 ) 312 # (addr, scope, iface) 313 ret.append((addr, int(tmp[3], 16), tmp[5])) 314 return ret 315 316def read_routes6(): 317 try: 318 f = open("/proc/net/ipv6_route","rb") 319 except IOError as err: 320 return [] 321 # 1. destination network 322 # 2. destination prefix length 323 # 3. source network displayed 324 # 4. source prefix length 325 # 5. next hop 326 # 6. metric 327 # 7. reference counter (?!?) 328 # 8. use counter (?!?) 329 # 9. flags 330 # 10. device name 331 routes = [] 332 def proc2r(p): 333 ret = struct.unpack('4s4s4s4s4s4s4s4s', raw(p)) 334 ret = b':'.join(ret).decode() 335 return scapy.utils6.in6_ptop(ret) 336 337 lifaddr = in6_getifaddr() 338 for l in f.readlines(): 339 l = plain_str(l) 340 d,dp,s,sp,nh,metric,rc,us,fl,dev = l.split() 341 metric = int(metric, 16) 342 fl = int(fl, 16) 343 344 if fl & RTF_UP == 0: 345 continue 346 if fl & RTF_REJECT: 347 continue 348 349 d = proc2r(d) ; dp = int(dp, 16) 350 s = proc2r(s) ; sp = int(sp, 16) 351 nh = proc2r(nh) 352 353 cset = [] # candidate set (possible source addresses) 354 if dev == LOOPBACK_NAME: 355 if d == '::': 356 continue 357 cset = ['::1'] 358 else: 359 devaddrs = (x for x in lifaddr if x[2] == dev) 360 cset = scapy.utils6.construct_source_candidate_set(d, dp, devaddrs) 361 362 if len(cset) != 0: 363 routes.append((d, dp, nh, dev, cset, metric)) 364 f.close() 365 return routes 366 367 368def get_if_index(iff): 369 return int(struct.unpack("I",get_if(iff, SIOCGIFINDEX)[16:20])[0]) 370 371if os.uname()[4] in [ 'x86_64', 'aarch64' ]: 372 def get_last_packet_timestamp(sock): 373 ts = ioctl(sock, SIOCGSTAMP, "1234567890123456") 374 s,us = struct.unpack("QQ",ts) 375 return s+us/1000000.0 376else: 377 def get_last_packet_timestamp(sock): 378 ts = ioctl(sock, SIOCGSTAMP, "12345678") 379 s,us = struct.unpack("II",ts) 380 return s+us/1000000.0 381 382 383def _flush_fd(fd): 384 if hasattr(fd, 'fileno'): 385 fd = fd.fileno() 386 while True: 387 r,w,e = select([fd],[],[],0) 388 if r: 389 os.read(fd,MTU) 390 else: 391 break 392 393 394 395 396 397class L3PacketSocket(SuperSocket): 398 desc = "read/write packets at layer 3 using Linux PF_PACKET sockets" 399 def __init__(self, type = ETH_P_ALL, filter=None, promisc=None, iface=None, nofilter=0): 400 self.type = type 401 self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type)) 402 self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 0) 403 if iface: 404 self.ins.bind((iface, type)) 405 if not nofilter: 406 if conf.except_filter: 407 if filter: 408 filter = "(%s) and not (%s)" % (filter, conf.except_filter) 409 else: 410 filter = "not (%s)" % conf.except_filter 411 if filter is not None: 412 attach_filter(self.ins, filter, iface) 413 _flush_fd(self.ins) 414 self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2**30) 415 self.outs = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type)) 416 self.outs.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 2**30) 417 self.promisc = conf.promisc if promisc is None else promisc 418 if self.promisc: 419 if iface is None: 420 self.iff = get_if_list() 421 elif isinstance(iface, list): 422 self.iff = iface 423 else: 424 self.iff = [iface] 425 for i in self.iff: 426 set_promisc(self.ins, i) 427 def close(self): 428 if self.closed: 429 return 430 self.closed = 1 431 if self.promisc: 432 for i in self.iff: 433 set_promisc(self.ins, i, 0) 434 SuperSocket.close(self) 435 def recv(self, x=MTU): 436 pkt, sa_ll = self.ins.recvfrom(x) 437 if sa_ll[2] == socket.PACKET_OUTGOING: 438 return None 439 if sa_ll[3] in conf.l2types: 440 cls = conf.l2types[sa_ll[3]] 441 lvl = 2 442 elif sa_ll[1] in conf.l3types: 443 cls = conf.l3types[sa_ll[1]] 444 lvl = 3 445 else: 446 cls = conf.default_l2 447 warning("Unable to guess type (interface=%s protocol=%#x family=%i). Using %s", sa_ll[0], sa_ll[1], sa_ll[3], cls.name) 448 lvl = 2 449 450 try: 451 pkt = cls(pkt) 452 except KeyboardInterrupt: 453 raise 454 except: 455 if conf.debug_dissector: 456 raise 457 pkt = conf.raw_layer(pkt) 458 if lvl == 2: 459 pkt = pkt.payload 460 461 if pkt is not None: 462 pkt.time = get_last_packet_timestamp(self.ins) 463 return pkt 464 465 def send(self, x): 466 iff,a,gw = x.route() 467 if iff is None: 468 iff = conf.iface 469 sdto = (iff, self.type) 470 self.outs.bind(sdto) 471 sn = self.outs.getsockname() 472 ll = lambda x:x 473 if type(x) in conf.l3types: 474 sdto = (iff, conf.l3types[type(x)]) 475 if sn[3] in conf.l2types: 476 ll = lambda x:conf.l2types[sn[3]]()/x 477 sx = raw(ll(x)) 478 x.sent_time = time.time() 479 try: 480 self.outs.sendto(sx, sdto) 481 except socket.error as msg: 482 if msg[0] == 22 and len(sx) < conf.min_pkt_size: 483 self.outs.send(sx + b"\x00" * (conf.min_pkt_size - len(sx))) 484 elif conf.auto_fragment and msg[0] == 90: 485 for p in x.fragment(): 486 self.outs.sendto(raw(ll(p)), sdto) 487 else: 488 raise 489 490 491 492class L2Socket(SuperSocket): 493 desc = "read/write packets at layer 2 using Linux PF_PACKET sockets" 494 def __init__(self, iface=None, type=ETH_P_ALL, promisc=None, filter=None, nofilter=0): 495 self.iface = conf.iface if iface is None else iface 496 self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type)) 497 self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 0) 498 if not nofilter: 499 if conf.except_filter: 500 if filter: 501 filter = "(%s) and not (%s)" % (filter, conf.except_filter) 502 else: 503 filter = "not (%s)" % conf.except_filter 504 if filter is not None: 505 attach_filter(self.ins, filter, iface) 506 self.promisc = conf.sniff_promisc if promisc is None else promisc 507 if self.promisc: 508 set_promisc(self.ins, self.iface) 509 self.ins.bind((self.iface, type)) 510 _flush_fd(self.ins) 511 self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2**30) 512 self.outs = self.ins 513 self.outs.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 2**30) 514 sa_ll = self.outs.getsockname() 515 if sa_ll[3] in conf.l2types: 516 self.LL = conf.l2types[sa_ll[3]] 517 elif sa_ll[1] in conf.l3types: 518 self.LL = conf.l3types[sa_ll[1]] 519 else: 520 self.LL = conf.default_l2 521 warning("Unable to guess type (interface=%s protocol=%#x family=%i). Using %s", sa_ll[0], sa_ll[1], sa_ll[3], self.LL.name) 522 def close(self): 523 if self.closed: 524 return 525 self.closed = 1 526 if self.promisc: 527 set_promisc(self.ins, self.iface, 0) 528 SuperSocket.close(self) 529 def recv(self, x=MTU): 530 pkt, sa_ll = self.ins.recvfrom(x) 531 if sa_ll[2] == socket.PACKET_OUTGOING: 532 return None 533 try: 534 q = self.LL(pkt) 535 except KeyboardInterrupt: 536 raise 537 except: 538 if conf.debug_dissector: 539 raise 540 q = conf.raw_layer(pkt) 541 q.time = get_last_packet_timestamp(self.ins) 542 return q 543 def send(self, x): 544 try: 545 return SuperSocket.send(self, x) 546 except socket.error as msg: 547 if msg[0] == 22 and len(x) < conf.min_pkt_size: 548 padding = b"\x00" * (conf.min_pkt_size - len(x)) 549 if isinstance(x, Packet): 550 return SuperSocket.send(self, x / Padding(load=padding)) 551 else: 552 return SuperSocket.send(self, raw(x) + padding) 553 raise 554 555 556class L2ListenSocket(SuperSocket): 557 desc = "read packets at layer 2 using Linux PF_PACKET sockets" 558 def __init__(self, iface = None, type = ETH_P_ALL, promisc=None, filter=None, nofilter=0): 559 self.type = type 560 self.outs = None 561 self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type)) 562 self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 0) 563 if iface is not None: 564 self.ins.bind((iface, type)) 565 if not nofilter: 566 if conf.except_filter: 567 if filter: 568 filter = "(%s) and not (%s)" % (filter, conf.except_filter) 569 else: 570 filter = "not (%s)" % conf.except_filter 571 if filter is not None: 572 attach_filter(self.ins, filter, iface) 573 if promisc is None: 574 promisc = conf.sniff_promisc 575 self.promisc = promisc 576 if iface is None: 577 self.iff = get_if_list() 578 elif isinstance(iface, list): 579 self.iff = iface 580 else: 581 self.iff = [iface] 582 if self.promisc: 583 for i in self.iff: 584 set_promisc(self.ins, i) 585 _flush_fd(self.ins) 586 self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2**30) 587 def close(self): 588 if self.promisc: 589 for i in self.iff: 590 set_promisc(self.ins, i, 0) 591 SuperSocket.close(self) 592 593 def recv(self, x=MTU): 594 pkt, sa_ll = self.ins.recvfrom(x) 595 if sa_ll[3] in conf.l2types : 596 cls = conf.l2types[sa_ll[3]] 597 elif sa_ll[1] in conf.l3types: 598 cls = conf.l3types[sa_ll[1]] 599 else: 600 cls = conf.default_l2 601 warning("Unable to guess type (interface=%s protocol=%#x " 602 "family=%i). Using %s", sa_ll[0], sa_ll[1], sa_ll[3], 603 cls.name) 604 605 try: 606 pkt = cls(pkt) 607 except KeyboardInterrupt: 608 raise 609 except: 610 if conf.debug_dissector: 611 raise 612 pkt = conf.raw_layer(pkt) 613 pkt.time = get_last_packet_timestamp(self.ins) 614 pkt.direction = sa_ll[2] 615 return pkt 616 617 def send(self, x): 618 raise Scapy_Exception("Can't send anything with L2ListenSocket") 619 620 621conf.L3socket = L3PacketSocket 622conf.L2socket = L2Socket 623conf.L2listen = L2ListenSocket 624