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