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

Generated by: LCOV version 1.14