Commit fd7ca450 authored by Dimitris Aragiorgis's avatar Dimitris Aragiorgis

One socket per client and few logging fixes

Signed-off-by: default avatarDimitris Aragiorgis <dimara@grnet.gr>
parent 3f442273
......@@ -251,12 +251,47 @@ class Client(object):
self.gateway6 = gateway6
self.net6 = Subnet(net=subnet6, gw=gateway6, dev=tap)
self.eui64 = eui64
self.open_socket()
def is_valid(self):
return self.mac is not None and self.ip is not None\
and self.hostname is not None
def open_socket(self):
logging.info(" - Opening L2 socket and binding to %s", self.tap)
try:
s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, ETH_P_ALL)
s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 0)
s.bind((self.tap, ETH_P_ALL))
self.socket = s
except socket.error, e:
logging.warning(" - Cannot open socket %s", e)
def sendp(self, data):
if isinstance(data, BasePacket):
data = str(data)
logging.debug(" - Sending raw packet %r", data)
try:
count = self.socket.send(data, socket.MSG_DONTWAIT)
except socket.error, e:
logging.warn(" - Send with MSG_DONTWAIT failed: %s", str(e))
self.socket.close()
self.open_socket()
raise e
ldata = len(data)
logging.debug(" - Sent %d bytes on %s", count, self.tap)
if count != ldata:
logging.warn(" - Truncated msg: %d/%d bytes sent",
count, ldata)
class Subnet(object):
def __init__(self, net=None, gw=None, dev=None):
if isinstance(net, str):
......@@ -364,7 +399,6 @@ class VMNetProxy(object): # pylint: disable=R0902
#self.ifaces = {}
#self.v6nets = {}
self.nfq = {}
self.l2socket = self._socket()
# Inotify setup
self.wm = pyinotify.WatchManager()
......@@ -376,7 +410,7 @@ class VMNetProxy(object): # pylint: disable=R0902
# NFQUEUE setup
if dhcp_queue_num is not None:
self._setup_nfqueue(dhcp_queue_num, AF_INET, self.dhcp_response, 5000)
self._setup_nfqueue(dhcp_queue_num, AF_INET, self.dhcp_response, 0)
if rs_queue_num is not None:
self._setup_nfqueue(rs_queue_num, AF_INET6, self.rs_response, 10)
......@@ -386,14 +420,6 @@ class VMNetProxy(object): # pylint: disable=R0902
self._setup_nfqueue(ns_queue_num, AF_INET6, self.ns_response, 10)
self.ipv6_enabled = True
def _socket(self):
logging.info("Opening L2 socket")
try:
s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, ETH_P_ALL)
s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 0)
except socket.error, e:
logging.warning(" - Cannot open socket %s", e)
return s
def _cleanup(self):
""" Free all resources for a graceful exit
......@@ -402,12 +428,9 @@ class VMNetProxy(object): # pylint: disable=R0902
logging.info("Cleaning up")
logging.debug(" - Closing netfilter queues")
for q in self.nfq.values():
for q, num in self.nfq.values():
q.close()
logging.debug(" - Closing socket")
self.l2socket.close()
logging.debug(" - Stopping inotify watches")
self.notifier.stop()
......@@ -425,29 +448,14 @@ class VMNetProxy(object): # pylint: disable=R0902
self.nfq[q.get_fd()] = (q, pending)
logging.debug(" - Successfully set up NFQUEUE %d", queue_num)
def sendp(self, data, dev):
def sendp(self, data, binding):
""" Send a raw packet using a layer-2 socket
"""
if isinstance(data, BasePacket):
data = str(data)
logging.info(" - Sending raw packet on %s (%s)",
binding.tap, binding.hostname)
binding.sendp(data)
logging.debug(" - Sending raw packet %r", data)
self.l2socket.bind((dev, ETH_P_ALL))
try:
count = self.l2socket.send(data, socket.MSG_DONTWAIT)
except socket.error, e:
logging.warn(" - Send with MSG_DONTWAIT failed: %s", str(e))
self.l2socket.close()
self.l2socket = self._socket()
raise e
ldata = len(data)
logging.debug(" - Sent %d bytes to device %s", count, dev)
if count != ldata:
logging.warn(" - Truncated send on %s (%d/%d bytes sent)",
dev, count, ldata)
def build_config(self):
self.clients.clear()
......@@ -526,7 +534,7 @@ class VMNetProxy(object): # pylint: disable=R0902
"""
tap = os.path.basename(path)
logging.debug("Updating configuration for %s", tap)
logging.info("Updating configuration for %s", tap)
b = parse_binding_file(path)
if b is None:
return
......@@ -551,18 +559,21 @@ class VMNetProxy(object): # pylint: disable=R0902
try:
for k, cl in self.clients.items():
if cl.tap == tap:
logging.debug("Removing client on interface %s", tap)
logging.debug("%10s | %10s %20s %10s %20s",
logging.info("Removing client %s and closing socket on %s",
cl.hostname, cl.tap)
logging.debug(" - %10s | %10s %20s %10s %20s",
k, cl.hostname, cl.mac, cl.tap, cl.ip)
cl.socket.close()
del self.clients[k]
except:
logging.debug("Client on %s disappeared!!!", tap)
def dhcp_response(self, dummy, payload): # pylint: disable=W0613,R0914
""" Generate a reply to bnetfilter-queue-deva BOOTP/DHCP request
"""
logging.debug(" * Processing pending DHCP request")
logging.info(" * Processing pending DHCP request")
# Decode the response - NFQUEUE relays IP packets
pkt = IP(payload.get_data())
#logging.debug(pkt.show())
......@@ -596,7 +607,7 @@ class VMNetProxy(object): # pylint: disable=R0902
logging.warn(" - Recieved spoofed DHCP request for mac %s from tap %s", mac, indev)
return
logging.debug(" - Generating DHCP response for host %s (mac %s) on tap %s",
logging.info(" - Generating DHCP response for host %s (mac %s) on tap %s",
binding.hostname, mac, binding.tap)
......@@ -671,18 +682,19 @@ class VMNetProxy(object): # pylint: disable=R0902
logging.info(" - %s to %s (%s) on %s", DHCP_TYPES[resp_type], mac,
binding.ip, binding.tap)
try:
self.sendp(resp, binding.indev)
self.sendp(resp, binding)
except socket.error, e:
logging.warn(" - DHCP response on %s failed: %s", binding.indev, str(e))
logging.warn(" - DHCP response on %s (%s) failed: %s",
binding.tap, binding.hostname, str(e))
except Exception, e:
logging.warn(" - Unkown error during DHCP response on %s: %s",
binding.indev, str(e))
logging.warn(" - Unkown error during DHCP response on %s (%s): %s",
binding.tap, binding.hostname, str(e))
def rs_response(self, dummy, payload): # pylint: disable=W0613
""" Generate a reply to a BOOTP/DHCP request
"""
logging.debug(" * Processing pending RS request")
logging.info(" * Processing pending RS request")
pkt = IPv6(payload.get_data())
#logging.debug(pkt.show())
try:
......@@ -722,7 +734,7 @@ class VMNetProxy(object): # pylint: disable=R0902
if ifll is None:
return
logging.debug(" - Generating RA for host %s (mac %s) on tap %s",
logging.info(" - Generating RA for host %s (mac %s) on tap %s",
binding.hostname, mac, binding.tap)
resp = Ether(src=indevmac)/\
......@@ -735,19 +747,20 @@ class VMNetProxy(object): # pylint: disable=R0902
lifetime=self.ra_period * 3)
try:
self.sendp(resp, binding.indev)
self.sendp(resp, binding)
except socket.error, e:
logging.warn(" - RA on %s failed: %s", binding.indev, str(e))
logging.warn(" - RA on %s (%s) failed: %s",
binding.tap, binding.hostname, str(e))
except Exception, e:
logging.warn(" - Unkown error during RA on %s: %s",
binding.indev, str(e))
logging.warn(" - Unkown error during RA on %s (%s): %s",
binding.tap, binding.hostname, str(e))
def ns_response(self, dummy, payload): # pylint: disable=W0613
""" Generate a reply to an ICMPv6 neighbor solicitation
"""
logging.debug(" * Processing pending NS request")
logging.info(" * Processing pending NS request")
ns = IPv6(payload.get_data())
#logging.debug(ns.show())
......@@ -793,8 +806,8 @@ class VMNetProxy(object): # pylint: disable=R0902
logging.debug(" - Received NS for a non-routable IP (%s)", ns.tgt)
return 1
logging.debug(" - Generating NA for host %s (mac %s) on tap %s",
binding.hostname, mac, binding.tap)
logging.info(" - Generating NA for host %s (mac %s) on tap %s",
binding.hostname, mac, binding.tap)
resp = Ether(src=indevmac, dst=binding.mac)/\
IPv6(src=str(ifll), dst=ns.src)/\
......@@ -802,12 +815,13 @@ class VMNetProxy(object): # pylint: disable=R0902
ICMPv6NDOptDstLLAddr(lladdr=indevmac)
try:
self.sendp(resp, binding.indev)
self.sendp(resp, binding)
except socket.error, e:
logging.warn(" - NA on %s failed: %s", binding.indev, str(e))
logging.warn(" - NA on %s (%s) failed: %s",
bindig.tap, binding.hostname, str(e))
except Exception, e:
logging.warn(" - Unkown error during periodic NA on %s: %s",
binding.indev, str(e))
logging.warn(" - Unkown error during periodic NA to %s (%s): %s",
binding.tap, binding.hostname, str(e))
def send_periodic_ra(self):
# Use a separate thread as this may take a _long_ time with
......@@ -815,7 +829,7 @@ class VMNetProxy(object): # pylint: disable=R0902
threading.Thread(target=self._send_periodic_ra).start()
def _send_periodic_ra(self):
logging.debug("Sending out periodic RAs")
logging.info("Sending out periodic RAs")
start = time.time()
i = 0
for binding in self.clients.values():
......@@ -839,14 +853,15 @@ class VMNetProxy(object): # pylint: disable=R0902
resp /= ICMPv6NDOptRDNSS(dns=self.ipv6_nameservers,
lifetime=self.ra_period * 3)
try:
self.sendp(resp, indev)
self.sendp(resp, binding)
except socket.error, e:
logging.warn(" - Periodic RA on %s failed: %s", tap, str(e))
logging.warn(" - Periodic RA on %s (%s) failed: %s",
tap, binding.hostname, str(e))
except Exception, e:
logging.warn(" - Unkown error during periodic RA on %s: %s",
tap, str(e))
logging.warn(" - Unkown error during periodic RA on %s (%s):"
" %s", tap, binding.hostname, str(e))
i += 1
logging.debug(" - Sent %d RAs in %.2f seconds", i, time.time() - start)
logging.info(" - Sent %d RAs in %.2f seconds", i, time.time() - start)
def serve(self):
""" Safely perform the main loop, freeing all resources upon exit
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment