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 "oper/vn.h"
13 : #include "pkt/pkt_init.h"
14 : #include "services/dhcp_proto.h"
15 : #include "services/dhcp_lease_db.h"
16 : #include "services/services_types.h"
17 : #include "services/services_init.h"
18 : #include "services/dns_proto.h"
19 : #include "services/services_sandesh.h"
20 : #include "bind/bind_util.h"
21 : #include "bind/xmpp_dns_agent.h"
22 :
23 : #include <boost/assign/list_of.hpp>
24 : #include <bind/bind_util.h>
25 :
26 : using namespace boost::assign;
27 : Dhcpv4NameCodeMap g_dhcpv4_namecode_map =
28 : map_list_of<std::string, uint32_t>
29 : ("subnet-mask", DHCP_OPTION_SUBNET_MASK)
30 : ("time-offset", DHCP_OPTION_TIME_OFFSET)
31 : ("routers", DHCP_OPTION_ROUTER)
32 : ("time-servers", DHCP_OPTION_TIME_SERVER)
33 : ("name-servers", DHCP_OPTION_NAME_SERVER)
34 : ("domain-name-servers", DHCP_OPTION_DNS)
35 : ("log-servers", DHCP_OPTION_LOG_SERVER)
36 : ("quote-servers", DHCP_OPTION_QUOTE_SERVER)
37 : ("lpr-servers", DHCP_OPTION_LPR_SERVER)
38 : ("impress-servers", DHCP_OPTION_IMPRESS_SERVER)
39 : ("resource-location-servers", DHCP_OPTION_RESOURCE_LOCATION_SERVER)
40 : ("host-name", DHCP_OPTION_HOST_NAME)
41 : ("boot-size", DHCP_OPTION_BOOT_FILE_SIZE)
42 : ("merit-dump", DHCP_OPTION_MERIT_DUMP_FILE)
43 : ("domain-name", DHCP_OPTION_DOMAIN_NAME)
44 : ("swap-server", DHCP_OPTION_SWAP_SERVER)
45 : ("root-path", DHCP_OPTION_ROOT_PATH)
46 : ("extension-path", DHCP_OPTION_EXTENSION_PATH)
47 : ("ip-forwarding", DHCP_OPTION_IP_FWD_CONTROL)
48 : ("non-local-source-routing", DHCP_OPTION_NL_SRC_ROUTING)
49 : ("policy-filter", DHCP_OPTION_POLICY_FILTER)
50 : ("max-dgram-reassembly", DHCP_OPTION_MAX_DG_REASSEMBLY_SIZE)
51 : ("default-ip-ttl", DHCP_OPTION_DEFAULT_IP_TTL)
52 : ("path-mtu-aging-timeout", DHCP_OPTION_PATH_MTU_AGING_TIMEOUT)
53 : ("path-mtu-plateau-table", DHCP_OPTION_PATH_MTU_PLATEAU_TABLE)
54 : ("interface-mtu", DHCP_OPTION_INTERFACE_MTU)
55 : ("all-subnets-local", DHCP_OPTION_ALL_SUBNETS_LOCAL)
56 : ("broadcast-address", DHCP_OPTION_BCAST_ADDRESS)
57 : ("perform-mask-discovery", DHCP_OPTION_PERFORM_MASK_DISCOVERY)
58 : ("mask-supplier", DHCP_OPTION_MASK_SUPPLIER)
59 : ("router-discovery", DHCP_OPTION_PERFORM_ROUTER_DISCOVERY)
60 : ("router-solicitation-address", DHCP_OPTION_ROUTER_SOLICIT_ADDRESS)
61 : ("static-routes", DHCP_OPTION_STATIC_ROUTING_TABLE)
62 : ("trailer-encapsulation", DHCP_OPTION_TRAILER_ENCAP)
63 : ("arp-cache-timeout", DHCP_OPTION_ARP_CACHE_TIMEOUT)
64 : ("ieee802-3-encapsulation", DHCP_OPTION_ETHERNET_ENCAP)
65 : ("default-tcp-ttl", DHCP_OPTION_DEFAULT_TCP_TTL)
66 : ("tcp-keepalive-interval", DHCP_OPTION_TCP_KEEPALIVE_INTERVAL)
67 : ("tcp-keepalive-garbage", DHCP_OPTION_TCP_KEEPALIVE_GARBAGE)
68 : ("nis-domain", DHCP_OPTION_NIS_DOMAIN)
69 : ("nis-servers", DHCP_OPTION_NIS_SERVERS)
70 : ("ntp-servers", DHCP_OPTION_NTP_SERVERS)
71 : ("vendor-encapsulated-options", DHCP_OPTION_VENDOR_SPECIFIC_INFO)
72 : ("netbios-name-servers", DHCP_OPTION_NETBIOS_OVER_TCP_NS)
73 : ("netbios-dd-server", DHCP_OPTION_NETBIOS_OVER_TCP_DG_DS)
74 : ("netbios-node-type", DHCP_OPTION_NETBIOS_OVER_TCP_NODE_TYPE)
75 : ("netbios-scope", DHCP_OPTION_NETBIOS_OVER_TCP_SCOPE)
76 : ("font-servers", DHCP_OPTION_XWINDOW_FONT_SERVER)
77 : ("x-display-manager", DHCP_OPTION_XWINDOW_SYSTEM_DISP_MGR)
78 : ("dhcp-requested-address", DHCP_OPTION_REQ_IP_ADDRESS)
79 : ("dhcp-lease-time", DHCP_OPTION_IP_LEASE_TIME)
80 : ("dhcp-option-overload", DHCP_OPTION_OVERLOAD)
81 : ("dhcp-message-type", DHCP_OPTION_MSG_TYPE)
82 : ("dhcp-server-identifier", DHCP_OPTION_SERVER_IDENTIFIER)
83 : ("dhcp-parameter-request-list", DHCP_OPTION_PARAMETER_REQUEST_LIST)
84 : ("dhcp-message", DHCP_OPTION_MESSAGE)
85 : ("dhcp-max-message-size", DHCP_OPTION_MAX_DHCP_MSG_SIZE)
86 : ("dhcp-renewal-time", DHCP_OPTION_RENEW_TIME_VALUE)
87 : ("dhcp-rebinding-time", DHCP_OPTION_REBIND_TIME_VALUE)
88 : ("class-id", DHCP_OPTION_CLASS_ID)
89 : ("dhcp-client-identifier", DHCP_OPTION_CLIENT_ID)
90 : ("nwip-domain", DHCP_OPTION_NETWARE_IP_DOMAIN_NAME)
91 : ("nwip-suboptions", DHCP_OPTION_NETWARE_IP_INFO)
92 : ("nisplus-domain", DHCP_OPTION_NIS_PLUS_DOMAIN)
93 : ("nisplus-servers", DHCP_OPTION_NIS_PLUS_SERVERS)
94 : ("tftp-server-name", DHCP_OPTION_TFTP_SERVER_NAME)
95 : ("bootfile-name", DHCP_OPTION_BOOTFILE_NAME)
96 : ("mobile-ip-home-agent", DHCP_OPTION_MOBILE_IP_HA)
97 : ("smtp-server", DHCP_OPTION_SMTP_SERVER)
98 : ("pop-server", DHCP_OPTION_POP_SERVER)
99 : ("nntp-server", DHCP_OPTION_NNTP_SERVER)
100 : ("www-server", DHCP_OPTION_DEFAULT_WWW_SERVER)
101 : ("finger-server", DHCP_OPTION_DEFAULT_FINGER_SERVER)
102 : ("irc-server", DHCP_OPTION_DEFAULT_IRC_SERVER)
103 : ("streettalk-server", DHCP_OPTION_STREETTALK_SERVER)
104 : ("streettalk-directory-assistance-server", DHCP_OPTION_STREETTALK_DA_SERVER)
105 : ("user-class", DHCP_OPTION_USER_CLASS_INFO)
106 : ("slp-directory-agent", DHCP_OPTION_SLP_DIRECTORY_AGENT)
107 : ("slp-service-scope", DHCP_OPTION_SLP_SERVICE_SCOPE)
108 : ("rapid-commit", DHCP_OPTION_RAPID_COMMIT)
109 : ("client-fqdn", DHCP_OPTION_CLIENT_FQDN)
110 : ("storage-ns", DHCP_OPTION_STORAGE_NS)
111 : // option 82 not required
112 : ("nds-servers", DHCP_OPTION_NDS_SERVERS)
113 : ("nds-tree-name", DHCP_OPTION_NDS_TREE_NAME)
114 : ("nds-context", DHCP_OPTION_NDS_CONTEXT)
115 : ("bcms-controller-names", DHCP_OPTION_BCMCS_DN_LIST)
116 : ("bcms-controller-address", DHCP_OPTION_BCMCS_ADDR_LIST)
117 : ("dhcp-auth", DHCP_OPTION_AUTH)
118 : ("dhcp-client-last-time", DHCP_OPTION_CLIENT_LAST_XTIME)
119 : ("associated-ip", DHCP_OPTION_ASSOCIATE_IP)
120 : ("system-architecture", DHCP_OPTION_CLIENT_SYSARCH_TYPE)
121 : ("interface-id", DHCP_OPTION_CLIENT_NW_INTERFACE_ID)
122 : ("ldap-servers", DHCP_OPTION_LDAP)
123 : ("machine-id", DHCP_OPTION_CLIENT_MACHINE_ID)
124 : ("user-auth", DHCP_OPTION_OPENGROUP_USER_AUTH)
125 : ("geoconf-civic", DHCP_OPTION_GEOCONF_CIVIC)
126 : ("ieee-1003-1-tz", DHCP_OPTION_IEEE_1003_1_TZ)
127 : ("ref-tz-db", DHCP_OPTION_REF_TZ_DB)
128 : ("netinfo-server-address", DHCP_OPTION_NETINFO_PARENT_SERVER_ADDR)
129 : ("netinfo-server-tag", DHCP_OPTION_NETINFO_PARENT_SERVER_TAG)
130 : ("default-url", DHCP_OPTION_URL)
131 : ("auto-configure", DHCP_OPTION_AUTO_CONFIGURE)
132 : ("name-search", DHCP_OPTION_NAME_SERVICE_SEARCH)
133 : ("subnet-selection", DHCP_OPTION_SUBNET_SELECTION)
134 : ("domain-search", DHCP_OPTION_DNS_DOMAIN_SEARCH_LIST)
135 : ("sip-servers", DHCP_OPTION_SIP_SERVERS)
136 : ("classless-static-routes", DHCP_OPTION_CLASSLESS_ROUTE)
137 : ("dhcp-ccc", DHCP_OPTION_CCC)
138 : ("dhcp-geoconf", DHCP_OPTION_GEOCONF)
139 : ("vendor-class-identifier", DHCP_OPTION_VENDOR_ID_VENDOR_CLASS)
140 : ("vivso", DHCP_OPTION_VENDOR_ID_VENDOR_SPECIFIC)
141 : ("tftp-server", DHCP_OPTION_TFTP_SERVER)
142 : ("pxe-vendor-specific-129", DHCP_OPTION_PXE_VENDOR_SPECIFIC_129)
143 : ("pxe-vendor-specific-130", DHCP_OPTION_PXE_VENDOR_SPECIFIC_130)
144 : ("pxe-vendor-specific-131", DHCP_OPTION_PXE_VENDOR_SPECIFIC_131)
145 : ("pxe-vendor-specific-132", DHCP_OPTION_PXE_VENDOR_SPECIFIC_132)
146 : ("pxe-vendor-specific-133", DHCP_OPTION_PXE_VENDOR_SPECIFIC_133)
147 : ("pxe-vendor-specific-134", DHCP_OPTION_PXE_VENDOR_SPECIFIC_134)
148 : ("pxe-vendor-specific-135", DHCP_OPTION_PXE_VENDOR_SPECIFIC_135)
149 : ("pana-agent", DHCP_OPTION_PANA_AUTH_AGENT)
150 : ("lost-server", DHCP_OPTION_LOST_SERVER)
151 : ("capwap-ac-v4", DHCP_OPTION_CAPWAP_AC_ADDRESS)
152 : ("dhcp-mos", DHCP_OPTION_IPV4_ADDRESS_MOS)
153 : ("dhcp-fqdn-mos", DHCP_OPTION_IPV4_FQDN_MOS)
154 : ("sip-ua-config-domain", DHCP_OPTION_SIP_UA_CONFIG_DOMAIN)
155 : ("andsf-servers", DHCP_OPTION_IPV4_ADDRESS_ANDSF)
156 : ("dhcp-geoloc", DHCP_OPTION_GEOLOC)
157 : ("force-renew-nonce-cap", DHCP_OPTION_FORCERENEW_NONCE_CAP)
158 : ("rdnss-selection", DHCP_OPTION_RDNSS_SELECTION)
159 : ("tftp-server-address", DHCP_OPTION_TFTP_SERVER_ADDRESS)
160 : ("status-code", DHCP_OPTION_STATUS_CODE)
161 : ("dhcp-base-time", DHCP_OPTION_BASE_TIME)
162 : ("dhcp-state-start-time", DHCP_OPTION_START_TIME_OF_STATE)
163 : ("dhcp-query-start-time", DHCP_OPTION_QUERY_START_TIME)
164 : ("dhcp-query-end-time", DHCP_OPTION_QUERY_END_TIME)
165 : ("dhcp-state", DHCP_OPTION_DHCP_STATE)
166 : ("data-source", DHCP_OPTION_DATA_SOURCE)
167 : ("pcp-server", DHCP_OPTION_PCP_SERVER)
168 : ("dhcp-pxe-magic", DHCP_OPTION_PXELINUX_MAGIC)
169 : ("config-file", DHCP_OPTION_CONFIG_FILE)
170 : ("path-prefix", DHCP_OPTION_PATH_PREFIX)
171 : ("reboot-time", DHCP_OPTION_REBOOT_TIME)
172 : ("dhcp-6rd", DHCP_OPTION_6RD)
173 : ("dhcp-access-domain", DHCP_OPTION_V4_ACCESS_DOMAIN)
174 : ("subnet-allocation", DHCP_OPTION_SUBNET_ALLOCATION)
175 : ("dhcp-vss", DHCP_OPTION_VSS);
176 :
177 : Dhcpv4CategoryMap g_dhcpv4_category_map =
178 : map_list_of<uint32_t, DhcpHandler::DhcpOptionCategory>
179 : // (DHCP_OPTION_SUBNET_MASK, DhcpHandler::OneIPv4) // agent adds this option
180 : (DHCP_OPTION_TIME_OFFSET, DhcpHandler::Int32bit)
181 : (DHCP_OPTION_ROUTER, DhcpHandler::OneIPv4Plus)
182 : (DHCP_OPTION_TIME_SERVER, DhcpHandler::OneIPv4Plus)
183 : (DHCP_OPTION_NAME_SERVER, DhcpHandler::OneIPv4Plus)
184 : (DHCP_OPTION_DNS, DhcpHandler::OneIPv4Plus)
185 : (DHCP_OPTION_LOG_SERVER, DhcpHandler::OneIPv4Plus)
186 : (DHCP_OPTION_QUOTE_SERVER, DhcpHandler::OneIPv4Plus)
187 : (DHCP_OPTION_LPR_SERVER, DhcpHandler::OneIPv4Plus)
188 : (DHCP_OPTION_IMPRESS_SERVER, DhcpHandler::OneIPv4Plus)
189 : (DHCP_OPTION_RESOURCE_LOCATION_SERVER, DhcpHandler::OneIPv4Plus)
190 : (DHCP_OPTION_HOST_NAME, DhcpHandler::String)
191 : (DHCP_OPTION_BOOT_FILE_SIZE, DhcpHandler::Uint16bit)
192 : (DHCP_OPTION_MERIT_DUMP_FILE, DhcpHandler::String)
193 : (DHCP_OPTION_DOMAIN_NAME, DhcpHandler::String)
194 : (DHCP_OPTION_SWAP_SERVER, DhcpHandler::OneIPv4)
195 : (DHCP_OPTION_ROOT_PATH, DhcpHandler::String)
196 : (DHCP_OPTION_EXTENSION_PATH, DhcpHandler::String)
197 : (DHCP_OPTION_IP_FWD_CONTROL, DhcpHandler::Bool)
198 : (DHCP_OPTION_NL_SRC_ROUTING, DhcpHandler::Bool)
199 : (DHCP_OPTION_POLICY_FILTER, DhcpHandler::TwoIPv4Plus)
200 : (DHCP_OPTION_MAX_DG_REASSEMBLY_SIZE, DhcpHandler::Uint16bit)
201 : (DHCP_OPTION_DEFAULT_IP_TTL, DhcpHandler::Byte)
202 : (DHCP_OPTION_PATH_MTU_AGING_TIMEOUT, DhcpHandler::Uint32bit)
203 : (DHCP_OPTION_PATH_MTU_PLATEAU_TABLE, DhcpHandler::Uint16bitArray)
204 : (DHCP_OPTION_INTERFACE_MTU, DhcpHandler::Uint16bit)
205 : (DHCP_OPTION_ALL_SUBNETS_LOCAL, DhcpHandler::Bool)
206 : // (DHCP_OPTION_BCAST_ADDRESS, DhcpHandler::OneIPv4) // agent adds this option
207 : (DHCP_OPTION_PERFORM_MASK_DISCOVERY, DhcpHandler::Bool)
208 : (DHCP_OPTION_MASK_SUPPLIER, DhcpHandler::Bool)
209 : (DHCP_OPTION_PERFORM_ROUTER_DISCOVERY, DhcpHandler::Bool)
210 : (DHCP_OPTION_ROUTER_SOLICIT_ADDRESS, DhcpHandler::OneIPv4)
211 : (DHCP_OPTION_STATIC_ROUTING_TABLE, DhcpHandler::TwoIPv4Plus)
212 : (DHCP_OPTION_TRAILER_ENCAP, DhcpHandler::Bool)
213 : (DHCP_OPTION_ARP_CACHE_TIMEOUT, DhcpHandler::Uint32bit)
214 : (DHCP_OPTION_ETHERNET_ENCAP, DhcpHandler::Bool)
215 : (DHCP_OPTION_DEFAULT_TCP_TTL, DhcpHandler::Byte)
216 : (DHCP_OPTION_TCP_KEEPALIVE_INTERVAL, DhcpHandler::Uint32bit)
217 : (DHCP_OPTION_TCP_KEEPALIVE_GARBAGE, DhcpHandler::Bool)
218 : (DHCP_OPTION_NIS_DOMAIN, DhcpHandler::String)
219 : (DHCP_OPTION_NIS_SERVERS, DhcpHandler::OneIPv4Plus)
220 : (DHCP_OPTION_NTP_SERVERS, DhcpHandler::OneIPv4Plus)
221 : (DHCP_OPTION_VENDOR_SPECIFIC_INFO, DhcpHandler::String)
222 : (DHCP_OPTION_NETBIOS_OVER_TCP_NS, DhcpHandler::OneIPv4Plus)
223 : (DHCP_OPTION_NETBIOS_OVER_TCP_DG_DS, DhcpHandler::OneIPv4Plus)
224 : (DHCP_OPTION_NETBIOS_OVER_TCP_NODE_TYPE, DhcpHandler::Byte)
225 : (DHCP_OPTION_NETBIOS_OVER_TCP_SCOPE, DhcpHandler::String)
226 : (DHCP_OPTION_XWINDOW_FONT_SERVER, DhcpHandler::OneIPv4Plus)
227 : (DHCP_OPTION_XWINDOW_SYSTEM_DISP_MGR, DhcpHandler::OneIPv4Plus)
228 : (DHCP_OPTION_REQ_IP_ADDRESS, DhcpHandler::OneIPv4)
229 : (DHCP_OPTION_IP_LEASE_TIME, DhcpHandler::Uint32bit)
230 : (DHCP_OPTION_OVERLOAD, DhcpHandler::Byte)
231 : // (DHCP_OPTION_MSG_TYPE, DhcpHandler::Byte) // agent adds this option
232 : // (DHCP_OPTION_SERVER_IDENTIFIER, DhcpHandler::OneIPv4) // agent adds this option
233 : (DHCP_OPTION_PARAMETER_REQUEST_LIST, DhcpHandler::ByteArray)
234 : (DHCP_OPTION_MESSAGE, DhcpHandler::String)
235 : (DHCP_OPTION_MAX_DHCP_MSG_SIZE, DhcpHandler::Uint16bit)
236 : (DHCP_OPTION_RENEW_TIME_VALUE, DhcpHandler::Uint32bit)
237 : (DHCP_OPTION_REBIND_TIME_VALUE, DhcpHandler::Uint32bit)
238 : (DHCP_OPTION_CLASS_ID, DhcpHandler::String)
239 : (DHCP_OPTION_CLIENT_ID, DhcpHandler::ByteString)
240 : (DHCP_OPTION_NETWARE_IP_DOMAIN_NAME, DhcpHandler::String)
241 : (DHCP_OPTION_NETWARE_IP_INFO, DhcpHandler::ByteArray) // send encoded data
242 : (DHCP_OPTION_NIS_PLUS_DOMAIN, DhcpHandler::String)
243 : (DHCP_OPTION_NIS_PLUS_SERVERS, DhcpHandler::OneIPv4Plus)
244 : (DHCP_OPTION_TFTP_SERVER_NAME, DhcpHandler::String)
245 : (DHCP_OPTION_BOOTFILE_NAME, DhcpHandler::String)
246 : (DHCP_OPTION_MOBILE_IP_HA, DhcpHandler::ZeroIPv4Plus)
247 : (DHCP_OPTION_SMTP_SERVER, DhcpHandler::OneIPv4Plus)
248 : (DHCP_OPTION_POP_SERVER, DhcpHandler::OneIPv4Plus)
249 : (DHCP_OPTION_NNTP_SERVER, DhcpHandler::OneIPv4Plus)
250 : (DHCP_OPTION_DEFAULT_WWW_SERVER, DhcpHandler::OneIPv4Plus)
251 : (DHCP_OPTION_DEFAULT_FINGER_SERVER, DhcpHandler::OneIPv4Plus)
252 : (DHCP_OPTION_DEFAULT_IRC_SERVER, DhcpHandler::OneIPv4Plus)
253 : (DHCP_OPTION_STREETTALK_SERVER, DhcpHandler::OneIPv4Plus)
254 : (DHCP_OPTION_STREETTALK_DA_SERVER, DhcpHandler::OneIPv4Plus)
255 : (DHCP_OPTION_USER_CLASS_INFO, DhcpHandler::ByteArray) // send encoded data
256 : (DHCP_OPTION_SLP_DIRECTORY_AGENT, DhcpHandler::ByteOneIPPlus)
257 : (DHCP_OPTION_SLP_SERVICE_SCOPE, DhcpHandler::ByteString)
258 : (DHCP_OPTION_RAPID_COMMIT, DhcpHandler::NoData)
259 : // (DHCP_OPTION_CLIENT_FQDN, DhcpHandler::ByteArray) // sent by clients
260 : (DHCP_OPTION_STORAGE_NS, DhcpHandler::ByteArray) // send encoded data
261 : (DHCP_OPTION_NDS_SERVERS, DhcpHandler::OneIPv4Plus)
262 : (DHCP_OPTION_NDS_TREE_NAME, DhcpHandler::ByteArray) // send encoded data
263 : (DHCP_OPTION_NDS_CONTEXT, DhcpHandler::ByteArray) // send encoded data
264 : (DHCP_OPTION_BCMCS_DN_LIST, DhcpHandler::ByteArray) // send encoded data
265 : (DHCP_OPTION_BCMCS_ADDR_LIST, DhcpHandler::ByteArray) // send encoded data
266 : (DHCP_OPTION_AUTH, DhcpHandler::ByteArray) // send encoded data
267 : (DHCP_OPTION_CLIENT_LAST_XTIME, DhcpHandler::Uint32bit)
268 : (DHCP_OPTION_ASSOCIATE_IP, DhcpHandler::OneIPv4Plus)
269 : (DHCP_OPTION_CLIENT_SYSARCH_TYPE, DhcpHandler::Uint16bit)
270 : (DHCP_OPTION_CLIENT_NW_INTERFACE_ID, DhcpHandler::ByteArray)
271 : (DHCP_OPTION_LDAP, DhcpHandler::OneIPv4Plus)
272 : (DHCP_OPTION_CLIENT_MACHINE_ID, DhcpHandler::String)
273 : (DHCP_OPTION_OPENGROUP_USER_AUTH, DhcpHandler::String)
274 : (DHCP_OPTION_GEOCONF_CIVIC, DhcpHandler::ByteArray) // send encoded data
275 : (DHCP_OPTION_IEEE_1003_1_TZ, DhcpHandler::String)
276 : (DHCP_OPTION_REF_TZ_DB, DhcpHandler::String)
277 : (DHCP_OPTION_NETINFO_PARENT_SERVER_TAG, DhcpHandler::String)
278 : (DHCP_OPTION_NETINFO_PARENT_SERVER_ADDR, DhcpHandler::OneIPv4Plus)
279 : (DHCP_OPTION_URL, DhcpHandler::String)
280 : (DHCP_OPTION_AUTO_CONFIGURE, DhcpHandler::Bool)
281 : (DHCP_OPTION_NAME_SERVICE_SEARCH, DhcpHandler::Uint16bitArray)
282 : (DHCP_OPTION_SUBNET_SELECTION, DhcpHandler::OneIPv4)
283 : (DHCP_OPTION_DNS_DOMAIN_SEARCH_LIST, DhcpHandler::NameCompression)
284 : (DHCP_OPTION_SIP_SERVERS, DhcpHandler::ByteArray) // send encoded data
285 : (DHCP_OPTION_CLASSLESS_ROUTE, DhcpHandler::ClasslessRoute)
286 : (DHCP_OPTION_CCC, DhcpHandler::ByteArray) // send encoded data
287 : (DHCP_OPTION_GEOCONF, DhcpHandler::ByteArray) // send encoded data
288 : (DHCP_OPTION_VENDOR_ID_VENDOR_CLASS, DhcpHandler::ByteArray) // send encoded data
289 : (DHCP_OPTION_VENDOR_ID_VENDOR_SPECIFIC, DhcpHandler::ByteArray) // send encoded data
290 : (DHCP_OPTION_TFTP_SERVER, DhcpHandler::OneIPv4Plus)
291 : (DHCP_OPTION_PXE_VENDOR_SPECIFIC_129, DhcpHandler::String)
292 : (DHCP_OPTION_PXE_VENDOR_SPECIFIC_130, DhcpHandler::String)
293 : (DHCP_OPTION_PXE_VENDOR_SPECIFIC_131, DhcpHandler::String)
294 : (DHCP_OPTION_PXE_VENDOR_SPECIFIC_132, DhcpHandler::String)
295 : (DHCP_OPTION_PXE_VENDOR_SPECIFIC_133, DhcpHandler::String)
296 : (DHCP_OPTION_PXE_VENDOR_SPECIFIC_134, DhcpHandler::String)
297 : (DHCP_OPTION_PXE_VENDOR_SPECIFIC_135, DhcpHandler::String)
298 : (DHCP_OPTION_PANA_AUTH_AGENT, DhcpHandler::OneIPv4Plus)
299 : (DHCP_OPTION_LOST_SERVER, DhcpHandler::ByteArray) // send encoded data
300 : (DHCP_OPTION_CAPWAP_AC_ADDRESS, DhcpHandler::OneIPv4Plus)
301 : (DHCP_OPTION_IPV4_ADDRESS_MOS, DhcpHandler::ByteArray) // send encoded data
302 : (DHCP_OPTION_IPV4_FQDN_MOS, DhcpHandler::ByteArray) // send encoded data
303 : (DHCP_OPTION_SIP_UA_CONFIG_DOMAIN, DhcpHandler::ByteArray) // send encoded data
304 : (DHCP_OPTION_IPV4_ADDRESS_ANDSF, DhcpHandler::OneIPv4Plus)
305 : (DHCP_OPTION_GEOLOC, DhcpHandler::ByteArray) // send encoded data
306 : (DHCP_OPTION_FORCERENEW_NONCE_CAP, DhcpHandler::ByteArray) // send encoded data
307 : (DHCP_OPTION_RDNSS_SELECTION, DhcpHandler::ByteArray) // send encoded data
308 : (DHCP_OPTION_TFTP_SERVER_ADDRESS, DhcpHandler::OneIPv4Plus)
309 : (DHCP_OPTION_STATUS_CODE, DhcpHandler::ByteString)
310 : (DHCP_OPTION_BASE_TIME, DhcpHandler::Uint32bit)
311 : (DHCP_OPTION_START_TIME_OF_STATE, DhcpHandler::Uint32bit)
312 : (DHCP_OPTION_QUERY_START_TIME, DhcpHandler::Uint32bit)
313 : (DHCP_OPTION_QUERY_END_TIME, DhcpHandler::Uint32bit)
314 : (DHCP_OPTION_DHCP_STATE, DhcpHandler::Byte)
315 : (DHCP_OPTION_DATA_SOURCE, DhcpHandler::Byte)
316 : (DHCP_OPTION_PCP_SERVER, DhcpHandler::ByteArray) // send encoded data
317 : (DHCP_OPTION_PXELINUX_MAGIC, DhcpHandler::Uint32bit)
318 : (DHCP_OPTION_CONFIG_FILE, DhcpHandler::String)
319 : (DHCP_OPTION_PATH_PREFIX, DhcpHandler::String)
320 : (DHCP_OPTION_REBOOT_TIME, DhcpHandler::Uint32bit)
321 : (DHCP_OPTION_6RD, DhcpHandler::ByteArray) // send encoded data
322 : (DHCP_OPTION_SUBNET_ALLOCATION, DhcpHandler::ByteArray)
323 : (DHCP_OPTION_V4_ACCESS_DOMAIN, DhcpHandler::ByteArray) // send encoded data
324 : (DHCP_OPTION_VSS, DhcpHandler::ByteString)
325 : (DHCP_OPTION_PAD, DhcpHandler::None)
326 : (DHCP_OPTION_END, DhcpHandler::None);
327 :
328 0 : DhcpHandler::DhcpHandler(Agent *agent, boost::shared_ptr<PktInfo> info,
329 0 : boost::asio::io_context &io)
330 0 : : DhcpHandlerBase(agent, info, io), msg_type_(DHCP_UNKNOWN),
331 0 : out_msg_type_(DHCP_UNKNOWN),
332 0 : nak_msg_("cannot assign requested address") {
333 0 : option_.reset(new Dhcpv4OptionHandler(NULL));
334 0 : }
335 :
336 0 : DhcpHandler::~DhcpHandler() {
337 0 : }
338 :
339 0 : bool DhcpHandler::Run() {
340 0 : switch(pkt_info_->type) {
341 0 : case PktType::MESSAGE:
342 0 : return HandleMessage();
343 :
344 0 : default:
345 0 : return HandleVmRequest();
346 : }
347 : }
348 :
349 0 : bool DhcpHandler::HandleVmRequest() {
350 0 : DhcpProto *dhcp_proto = agent()->GetDhcpProto();
351 : // options length = pkt length - size of headers
352 0 : int16_t options_len = pkt_info_->len -
353 0 : (pkt_info_->data - (uint8_t *)pkt_info_->pkt)
354 0 : - DHCP_FIXED_LEN;
355 0 : if (options_len < 0) {
356 0 : agent()->GetDhcpProto()->IncrStatsErrors();
357 0 : DHCP_TRACE(Error, "Improper DHCP packet length; vrf = " <<
358 : pkt_info_->vrf << " ifindex = " << GetInterfaceIndex());
359 0 : return true;
360 : }
361 :
362 0 : dhcp_ = (dhcphdr *) pkt_info_->data;
363 0 : option_->SetDhcpOptionPtr(dhcp_->options);
364 0 : request_.UpdateData(dhcp_->xid, ntohs(dhcp_->flags), dhcp_->chaddr);
365 : Interface *itf =
366 0 : agent()->interface_table()->FindInterface(GetInterfaceIndex());
367 0 : if (itf == NULL) {
368 0 : dhcp_proto->IncrStatsOther();
369 0 : DHCP_TRACE(Error, "Received DHCP packet on invalid interface : "
370 : << GetInterfaceIndex());
371 0 : return true;
372 : }
373 :
374 0 : if (itf->type() != Interface::VM_INTERFACE) {
375 0 : dhcp_proto->IncrStatsErrors();
376 0 : DHCP_TRACE(Error, "Received DHCP packet on non VM port interface : "
377 : << GetInterfaceIndex());
378 0 : return true;
379 : }
380 0 : vm_itf_ = static_cast<VmInterface *>(itf);
381 0 : if (!vm_itf_->dhcp_enable_config()) {
382 0 : dhcp_proto->IncrDhcpDisabledDrops();
383 0 : DHCP_TRACE(Error, "DHCP request on VM port with dhcp services disabled: "
384 : << GetInterfaceIndex());
385 0 : return true;
386 : }
387 :
388 0 : if (vm_itf_->vm_mac() != request_.mac_addr) {
389 0 : dhcp_proto->IncrIncorrectMac();
390 0 : DHCP_TRACE(Error, "DHCP request for incorrect MAC: interface = "
391 : << GetInterfaceIndex() << " interface MAC = "
392 : << vm_itf_->vm_mac().ToString() << " requested MAC = "
393 : << request_.mac_addr.ToString());
394 0 : return true;
395 : }
396 :
397 : // For VM interfaces in default VRF, if the config doesnt have IP address,
398 : // send the request to fabric
399 0 : if (dhcp_proto->dhcp_relay_mode() &&
400 0 : vm_itf_->vrf() && vm_itf_->do_dhcp_relay()) {
401 0 : RelayRequestToFabric();
402 0 : return true;
403 : }
404 :
405 0 : if (!ReadOptions(options_len))
406 0 : return true;
407 :
408 0 : switch (msg_type_) {
409 0 : case DHCP_DISCOVER:
410 0 : out_msg_type_ = DHCP_OFFER;
411 0 : dhcp_proto->IncrStatsDiscover();
412 0 : DHCP_TRACE(Trace, "DHCP discover received on interface : "
413 : << vm_itf_->name() << " Mac : " <<
414 : request_.mac_addr.ToString());
415 0 : break;
416 :
417 0 : case DHCP_REQUEST:
418 0 : out_msg_type_ = DHCP_ACK;
419 0 : dhcp_proto->IncrStatsRequest();
420 0 : DHCP_TRACE(Trace, "DHCP request received on interface : "
421 : << vm_itf_->name() << " Mac : " <<
422 : request_.mac_addr.ToString());
423 0 : break;
424 :
425 0 : case DHCP_INFORM:
426 0 : out_msg_type_ = DHCP_ACK;
427 0 : dhcp_proto->IncrStatsInform();
428 0 : DHCP_TRACE(Trace, "DHCP inform received on interface : "
429 : << vm_itf_->name() << " Mac : " <<
430 : request_.mac_addr.ToString());
431 0 : break;
432 :
433 0 : case DHCP_DECLINE:
434 0 : dhcp_proto->IncrStatsDecline();
435 0 : DHCP_TRACE(Error, "DHCP Client declined the offer : vrf = " <<
436 : pkt_info_->vrf << " ifindex = " << GetInterfaceIndex() <<
437 : " Mac : " << request_.mac_addr.ToString());
438 0 : if (vm_itf_->vmi_type() == VmInterface::GATEWAY) {
439 0 : ReleaseGatewayInterfaceLease();
440 : }
441 0 : return true;
442 :
443 0 : case DHCP_RELEASE:
444 0 : DHCP_TRACE(Error, "DHCP lease released : vrf = " <<
445 : pkt_info_->vrf << " ifindex = " << GetInterfaceIndex() <<
446 : " Mac : " << request_.mac_addr.ToString());
447 0 : if (vm_itf_->vmi_type() == VmInterface::GATEWAY) {
448 0 : ReleaseGatewayInterfaceLease();
449 : }
450 0 : dhcp_proto->IncrStatsRelease();
451 0 : return true;
452 :
453 0 : case DHCP_ACK:
454 : case DHCP_NAK:
455 : case DHCP_LEASE_QUERY:
456 : case DHCP_LEASE_UNASSIGNED:
457 : case DHCP_LEASE_UNKNOWN:
458 : case DHCP_LEASE_ACTIVE:
459 : default:
460 0 : DHCP_TRACE(Trace, ServicesSandesh::DhcpMsgType(msg_type_) <<
461 : " received on interface : " << vm_itf_->name() <<
462 : " Mac : " << request_.mac_addr.ToString() <<
463 : "; ignoring");
464 0 : dhcp_proto->IncrStatsOther();
465 0 : return true;
466 : }
467 :
468 0 : if (FindLeaseData()) {
469 0 : SendDhcpResponse();
470 0 : DHCP_TRACE(Trace, "DHCP response sent; message = " <<
471 : ServicesSandesh::DhcpMsgType(out_msg_type_) <<
472 : "; ip = " << config_.ip_addr.to_string());
473 : }
474 :
475 0 : return true;
476 : }
477 :
478 0 : bool DhcpHandler::HandleMessage() {
479 0 : switch (pkt_info_->ipc->cmd) {
480 0 : case DhcpProto::DHCP_VHOST_MSG:
481 : // DHCP message from DHCP server port that we listen on
482 0 : if (agent()->GetDhcpProto()->dhcp_relay_mode())
483 0 : return HandleDhcpFromFabric();
484 :
485 : default:
486 0 : agent()->GetDhcpProto()->IncrUnknownMsgDrops();
487 0 : assert(0);
488 : }
489 :
490 : return true;
491 : }
492 :
493 : // Handle any DHCP response coming from fabric for a request that we relayed
494 0 : bool DhcpHandler::HandleDhcpFromFabric() {
495 0 : DhcpProto::DhcpVhostMsg *ipc = static_cast<DhcpProto::DhcpVhostMsg *>(pkt_info_->ipc);
496 0 : pkt_info_->len = ipc->len;
497 0 : dhcp_ = reinterpret_cast<dhcphdr *>(ipc->pkt);
498 0 : option_->SetDhcpOptionPtr(dhcp_->options);
499 0 : request_.UpdateData(dhcp_->xid, ntohs(dhcp_->flags), dhcp_->chaddr);
500 :
501 0 : int16_t options_len = ipc->len - DHCP_FIXED_LEN;
502 0 : if (ReadOptions(options_len) && vm_itf_ &&
503 0 : agent()->interface_table()->FindInterface(vm_itf_index_) == vm_itf_) {
504 : // this is a DHCP relay response for our request
505 0 : RelayResponseFromFabric();
506 : }
507 :
508 0 : delete ipc;
509 0 : return true;
510 : }
511 :
512 : // read DHCP options in the incoming packet
513 0 : bool DhcpHandler::ReadOptions(int16_t opt_rem_len) {
514 : // verify magic cookie
515 0 : if ((opt_rem_len < 4) ||
516 0 : memcmp(dhcp_->options, DHCP_OPTIONS_COOKIE, 4)) {
517 0 : agent()->GetDhcpProto()->IncrStatsErrors();
518 0 : DHCP_TRACE(Error, "DHCP options cookie missing; vrf = " <<
519 : pkt_info_->vrf << " ifindex = " << GetInterfaceIndex());
520 0 : return false;
521 : }
522 :
523 0 : opt_rem_len -= 4;
524 0 : Dhcpv4Options *opt = (Dhcpv4Options *)(dhcp_->options + 4);
525 : // parse thru the option fields
526 0 : while ((opt_rem_len > 0) && (opt->code != DHCP_OPTION_END)) {
527 0 : switch (opt->code) {
528 0 : case DHCP_OPTION_PAD:
529 0 : opt_rem_len -= 1;
530 0 : opt = (Dhcpv4Options *)((uint8_t *)opt + 1);
531 0 : continue;
532 :
533 0 : case DHCP_OPTION_MSG_TYPE:
534 0 : if (opt_rem_len >= opt->len + 2)
535 0 : msg_type_ = *(uint8_t *)opt->data;
536 0 : break;
537 :
538 0 : case DHCP_OPTION_REQ_IP_ADDRESS:
539 0 : if (opt_rem_len >= opt->len + 2) {
540 : union {
541 : uint8_t data[sizeof(in_addr_t)];
542 : in_addr_t addr;
543 : } bytes;
544 0 : memcpy(bytes.data, opt->data, sizeof(in_addr_t));
545 0 : request_.ip_addr = ntohl(bytes.addr);
546 : }
547 0 : break;
548 :
549 0 : case DHCP_OPTION_HOST_NAME:
550 0 : if (opt_rem_len >= opt->len + 2)
551 0 : config_.client_name_.assign((char *)opt->data, opt->len);
552 0 : break;
553 :
554 0 : case DHCP_OPTION_DOMAIN_NAME:
555 0 : if (opt_rem_len >= opt->len + 2)
556 0 : config_.domain_name_.assign((char *)opt->data, opt->len);
557 0 : break;
558 :
559 0 : case DHCP_OPTION_PARAMETER_REQUEST_LIST:
560 0 : if (opt_rem_len >= opt->len + 2)
561 0 : parameters_.assign((char *)opt->data, opt->len);
562 0 : break;
563 :
564 0 : case DHCP_OPTION_82:
565 0 : ReadOption82(opt);
566 0 : break;
567 :
568 0 : default:
569 0 : break;
570 0 : }
571 0 : opt_rem_len -= (2 + opt->len);
572 0 : opt = (Dhcpv4Options *)((uint8_t *)opt + 2 + opt->len);
573 : }
574 :
575 0 : return true;
576 : }
577 :
578 0 : void DhcpHandler::FillDhcpInfo(Ip4Address &addr, int plen,
579 : Ip4Address &gw, Ip4Address &dns) {
580 0 : config_.ip_addr = addr;
581 0 : config_.plen = plen;
582 0 : uint32_t mask = plen? (0xFFFFFFFF << (32 - plen)) : 0;
583 0 : config_.subnet_mask = mask;
584 0 : config_.bcast_addr = (addr.to_ulong() & mask) | ~mask;
585 0 : config_.gw_addr = gw;
586 0 : config_.dns_addr = dns;
587 0 : }
588 :
589 :
590 0 : bool DhcpHandler::GetGatewayInterfaceLease() {
591 0 : DhcpLeaseDb *dhcp_lease_db = agent()->GetDhcpProto()->GetLeaseDb(vm_itf_);
592 0 : if (dhcp_lease_db) {
593 0 : Ip4Address ip;
594 0 : const VnIpam *vn_ipam = (vm_itf_->vn()) ?
595 0 : vm_itf_->vn()->GetIpam(IpAddress(vm_itf_->subnet())) : NULL;
596 0 : if (!vn_ipam || !dhcp_lease_db->Allocate(request_.mac_addr, &ip,
597 : DHCP_GW_LEASE_TIME)) {
598 0 : agent()->GetDhcpProto()->IncrStatsErrors();
599 0 : DHCP_TRACE(Error, "DHCP request from Gateway interface failed :"
600 : " could not allocate IP address for Mac : " <<
601 : request_.mac_addr.ToString() << " on VMI : " <<
602 : vm_itf_->name());
603 0 : return false;
604 : }
605 0 : config_.lease_time = DHCP_GW_LEASE_TIME;
606 0 : Ip4Address gw = vn_ipam->default_gw.to_v4();
607 0 : Ip4Address dns = vn_ipam->dns_server.to_v4();
608 0 : FillDhcpInfo(ip, dhcp_lease_db->plen(), gw, dns);
609 0 : return true;
610 : }
611 :
612 0 : DHCP_TRACE(Error, "DHCP request on VMI " << vm_itf_->name() <<
613 : " could not be served - DHCP lease db is not created");
614 0 : return false;
615 : }
616 :
617 0 : void DhcpHandler::ReleaseGatewayInterfaceLease() {
618 0 : DhcpLeaseDb *dhcp_lease_db = agent()->GetDhcpProto()->GetLeaseDb(vm_itf_);
619 0 : if (!dhcp_lease_db || !dhcp_lease_db->Release(request_.mac_addr)) {
620 0 : agent()->GetDhcpProto()->IncrStatsErrors();
621 0 : DHCP_TRACE(Error, "DHCP lease release failed : vrf = " <<
622 : pkt_info_->vrf << " ifindex = " << GetInterfaceIndex() <<
623 : " Mac : " << request_.mac_addr.ToString());
624 : }
625 0 : }
626 :
627 0 : bool DhcpHandler::FindLeaseData() {
628 0 : Ip4Address unspecified;
629 0 : Ip4Address ip = vm_itf_->primary_ip_addr();
630 : // Change client name to VM name; this is the name assigned to the VM
631 0 : config_.client_name_ = vm_itf_->vm_name();
632 0 : FindDomainName(ip);
633 0 : if (vm_itf_->IsActive() || vm_itf_->device_type() == VmInterface::TOR) {
634 : // if the request is from a Gateway interface, get an address from the
635 : // relevant subnet
636 0 : if (vm_itf_->vmi_type() == VmInterface::GATEWAY) {
637 0 : return GetGatewayInterfaceLease();
638 : }
639 :
640 0 : if (vm_itf_->fabric_port()) {
641 : InetUnicastRouteEntry *rt =
642 0 : InetUnicastAgentRouteTable::FindResolveRoute(
643 0 : vm_itf_->vrf()->GetName(), ip);
644 0 : if (rt) {
645 0 : Ip4Address gw = agent()->vhost_default_gateway()[0];
646 0 : boost::system::error_code ec;
647 0 : if (IsIp4SubnetMember(rt->prefix_address().to_v4(),
648 0 : Ip4Address::from_string("169.254.0.0", ec), rt->prefix_length())) {
649 0 : gw = unspecified;
650 : }
651 0 : FillDhcpInfo(ip, rt->prefix_length(), gw, gw);
652 0 : return true;
653 : }
654 0 : agent()->GetDhcpProto()->IncrStatsErrors();
655 0 : DHCP_TRACE(Error, "DHCP fabric port request failed : "
656 : "could not find route for " << ip.to_string());
657 0 : return false;
658 : }
659 :
660 0 : const std::vector<VnIpam> &ipam = vm_itf_->vn()->GetVnIpam();
661 : unsigned int i;
662 0 : for (i = 0; i < ipam.size(); ++i) {
663 0 : if (!ipam[i].IsV4()) {
664 0 : continue;
665 : }
666 0 : if (IsIp4SubnetMember(ip, ipam[i].ip_prefix.to_v4(),
667 0 : ipam[i].plen)) {
668 0 : Ip4Address default_gw = ipam[i].default_gw.to_v4();
669 0 : Ip4Address service_address = ipam[i].dns_server.to_v4();
670 0 : if (service_address.is_unspecified())
671 0 : service_address = default_gw;
672 0 : FillDhcpInfo(ip, ipam[i].plen, default_gw, service_address);
673 0 : return true;
674 : }
675 : }
676 : }
677 :
678 : // We dont have the config yet; give a short lease
679 0 : config_.lease_time = DHCP_SHORTLEASE_TIME;
680 0 : if (ip.to_ulong()) {
681 : // Give address received from Nova
682 0 : FillDhcpInfo(ip, 32, unspecified, unspecified);
683 : } else {
684 : // Give a link local address
685 0 : boost::system::error_code ec;
686 : Ip4Address gwip = Ip4Address::from_string
687 0 : (agent()->v4_link_local_subnet(), ec);
688 0 : gwip = Ip4Address((gwip.to_ulong() & 0xFFFF0000) | (vm_itf_->id() & 0xFF));
689 0 : FillDhcpInfo(gwip, 16, unspecified, unspecified);
690 : }
691 0 : return true;
692 : }
693 :
694 0 : void DhcpHandler::WriteOption82(Dhcpv4Options *opt, uint16_t *optlen) {
695 0 : *optlen += 2;
696 0 : opt->code = DHCP_OPTION_82;
697 0 : opt->len = sizeof(uint32_t) + 2 + sizeof(VmInterface *) + 2;
698 0 : Dhcpv4Options *subopt = reinterpret_cast<Dhcpv4Options *>(opt->data);
699 0 : uint32_t value = htonl(vm_itf_->id());
700 0 : subopt->WriteData(DHCP_SUBOP_CKTID, 4, &value, optlen);
701 0 : subopt = subopt->GetNextOptionPtr();
702 0 : subopt->WriteData(DHCP_SUBOP_REMOTEID, sizeof(VmInterface *),
703 0 : &vm_itf_, optlen);
704 0 : }
705 :
706 0 : bool DhcpHandler::ReadOption82(Dhcpv4Options *opt) {
707 0 : if (opt->len != sizeof(uint32_t) + 2 + sizeof(VmInterface *) + 2)
708 0 : return false;
709 :
710 0 : Dhcpv4Options *subopt = reinterpret_cast<Dhcpv4Options *>(opt->data);
711 0 : for (int i = 0; i < 2; i++) {
712 0 : switch (subopt->code) {
713 0 : case DHCP_SUBOP_CKTID:
714 0 : if (subopt->len != sizeof(uint32_t))
715 0 : return false;
716 : union {
717 : uint8_t data[sizeof(uint32_t)];
718 : uint32_t index;
719 : } bytes;
720 :
721 0 : memcpy(bytes.data, subopt->data, sizeof(uint32_t));
722 0 : vm_itf_index_ = ntohl(bytes.index);
723 0 : break;
724 :
725 0 : case DHCP_SUBOP_REMOTEID:
726 0 : if (subopt->len != sizeof(VmInterface *))
727 0 : return false;
728 0 : memcpy(&vm_itf_, subopt->data, subopt->len);
729 0 : break;
730 :
731 0 : default:
732 0 : return false;
733 : }
734 0 : subopt = subopt->GetNextOptionPtr();
735 : }
736 :
737 0 : return true;
738 : }
739 :
740 0 : bool DhcpHandler::CreateRelayPacket() {
741 0 : PktInfo in_pkt_info = *pkt_info_.get();
742 :
743 0 : pkt_info_->AllocPacketBuffer(agent(), PktHandler::DHCP, DHCP_PKT_SIZE, 0);
744 0 : memset(pkt_info_->pkt, 0, DHCP_PKT_SIZE);
745 0 : pkt_info_->vrf = in_pkt_info.vrf;
746 0 : pkt_info_->eth = (struct ether_header *)(pkt_info_->pkt);
747 0 : int eth_len = 0;
748 0 : eth_len = EthHdr((char *)pkt_info_->eth, DHCP_PKT_SIZE,
749 : agent()->GetDhcpProto()->ip_fabric_interface_index(),
750 : agent()->GetDhcpProto()->ip_fabric_interface_mac(),
751 0 : MacAddress(in_pkt_info.eth->ether_dhost), ETHERTYPE_IP);
752 :
753 0 : pkt_info_->ip = (struct ip *)((char *)pkt_info_->eth + eth_len);
754 0 : pkt_info_->transp.udp = (udphdr *)(pkt_info_->ip + 1);
755 0 : dhcphdr *dhcp = (dhcphdr *)(pkt_info_->transp.udp + 1);
756 :
757 0 : memcpy((uint8_t *)dhcp, (uint8_t *)dhcp_, DHCP_FIXED_LEN);
758 0 : memcpy(dhcp->options, DHCP_OPTIONS_COOKIE, 4);
759 :
760 0 : int16_t opt_rem_len = in_pkt_info.len - eth_len - sizeof(struct ip)
761 0 : - sizeof(udphdr) - DHCP_FIXED_LEN - 4;
762 0 : uint16_t opt_len = 4;
763 0 : Dhcpv4Options *read_opt = (Dhcpv4Options *)(dhcp_->options + 4);
764 0 : Dhcpv4Options *write_opt = (Dhcpv4Options *)(dhcp->options + 4);
765 0 : while ((opt_rem_len > 0) && (read_opt->code != DHCP_OPTION_END)) {
766 0 : switch (read_opt->code) {
767 0 : case DHCP_OPTION_PAD:
768 0 : write_opt->WriteByte(DHCP_OPTION_PAD, &opt_len);
769 0 : write_opt = write_opt->GetNextOptionPtr();
770 0 : opt_rem_len -= 1;
771 0 : read_opt = read_opt->GetNextOptionPtr();
772 0 : continue;
773 :
774 0 : case DHCP_OPTION_82:
775 0 : break;
776 :
777 0 : case DHCP_OPTION_MSG_TYPE:
778 0 : msg_type_ = *(uint8_t *)read_opt->data;
779 0 : write_opt->WriteData(read_opt->code, read_opt->len, &msg_type_, &opt_len);
780 0 : write_opt = write_opt->GetNextOptionPtr();
781 0 : break;
782 :
783 0 : case DHCP_OPTION_HOST_NAME:
784 0 : config_.client_name_ = vm_itf_->vm_name();
785 0 : write_opt->WriteData(DHCP_OPTION_HOST_NAME,
786 0 : config_.client_name_.size(),
787 0 : config_.client_name_.c_str(), &opt_len);
788 0 : write_opt = write_opt->GetNextOptionPtr();
789 0 : break;
790 :
791 0 : default:
792 0 : write_opt->WriteData(read_opt->code, read_opt->len, &read_opt->data, &opt_len);
793 0 : write_opt = write_opt->GetNextOptionPtr();
794 0 : break;
795 :
796 : }
797 0 : opt_rem_len -= (2 + read_opt->len);
798 0 : read_opt = read_opt->GetNextOptionPtr();
799 : }
800 0 : dhcp_ = dhcp;
801 0 : option_->SetDhcpOptionPtr(dhcp_->options);
802 0 : dhcp->giaddr = htonl(agent()->router_id().to_ulong());
803 0 : WriteOption82(write_opt, &opt_len);
804 0 : write_opt = write_opt->GetNextOptionPtr();
805 0 : pkt_info_->sport = DHCP_SERVER_PORT;
806 0 : pkt_info_->dport = DHCP_SERVER_PORT;
807 0 : write_opt->WriteByte(DHCP_OPTION_END, &opt_len);
808 :
809 0 : uint32_t len = DHCP_FIXED_LEN + opt_len + eth_len + sizeof(udphdr);
810 :
811 0 : UdpHdr(len, in_pkt_info.ip->ip_src.s_addr, pkt_info_->sport,
812 0 : in_pkt_info.ip->ip_dst.s_addr, pkt_info_->dport);
813 0 : len += sizeof(struct ip);
814 0 : IpHdr(len, htonl(agent()->router_id().to_ulong()),
815 : 0xFFFFFFFF, IPPROTO_UDP, DEFAULT_IP_ID, DEFAULT_IP_TTL);
816 :
817 0 : pkt_info_->set_len(len);
818 0 : return true;
819 0 : }
820 :
821 0 : bool DhcpHandler::CreateRelayResponsePacket() {
822 0 : PktInfo in_pkt_info = *pkt_info_.get();
823 0 : pkt_info_->AllocPacketBuffer(agent(), PktHandler::DHCP, DHCP_PKT_SIZE, 0);
824 0 : memset(pkt_info_->pkt, 0, DHCP_PKT_SIZE);
825 0 : pkt_info_->vrf = vm_itf_->vrf()->vrf_id();
826 0 : pkt_info_->eth = (struct ether_header *)(pkt_info_->pkt);
827 :
828 0 : uint16_t eth_len = 0;
829 0 : eth_len = EthHdr((char *)pkt_info_->eth, DHCP_PKT_SIZE, vm_itf_index_,
830 : agent()->vhost_interface()->mac(),
831 0 : MacAddress(dhcp_->chaddr), ETHERTYPE_IP);
832 :
833 0 : pkt_info_->ip = (struct ip *)((char *)pkt_info_->eth + eth_len);
834 0 : pkt_info_->transp.udp = (udphdr *)(pkt_info_->ip + 1);
835 0 : dhcphdr *dhcp = (dhcphdr *)(pkt_info_->transp.udp + 1);
836 :
837 0 : memcpy((uint8_t *)dhcp, (uint8_t *)dhcp_, DHCP_FIXED_LEN);
838 0 : memcpy(dhcp->options, DHCP_OPTIONS_COOKIE, 4);
839 :
840 0 : int16_t opt_rem_len = in_pkt_info.len - DHCP_FIXED_LEN - 4;
841 0 : uint16_t opt_len = 4;
842 0 : Dhcpv4Options *read_opt = (Dhcpv4Options *)(dhcp_->options + 4);
843 0 : Dhcpv4Options *write_opt = (Dhcpv4Options *)(dhcp->options + 4);
844 0 : while ((opt_rem_len > 0) && (read_opt->code != DHCP_OPTION_END)) {
845 0 : switch (read_opt->code) {
846 0 : case DHCP_OPTION_PAD:
847 0 : write_opt->WriteByte(DHCP_OPTION_PAD, &opt_len);
848 0 : write_opt = write_opt->GetNextOptionPtr();
849 0 : opt_rem_len -= 1;
850 0 : read_opt = read_opt->GetNextOptionPtr();
851 0 : continue;
852 :
853 0 : case DHCP_OPTION_82:
854 0 : break;
855 :
856 0 : case DHCP_OPTION_MSG_TYPE:
857 0 : msg_type_ = *(uint8_t *)read_opt->data;
858 0 : write_opt->WriteData(read_opt->code, read_opt->len, &msg_type_, &opt_len);
859 0 : write_opt = write_opt->GetNextOptionPtr();
860 0 : break;
861 :
862 0 : default:
863 0 : write_opt->WriteData(read_opt->code, read_opt->len, &read_opt->data, &opt_len);
864 0 : write_opt = write_opt->GetNextOptionPtr();
865 0 : break;
866 :
867 : }
868 0 : opt_rem_len -= (2 + read_opt->len);
869 0 : read_opt = read_opt->GetNextOptionPtr();
870 : }
871 0 : dhcp_ = dhcp;
872 0 : option_->SetDhcpOptionPtr(dhcp_->options);
873 0 : dhcp->giaddr = 0;
874 0 : config_.client_name_ = vm_itf_->vm_name();
875 0 : write_opt->WriteData(DHCP_OPTION_HOST_NAME, config_.client_name_.size(),
876 0 : config_.client_name_.c_str(), &opt_len);
877 0 : write_opt = write_opt->GetNextOptionPtr();
878 0 : pkt_info_->sport = DHCP_SERVER_PORT;
879 0 : pkt_info_->dport = DHCP_CLIENT_PORT;
880 0 : write_opt->WriteByte(DHCP_OPTION_END, &opt_len);
881 :
882 0 : uint32_t len = DHCP_FIXED_LEN + opt_len + sizeof(udphdr) + eth_len;
883 :
884 0 : UdpHdr(len, agent()->router_id().to_ulong(), pkt_info_->sport,
885 0 : 0xFFFFFFFF, pkt_info_->dport);
886 0 : len += sizeof(struct ip);
887 0 : IpHdr(len, htonl(agent()->router_id().to_ulong()),
888 : 0xFFFFFFFF, IPPROTO_UDP, DEFAULT_IP_ID, DEFAULT_IP_TTL);
889 :
890 0 : pkt_info_->set_len(len);
891 0 : return true;
892 0 : }
893 :
894 0 : void DhcpHandler::RelayRequestToFabric() {
895 0 : CreateRelayPacket();
896 0 : DhcpProto *dhcp_proto = agent()->GetDhcpProto();
897 0 : Send(dhcp_proto->ip_fabric_interface_index(), pkt_info_->vrf,
898 : AgentHdr::TX_SWITCH, PktHandler::DHCP);
899 0 : dhcp_proto->IncrStatsRelayReqs();
900 0 : }
901 :
902 0 : void DhcpHandler::RelayResponseFromFabric() {
903 0 : if (!CreateRelayResponsePacket()) {
904 0 : DHCP_TRACE(Trace, "Ignoring received DHCP packet from fabric interface");
905 0 : return;
906 : }
907 :
908 0 : if (msg_type_ == DHCP_ACK) {
909 : // Populate the DHCP Snoop table
910 : agent()->interface_table()->AddDhcpSnoopEntry
911 0 : (vm_itf_->name(), Ip4Address(ntohl(dhcp_->yiaddr)));
912 : // Enqueue RESYNC to update the IP address
913 0 : DBRequest req(DBRequest::DB_ENTRY_ADD_CHANGE);
914 0 : req.key.reset(new VmInterfaceKey(AgentKey::RESYNC, vm_itf_->GetUuid(),
915 0 : vm_itf_->name()));
916 0 : req.data.reset(new VmInterfaceIpAddressData());
917 0 : agent()->interface_table()->Enqueue(&req);
918 0 : }
919 :
920 0 : Send(vm_itf_index_, pkt_info_->vrf, AgentHdr::TX_SWITCH, PktHandler::DHCP);
921 0 : agent()->GetDhcpProto()->IncrStatsRelayResps();
922 : }
923 :
924 : // Add an IP address to the option
925 0 : uint16_t DhcpHandler::AddIP(uint16_t opt_len, const std::string &input) {
926 0 : boost::system::error_code ec;
927 0 : uint32_t ip = Ip4Address::from_string(input, ec).to_ulong();
928 0 : if (!ec.value() && ip) {
929 0 : ip = htonl(ip);
930 0 : option_->AppendData(4, &ip, &opt_len);
931 : } else {
932 0 : DHCP_TRACE(Error, "Invalid DHCP option " << option_->GetCode() <<
933 : " data : " << input << " for VM " <<
934 : config_.ip_addr.to_string() << "; has to be IP address");
935 : }
936 0 : return opt_len;
937 : }
938 :
939 : // Add domain name from IPAM to the option
940 0 : uint16_t DhcpHandler::AddDomainNameOption(uint16_t opt_len) {
941 0 : if (ipam_type_.ipam_dns_method == "virtual-dns-server") {
942 0 : if (is_dns_enabled() && config_.domain_name_.size()) {
943 0 : option_->WriteData(DHCP_OPTION_DOMAIN_NAME, 0, NULL, &opt_len);
944 0 : option_->AppendData(config_.domain_name_.size(),
945 0 : config_.domain_name_.c_str(), &opt_len);
946 : }
947 : }
948 0 : return opt_len;
949 : }
950 :
951 0 : uint16_t DhcpHandler::DhcpHdr(in_addr_t yiaddr, in_addr_t siaddr) {
952 0 : dhcp_->op = BOOT_REPLY;
953 0 : dhcp_->htype = HW_TYPE_ETHERNET;
954 0 : dhcp_->hlen = ETHER_ADDR_LEN;
955 0 : dhcp_->hops = 0;
956 0 : dhcp_->xid = request_.xid;
957 0 : dhcp_->secs = 0;
958 0 : dhcp_->flags = htons(request_.flags);
959 0 : dhcp_->ciaddr = 0;
960 0 : dhcp_->yiaddr = yiaddr;
961 0 : dhcp_->siaddr = siaddr;
962 0 : dhcp_->giaddr = 0;
963 0 : memset (dhcp_->chaddr, 0, DHCP_CHADDR_LEN);
964 0 : request_.mac_addr.ToArray(dhcp_->chaddr, ETHER_ADDR_LEN);
965 : // not supporting dhcp_->sname, dhcp_->file for now
966 0 : memset(dhcp_->sname, '\0', DHCP_NAME_LEN);
967 0 : memset(dhcp_->file, '\0', DHCP_FILE_LEN);
968 :
969 0 : memcpy(dhcp_->options, DHCP_OPTIONS_COOKIE, 4);
970 :
971 0 : uint16_t opt_len = 4;
972 0 : option_->SetNextOptionPtr(opt_len);
973 0 : option_->WriteData(DHCP_OPTION_MSG_TYPE, 1, &out_msg_type_, &opt_len);
974 :
975 0 : option_->SetNextOptionPtr(opt_len);
976 0 : option_->WriteData(DHCP_OPTION_SERVER_IDENTIFIER, 4, &siaddr, &opt_len);
977 :
978 0 : if (out_msg_type_ == DHCP_NAK) {
979 0 : option_->SetNextOptionPtr(opt_len);
980 0 : option_->WriteData(DHCP_OPTION_MESSAGE, nak_msg_.size(),
981 0 : nak_msg_.data(), &opt_len);
982 : }
983 : else {
984 :
985 0 : if (config_.subnet_mask) {
986 0 : option_->SetNextOptionPtr(opt_len);
987 0 : uint32_t value = htonl(config_.subnet_mask);
988 0 : option_->WriteData(DHCP_OPTION_SUBNET_MASK, 4, &value, &opt_len);
989 : }
990 :
991 0 : if (config_.bcast_addr) {
992 0 : option_->SetNextOptionPtr(opt_len);
993 0 : uint32_t value = htonl(config_.bcast_addr);
994 0 : option_->WriteData(DHCP_OPTION_BCAST_ADDRESS, 4, &value, &opt_len);
995 : }
996 :
997 : // Add dhcp options coming from Config
998 0 : opt_len = AddConfigDhcpOptions(opt_len, false);
999 :
1000 0 : if (msg_type_ != DHCP_INFORM &&
1001 0 : !is_flag_set(DHCP_OPTION_IP_LEASE_TIME)) {
1002 0 : option_->SetNextOptionPtr(opt_len);
1003 0 : uint32_t value = htonl(config_.lease_time);
1004 0 : option_->WriteData(DHCP_OPTION_IP_LEASE_TIME, 4, &value, &opt_len);
1005 : }
1006 :
1007 : // Add classless route option
1008 0 : option_->SetNextOptionPtr(opt_len);
1009 0 : opt_len = AddClasslessRouteOption(opt_len);
1010 :
1011 0 : if (IsRouterOptionNeeded()) {
1012 0 : option_->SetNextOptionPtr(opt_len);
1013 0 : opt_len = AddIpv4Option(DHCP_OPTION_ROUTER, opt_len,
1014 0 : routers_, 1, 0, 0);
1015 : }
1016 :
1017 0 : if (!is_flag_set(DHCP_OPTION_HOST_NAME) &&
1018 0 : config_.client_name_.size()) {
1019 0 : option_->SetNextOptionPtr(opt_len);
1020 0 : option_->WriteData(DHCP_OPTION_HOST_NAME, config_.client_name_.size(),
1021 0 : config_.client_name_.c_str(), &opt_len);
1022 : }
1023 :
1024 0 : if (!is_flag_set(DHCP_OPTION_DNS)) {
1025 0 : uint16_t old_opt_len = opt_len;
1026 0 : option_->SetNextOptionPtr(opt_len);
1027 0 : option_->WriteData(DHCP_OPTION_DNS, 0, NULL, &opt_len);
1028 0 : opt_len = AddDnsServers(opt_len);
1029 : // if there was no DNS server, revert the option
1030 0 : if (opt_len == old_opt_len + option_->GetFixedLen())
1031 0 : opt_len = old_opt_len;
1032 : }
1033 :
1034 0 : if (!is_flag_set(DHCP_OPTION_DOMAIN_NAME)) {
1035 0 : option_->SetNextOptionPtr(opt_len);
1036 0 : opt_len = AddDomainNameOption(opt_len);
1037 : }
1038 :
1039 : // update dhcp siaddr with stored value
1040 0 : if (is_flag_set(DHCP_OPTION_TFTP_SERVER_NAME)) {
1041 0 : dhcp_->siaddr = siaddr_tftp_;
1042 : }
1043 : }
1044 :
1045 0 : option_->SetNextOptionPtr(opt_len);
1046 0 : option_->SetCode(DHCP_OPTION_END);
1047 0 : opt_len += 1;
1048 :
1049 0 : return (DHCP_FIXED_LEN + opt_len);
1050 : }
1051 :
1052 0 : uint16_t DhcpHandler::FillDhcpResponse(const MacAddress &dest_mac,
1053 : in_addr_t src_ip, in_addr_t dest_ip,
1054 : in_addr_t siaddr, in_addr_t yiaddr) {
1055 0 : pkt_info_->eth = (struct ether_header *)(pkt_info_->pkt);
1056 :
1057 0 : uint16_t eth_len = 0;
1058 0 : eth_len = EthHdr((char *)pkt_info_->eth,
1059 0 : pkt_info_->packet_buffer()->data_len(),
1060 : GetInterfaceIndex(),
1061 : agent()->vhost_interface()->mac(), dest_mac, ETHERTYPE_IP);
1062 :
1063 0 : pkt_info_->ip = (struct ip *)((char *)pkt_info_->eth + eth_len);
1064 0 : pkt_info_->transp.udp = (udphdr *)(pkt_info_->ip + 1);
1065 0 : dhcphdr *dhcp = (dhcphdr *)(pkt_info_->transp.udp + 1);
1066 0 : dhcp_ = dhcp;
1067 0 : option_->SetDhcpOptionPtr(dhcp_->options);
1068 :
1069 0 : uint16_t len = DhcpHdr(yiaddr, siaddr);
1070 0 : len += sizeof(udphdr);
1071 0 : UdpHdr(len, src_ip, DHCP_SERVER_PORT, dest_ip, DHCP_CLIENT_PORT);
1072 0 : len += sizeof(struct ip);
1073 0 : IpHdr(len, src_ip, dest_ip, IPPROTO_UDP, DEFAULT_IP_ID, DEFAULT_IP_TTL);
1074 :
1075 0 : pkt_info_->set_len(len + eth_len);
1076 0 : return pkt_info_->packet_buffer()->data_len();
1077 : }
1078 :
1079 0 : void DhcpHandler::SendDhcpResponse() {
1080 : // TODO: If giaddr is set, what to do ?
1081 :
1082 : // In TSN, the source address for DHCP response should be the address
1083 : // in the subnet reserved for service node. Otherwise, it will be the
1084 : // GW address. dns_addr field has this address, use it as the source IP.
1085 0 : in_addr_t src_ip = htonl(config_.dns_addr.to_v4().to_ulong());
1086 0 : in_addr_t dest_ip = 0xFFFFFFFF;
1087 0 : in_addr_t yiaddr = htonl(config_.ip_addr.to_v4().to_ulong());
1088 0 : in_addr_t siaddr = src_ip;
1089 0 : MacAddress dest_mac = MacAddress::BroadcastMac();
1090 :
1091 : // If requested IP address is not available, send NAK
1092 0 : if ((msg_type_ == DHCP_REQUEST) && (request_.ip_addr) &&
1093 0 : (config_.ip_addr.to_v4().to_ulong() != request_.ip_addr)) {
1094 0 : out_msg_type_ = DHCP_NAK;
1095 0 : yiaddr = 0;
1096 0 : siaddr = 0;
1097 : }
1098 :
1099 : // send a unicast response when responding to INFORM
1100 : // or when incoming giaddr is zero and ciaddr is set
1101 : // or when incoming bcast flag is not set (with giaddr & ciaddr being zero)
1102 0 : if ((msg_type_ == DHCP_INFORM) ||
1103 0 : (!dhcp_->giaddr && (dhcp_->ciaddr ||
1104 0 : !(request_.flags & DHCP_BCAST_FLAG)))) {
1105 0 : dest_ip = yiaddr;
1106 0 : dest_mac = dhcp_->chaddr;
1107 0 : if (msg_type_ == DHCP_INFORM)
1108 0 : yiaddr = 0;
1109 : }
1110 :
1111 0 : UpdateStats();
1112 :
1113 0 : FillDhcpResponse(dest_mac, src_ip, dest_ip, siaddr, yiaddr);
1114 : uint32_t interface =
1115 0 : (pkt_info_->agent_hdr.cmd == AgentHdr::TRAP_TOR_CONTROL_PKT) ?
1116 0 : agent_->GetDhcpProto()->pkt_interface_index() : GetInterfaceIndex();
1117 : uint16_t command =
1118 0 : (pkt_info_->agent_hdr.cmd == AgentHdr::TRAP_TOR_CONTROL_PKT) ?
1119 0 : (uint16_t)AgentHdr::TX_ROUTE : AgentHdr::TX_SWITCH;
1120 0 : Send(interface, pkt_info_->vrf, command, PktHandler::DHCP);
1121 0 : }
1122 :
1123 : // Check if the option is requested by the client or not
1124 0 : bool DhcpHandler::IsOptionRequested(uint8_t option) {
1125 0 : for (uint32_t i = 0; i < parameters_.size(); i++) {
1126 0 : if (parameters_[i] == option)
1127 0 : return true;
1128 : }
1129 0 : return false;
1130 : }
1131 :
1132 0 : bool DhcpHandler::IsRouterOptionNeeded() {
1133 : // If GW is not configured, dont include
1134 0 : if (config_.gw_addr.is_unspecified() && routers_.empty())
1135 0 : return false;
1136 :
1137 : // When client requests Classless Static Routes option and this is
1138 : // included in the response, Router option is not included (RFC3442)
1139 0 : if (IsOptionRequested(DHCP_OPTION_CLASSLESS_ROUTE) &&
1140 0 : is_flag_set(DHCP_OPTION_CLASSLESS_ROUTE))
1141 0 : return false;
1142 :
1143 0 : return true;
1144 : }
1145 :
1146 0 : void DhcpHandler::UpdateStats() {
1147 0 : DhcpProto *dhcp_proto = agent()->GetDhcpProto();
1148 0 : (out_msg_type_ == DHCP_OFFER) ? dhcp_proto->IncrStatsOffers() :
1149 0 : ((out_msg_type_ == DHCP_ACK) ? dhcp_proto->IncrStatsAcks() :
1150 0 : dhcp_proto->IncrStatsNacks());
1151 0 : }
1152 :
1153 : DhcpHandler::DhcpOptionCategory
1154 0 : DhcpHandler::OptionCategory(uint32_t option) const {
1155 0 : Dhcpv4CategoryIter iter = g_dhcpv4_category_map.find(option);
1156 0 : if (iter == g_dhcpv4_category_map.end())
1157 0 : return None;
1158 0 : return iter->second;
1159 : }
1160 :
1161 0 : uint32_t DhcpHandler::OptionCode(const std::string &option) const {
1162 : // if the option name is a number, use it as DHCP code
1163 : // otherwise, use it as option name
1164 0 : std::stringstream str(option);
1165 :
1166 0 : uint32_t code = 0;
1167 0 : str >> code;
1168 0 : if (code) return code;
1169 :
1170 : Dhcpv4NameCodeIter iter =
1171 0 : g_dhcpv4_namecode_map.find(boost::to_lower_copy(option));
1172 :
1173 0 : if(iter != g_dhcpv4_namecode_map.end()){
1174 0 : return iter->second;
1175 : }
1176 :
1177 0 : std::stringstream str_new(option);
1178 : //Checking if there is comma in the option
1179 0 : bool is_delimeter_set = false;
1180 0 : while(!(str_new.eof())){
1181 0 : str_new.get();
1182 0 : if (str_new.peek() == ','){
1183 0 : is_delimeter_set = true;
1184 : }
1185 : }
1186 0 : std::stringstream str_orig(option);
1187 : //If option name has a comma in it,
1188 : //eg: tag:!ipxe,67 , we should pick 67
1189 0 : if(is_delimeter_set){
1190 0 : vector<string> v;
1191 0 : while (str_orig.good()) {
1192 0 : string substr;
1193 0 : getline(str_orig, substr, ',');
1194 0 : v.push_back(substr);
1195 0 : }
1196 0 : std::stringstream str_temp(v[1]);
1197 0 : str_temp >> code;
1198 0 : }
1199 :
1200 0 : return code;
1201 0 : }
1202 :
1203 :
1204 0 : void DhcpHandler::DhcpTrace(const std::string &msg) const {
1205 0 : DHCP_TRACE(Error, "VM " << config_.ip_addr.to_string() << " : " << msg);
1206 0 : }
|