def get_reply_dhcp_options(self, mac, message, req_options): option_list = [] client_ident = self.get_dhcpv6_client_ident(mac, req_options) option_list.append( dhcp6.option(code=dhcp6.DHCPV6_OPTION_CLIENTID, data=client_ident, length=len(client_ident))) server_id_bin = self.get_dhcpv6_server_ident() option_list.append( dhcp6.option(code=dhcp6.DHCPV6_OPTION_SERVERID, data=server_id_bin, length=len(server_id_bin))) # Status Message: "<message>" status_bin = self.get_dhcpv6_status_code( message, code=DHCPV6_STATUS_CODE_SUCCESS) option_list.append( dhcp6.option(code=dhcp6.DHCPV6_OPTION_STATUS_CODE, data=status_bin, length=len(status_bin))) # Final option list options = dhcp6.options(option_list=option_list) return options
def _create_test_dhcp6_packet(self, zero_time=False): ret_pkt = packet.Packet() ret_pkt.add_protocol( ethernet.ethernet( ethertype=ether_types.ETH_TYPE_IPV6, dst='33:33:00:01:00:02', src=self.port_info['mac_address'])) ret_pkt.add_protocol( ipv6.ipv6( src='fe80::f816:3eff:fe60:714b', dst='ff02::1:2', nxt=inet.IPPROTO_UDP)) ret_pkt.add_protocol( udp.udp( src_port=constants.DHCPV6_RESPONSE_PORT, dst_port=constants.DHCPV6_CLIENT_PORT)) options = [dhcp6.option( code=1, data=b"\x00\x01\x00\x01", length=4)] if zero_time: options.append(dhcp6.option( code=3, data=b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", length=12)) else: options.append(dhcp6.option( code=3, data=b"\x01\x02\x03\x04\x05\x06\x07\x08\x0a\x0b\x0c\x0d", length=12)) ret_pkt.add_protocol(dhcp6.dhcp6( dhcp6.DHCPV6_REQUEST, dhcp6.options(option_list=options))) return ret_pkt
def _test_get_dhcp_options(self, zero_time=False): ip_info = self.dhcp6_responer.get_port_ip(self.port_info, ip_version=6) mac = self.port_info['mac_address'] option_list = [ dhcp6.option( code=1, data=b"\x00\x01\x00\x01", length=4), dhcp6.option( code=2, data=b'\x00\x01\x00\x01\x00\x00\x00\x01\xfa\x16>\x00\x00\x00', length=14), dhcp6.option(code=13, data=b'\x00\x00success', length=9), dhcp6.option( code=23, data=(b'\xfd\xa7\xa5\xcc4`\x00\x01\x00' b'\x00\x00\x00\x00\x00\x00\x01'), length=16), dhcp6.option( code=24, data=b'\x0eopenstacklocal\x00', length=16), dhcp6.option( code=39, data=b'\x03(host-fda7-a5cc-3460-1--bf.openstacklocal', length=42)] if zero_time: option_list.append(dhcp6.option(code=3, data=(b'\x00\x00\x00\x01\x00\x01Q\x80\x00\x01Q' b'\x80\x00\x05\x00\x18\xfd\xa7\xa5\xcc4`' b'\x00\x01\x00\x00\x00\x00\x00\x00\x00' b'\xbf\x00\x01Q\x80\x00\x01Q\x80'), length=40)) else: option_list.append(dhcp6.option(code=3, data=(b'\x01\x02\x03\x04\x05\x06\x07\x08\n\x0b\x0c\r' b'\x00\x05\x00\x18\xfd\xa7\xa5\xcc4`' b'\x00\x01\x00\x00\x00\x00\x00\x00\x00' b'\xbf\x05\x06\x07\x08\n\x0b\x0c\r'), length=40)) test_options = dhcp6.options( option_list=option_list, options_len=0) time_p = mock.patch.object(time, 'time', return_value=ONE_SEC_AFTER_2000) time_p.start() self.addCleanup(time_p.stop) packet_in = self._create_test_dhcp6_packet(zero_time=zero_time) pkt_dhcp = packet_in.get_protocol(dhcp6.dhcp6) dhcp_req_state = dhcp_ipv6.DHCPV6_TYPE_MAP.get(pkt_dhcp.msg_type) dhcp_options = self.dhcp6_responer.get_dhcp_options( mac, ip_info, pkt_dhcp.options.option_list, dhcp_req_state) self._compare_option_values(test_options.option_list, dhcp_options.option_list)
def test_get_reply_dhcp_options(self): mac = '00:01:02:03:04:05' packet_in = self._create_test_dhcp6_packet() header_dhcp = packet_in.get_protocol(dhcp6.dhcp6) time.time = mock.Mock(return_value=ONE_SEC_AFTER_2000) dhcp_options = self.dhcp6_responer.get_reply_dhcp_options( mac, message="all addresses still on link", req_options=header_dhcp.options.option_list) test_options = dhcp6.options(option_list=[ dhcp6.option(code=1, data=b'\x00\x01\x00\x01', length=4), dhcp6.option( code=2, data=b'\x00\x01\x00\x01\x00\x00\x00\x01\xfa\x16>\x00\x00\x00', length=14), dhcp6.option(code=13, data=b'\x00\x00all addresses still on link', length=29)], options_len=0) self._compare_option_values(test_options.option_list, dhcp_options.option_list)
def get_dhcp_options(self, mac, ip_info, req_options, req_type): ip_addr = ip_info['ip_address'] gateway_ip = ip_info['gateway_ip'] dns_nameservers = ip_info['dns_nameservers'] option_list = [] client_ident = self.get_dhcpv6_client_ident(mac, req_options) option_list.append( dhcp6.option(code=dhcp6.DHCPV6_OPTION_CLIENTID, data=client_ident, length=len(client_ident))) server_id_bin = self.get_dhcpv6_server_ident() option_list.append( dhcp6.option(code=dhcp6.DHCPV6_OPTION_SERVERID, data=server_id_bin, length=len(server_id_bin))) ia_na_data = self._get_ia_na_opt(req_options, ip_addr) option_list.append( dhcp6.option(code=dhcp6.DHCPV6_OPTION_IA_NA, data=ia_na_data, length=len(ia_na_data))) # Status Message: success status_bin = self.get_dhcpv6_status_code("success") option_list.append( dhcp6.option(code=dhcp6.DHCPV6_OPTION_STATUS_CODE, data=status_bin, length=len(status_bin))) if req_type == 'SOLICIT': # for DHCP6 advertise packet # DHCPV6_OPTION_PREFERENCE = 7 # Pref-value: 0 perference = struct.pack('!b', 0) option_list.append( dhcp6.option(code=dhcp6.DHCPV6_OPTION_PREFERENCE, data=perference, length=len(perference))) # 24: Domain Search List if req_type == 'REQUEST' and cfg.CONF.dns_domain: # Domain Search List FQDN: default openstacklocal dns_domain = struct.pack('!%ds' % len(str(cfg.CONF.dns_domain)), bytes(str(cfg.CONF.dns_domain).encode())) dns_str_len = struct.pack('!b', len(dns_domain)) dns_str_end = struct.pack('!b', 0) dns_domain_data = dns_str_len + dns_domain + dns_str_end option_list.append( dhcp6.option(code=DHCPV6_OPTION_DOMAIN_SEARCH_LIST, data=dns_domain_data, length=len(dns_domain_data))) # 23: DNS recursive name server if dns_nameservers: domain_serach = self.get_bin_dns(dns_nameservers) option_list.append( dhcp6.option(code=DHCPV6_OPTION_DNS_RECURSIVE_NS, data=domain_serach, length=len(domain_serach))) else: # use gateway as the default DNS server address domain_serach = addrconv.ipv6.text_to_bin(str(gateway_ip)) option_list.append( dhcp6.option(code=DHCPV6_OPTION_DNS_RECURSIVE_NS, data=domain_serach, length=len(domain_serach))) # 39: Fully Qualified Domain Name fqdn = 'host-%s' % ip_addr.replace('.', '-').replace(':', '-') if req_type == 'REQUEST' and cfg.CONF.dns_domain: fqdn = '%s.%s' % (fqdn, cfg.CONF.dns_domain) # 0000 0... = Reserved: 0x00 # .... .0.. = N bit: Server should perform DNS updates # .... ..1. = O bit: Server has overridden client's S bit preference # .... ...1 = S bit: Server should perform forward DNS updates dns_tag = struct.pack('!b', 3) # Client FQDN: host-<ip-v6-address> fqdn_bin = struct.pack('!%ds' % len(fqdn), bytes(str(fqdn).encode())) fqdn_str_len = struct.pack('!b', len(fqdn_bin)) dns_data = (dns_tag + fqdn_str_len + fqdn_bin) option_list.append( dhcp6.option(code=DHCPV6_OPTION_FQDN, data=dns_data, length=len(dns_data))) # Final option list options = dhcp6.options(option_list=option_list) return options