Revision ed7f0f2a nfdhcpd/nfdhcpd

b/nfdhcpd/nfdhcpd
116 116
    }
117 117

  
118 118

  
119
def parse_routing_table(table="main", family=4):
120
    """ Parse the given routing table to get connected route, gateway and
121
    default device.
122

  
123
    """
124
    ipro = subprocess.Popen(["ip", "-%d" % family, "ro", "ls",
125
                             "table", table], stdout=subprocess.PIPE)
126
    routes = ipro.stdout.readlines()
127

  
128
    def_gw = None
129
    def_dev = None
130
    def_net = None
131

  
132
    for route in routes:
133
        # Find the least-specific connected route
134
        m = re.match("^([\S]+/[\S]+) dev ([\S]+)", route)
135
        if not m:
136
            continue
137

  
138
        if family == 6 and m.group(1).startswith("fe80:"):
139
            # Skip link-local declarations in "main" table
140
            continue
141

  
142
        def_net, def_dev = m.groups()
143

  
144
        try:
145
            def_net = IPy.IP(def_net)
146
        except ValueError, e:
147
            logging.warn("Unable to parse default route entry %s: %s",
148
                         def_net, str(e))
149

  
150
    for route in routes:
151
        match = re.match(r'^default.*via ([\S]+).*dev ([\S]+)', route)
152
        if match:
153
            def_gw, def_dev = match.groups()
154
            break
155

  
156
    return Subnet(net=def_net, gw=def_gw, dev=def_dev)
157

  
158

  
159 119
def parse_binding_file(path):
160 120
    """ Read a client configuration from a tap file
161 121

  
......
171 131
    ips = None
172 132
    link = None
173 133
    hostname = None
134
    subnet = None
135
    gateway = None
136
    subnet6 = None
137
    gateway6 = None
174 138

  
175 139
    for line in iffile:
176 140
        if line.startswith("IP="):
......
184 148
            hostname = line.strip().split("=")[1]
185 149
        elif line.startswith("IFACE="):
186 150
            iface = line.strip().split("=")[1]
187

  
188
    return Client(ifname=ifname, mac=mac, ips=ips, link=link, hostname=hostname, iface=iface)
189

  
151
        elif line.startswith("SUBNET="):
152
            subnet = line.strip().split("=")[1]
153
        elif line.startswith("GATEWAY="):
154
            gateway = line.strip().split("=")[1]
155
        elif line.startswith("SUBNET6="):
156
            subnet6 = line.strip().split("=")[1]
157
        elif line.startswith("GATEWAY6="):
158
            gatewa6 = line.strip().split("=")[1]
159

  
160
    return Client(ifname=ifname, mac=mac, ips=ips, link=link,
161
                  hostname=hostname,iface=iface, subnet=subnet,
162
                  gateway=gateway, subnet6=subnet6, gateway6=gateway6 )
190 163

  
191 164
class ClientFileHandler(pyinotify.ProcessEvent):
192 165
    def __init__(self, server):
......
211 184

  
212 185

  
213 186
class Client(object):
214
    def __init__(self, ifname=None, mac=None, ips=None, link=None, hostname=None, iface=None):
187
    def __init__(self, ifname=None, mac=None, ips=None, link=None,
188
                 hostname=None, iface=None, subnet=None, gateway=None,
189
                 subnet6=None, gateway6=None ):
215 190
        self.mac = mac
216 191
        self.ips = ips
217 192
        self.hostname = hostname
218 193
        self.link = link
219 194
        self.iface = iface
220 195
        self.ifname = ifname
196
        self.subnet = subnet
197
        self.gateway = gateway
198
        self.net = Subnet(net=subnet, gw=gateway, dev=ifname)
199
        self.subnet6 = subnet6
200
        self.gateway6 = gateway6
201
        self.net6 = Subnet(net=subnet6, gw=gateway6, dev=ifname)
221 202

  
222 203
    @property
223 204
    def ip(self):
......
318 299
        self.ipv6_enabled = False
319 300

  
320 301
        self.clients = {}
321
        self.subnets = {}
302
        #self.subnets = {}
322 303
        self.ifaces = {}
323
        self.v6nets = {}
304
        #self.v6nets = {}
324 305
        self.nfq = {}
325 306
        self.l2socket = socket.socket(socket.AF_PACKET,
326 307
                                      socket.SOCK_RAW, ETH_P_ALL)
......
392 373

  
393 374
    def build_config(self):
394 375
        self.clients.clear()
395
        self.subnets.clear()
396 376

  
397 377
        for path in glob.glob(os.path.join(self.data_path, "*")):
398 378
            self.add_iface(path)
......
475 455
        else:
476 456
            if binding.is_valid():
477 457
                self.clients[binding.mac] = binding
478
                self.subnets[binding.link] = parse_routing_table(binding.link)
479 458
                logging.debug("Added client %s on %s", binding.hostname, iface)
480 459
                self.ifaces[ifindex] = binding.iface
481
                self.v6nets[iface] = parse_routing_table(binding.link, 6)
482 460

  
483 461
    def remove_iface(self, ifname):
484 462
        """ Cleanup clients on a removed interface
485 463

  
486 464
        """
487
        if ifname in self.v6nets:
488
            del self.v6nets[ifname]
489

  
490 465
        for mac in self.clients.keys():
491 466
            if self.clients[mac].ifname == ifname:
492 467
                iface = self.client[mac].iface
......
546 521
        resp = Ether(dst=mac, src=self.get_iface_hw_addr(iface))/\
547 522
               IP(src=DHCP_DUMMY_SERVER_IP, dst=binding.ip)/\
548 523
               UDP(sport=pkt.dport, dport=pkt.sport)/resp
549
        subnet = self.subnets[binding.link]
524
        subnet = binding.net
550 525

  
551 526
        if not DHCP in pkt:
552 527
            logging.warn("Invalid request from %s on %s, no DHCP"
......
627 602
            return
628 603

  
629 604
        ifmac = self.get_iface_hw_addr(iface)
630
        subnet = self.v6nets[iface]
605
        binding = self.clients[ifmac]
606
        subnet = binding.net6
631 607
        ifll = subnet.make_ll64(ifmac)
632 608

  
633 609
        # Signal the kernel that it shouldn't further process the packet
......
662 638
            return
663 639

  
664 640
        ifmac = self.get_iface_hw_addr(iface)
665
        subnet = self.v6nets[iface]
641
        binding = self.clients[ifmac]
642
        subnet = binding.net6
666 643
        ifll = subnet.make_ll64(ifmac)
667 644

  
668 645
        ns = IPv6(payload.get_data())
......
703 680
            if not ifmac:
704 681
                continue
705 682

  
706
            subnet = self.v6nets[iface]
683
            binding = self.clients[ifmac]
684
            subnet = binding.net6
707 685
            if subnet.net is None:
708 686
                logging.debug("Skipping periodic RA on interface %s,"
709 687
                              " as it is not IPv6-connected", iface)

Also available in: Unified diff