forked from akkana/scripts
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathipsearch
More file actions
executable file
·138 lines (116 loc) · 3.65 KB
/
ipsearch
File metadata and controls
executable file
·138 lines (116 loc) · 3.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#! /usr/bin/env python3
# Search for IP clients on the current network.
# Only tested on Linux; requires ping or the Linux arguments for arp.
# ipsearch with no arguments uses ping; it takes a while but should be reliable.
# ipsearch -a uses arp only, which is fast but only shows
# hosts in the arp cache.
import sys
import subprocess
import socket
import fcntl
import struct
import re
try:
from arpreq import arpreq
except:
arpreq = None
try:
from mac_lookup import match_mac
except:
match_mac = None
def ping(host):
"""Ping a host by name or address.
return True if it answers, False otherwise.
"""
rv = subprocess.call(["ping", "-q", "-c", "1", "-W", "1", host],
stdout = subprocess.PIPE,
stderr = subprocess.PIPE)
if rv == 0:
return ""
return None
def arp(host):
"""Call arp -a on an address.
return True if it answers, False otherwise.
"""
# print("host", host)
proc = subprocess.Popen(["arp", "-a", host],
stdout = subprocess.PIPE,
stderr = subprocess.PIPE)
proc_out = proc.communicate()[0].strip()
# print("proc_out is '%s'" % proc_out)
if b"no match found" in proc_out:
# print("no match found, returning none")
return None
# else:
# print("'no match found' isn't in '%s'" % proc_out)
if b"<incomplete>" in proc_out:
return None
match = re.search(b'([0-9A-F]{2}[:-]){5}([0-9A-F]{2})', proc_out, re.I)
if match:
return match.group().decode("utf-8")
return None
def ip_addr(iface):
"""Get the IP address of the interface (e.g. eth0)
"""
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
info = fcntl.ioctl(s.fileno(),
0x8915, # SIOCGIFADDR
struct.pack('256s', bytes(iface[:15], "utf-8")))
return socket.inet_ntoa(info[20:24])
def scan(iface="eth0", ping_fn=ping, ping_first=True):
myip = ip_addr(iface)
print("My IP is", myip, "on", iface)
mynetwork = '.'.join(myip.split('.')[0:3])
print("My network is", mynetwork)
fmt = "%16s %18s %12s %s"
for h in range(1, 255): # I know, it should adjust based on net class
hostip = "%s.%d" % (mynetwork, h)
if ping_first:
out = ping_fn(hostip)
if arpreq:
mac = arpreq(hostip)
else:
mac = arp(hostip)
if not mac:
continue
if match_mac:
oui = match_mac(mac)
else:
oui = ''
try:
hostname, blah1, blah2 = socket.gethostbyaddr(hostip)
except:
hostname = '?'
if hostip == myip:
print(fmt % (hostip, mac, hostname, oui), "(that's me)")
else:
print(fmt % (hostip, mac, hostname, oui))
if __name__ == "__main__":
def Usage():
print("""Usage: %s [-a] [-p]
-p: ping each host first, in case they weren't in the arp cache already
-a: Use arp -a to ping.
""" % sys.argv[0])
sys.exit(1)
ifaces = [ "eth0", "wlan0" ]
myip = None
for iface in ifaces:
try:
myip = ip_addr(iface)
break
except OSError:
continue
if not myip:
print("Couldn't find my IP address")
sys.exit(1)
try:
if len(sys.argv) > 1 and sys.argv[1].startswith("-a"):
scan(iface, arp)
elif len(sys.argv) > 1 and sys.argv[1].startswith("-p"):
scan(iface, ping_first=False)
elif len(sys.argv) > 1:
Usage()
else:
scan(iface)
except KeyboardInterrupt:
print("Interrupt")