LCOV - code coverage report
Current view: top level - vnsw/agent/services - dhcpv6_handler.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 0 331 0.0 %
Date: 2026-06-04 02:06:09 Functions: 0 20 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #include <stdint.h>
       6             : #include "base/os.h"
       7             : #include "base/address_util.h"
       8             : #include "vr_defs.h"
       9             : #include "cmn/agent_cmn.h"
      10             : #include "oper/route_common.h"
      11             : #include "pkt/pkt_init.h"
      12             : #include "services/dhcpv6_proto.h"
      13             : #include "services/services_types.h"
      14             : #include "services/services_init.h"
      15             : #include "services/dns_proto.h"
      16             : #include "services/services_sandesh.h"
      17             : #include "bind/bind_util.h"
      18             : #include "bind/xmpp_dns_agent.h"
      19             : 
      20             : #include <boost/assign/list_of.hpp>
      21             : #include <boost/scoped_array.hpp>
      22             : using namespace boost::assign;
      23             : 
      24             : // since the DHCPv4 and DHCPv6 option codes mean different things
      25             : // and since we get only one set of DHCP options from the config or
      26             : // from Neutron, it is assumed that if the option code is a number,
      27             : // it represents DHCPv4 code and the code string for DHCPv6 and
      28             : // DHCPv4 do not overlap.
      29             : Dhcpv6NameCodeMap g_dhcpv6_namecode_map =
      30             :         map_list_of<std::string, uint32_t>
      31             :         ("v6-client-id", DHCPV6_OPTION_CLIENTID)
      32             :         ("v6-server-id", DHCPV6_OPTION_SERVERID)
      33             :         ("v6-ia-na", DHCPV6_OPTION_IA_NA)
      34             :         ("v6-ia-ta", DHCPV6_OPTION_IA_TA)
      35             :         ("v6-ia-addr", DHCPV6_OPTION_IAADDR)
      36             :         ("v6-oro", DHCPV6_OPTION_ORO)
      37             :         ("v6-preference", DHCPV6_OPTION_PREFERENCE)
      38             :         ("v6-elapsed-time", DHCPV6_OPTION_ELAPSED_TIME)
      39             :         ("v6-relay-msg", DHCPV6_OPTION_RELAY_MSG)
      40             :         ("v6-auth", DHCPV6_OPTION_AUTH)
      41             :         ("v6-unicast", DHCPV6_OPTION_UNICAST)
      42             :         ("v6-status-code", DHCPV6_OPTION_STATUS_CODE)
      43             :         ("v6-rapid-commit", DHCPV6_OPTION_RAPID_COMMIT)
      44             :         ("v6-user-class", DHCPV6_OPTION_USER_CLASS)
      45             :         ("v6-vendor-class", DHCPV6_OPTION_VENDOR_CLASS)
      46             :         ("v6-vendor-opts", DHCPV6_OPTION_VENDOR_OPTS)
      47             :         ("v6-interface-id", DHCPV6_OPTION_INTERFACE_ID)
      48             :         ("v6-reconf-msg",  DHCPV6_OPTION_RECONF_MSG)
      49             :         ("v6-reconf-accept", DHCPV6_OPTION_RECONF_ACCEPT)
      50             :         ("v6-sip-server-names", DHCPV6_OPTION_SIP_SERVER_D)
      51             :         ("v6-sip-server-addresses", DHCPV6_OPTION_SIP_SERVER_A)
      52             :         ("v6-name-servers", DHCPV6_OPTION_DNS_SERVERS)
      53             :         ("v6-domain-search", DHCPV6_OPTION_DOMAIN_LIST)
      54             :         ("v6-ia-pd", DHCPV6_OPTION_IA_PD)
      55             :         ("v6-ia-prefix", DHCPV6_OPTION_IAPREFIX)
      56             :         ("v6-nis-servers", DHCPV6_OPTION_NIS_SERVERS)
      57             :         ("v6-nisp-servers", DHCPV6_OPTION_NISP_SERVERS)
      58             :         ("v6-nis-domain-name", DHCPV6_OPTION_NIS_DOMAIN_NAME)
      59             :         ("v6-nisp-domain-name", DHCPV6_OPTION_NISP_DOMAIN_NAME)
      60             :         ("v6-sntp-servers", DHCPV6_OPTION_SNTP_SERVERS)
      61             :         ("v6-info-refresh-time", DHCPV6_OPTION_INFORMATION_REFRESH_TIME)
      62             :         ("v6-bcms-server-d", DHCPV6_OPTION_BCMCS_SERVER_D)
      63             :         ("v6-bcms-server-a", DHCPV6_OPTION_BCMCS_SERVER_A)
      64             :         ("v6-geoconf-civic", DHCPV6_OPTION_GEOCONF_CIVIC)
      65             :         ("v6-remote-id", DHCPV6_OPTION_REMOTE_ID)
      66             :         ("v6-subscriber-id", DHCPV6_OPTION_SUBSCRIBER_ID)
      67             :         ("v6-client-fqdn", DHCPV6_OPTION_CLIENT_FQDN)
      68             :         ("v6-pana-agent", DHCPV6_OPTION_PANA_AGENT)
      69             :         ("v6-posiz-timezone", DHCPV6_OPTION_NEW_POSIX_TIMEZONE)
      70             :         ("v6-tzdc-timezone", DHCPV6_OPTION_NEW_TZDB_TIMEZONE)
      71             :         ("v6-ero", DHCPV6_OPTION_ERO)
      72             :         ("v6-lq-query", DHCPV6_OPTION_LQ_QUERY)
      73             :         ("v6-client-data", DHCPV6_OPTION_CLIENT_DATA)
      74             :         ("v6-clt-time", DHCPV6_OPTION_CLT_TIME)
      75             :         ("v6-lq-relay-data", DHCPV6_OPTION_LQ_RELAY_DATA)
      76             :         ("v6-lq-client-link", DHCPV6_OPTION_LQ_CLIENT_LINK)
      77             :         ("mip6-hnidf", DHCPV6_OPTION_MIP6_HNIDF)
      78             :         ("mip6-vdinf", DHCPV6_OPTION_MIP6_VDINF)
      79             :         ("v6-lost", DHCPV6_OPTION_V6_LOST)
      80             :         ("v6-capwap-ac", DHCPV6_OPTION_CAPWAP_AC_V6)
      81             :         ("v6-relay-id", DHCPV6_OPTION_RELAY_ID)
      82             :         ("v6-address-mos", DHCPV6_OPTION_IPv6_Address_MoS)
      83             :         ("v6-fqdn-mos", DHCPV6_OPTION_IPv6_FQDN_MoS)
      84             :         ("v6-ntp-server", DHCPV6_OPTION_NTP_SERVER)
      85             :         ("v6-access-domain", DHCPV6_OPTION_V6_ACCESS_DOMAIN)
      86             :         ("v6-sip-ua-cs-list", DHCPV6_OPTION_SIP_UA_CS_LIST)
      87             :         ("v6-bootfile-url", DHCPV6_OPT_BOOTFILE_URL)
      88             :         ("v6-bootfile-param", DHCPV6_OPT_BOOTFILE_PARAM)
      89             :         ("v6-client-arch-type", DHCPV6_OPTION_CLIENT_ARCH_TYPE)
      90             :         ("v6-nii", DHCPV6_OPTION_NII)
      91             :         ("v6-geolocation", DHCPV6_OPTION_GEOLOCATION)
      92             :         ("v6-aftr-name", DHCPV6_OPTION_AFTR_NAME)
      93             :         ("v6-erp-local-domain-name", DHCPV6_OPTION_ERP_LOCAL_DOMAIN_NAME)
      94             :         ("v6-rsoo", DHCPV6_OPTION_RSOO)
      95             :         ("v6-pd-exclude", DHCPV6_OPTION_PD_EXCLUDE)
      96             :         ("v6-vss", DHCPV6_OPTION_VSS)
      97             :         ("mip6-idinf", DHCPV6_OPTION_MIP6_IDINF)
      98             :         ("mip6-udinf", DHCPV6_OPTION_MIP6_UDINF)
      99             :         ("mip6-hnp", DHCPV6_OPTION_MIP6_HNP)
     100             :         ("mip6-haa", DHCPV6_OPTION_MIP6_HAA)
     101             :         ("mip6-haf", DHCPV6_OPTION_MIP6_HAF)
     102             :         ("v6-rdnss-selection", DHCPV6_OPTION_RDNSS_SELECTION)
     103             :         ("v6-krb-principal-name", DHCPV6_OPTION_KRB_PRINCIPAL_NAME)
     104             :         ("v6-krb-realm-name", DHCPV6_OPTION_KRB_REALM_NAME)
     105             :         ("v6-krb-default-realm-name", DHCPV6_OPTION_KRB_DEFAULT_REALM_NAME)
     106             :         ("v6-krb-kdc", DHCPV6_OPTION_KRB_KDC)
     107             :         ("v6-client-linklayer-addr", DHCPV6_OPTION_CLIENT_LINKLAYER_ADDR)
     108             :         ("v6-link-address", DHCPV6_OPTION_LINK_ADDRESS)
     109             :         ("v6-radius", DHCPV6_OPTION_RADIUS)
     110             :         ("v6-sol-max-rt", DHCPV6_OPTION_SOL_MAX_RT)
     111             :         ("v6-inf-max-rt", DHCPV6_OPTION_INF_MAX_RT)
     112             :         ("v6-addrsel", DHCPV6_OPTION_ADDRSEL)
     113             :         ("v6-addrsel-table", DHCPV6_OPTION_ADDRSEL_TABLE)
     114             :         ("v6-pcp-server", DHCPV6_OPTION_V6_PCP_SERVER)
     115             :         ("v6-dhcpv4-msg", DHCPV6_OPTION_DHCPV4_MSG)
     116             :         ("v6-dhcpv4-o-dhcpv6-server", DHCPV6_OPTION_DHCP4_O_DHCP6_SERVER)
     117             :         ("v6-s46-rule", DHCPV6_OPTION_S46_RULE)
     118             :         ("v6-s46-br", DHCPV6_OPTION_S46_BR)
     119             :         ("v6-s46-dmr", DHCPV6_OPTION_S46_DMR)
     120             :         ("v6-s46-v4v6bind", DHCPV6_OPTION_S46_V4V6BIND)
     121             :         ("v6-s46-portparams", DHCPV6_OPTION_S46_PORTPARAMS)
     122             :         ("v6-s46-cont-mape", DHCPV6_OPTION_S46_CONT_MAPE)
     123             :         ("v6-s46-cont-mapt", DHCPV6_OPTION_S46_CONT_MAPT)
     124             :         ("v6-s46-cont-lw", DHCPV6_OPTION_S46_CONT_LW)
     125             :         ("v6-address-andsf", DHCPV6_OPTION_IPv6_ADDRESS_ANDSF);
     126             : 
     127             : Dhcpv6CategoryMap g_dhcpv6_category_map =
     128             :     map_list_of<uint32_t, Dhcpv6Handler::DhcpOptionCategory>
     129             :         // the following are sent from Agent
     130             :         // (DHCPV6_OPTION_CLIENTID, Dhcpv6Handler::ByteArray)
     131             :         // (DHCPV6_OPTION_SERVERID, Dhcpv6Handler::ByteArray)
     132             :         // (DHCPV6_OPTION_IA_NA, Dhcpv6Handler::ByteArray)
     133             :         // (DHCPV6_OPTION_IA_TA, Dhcpv6Handler::ByteArray)
     134             :         // (DHCPV6_OPTION_IAADDR, Dhcpv6Handler::ByteArray)
     135             :         // (DHCPV6_OPTION_ORO, Dhcpv6Handler::ByteArray)
     136             :         (DHCPV6_OPTION_PREFERENCE, Dhcpv6Handler::Byte)
     137             :         // (DHCPV6_OPTION_ELAPSED_TIME, Dhcpv6Handler::Uint16bit)
     138             :         // (DHCPV6_OPTION_RELAY_MSG, Dhcpv6Handler::ByteArray)
     139             :         // (DHCPV6_OPTION_AUTH, Dhcpv6Handler::ByteArray)
     140             :         // (DHCPV6_OPTION_UNICAST, Dhcpv6Handler::OneIPv6)
     141             :         // (DHCPV6_OPTION_STATUS_CODE, Dhcpv6Handler::ByteArray)
     142             :         (DHCPV6_OPTION_RAPID_COMMIT, Dhcpv6Handler::NoData)
     143             :         (DHCPV6_OPTION_USER_CLASS, Dhcpv6Handler::ByteArray)
     144             :         (DHCPV6_OPTION_VENDOR_CLASS, Dhcpv6Handler::ByteArray)
     145             :         (DHCPV6_OPTION_VENDOR_OPTS, Dhcpv6Handler::ByteArray)
     146             :         (DHCPV6_OPTION_INTERFACE_ID, Dhcpv6Handler::ByteArray)
     147             :         (DHCPV6_OPTION_RECONF_MSG, Dhcpv6Handler::Byte)
     148             :         (DHCPV6_OPTION_RECONF_ACCEPT, Dhcpv6Handler::NoData)
     149             :         (DHCPV6_OPTION_SIP_SERVER_D, Dhcpv6Handler::NameCompressionArray)
     150             :         (DHCPV6_OPTION_SIP_SERVER_A, Dhcpv6Handler::OneIPv6Plus)
     151             :         (DHCPV6_OPTION_DNS_SERVERS, Dhcpv6Handler::OneIPv6Plus)
     152             :         (DHCPV6_OPTION_DOMAIN_LIST, Dhcpv6Handler::NameCompressionArray)
     153             :         (DHCPV6_OPTION_IA_PD, Dhcpv6Handler::ByteArray)
     154             :         (DHCPV6_OPTION_IAPREFIX, Dhcpv6Handler::ByteArray)
     155             :         (DHCPV6_OPTION_NIS_SERVERS, Dhcpv6Handler::OneIPv6Plus)
     156             :         (DHCPV6_OPTION_NISP_SERVERS, Dhcpv6Handler::OneIPv6Plus)
     157             :         (DHCPV6_OPTION_NIS_DOMAIN_NAME, Dhcpv6Handler::NameCompression)
     158             :         (DHCPV6_OPTION_NISP_DOMAIN_NAME, Dhcpv6Handler::NameCompression)
     159             :         (DHCPV6_OPTION_SNTP_SERVERS, Dhcpv6Handler::OneIPv6Plus)
     160             :         (DHCPV6_OPTION_INFORMATION_REFRESH_TIME, Dhcpv6Handler::Uint32bit)
     161             :         (DHCPV6_OPTION_BCMCS_SERVER_D, Dhcpv6Handler::NameCompressionArray)
     162             :         (DHCPV6_OPTION_BCMCS_SERVER_A, Dhcpv6Handler::OneIPv6Plus)
     163             :         (DHCPV6_OPTION_GEOCONF_CIVIC, Dhcpv6Handler::ByteArray)
     164             :         (DHCPV6_OPTION_REMOTE_ID, Dhcpv6Handler::ByteArray)
     165             :         (DHCPV6_OPTION_SUBSCRIBER_ID, Dhcpv6Handler::ByteArray)
     166             :         (DHCPV6_OPTION_CLIENT_FQDN, Dhcpv6Handler::ByteNameCompression)
     167             :         (DHCPV6_OPTION_PANA_AGENT, Dhcpv6Handler::OneIPv6Plus)
     168             :         (DHCPV6_OPTION_NEW_POSIX_TIMEZONE, Dhcpv6Handler::String)
     169             :         (DHCPV6_OPTION_NEW_TZDB_TIMEZONE, Dhcpv6Handler::String)
     170             :         (DHCPV6_OPTION_ERO, Dhcpv6Handler::Uint16bitArray)
     171             :         (DHCPV6_OPTION_LQ_QUERY, Dhcpv6Handler::ByteArray)
     172             :         (DHCPV6_OPTION_CLIENT_DATA, Dhcpv6Handler::ByteArray)
     173             :         (DHCPV6_OPTION_CLT_TIME, Dhcpv6Handler::Uint32bit)
     174             :         (DHCPV6_OPTION_LQ_RELAY_DATA, Dhcpv6Handler::ByteArray)
     175             :         (DHCPV6_OPTION_LQ_CLIENT_LINK, Dhcpv6Handler::OneIPv6Plus)
     176             :         (DHCPV6_OPTION_MIP6_HNIDF, Dhcpv6Handler::NameCompression)
     177             :         (DHCPV6_OPTION_MIP6_VDINF, Dhcpv6Handler::ByteArray)
     178             :         (DHCPV6_OPTION_V6_LOST, Dhcpv6Handler::NameCompression)
     179             :         (DHCPV6_OPTION_CAPWAP_AC_V6, Dhcpv6Handler::OneIPv6Plus)
     180             :         (DHCPV6_OPTION_RELAY_ID, Dhcpv6Handler::ByteArray)
     181             :         (DHCPV6_OPTION_IPv6_Address_MoS, Dhcpv6Handler::ByteArray)
     182             :         (DHCPV6_OPTION_IPv6_FQDN_MoS, Dhcpv6Handler::ByteArray)
     183             :         (DHCPV6_OPTION_NTP_SERVER, Dhcpv6Handler::ByteArray)
     184             :         (DHCPV6_OPTION_V6_ACCESS_DOMAIN, Dhcpv6Handler::NameCompression)
     185             :         (DHCPV6_OPTION_SIP_UA_CS_LIST, Dhcpv6Handler::NameCompressionArray)
     186             :         (DHCPV6_OPT_BOOTFILE_URL, Dhcpv6Handler::String)
     187             :         (DHCPV6_OPT_BOOTFILE_PARAM, Dhcpv6Handler::ByteArray)
     188             :         (DHCPV6_OPTION_CLIENT_ARCH_TYPE, Dhcpv6Handler::Uint16bitArray)
     189             :         (DHCPV6_OPTION_NII, Dhcpv6Handler::ByteArray)
     190             :         (DHCPV6_OPTION_GEOLOCATION, Dhcpv6Handler::ByteArray)
     191             :         (DHCPV6_OPTION_AFTR_NAME, Dhcpv6Handler::NameCompression)
     192             :         (DHCPV6_OPTION_ERP_LOCAL_DOMAIN_NAME, Dhcpv6Handler::NameCompression)
     193             :         (DHCPV6_OPTION_RSOO, Dhcpv6Handler::ByteArray)
     194             :         (DHCPV6_OPTION_PD_EXCLUDE, Dhcpv6Handler::ByteArray)
     195             :         (DHCPV6_OPTION_VSS, Dhcpv6Handler::ByteArray)
     196             :         (DHCPV6_OPTION_MIP6_IDINF, Dhcpv6Handler::ByteArray)
     197             :         (DHCPV6_OPTION_MIP6_UDINF, Dhcpv6Handler::ByteArray)
     198             :         (DHCPV6_OPTION_MIP6_HNP, Dhcpv6Handler::ByteArray)
     199             :         (DHCPV6_OPTION_MIP6_HAA, Dhcpv6Handler::OneIPv6)
     200             :         (DHCPV6_OPTION_MIP6_HAF, Dhcpv6Handler::NameCompression)
     201             :         (DHCPV6_OPTION_RDNSS_SELECTION, Dhcpv6Handler::ByteArray)
     202             :         (DHCPV6_OPTION_KRB_PRINCIPAL_NAME, Dhcpv6Handler::ByteArray)
     203             :         (DHCPV6_OPTION_KRB_REALM_NAME, Dhcpv6Handler::ByteArray)
     204             :         (DHCPV6_OPTION_KRB_DEFAULT_REALM_NAME, Dhcpv6Handler::ByteArray)
     205             :         (DHCPV6_OPTION_KRB_KDC, Dhcpv6Handler::ByteArray)
     206             :         (DHCPV6_OPTION_CLIENT_LINKLAYER_ADDR, Dhcpv6Handler::ByteArray)
     207             :         (DHCPV6_OPTION_LINK_ADDRESS, Dhcpv6Handler::OneIPv6)
     208             :         (DHCPV6_OPTION_RADIUS, Dhcpv6Handler::ByteArray)
     209             :         (DHCPV6_OPTION_SOL_MAX_RT, Dhcpv6Handler::Uint32bit)
     210             :         (DHCPV6_OPTION_INF_MAX_RT, Dhcpv6Handler::Uint32bit)
     211             :         (DHCPV6_OPTION_ADDRSEL, Dhcpv6Handler::ByteArray)
     212             :         (DHCPV6_OPTION_ADDRSEL_TABLE, Dhcpv6Handler::ByteArray)
     213             :         (DHCPV6_OPTION_V6_PCP_SERVER, Dhcpv6Handler::OneIPv6Plus)
     214             :         (DHCPV6_OPTION_DHCPV4_MSG, Dhcpv6Handler::ByteArray)
     215             :         (DHCPV6_OPTION_DHCP4_O_DHCP6_SERVER, Dhcpv6Handler::ByteArray)
     216             :         (DHCPV6_OPTION_S46_RULE, Dhcpv6Handler::ByteArray)
     217             :         (DHCPV6_OPTION_S46_BR, Dhcpv6Handler::OneIPv6)
     218             :         (DHCPV6_OPTION_S46_DMR, Dhcpv6Handler::ByteArray)
     219             :         (DHCPV6_OPTION_S46_V4V6BIND, Dhcpv6Handler::ByteArray)
     220             :         (DHCPV6_OPTION_S46_PORTPARAMS, Dhcpv6Handler::ByteArray)
     221             :         (DHCPV6_OPTION_S46_CONT_MAPE, Dhcpv6Handler::ByteArray)
     222             :         (DHCPV6_OPTION_S46_CONT_MAPT, Dhcpv6Handler::ByteArray)
     223             :         (DHCPV6_OPTION_S46_CONT_LW, Dhcpv6Handler::ByteArray)
     224             :         (DHCPV6_OPTION_IPv6_ADDRESS_ANDSF, Dhcpv6Handler::OneIPv6Plus);
     225             : 
     226           0 : Dhcpv6Handler::Dhcpv6Handler(Agent *agent, boost::shared_ptr<PktInfo> info,
     227           0 :                              boost::asio::io_context &io)
     228             :         : DhcpHandlerBase(agent, info, io),
     229           0 :           msg_type_(DHCPV6_UNKNOWN), out_msg_type_(DHCPV6_UNKNOWN),
     230           0 :           rapid_commit_(false), reconfig_accept_(false),
     231           0 :           client_duid_len_(0), server_duid_len_(0),
     232           0 :           client_duid_(NULL), server_duid_(NULL), is_ia_na_(true) {
     233           0 :     memset(xid_, 0, sizeof(xid_));
     234           0 :     option_.reset(new Dhcpv6OptionHandler(NULL));
     235           0 : }
     236             : 
     237           0 : Dhcpv6Handler::~Dhcpv6Handler() {
     238           0 : }
     239             : 
     240           0 : bool Dhcpv6Handler::Run() {
     241           0 :     Dhcpv6Proto *dhcp_proto = agent()->dhcpv6_proto();
     242             :     // options length = pkt length - size of headers
     243           0 :     int16_t options_len = pkt_info_->len -
     244           0 :                           (pkt_info_->data - (uint8_t *)pkt_info_->pkt)
     245           0 :                           - DHCPV6_FIXED_LEN;
     246           0 :     if (options_len < 0) {
     247           0 :         dhcp_proto->IncrStatsError();
     248           0 :         DHCPV6_TRACE(Error, "Improper DHCPv6 packet length; vrf = " <<
     249             :                      pkt_info_->vrf << " ifindex = " << GetInterfaceIndex());
     250           0 :         return true;
     251             :     }
     252             : 
     253           0 :     dhcp_ = (Dhcpv6Hdr *) pkt_info_->data;
     254           0 :     option_->SetDhcpOptionPtr((uint8_t *)dhcp_ + DHCPV6_FIXED_LEN);
     255             :     // request_.UpdateData(dhcp_->xid, ntohs(dhcp_->flags), dhcp_->chaddr);
     256             :     Interface *itf =
     257           0 :         agent()->interface_table()->FindInterface(GetInterfaceIndex());
     258           0 :     if (itf == NULL) {
     259           0 :         dhcp_proto->IncrStatsError();
     260           0 :         DHCPV6_TRACE(Error, "Received DHCP packet on invalid interface : "
     261             :                      << GetInterfaceIndex());
     262           0 :         return true;
     263             :     }
     264             : 
     265           0 :     if (itf->type() != Interface::VM_INTERFACE) {
     266           0 :         dhcp_proto->IncrStatsError();
     267           0 :         DHCPV6_TRACE(Error, "Received DHCP packet on non VM port interface : "
     268             :                      << GetInterfaceIndex());
     269           0 :         return true;
     270             :     }
     271           0 :     vm_itf_ = static_cast<VmInterface *>(itf);
     272           0 :     if (!vm_itf_->dhcp_enable_v6_config()) {
     273           0 :         dhcp_proto->IncrStatsError();
     274           0 :         DHCPV6_TRACE(Error, "DHCP request on VM port with dhcp services disabled: "
     275             :                      << GetInterfaceIndex());
     276           0 :         return true;
     277             :     }
     278             : 
     279           0 :     msg_type_ = dhcp_->type;
     280           0 :     memcpy(xid_, dhcp_->xid, 3);
     281           0 :     ReadOptions(options_len);
     282             : 
     283           0 :     switch (msg_type_) {
     284           0 :         case DHCPV6_SOLICIT:
     285           0 :             out_msg_type_ = DHCPV6_ADVERTISE;
     286           0 :             dhcp_proto->IncrStatsSolicit();
     287           0 :             DHCPV6_TRACE(Trace, "DHCP solicit received on interface : "
     288             :                          << vm_itf_->name());
     289           0 :             break;
     290             : 
     291           0 :         case DHCPV6_REQUEST:
     292           0 :             out_msg_type_ = DHCPV6_REPLY;
     293           0 :             dhcp_proto->IncrStatsRequest();
     294           0 :             DHCPV6_TRACE(Trace, "DHCP request received on interface : "
     295             :                          << vm_itf_->name());
     296           0 :             break;
     297             : 
     298             :         // TODO: following messages require special handling
     299           0 :         case DHCPV6_CONFIRM:
     300           0 :             out_msg_type_ = DHCPV6_REPLY;
     301           0 :             dhcp_proto->IncrStatsConfirm();
     302           0 :             DHCPV6_TRACE(Trace, "DHCP confirm received on interface : "
     303             :                          << vm_itf_->name());
     304           0 :             break;
     305             : 
     306           0 :         case DHCPV6_RENEW:
     307           0 :             out_msg_type_ = DHCPV6_REPLY;
     308           0 :             dhcp_proto->IncrStatsRenew();
     309           0 :             DHCPV6_TRACE(Trace, "DHCP renew received on interface : "
     310             :                          << vm_itf_->name());
     311           0 :             break;
     312             : 
     313           0 :         case DHCPV6_REBIND:
     314           0 :             out_msg_type_ = DHCPV6_REPLY;
     315           0 :             dhcp_proto->IncrStatsRebind();
     316           0 :             DHCPV6_TRACE(Trace, "DHCP bind received on interface : "
     317             :                          << vm_itf_->name());
     318           0 :             break;
     319             : 
     320           0 :         case DHCPV6_RELEASE:
     321           0 :             out_msg_type_ = DHCPV6_REPLY;
     322           0 :             dhcp_proto->IncrStatsRelease();
     323           0 :             DHCPV6_TRACE(Trace, "DHCP release received on interface : "
     324             :                          << vm_itf_->name());
     325           0 :             break;
     326             : 
     327           0 :         case DHCPV6_DECLINE:
     328           0 :             out_msg_type_ = DHCPV6_REPLY;
     329           0 :             dhcp_proto->IncrStatsDecline();
     330           0 :             DHCPV6_TRACE(Trace, "DHCP decline received on interface : "
     331             :                          << vm_itf_->name());
     332           0 :             break;
     333             : 
     334           0 :         case DHCPV6_RECONFIGURE:
     335           0 :             dhcp_proto->IncrStatsReconfigure();
     336           0 :             DHCPV6_TRACE(Trace, "DHCP reconfigure received on interface : "
     337             :                          << vm_itf_->name());
     338           0 :             break;
     339             : 
     340           0 :         case DHCPV6_INFORMATION_REQUEST:
     341           0 :             dhcp_proto->IncrStatsInformationRequest();
     342           0 :             DHCPV6_TRACE(Trace,
     343             :                          "DHCP information request received on interface : "
     344             :                          << vm_itf_->name());
     345           0 :             break;
     346             : 
     347           0 :         default:
     348           0 :             DHCPV6_TRACE(Trace, "DHCP message " << msg_type_ <<
     349             :                          " received on interface : " << vm_itf_->name() <<
     350             :                        "; ignoring");
     351           0 :             dhcp_proto->IncrStatsError();
     352           0 :             return true;
     353             :     }
     354             : 
     355           0 :     if (FindLeaseData()) {
     356           0 :         SendDhcpResponse();
     357           0 :         DHCPV6_TRACE(Trace, "DHCP response sent; message = " <<
     358             :                      ServicesSandesh::Dhcpv6MsgType(out_msg_type_) <<
     359             :                      "; ip = " << config_.ip_addr.to_string());
     360             :     }
     361             : 
     362           0 :     return true;
     363             : }
     364             : 
     365             : // read DHCP options in the incoming packet
     366           0 : void Dhcpv6Handler::ReadOptions(int16_t opt_rem_len) {
     367           0 :     Dhcpv6Options *opt = reinterpret_cast<Dhcpv6Options *>(
     368           0 :         (uint8_t *)dhcp_ + DHCPV6_FIXED_LEN);
     369             :     // parse thru the option fields
     370           0 :     while (opt_rem_len > 0) {
     371           0 :         uint16_t option_code = ntohs(opt->code);
     372           0 :         uint16_t option_len = ntohs(opt->len);
     373           0 :         if (option_len > opt_rem_len) {
     374           0 :             DHCPV6_TRACE(Error, "DHCP option parsing error");
     375           0 :             break;
     376             :         }
     377           0 :         switch (option_code) {
     378           0 :             case DHCPV6_OPTION_CLIENTID:
     379           0 :                 client_duid_len_ = option_len;
     380           0 :                 client_duid_.reset(new uint8_t[client_duid_len_]);
     381           0 :                 memcpy(client_duid_.get(), opt->data, client_duid_len_);
     382           0 :                 break;
     383             : 
     384           0 :             case DHCPV6_OPTION_SERVERID:
     385           0 :                 server_duid_len_ = option_len;
     386           0 :                 server_duid_.reset(new uint8_t[server_duid_len_]);
     387           0 :                 memcpy(server_duid_.get(), opt->data, server_duid_len_);
     388           0 :                 break;
     389             : 
     390           0 :             case DHCPV6_OPTION_IA_NA:
     391           0 :                 is_ia_na_ = true;
     392           0 :                 ReadIA(opt->data, option_len, option_code);
     393           0 :                 break;
     394             : 
     395           0 :             case DHCPV6_OPTION_IA_TA:
     396           0 :                 is_ia_na_ = false;
     397           0 :                 ReadIA(opt->data, option_len, option_code);
     398           0 :                 break;
     399             : 
     400           0 :             case DHCPV6_OPTION_RAPID_COMMIT:
     401           0 :                 rapid_commit_ = true;
     402           0 :                 break;
     403             : 
     404           0 :             case DHCPV6_OPTION_RECONF_ACCEPT:
     405           0 :                 reconfig_accept_ = true;
     406           0 :                 break;
     407             : 
     408           0 :             case DHCPV6_OPTION_ORO: // list of requested options
     409             :             case DHCPV6_OPTION_PREFERENCE: // server preference, sent by server
     410             :             case DHCPV6_OPTION_ELAPSED_TIME: // time client has been trying
     411             :             case DHCPV6_OPTION_RELAY_MSG: // relay DHCP types are not handled
     412             :             case DHCPV6_OPTION_AUTH: // authentication
     413             :             case DHCPV6_OPTION_UNICAST: // server option, sent to get ucast msgs
     414             :             case DHCPV6_OPTION_USER_CLASS: // type of user
     415             :             case DHCPV6_OPTION_VENDOR_CLASS: // vendor
     416             :             case DHCPV6_OPTION_VENDOR_OPTS:
     417             :             case DHCPV6_OPTION_INTERFACE_ID: // used by relay agent
     418             :             case DHCPV6_OPTION_RECONF_MSG: // can only appear in reconfigure msg
     419             :                 // ignore these options
     420           0 :                 break;
     421             : 
     422           0 :             default:
     423           0 :                 break;
     424             :         }
     425           0 :         opt_rem_len -= (4 + option_len);
     426           0 :         opt = (Dhcpv6Options *)((uint8_t *)opt + 4 + option_len);
     427             :     }
     428           0 : }
     429             : 
     430           0 : bool Dhcpv6Handler::ReadIA(uint8_t *ptr, uint16_t len, uint16_t code) {
     431           0 :     if (ia_na_.get() == NULL) {
     432           0 :         ia_na_.reset(new Dhcpv6IaData());
     433             :     }
     434             : 
     435           0 :     ia_na_->AddIa((Dhcpv6Ia *)ptr);
     436             : 
     437           0 :     int16_t iana_rem_len = len - sizeof(Dhcpv6Ia);
     438           0 :     Dhcpv6Options *iana_option = (Dhcpv6Options *)(ptr + sizeof(Dhcpv6Ia));
     439           0 :     while (iana_rem_len > 0) {
     440           0 :         uint16_t iana_option_code = ntohs(iana_option->code);
     441           0 :         uint16_t iana_option_len = ntohs(iana_option->len);
     442           0 :         switch (iana_option_code) {
     443           0 :             case DHCPV6_OPTION_IAADDR: {
     444           0 :                 ia_na_->AddIaAddr((Dhcpv6IaAddr *)iana_option->data);
     445           0 :                 break;
     446             :             }
     447             : 
     448           0 :             case DHCPV6_OPTION_STATUS_CODE: {
     449           0 :                 uint16_t *s_ptr = reinterpret_cast<uint16_t *>
     450             :                                       (iana_option->data);
     451           0 :                 uint16_t status = ntohs(*s_ptr);
     452           0 :                 if (status != DHCPV6_SUCCESS) {
     453           0 :                     std::string msg((const char *)iana_option->data + 2,
     454           0 :                                     iana_option_len - 2);
     455           0 :                     DHCPV6_TRACE(Trace, "DHCP message with error status : " <<
     456             :                                  status <<  " error msg : " << msg <<
     457             :                                  "; received on interface : " <<
     458             :                                  vm_itf_->name() << "; ignoring");
     459           0 :                 }
     460           0 :                 return false;
     461             :             }
     462             : 
     463           0 :             default:
     464           0 :                 break;
     465             :         }
     466           0 :         iana_rem_len -= (4 + iana_option_len);
     467           0 :         iana_option = (Dhcpv6Options *)((uint8_t *)iana_option + 4 + iana_option_len);
     468             :     }
     469             : 
     470           0 :     return true;
     471             : }
     472             : 
     473           0 : void Dhcpv6Handler::FillDhcpInfo(Ip6Address &addr, int plen,
     474             :                                  Ip6Address &gw, Ip6Address &dns) {
     475           0 :     config_.ip_addr = addr;
     476           0 :     config_.plen = plen;
     477           0 :     config_.gw_addr = gw;
     478           0 :     config_.dns_addr = dns;
     479           0 : }
     480             : 
     481           0 : bool Dhcpv6Handler::FindLeaseData() {
     482           0 :     Ip6Address ip = vm_itf_->primary_ip6_addr();
     483           0 :     FindDomainName(ip);
     484           0 :     if (vm_itf_->IsActive()) {
     485           0 :         if (vm_itf_->fabric_port()) {
     486             :             // TODO
     487           0 :             agent()->dhcpv6_proto()->IncrStatsError();
     488           0 :             DHCPV6_TRACE(Error, "DHCP fabric port request failed for : "
     489             :                          << ip.to_string());
     490           0 :             return false;
     491             :         }
     492             : 
     493           0 :         const std::vector<VnIpam> &ipam = vm_itf_->vn()->GetVnIpam();
     494           0 :         for (uint32_t i = 0; i < ipam.size(); ++i) {
     495           0 :             if (!ipam[i].IsV6()) {
     496           0 :                 continue;
     497             :             }
     498           0 :             if (IsIp6SubnetMember(ip, ipam[i].ip_prefix.to_v6(),
     499           0 :                                   ipam[i].plen)) {
     500           0 :                 Ip6Address default_gw;
     501           0 :                 if (ipam[i].default_gw.is_v6()) {
     502           0 :                     default_gw = ipam[i].default_gw.to_v6();
     503             :                 }
     504           0 :                 Ip6Address service_address;
     505           0 :                 if (ipam[i].dns_server.is_unspecified()) {
     506           0 :                     service_address = default_gw;
     507             :                 } else {
     508           0 :                     if (ipam[i].dns_server.is_v6()) {
     509           0 :                         service_address = ipam[i].dns_server.to_v6();
     510             :                     }
     511             :                 }
     512           0 :                 FillDhcpInfo(ip, ipam[i].plen, default_gw, service_address);
     513           0 :                 return true;
     514             :             }
     515             :         }
     516             :     }
     517             : 
     518             :     // We dont have the config yet; give a short lease
     519           0 :     config_.preferred_time = DHCPV6_SHORTLEASE_TIME;
     520           0 :     config_.valid_time = 2 * DHCPV6_SHORTLEASE_TIME;
     521             :     // Give address received from Nova
     522           0 :     Ip6Address empty;
     523           0 :     FillDhcpInfo(ip, 128, empty, empty);
     524           0 :     DHCPV6_TRACE(Trace, "DHCP giving short lease given for : " << ip.to_string()
     525             :                  << "; IPv6 not active in Agent");
     526           0 :     return true;
     527             : }
     528             : 
     529             : // Add an IP address to the option
     530           0 : uint16_t Dhcpv6Handler::AddIP(uint16_t opt_len, const std::string &input) {
     531           0 :     boost::system::error_code ec;
     532           0 :     Ip6Address ip = Ip6Address::from_string(input, ec);
     533           0 :     if (!ec.value()) {
     534           0 :         option_->AppendData(16, ip.to_bytes().data(), &opt_len);
     535             :     } else {
     536           0 :         DHCPV6_TRACE(Error, "Invalid DHCP option " << option_->GetCode() <<
     537             :                      " for VM " << config_.ip_addr.to_string() <<
     538             :                      "; has to be IP address");
     539             :     }
     540           0 :     return opt_len;
     541             : }
     542             : 
     543             : // Add domain name from IPAM to the option
     544           0 : uint16_t Dhcpv6Handler::AddDomainNameOption(uint16_t opt_len) {
     545           0 :     if (ipam_type_.ipam_dns_method == "virtual-dns-server") {
     546           0 :         if (is_dns_enabled() && config_.domain_name_.size()) {
     547             :             // encode the domain name in the dns encoding format
     548           0 :             boost::scoped_array<uint8_t> domain_name(new uint8_t[config_.domain_name_.size() * 2 + 2]);
     549           0 :             uint16_t len = 0;
     550           0 :             BindUtil::AddName(domain_name.get(), config_.domain_name_, 0, 0, len);
     551           0 :             option_->WriteData(DHCPV6_OPTION_DOMAIN_LIST, len,
     552           0 :                                domain_name.get(), &opt_len);
     553           0 :         }
     554             :     }
     555           0 :     return opt_len;
     556             : }
     557             : 
     558           0 : uint16_t Dhcpv6Handler::FillDhcpv6Hdr() {
     559           0 :     Dhcpv6Proto *dhcp_proto = agent()->dhcpv6_proto();
     560             : 
     561           0 :     dhcp_->type = out_msg_type_;
     562           0 :     memcpy(dhcp_->xid, xid_, 3);
     563             : 
     564           0 :     uint16_t opt_len = 0;
     565             : 
     566             :     // server duid
     567           0 :     option_->SetNextOptionPtr(opt_len);
     568           0 :     option_->WriteData(DHCPV6_OPTION_SERVERID, sizeof(Dhcpv6Proto::Duid),
     569           0 :                        (void *)dhcp_proto->server_duid(), &opt_len);
     570             : 
     571             :     // client duid
     572           0 :     if (client_duid_len_) {
     573           0 :         option_->SetNextOptionPtr(opt_len);
     574           0 :         option_->WriteData(DHCPV6_OPTION_CLIENTID, client_duid_len_,
     575           0 :                            (void *)client_duid_.get(), &opt_len);
     576             :     }
     577             : 
     578             :     // IA
     579           0 :     option_->SetNextOptionPtr(opt_len);
     580           0 :     WriteIaOption(opt_len);
     581             : 
     582             :     // Add dhcp options coming from Config
     583           0 :     opt_len = AddConfigDhcpOptions(opt_len, true);
     584             : 
     585             :     // GW doesnt come in DHCPV6, it should come via router advertisement
     586             : 
     587           0 :     if (!is_flag_set(DHCPV6_OPTION_DNS_SERVERS)) {
     588           0 :         uint16_t old_opt_len = opt_len;
     589           0 :         option_->SetNextOptionPtr(opt_len);
     590           0 :         option_->WriteData(DHCPV6_OPTION_DNS_SERVERS, 0, NULL, &opt_len);
     591           0 :         opt_len = AddDnsServers(opt_len);
     592             :         // if there was no DNS server, revert the option
     593           0 :         if (opt_len == old_opt_len + option_->GetFixedLen())
     594           0 :             opt_len = old_opt_len;
     595             :     }
     596             : 
     597           0 :     if (!is_flag_set(DHCPV6_OPTION_DOMAIN_LIST)) {
     598           0 :         option_->SetNextOptionPtr(opt_len);
     599           0 :         opt_len = AddDomainNameOption(opt_len);
     600             :     }
     601             : 
     602           0 :     return (DHCPV6_FIXED_LEN + opt_len);
     603             : }
     604             : 
     605           0 : void Dhcpv6Handler::IncrementByteInAddress(Ip6Address::bytes_type &bytes, uint8_t index) {
     606           0 :     if (index > 15) {
     607           0 :         return;
     608             :     }
     609           0 :     bytes[index]++;
     610           0 :     if (bytes[index] != 0) {
     611           0 :         return;
     612             :     } else {
     613           0 :         IncrementByteInAddress(bytes, index - 1);
     614             :     }
     615             : }
     616             : 
     617           0 : Ip6Address Dhcpv6Handler::GetNextV6Address(uint8_t addr[16]) {
     618             :     Ip6Address::bytes_type bytes;
     619           0 :     for (int i = 0; i < 16; i++) {
     620           0 :         bytes[i] = addr[i];
     621             :     }
     622           0 :     IncrementByteInAddress(bytes, 15);
     623           0 :     return Ip6Address(bytes);
     624             : }
     625             : 
     626           0 : void Dhcpv6Handler::WriteIaOption(uint16_t &optlen) {
     627           0 :     if (ia_na_.get() == NULL) {
     628           0 :         return;
     629             :     }
     630             : 
     631           0 :     uint32_t alloc_unit = 1;
     632             :     // for ia_ta, send only one address
     633           0 :     if (vm_itf_ && vm_itf_->vn() && is_ia_na_) {
     634           0 :         alloc_unit = vm_itf_->vn()->GetAllocUnitFromIpam(config_.ip_addr);
     635             :     }
     636           0 :     if (alloc_unit > 128) {
     637           0 :         DHCPV6_TRACE(Error, "Alloc-unit(" << alloc_unit << ") in Ipam is"
     638             :                      " higher than supported value(128), using max supported"
     639             :                      " value");
     640           0 :         alloc_unit = 128;
     641             :     }
     642           0 :     Dhcpv6IaAddr ia_addr(config_.ip_addr.to_v6().to_bytes().data(),
     643             :                          config_.preferred_time,
     644           0 :                          config_.valid_time);
     645             : 
     646           0 :     uint16_t ia_option = (is_ia_na_)? DHCPV6_OPTION_IA_NA : DHCPV6_OPTION_IA_TA;
     647           0 :     uint16_t ia_option_length = (is_ia_na_)? sizeof(Dhcpv6Ia) : 16;
     648           0 :     option_->WriteData(ia_option, ia_option_length, (void *)&ia_na_->ia, &optlen);
     649             : 
     650           0 :     for (uint32_t i = 0; i < alloc_unit; i++) {
     651           0 :         Dhcpv6Options *ia_addr_opt = GetNextOptionPtr(optlen);
     652           0 :         if (msg_type_ != DHCPV6_CONFIRM ||
     653           0 :             (msg_type_ == DHCPV6_CONFIRM && ia_na_->DelIaAddr(ia_addr))) {
     654           0 :             ia_addr_opt->WriteData(DHCPV6_OPTION_IAADDR, sizeof(Dhcpv6IaAddr),
     655             :                                    (void *)&ia_addr, &optlen);
     656           0 :             option_->AddLen(sizeof(Dhcpv6IaAddr) + 4);
     657             :         }
     658           0 :         Ip6Address next_ip = GetNextV6Address(ia_addr.address);
     659           0 :         memcpy(ia_addr.address, next_ip.to_bytes().data(), 16);
     660             :     }
     661             : 
     662             :     // in case of confirm, if there are any remaining addresses in ia_na_
     663             :     // add them with status as "NotOnLink".
     664           0 :     if (msg_type_ == DHCPV6_CONFIRM && !ia_na_->ia_addr.empty()) {
     665           0 :         for (std::vector<Dhcpv6IaAddr>::iterator it = ia_na_->ia_addr.begin();
     666           0 :              it != ia_na_->ia_addr.end(); ++it) {
     667           0 :             memcpy(ia_addr.address, it->address, 16);
     668           0 :             Dhcpv6Options *ia_addr_opt = GetNextOptionPtr(optlen);
     669           0 :             ia_addr_opt->WriteData(DHCPV6_OPTION_IAADDR, sizeof(Dhcpv6IaAddr),
     670             :                                    (void *)&ia_addr, &optlen);
     671           0 :             option_->AddLen(sizeof(Dhcpv6IaAddr) + 4);
     672           0 :             ia_addr_opt = GetNextOptionPtr(optlen);
     673           0 :             std::string message = "Some of the addresses are not on link";
     674           0 :             uint16_t status_code = htons(DHCPV6_NOT_ON_LINK);
     675           0 :             ia_addr_opt->WriteData(DHCPV6_OPTION_STATUS_CODE, 2,
     676             :                                    (void *)&status_code, &optlen);
     677           0 :             ia_addr_opt->AppendData(message.length(), message.c_str(), &optlen);
     678           0 :             option_->AddLen(message.length() + 6);
     679           0 :         }
     680             :     }
     681             : }
     682             : 
     683           0 : uint16_t Dhcpv6Handler::FillDhcpResponse(const MacAddress &dest_mac,
     684             :                                          Ip6Address src_ip, Ip6Address dest_ip) {
     685           0 :     pkt_info_->eth = (struct ether_header *)(pkt_info_->pkt);
     686           0 :     uint16_t eth_len = 0;
     687           0 :     eth_len = EthHdr((char *)pkt_info_->eth,
     688           0 :                      pkt_info_->packet_buffer()->data_len(),
     689             :                      GetInterfaceIndex(),
     690             :                      agent()->vhost_interface()->mac(), dest_mac,
     691             :                      ETHERTYPE_IPV6);
     692           0 :     pkt_info_->ip6 = (struct ip6_hdr *)((char *)pkt_info_->eth + eth_len);
     693           0 :     pkt_info_->transp.udp = (udphdr *)(pkt_info_->ip6 + 1);
     694           0 :     dhcp_ = (Dhcpv6Hdr *)(pkt_info_->transp.udp + 1);
     695           0 :     option_->SetDhcpOptionPtr((uint8_t *)dhcp_ + DHCPV6_FIXED_LEN);
     696             : 
     697           0 :     uint16_t len = FillDhcpv6Hdr();
     698           0 :     len += sizeof(udphdr);
     699           0 :     UdpHdr(len, src_ip.to_bytes().data(), DHCPV6_SERVER_PORT,
     700           0 :            dest_ip.to_bytes().data(), DHCPV6_CLIENT_PORT, IPPROTO_UDP);
     701           0 :     Ip6Hdr(pkt_info_->ip6, len, IPPROTO_UDP, 64, src_ip.to_bytes().data(),
     702           0 :            dest_ip.to_bytes().data());
     703           0 :     len += sizeof(ip6_hdr);
     704             : 
     705           0 :     pkt_info_->set_len(len + eth_len);
     706           0 :     return pkt_info_->packet_buffer()->data_len();
     707             : }
     708             : 
     709           0 : void Dhcpv6Handler::SendDhcpResponse() {
     710           0 :     UpdateStats();
     711             :     // In TSN, the source address for DHCP response should be the address
     712             :     // in the subnet reserved for service node. Otherwise, it will be the
     713             :     // GW address. dns_addr field has this address, use it as the source IP.
     714           0 :     FillDhcpResponse(MacAddress(pkt_info_->eth->ether_shost),
     715           0 :                      config_.dns_addr.to_v6(),
     716           0 :                      pkt_info_->ip_saddr.to_v6());
     717             :     uint32_t interface =
     718           0 :         (pkt_info_->agent_hdr.cmd == AgentHdr::TRAP_TOR_CONTROL_PKT) ?
     719           0 :         pkt_info_->agent_hdr.cmd_param : GetInterfaceIndex();
     720             :     uint16_t command =
     721           0 :         (pkt_info_->agent_hdr.cmd == AgentHdr::TRAP_TOR_CONTROL_PKT) ?
     722           0 :         (uint16_t)AgentHdr::TX_ROUTE : AgentHdr::TX_SWITCH;
     723           0 :     Send(interface, pkt_info_->vrf, command, PktHandler::DHCPV6);
     724           0 : }
     725             : 
     726           0 : void Dhcpv6Handler::UpdateStats() {
     727           0 :     Dhcpv6Proto *dhcp_proto = agent()->dhcpv6_proto();
     728           0 :     (out_msg_type_ == DHCPV6_ADVERTISE) ? dhcp_proto->IncrStatsAdvertise() :
     729           0 :                                           dhcp_proto->IncrStatsReply();
     730           0 : }
     731             : 
     732             : Dhcpv6Handler::DhcpOptionCategory
     733           0 : Dhcpv6Handler::OptionCategory(uint32_t option) const {
     734           0 :     Dhcpv6CategoryIter iter = g_dhcpv6_category_map.find(option);
     735           0 :     if (iter == g_dhcpv6_category_map.end())
     736           0 :         return None;
     737           0 :     return iter->second;
     738             : }
     739             : 
     740           0 : uint32_t Dhcpv6Handler::OptionCode(const std::string &option) const {
     741             :     Dhcpv6NameCodeIter iter =
     742           0 :         g_dhcpv6_namecode_map.find(boost::to_lower_copy(option));
     743           0 :     return (iter == g_dhcpv6_namecode_map.end()) ? 0 : iter->second;
     744             : }
     745             : 
     746           0 : void Dhcpv6Handler::DhcpTrace(const std::string &msg) const {
     747           0 :     DHCPV6_TRACE(Error, "VM " << config_.ip_addr.to_string() << " : " << msg);
     748           0 : }

Generated by: LCOV version 1.14