def start_dhcp(self, subnets): """Start a DHCP server for the specified subnets. This allows consumers of the access point objects to control DHCP. Args: subnets: A list of Subnets. """ return self._dhcp.start(config=dhcp_config.DhcpConfig(subnets))
def stop_ap(self, identifier): """Stops a running ap on this controller. Args: identifier: The identify of the ap that should be taken down. """ if identifier not in self._aps: raise ValueError('Invalid identifer %s given' % identifier) instance = self._aps.get(identifier) instance.hostapd.stop() self._dhcp.stop() self._ip_cmd.clear_ipv4_addresses(identifier) # DHCP server needs to refresh in order to tear down the subnet no # longer being used. In the event that all interfaces are torn down # then an exception gets thrown. We need to catch this exception and # check that all interfaces should actually be down. configured_subnets = [x.subnet for x in self._aps.values()] if configured_subnets: self._dhcp.start(dhcp_config.DhcpConfig(configured_subnets))
def start_ap(self, hostapd_config, additional_parameters=None): """Starts as an ap using a set of configurations. This will start an ap on this host. To start an ap the controller selects a network interface to use based on the configs given. It then will start up hostapd on that interface. Next a subnet is created for the network interface and dhcp server is refreshed to give out ips for that subnet for any device that connects through that interface. Args: hostapd_config: hostapd_config.HostapdConfig, The configurations to use when starting up the ap. additional_parameters: A dictionary of parameters that can sent directly into the hostapd config file. This can be used for debugging and or adding one off parameters into the config. Returns: An identifier for the ap being run. This identifier can be used later by this controller to control the ap. Raises: Error: When the ap can't be brought up. """ if hostapd_config.frequency < 5000: interface = self.wlan_2g subnet = self._AP_2G_SUBNET else: interface = self.wlan_5g subnet = self._AP_5G_SUBNET # In order to handle dhcp servers on any interface, the initiation of # the dhcp server must be done after the wlan interfaces are figured # out as opposed to being in __init__ self._dhcp = dhcp_server.DhcpServer(self.ssh, interface=interface) # For multi bssid configurations the mac address # of the wireless interface needs to have enough space to mask out # up to 8 different mac addresses. The easiest way to do this # is to set the last byte to 0. While technically this could # cause a duplicate mac address it is unlikely and will allow for # one radio to have up to 8 APs on the interface. interface_mac_orig = None cmd = "ifconfig %s|grep ether|awk -F' ' '{print $2}'" % interface interface_mac_orig = self.ssh.run(cmd) hostapd_config.bssid = interface_mac_orig.stdout[:-1] + '0' if interface in self._aps: raise ValueError('No WiFi interface available for AP on ' 'channel %d' % hostapd_config.channel) apd = hostapd.Hostapd(self.ssh, interface) new_instance = _ApInstance(hostapd=apd, subnet=subnet) self._aps[interface] = new_instance # Turn off the DHCP server, we're going to change its settings. self._dhcp.stop() # Clear all routes to prevent old routes from interfering. self._route_cmd.clear_routes(net_interface=interface) if hostapd_config.bss_lookup: # The dhcp_bss dictionary is created to hold the key/value # pair of the interface name and the ip scope that will be # used for the particular interface. The a, b, c, d # variables below are the octets for the ip address. The # third octet is then incremented for each interface that # is requested. This part is designed to bring up the # hostapd interfaces and not the DHCP servers for each # interface. dhcp_bss = {} counter = 1 for bss in hostapd_config.bss_lookup: if interface_mac_orig: hostapd_config.bss_lookup[ bss].bssid = interface_mac_orig.stdout[:-1] + str( counter) self._route_cmd.clear_routes(net_interface=str(bss)) if interface is self.wlan_2g: starting_ip_range = self._AP_2G_SUBNET_STR else: starting_ip_range = self._AP_5G_SUBNET_STR a, b, c, d = starting_ip_range.split('.') dhcp_bss[bss] = dhcp_config.Subnet( ipaddress.ip_network('%s.%s.%s.%s' % (a, b, str(int(c) + counter), d))) counter = counter + 1 apd.start(hostapd_config, additional_parameters=additional_parameters) # The DHCP serer requires interfaces to have ips and routes before # the server will come up. interface_ip = ipaddress.ip_interface( '%s/%s' % (subnet.router, subnet.network.netmask)) self._ip_cmd.set_ipv4_address(interface, interface_ip) if hostapd_config.bss_lookup: # This loop goes through each interface that was setup for # hostapd and assigns the DHCP scopes that were defined but # not used during the hostapd loop above. The k and v # variables represent the interface name, k, and dhcp info, v. for k, v in dhcp_bss.items(): bss_interface_ip = ipaddress.ip_interface( '%s/%s' % (dhcp_bss[k].router, dhcp_bss[k].network.netmask)) self._ip_cmd.set_ipv4_address(str(k), bss_interface_ip) # Restart the DHCP server with our updated list of subnets. configured_subnets = [x.subnet for x in self._aps.values()] if hostapd_config.bss_lookup: for k, v in dhcp_bss.items(): configured_subnets.append(v) self._dhcp.start(config=dhcp_config.DhcpConfig(configured_subnets)) # The following three commands are needed to enable bridging between # the WAN and LAN/WLAN ports. This means anyone connecting to the # WLAN/LAN ports will be able to access the internet if the WAN port # is connected to the internet. self.ssh.run('iptables -t nat -F') self.ssh.run('iptables -t nat -A POSTROUTING -o %s -j MASQUERADE' % self.wan) self.ssh.run('echo 1 > /proc/sys/net/ipv4/ip_forward') return interface