def get_ifname_and_smacaddr(saddr): err = 0 plib = pcaplib.pcaplib() if plib.lib == None: print "Error: failed to load libpcap" return "", 0, -1 devs, err = plib.Pcap_findalldevs() if err: return "", 0, err ostype = os.uname()[0] ifname = "" smacaddr = 0 found = 0 for dev in devs: if len(dev) < 2: continue for addr in dev[1:len(dev)]: if addr[0] == socket.AF_INET and addr[1] == saddr: ifname = dev[0] for tmp in dev[1:len(dev)]: if ((ostype == 'FreeBSD' or ostype == 'Darwin') and \ tmp[0] == 18) or \ ostype == 'Linux' and tmp[0] == 17: smacaddr = tmp[1] break return ifname, smacaddr, 0 return ifname, smacaddr, -1
def pcap_send_segments(ifname, pkts, smacaddr=0, dmacaddr=0, sent=None): # Open pcap descripter plib = pcaplib.pcaplib() if plib.lib == None: print "Error: failed to load libpcap" return -1 descrip = plib.Pcap_open_live(ifname) if descrip == None: print "Error: failed to open pcap descripter" return -1 # Compose packets including datalink header frms = [] dltype = plib.Pcap_datalink(descrip) for pkt in pkts: frm = "" if dltype == pcaplib.DLT_EN10MB: etherh = tcplib.etherhdr(dmacaddr, smacaddr, 0x0800) frm = etherh.bin() elif dltype == pcaplib.DLT_PPP or (dltype == 0 and re.match('ng[0-9]', ifname)): frm = struct.pack('!BBBB', 0xff, 0x03, 0x00, 0x21) else: print "Error: unsupported link type" return -1 frm += pkt frms.append(frm) # Send frames for frm in frms: err = plib.Pcap_inject(descrip, frm, len(frm)) if err < 0: plib.Pcap_close(descrip) print "Error: pcap_inject failed" return -1 if sent != None: sent.set() plib.Pcap_close(descrip) return 0
def pcap_sendrecv_segments(ifname, pkts, timeout=1.0, sflags=0, \ smacaddr=0, dmacaddr=0): rcvfrms = [] rcvpkts = [] err = 0 # Open pcap descripter plib = pcaplib.pcaplib() if plib.lib == None: print "Error: failed to load libpcap" return rcvpkts, -1 to_ms = int(1.0*1000) descrip = plib.Pcap_open_live(ifname, to_ms=to_ms) if descrip == None: print "Error: failed to open pcap descripter" return rcvpkts, -1 dltype = plib.Pcap_datalink(descrip) # Set bpf filter iph, tcph, tcpo, payload = parse_headers(pkts[0]) filter ='(src host %s and src port %d and dst port %d and udp and ip[8] = 1) or '%\ (socket.inet_ntop(socket.AF_INET, struct.pack('!L', iph.srcaddr)), \ tcph.srcport, PCAP_BREAK_DPORT) filter += '(ip[8] > 1 and src host %s and src port %d and dst host %s and dst port %d and tcp'%\ (socket.inet_ntop(socket.AF_INET, \ struct.pack('!L', iph.dstaddr)), tcph.dstport, socket.inet_ntop(socket.AF_INET, \ struct.pack('!L', iph.srcaddr)), tcph.srcport) if (sflags & tcplib.TH_SYN) is True: filter += ' and tcp[tcpflags] & (tcp-syn|tcp-ack) != 0' filter += ')' err = plib.Pcap_compile(descrip, filter) if err != 0: plib.Pcap_close(descrip) print "Error: failed to set pcap filter" return rcvpkts, -1 sent = threading.Event() th = threading.Thread(target=pcap_send_segments, args=(ifname, tuple(pkts), smacaddr, dmacaddr, sent)) th.setDaemon(True) # In some platforms (e.g., old Linux), timeout at open_live doesn't work # We define the killer packet to force finish pcap reading packets stopped = threading.Event() stopper = threading.Timer(timeout , send_pcapbreak, args=(pkts[0], stopped)) stopper.start() th.start() while True: err, rcvfrm = plib.Pcap_next_ex(descrip) if err > 0: # Quick check of TTL and Protocol in IP header if dltype == pcaplib.DLT_EN10MB: if struct.unpack('!BB', rcvfrm[22:24]) == (1, 17): err = -2 break elif dltype == pcaplib.DLT_PPP: if struct.unpack('!BB', rcvfrm[12:14]) == (1, 17): err = -2 break rcvfrms.append(rcvfrm) if sflags & tcplib.TH_SYN: break continue elif err == 0: continue elif err == -2: break elif err == -1: print "Error: failed in pcap_next_ex" break if sent.isSet() == False: print "Error: timeout in pcap_send_segments" err = -1 stopper.cancel() stopped.set() th.join() plib.Pcap_close(descrip) if err == -1: return rcvpkts, -1 for rcvfrm in rcvfrms: if dltype == pcaplib.DLT_EN10MB: etherhdr, pkt = parse_ether_header(rcvfrm) elif dltype == pcaplib.DLT_PPP: pkt = rcvfrm[4:] iph, tcph, tcpo, payload = parse_headers(pkt) rcvpkts.append((iph, tcph, tcpo, payload)) return rcvpkts, 0
def peep_os_synack(): global Peeped_synacks Peeper_lock.acquire() for i in range(0, 10): Peeped_synacks.append((0,0,0)) Peeper_lock.release() os.putenv('LANG', 'C') os.putenv('PATH', '/bin:/sbin:/usr/bin:/usr/sbin:$PATH') cmd = 'netstat -rn | grep ^0.0.0.0 | sed s/\' \{2,\}\'/\' \'/g | cut -d\' \' -f2,8' s = commands.getoutput(cmd) (nxthop_str, dummy, ifname) = s.partition(' ') try: fqdn = socket.getfqdn() except socket.gaierror: sys.exit(1) try: saddr_str = socket.gethostbyname(fqdn) except socket.gaierror: sys.exit(1) plib = pcaplib.pcaplib() if plib.lib == None: return descrip = plib.Pcap_open_live(ifname, to_ms=4000) if descrip == None: return filter = '(ip[8] = 1 and src host %s and src port %d and tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack != 0) or (ip[8] = 1 and src host %s and dst port %d and udp)'%(saddr_str, MPTCP_PORT, saddr_str, PEEP_BREAK_DPORT) err = plib.Pcap_compile(descrip, filter) if err != 0: plib.Pcap_close(descrip) return while True: err, rcvfrm = plib.Pcap_next_ex(descrip) if err > 0: ttl, proto = struct.unpack('!BB', rcvfrm[22:24]) # handling breaking packet (1-TTL UDP packet to BREAK_DPORT) if ttl == 1 and proto == 17: err = -2 break # handling reset for managing accepted list # quick filtering of SYNACK from OS by TTL elif ttl != 1 or proto != 6: continue Peeper_lock.acquire() Peeped_synacks.pop(0) Peeped_synacks.append((struct.unpack('!L', rcvfrm[30:34])[0], \ struct.unpack('!H', rcvfrm[36:38])[0], \ struct.unpack('!L', rcvfrm[38:42])[0])) Peeper_lock.release() continue elif err == 0: continue elif err == -2 or err == -1: # print 'Error: pcap_next_ex returned %d'%err break plib.Pcap_close(descrip) return