Revision 06e6d9bc nfdhcpd

b/nfdhcpd
53 53
                               ICMPv6NDOptPrefixInfo, \
54 54
                               ICMPv6NDOptRDNSS
55 55
from scapy.layers.dhcp import BOOTP, DHCP
56
from scapy.layers.dhcp6 import DHCP6_Reply, DHCP6OptDNSServers, \
57
                               DHCP6OptServerId, DHCP6OptClientId, \
58
                               DUID_LLT, DHCP6_InfoRequest
56 59

  
57 60

  
58 61
DEFAULT_CONFIG = "/etc/nfdhcpd/nfdhcpd.conf"
......
91 94
ra_period = integer(min=1, max=4294967295)
92 95
rs_queue = integer(min=0, max=65535)
93 96
ns_queue = integer(min=0, max=65535)
97
dhcp_queue = integer(min=0, max=65535)
94 98
nameservers = ip_addr_list(family=6)
95 99
"""
96 100

  
......
349 353

  
350 354
class VMNetProxy(object):  # pylint: disable=R0902
351 355
    def __init__(self, data_path, dhcp_queue_num=None,  # pylint: disable=R0913
352
                 rs_queue_num=None, ns_queue_num=None,
356
                 rs_queue_num=None, ns_queue_num=None, dhcpv6_queue_num=None,
353 357
                 dhcp_lease_lifetime=DEFAULT_LEASE_LIFETIME,
354 358
                 dhcp_lease_renewal=DEFAULT_LEASE_RENEWAL,
355 359
                 dhcp_domain='',
......
405 409
            self._setup_nfqueue(ns_queue_num, AF_INET6, self.ns_response, 10)
406 410
            self.ipv6_enabled = True
407 411

  
412
        if dhcpv6_queue_num is not None:
413
            self._setup_nfqueue(dhcpv6_queue_num, AF_INET6, self.dhcpv6_response, 10)
414
            self.ipv6_enabled = True
415

  
408 416
    def get_binding(self, ifindex, mac):
409 417
        try:
410 418
            if self.mac_indexed_clients:
......
694 702
            logging.warn(" - Unkown error during DHCP response on %s (%s): %s",
695 703
                         binding.tap, binding.hostname, str(e))
696 704

  
705
    def dhcpv6_response(self, arg1, arg2=None):  # pylint: disable=W0613
706

  
707
        logging.info(" * Processing pending DHCPv6 request")
708
        # Workaround for supporting both squeezy's nfqueue-bindings-python
709
        # and wheezy's python-nfqueue because for some reason the function's
710
        # signature has changed and has broken compatibility
711
        # See bug http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=718894
712
        if arg2:
713
            payload = arg2
714
        else:
715
            payload = arg1
716
        pkt = IPv6(payload.get_data())
717
        indev = get_indev(payload)
718

  
719
        #TODO: figure out how to find the src mac
720
        mac = None
721
        binding = self.get_binding(indev, mac)
722
        if binding is None:
723
            # We don't know anything about this interface, so accept the packet
724
            # and return
725
            logging.debug(" - Ignoring dhcpv6 request for mac %s", mac)
726
            # We don't know what to do with this packet, so let the kernel
727
            # handle it
728
            payload.set_verdict(nfqueue.NF_ACCEPT)
729
            return
730

  
731
        # Signal the kernel that it shouldn't further process the packet
732
        payload.set_verdict(nfqueue.NF_DROP)
733

  
734
        subnet = binding.net6
735

  
736
        indevmac = self.get_iface_hw_addr(binding.indev)
737
        ifll = subnet.make_ll64(indevmac)
738
        if ifll is None:
739
            return
740

  
741
        ofll = subnet.make_ll64(binding.mac)
742
        if ofll is None:
743
            return
744

  
745
        logging.info(" - Generating DHCPv6 response for host %s (mac %s) on tap %s",
746
                      binding.hostname, binding.mac, binding.tap)
747

  
748
        resp = Ether(src=indevmac, dst=binding.mac)/\
749
               IPv6(tc=192, src=str(ifll), dst=str(ofll))/\
750
               UDP(sport=pkt.dport, dport=pkt.sport)/\
751
               DHCP6_Reply(trid=pkt[DHCP6_InfoRequest].trid)/\
752
               DHCP6OptClientId(duid=pkt[DHCP6OptClientId].duid)/\
753
               DHCP6OptServerId(duid=DUID_LLT(lladdr=indevmac, timeval=time.time()))/\
754
               DHCP6OptDNSServers(dnsservers=self.ipv6_nameservers,
755
                                  optlen=16 * len(self.ipv6_nameservers))
756

  
757
        try:
758
            binding.sendp(resp)
759
        except socket.error, e:
760
            logging.warn(" - DHCPv6 on %s (%s) failed: %s",
761
                         binding.tap, binding.hostname, str(e))
762
        except Exception, e:
763
            logging.warn(" - Unkown error during DHCPv6 on %s (%s): %s",
764
                         binding.tap, binding.hostname, str(e))
765

  
766

  
697 767
    def rs_response(self, arg1, arg2=None):  # pylint: disable=W0613
698 768
        """ Generate a reply to a BOOTP/DHCP request
699 769

  
......
750 820
                      binding.hostname, mac, binding.tap)
751 821

  
752 822
        resp = Ether(src=indevmac)/\
753
               IPv6(src=str(ifll))/ICMPv6ND_RA(routerlifetime=14400)/\
823
               IPv6(src=str(ifll))/ICMPv6ND_RA(O=1, routerlifetime=14400)/\
754 824
               ICMPv6NDOptPrefixInfo(prefix=str(subnet.prefix),
755 825
                                     prefixlen=subnet.prefixlen)
756 826

  
......
1111 1181

  
1112 1182
    if config["ipv6"].as_bool("enable_ipv6"):
1113 1183
        proxy_opts.update({
1184
            "dhcpv6_queue_num": config["ipv6"].as_int("dhcp_queue"),
1114 1185
            "rs_queue_num": config["ipv6"].as_int("rs_queue"),
1115 1186
            "ns_queue_num": config["ipv6"].as_int("ns_queue"),
1116 1187
            "ra_period": config["ipv6"].as_int("ra_period"),

Also available in: Unified diff