}
+def get_indev(payload):
+ try:
+ indev_ifindex = payload.get_physindev()
+ if indev_ifindex:
+ logging.debug("Incomming packet from bridge %s", indev_ifindex)
+ return indev_ifindex
+ except AttributeError:
+ #TODO: return error value
+ logging.debug("No get_physindev supported")
+ return 0
+
+ indev_ifindex = payload.get_indev()
+ logging.debug("Incomming packet from tap %s", indev_ifindex)
+
+ return indev_ifindex
+
+def get_binding(proxy, ifindex, mac):
+ try:
+ if proxy.mac_indexed_clients:
+ b = proxy.clients[mac]
+ else:
+ b = proxy.clients[ifindex]
+ return b
+ except KeyError:
+ logging.debug("No client found for mac/ifindex %s/%s", mac, ifindex)
+ return None
+
def parse_binding_file(path):
""" Read a client configuration from a tap file
dhcp_server_ip=DHCP_DUMMY_SERVER_IP, dhcp_nameservers=None,
ra_period=DEFAULT_RA_PERIOD, ipv6_nameservers=None):
+ try:
+ getattr(nfqueue.payload, 'get_physindev')
+ self.mac_indexed_clients = False
+ except AttributeError:
+ self.mac_indexed_clients = True
self.data_path = data_path
self.lease_lifetime = dhcp_lease_lifetime
self.lease_renewal = dhcp_lease_renewal
logging.warn("Stale configuration for %s found", tap)
else:
if b.is_valid():
- self.clients[b.mac] = b
+ if self.mac_indexed_clients:
+ self.clients[b.mac] = b
+ else:
+ self.clients[ifindex] = b
logging.debug("Added client:")
- logging.debug("%10s %20s %7s %15s", b.hostname, b.mac, b.tap, b.ip)
+ logging.debug("%5s: %10s %20s %7s %15s",
+ ifindex, b.hostname, b.mac, b.tap, b.ip)
+ logging.debug("\n\n\n\n\n")
logging.debug("%10s %20s %7s %15s", 'Client', 'MAC', 'TAP', 'IP')
- for mac in self.clients.keys():
- b = self.clients[mac]
- logging.debug("%10s %20s %7s %15s", b.hostname, b.mac, b.tap, b.ip)
+ for b in self.clients.values():
+ logging.debug("%10s %20s %7s %15s", b.hostname, b.mac, b.tap, b.ip)
def remove_tap(self, tap):
""" Cleanup clients on a removed interface
"""
- for b in self.clients.values():
- if b.tap == tap:
- #os.remove(self.data_path+'/'+tap)
- logging.debug("Removed interface %s", self.data_path+'/'+tap)
- logging.debug("%10s %20s %7s %15s", b.hostname, b.mac, b.tap, b.ip)
- del b
+ try:
+ for k in self.clients.keys():
+ if self.clients[k].tap = tap:
+ logging.debug("Removing client on interface %s", tap)
+ logging.debug("%10s %20s %7s %15s",
+ b.hostname, b.mac, b.tap, b.ip)
+ del self.clients[k]
+ except:
+ logging.debug("Client on %s disappeared!!!", tap)
def dhcp_response(self, i, payload): # pylint: disable=W0613,R0914
# Decode the response - NFQUEUE relays IP packets
pkt = IP(payload.get_data())
logging.debug("IN DHCP RESPONCE")
- logging.debug(pkt.show())
+ #logging.debug(pkt.show())
# Get the client MAC address
resp = pkt.getlayer(BOOTP).copy()
resp.op = "BOOTREPLY"
del resp.payload
- try:
- binding = self.clients[mac]
- except KeyError:
- logging.warn("Invalid client for mac %s ", mac)
+ indev = get_indev(payload)
+
+ binding = get_binding(self, indev, mac)
+ if binding is None:
+ # We don't know anything about this interface, so accept the packet
+ # and return
+ logging.debug("Ignoring DHCP request on unknown iface %d", indev)
+ # We don't know what to do with this packet, so let the kernel
+ # handle it
payload.set_verdict(nfqueue.NF_ACCEPT)
return
+
# Signal the kernel that it shouldn't further process the packet
payload.set_verdict(nfqueue.NF_DROP)
+ if mac != binding.mac:
+ logging.warn("Recieved spoofed DHCP request for mac %s from tap %s", mac, tap)
+ return
+
resp = Ether(dst=mac, src=self.get_iface_hw_addr(binding.indev))/\
IP(src=DHCP_DUMMY_SERVER_IP, dst=binding.ip)/\
UDP(sport=pkt.dport, dport=pkt.sport)/resp
if req_type == DHCPREQUEST and requested_addr != binding.ip:
resp_type = DHCPNAK
logging.info("Sending DHCPNAK to %s on %s: requested %s"
- " instead of %s", binding.mac, binding.tap, requested_addr,
- binding.ip)
+ " instead of %s", binding.mac, binding.tap,
+ requested_addr, binding.ip)
elif req_type in (DHCPDISCOVER, DHCPREQUEST):
resp_type = DHCP_REQRESP[req_type]
- resp.yiaddr = self.clients[mac].ip
+ resp.yiaddr = binding.ip
dhcp_options += [
("hostname", binding.hostname),
("domain", domainname),
]
resp /= DHCP(options=dhcp_options)
- if payload.get_indev() != self.get_ifindex(binding.indev):
- logging.warn("Received spoofed DHCP request for %s from interface"
- " %s instead of %s", mac, payload.get_indev(), binding.indev)
- return
-
logging.info("%s to %s (%s) on %s", DHCP_TYPES[resp_type], mac,
binding.ip, binding.tap)
self.sendp(resp, binding.indev)
"""
pkt = IPv6(payload.get_data())
logging.debug("IN RS RESPONCE")
- logging.debug(pkt.show())
+ #logging.debug(pkt.show())
mac = pkt.lladdr
logging.debug("rs for mac %s", mac)
- try:
- binding = self.clients[mac]
- except KeyError:
- logging.debug("Ignoring router solicitation on"
- " for mac %s", mac)
+
+ indev = get_indev(payload)
+
+ binding = get_binding(self, indev, mac)
+ if binding is None:
+ # We don't know anything about this interface, so accept the packet
+ # and return
+ logging.debug("Ignoring router solicitation on for mac %s", mac)
# We don't know what to do with this packet, so let the kernel
# handle it
payload.set_verdict(nfqueue.NF_ACCEPT)
# Signal the kernel that it shouldn't further process the packet
payload.set_verdict(nfqueue.NF_DROP)
+ if mac != binding.mac:
+ logging.warn("Recieved spoofed RS request for mac %s from tap %s", mac, tap)
+ return
+
subnet = binding.net6
if subnet.net is None:
logging.debug("No IPv6 network assigned for the interface")
return
- ifmac = self.get_iface_hw_addr(binding.indev)
- ifll = subnet.make_ll64(ifmac)
+ indevmac = self.get_iface_hw_addr(binding.indev)
+ ifll = subnet.make_ll64(indevmac)
- resp = Ether(src=ifmac)/\
+ resp = Ether(src=indevmac)/\
IPv6(src=str(ifll))/ICMPv6ND_RA(routerlifetime=14400)/\
ICMPv6NDOptPrefixInfo(prefix=str(subnet.prefix),
prefixlen=subnet.prefixlen)
ns = IPv6(payload.get_data())
logging.debug("IN NS RESPONCE")
logging.debug(ns.show())
+ mac = ns.lladdr
logging.debug("dst %s tgt %s" , ns.dst, ns.tgt)
- try:
- binding = self.clients[ns.lladdr]
- except:
- logging.debug("Ignoring neighbour solicitation for eui64 %s", ns.tgt)
- # We don't know what to do with this packet, so let the kernel
- # handle it
- payload.set_verdict(nfqueue.NF_ACCEPT)
- return
+ indev = get_indev(payload)
+
+ binding = get_binding(self, indev, mac)
+ if binding is None:
+ # We don't know anything about this interface, so accept the packet
+ # and return
+ logging.debug("Ignoring neighbour solicitation for eui64 %s", ns.tgt)
+ # We don't know what to do with this packet, so let the kernel
+ # handle it
+ payload.set_verdict(nfqueue.NF_ACCEPT)
+ return
+
+ payload.set_verdict(nfqueue.NF_DROP)
+
+ if mac != binding.mac:
+ logging.warn("Recieved spoofed NS request for mac %s from tap %s", mac, tap)
+ return
subnet = binding.net6
if subnet.net is None:
logging.debug("No IPv6 network assigned for the interface")
- payload.set_verdict(nfqueue.NF_ACCEPT)
return
- payload.set_verdict(nfqueue.NF_DROP)
-
indevmac = self.get_iface_hw_addr(binding.indev)
ifll = subnet.make_ll64(indevmac)