xref: /titanic_44/usr/src/cmd/cmd-inet/sbin/dhcpagent/agent.c (revision 70ab954a5d6c4d36858fd6e7e3dd4498d06d2c40)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/types.h>
29 #include <stdlib.h>
30 #include <errno.h>
31 #include <locale.h>
32 #include <string.h>
33 #include <unistd.h>
34 #include <signal.h>
35 #include <stdio.h>
36 #include <stdio_ext.h>
37 #include <dhcp_hostconf.h>
38 #include <dhcpagent_ipc.h>
39 #include <dhcpmsg.h>
40 #include <netinet/dhcp.h>
41 #include <net/route.h>
42 #include <sys/sockio.h>
43 
44 #include "async.h"
45 #include "agent.h"
46 #include "script_handler.h"
47 #include "util.h"
48 #include "class_id.h"
49 #include "states.h"
50 #include "packet.h"
51 
52 #ifndef	TEXT_DOMAIN
53 #define	TEXT_DOMAIN	"SYS_TEST"
54 #endif
55 
56 iu_timer_id_t		inactivity_id;
57 int			class_id_len = 0;
58 char			*class_id;
59 iu_eh_t			*eh;
60 iu_tq_t			*tq;
61 pid_t			grandparent;
62 int			rtsock_fd;
63 
64 static boolean_t	shutdown_started = B_FALSE;
65 static boolean_t	do_adopt = B_FALSE;
66 static unsigned int	debug_level = 0;
67 static iu_eh_callback_t	accept_event, ipc_event, rtsock_event;
68 
69 /*
70  * The ipc_cmd_allowed[] table indicates which IPC commands are allowed in
71  * which states; a non-zero value indicates the command is permitted.
72  *
73  * START is permitted if the interface is fresh, or if we are in the process
74  * of trying to obtain a lease (as a convenience to save the administrator
75  * from having to do an explicit DROP).  EXTEND, RELEASE, and GET_TAG require
76  * a lease to be obtained in order to make sense.  INFORM is permitted if the
77  * interface is fresh or has an INFORM in progress or previously done on it --
78  * otherwise a DROP or RELEASE is first required.  PING and STATUS always make
79  * sense and thus are always permitted, as is DROP in order to permit the
80  * administrator to always bail out.
81  */
82 static int ipc_cmd_allowed[DHCP_NSTATES][DHCP_NIPC] = {
83 	/*			  D  E	P  R  S	 S  I  G */
84 	/*			  R  X	I  E  T	 T  N  E */
85 	/*			  O  T	N  L  A	 A  F  T */
86 	/*			  P  E	G  E  R	 T  O  _ */
87 	/*			  .  N  .  A  T  U  R  T */
88 	/*			  .  D	.  S  .  S  M  A */
89 	/*			  .  .  .  E  .  .  .  G */
90 	/* INIT		*/	{ 1, 0, 1, 0, 1, 1, 1, 0 },
91 	/* SELECTING	*/	{ 1, 0, 1, 0, 1, 1, 0, 0 },
92 	/* REQUESTING	*/	{ 1, 0, 1, 0, 1, 1, 0, 0 },
93 	/* PRE_BOUND	*/	{ 1, 1, 1, 1, 0, 1, 0, 1 },
94 	/* BOUND	*/	{ 1, 1, 1, 1, 0, 1, 0, 1 },
95 	/* RENEWING	*/	{ 1, 1, 1, 1, 0, 1, 0, 1 },
96 	/* REBINDING	*/	{ 1, 1, 1, 1, 0, 1, 0, 1 },
97 	/* INFORMATION  */	{ 1, 0, 1, 0, 0, 1, 1, 1 },
98 	/* INIT_REBOOT  */	{ 1, 0, 1, 0, 1, 1, 0, 0 },
99 	/* ADOPTING	*/	{ 1, 0, 1, 0, 0, 1, 0, 0 },
100 	/* INFORM_SENT  */	{ 1, 0, 1, 0, 0, 1, 1, 0 }
101 };
102 
103 int
104 main(int argc, char **argv)
105 {
106 	boolean_t	is_daemon  = B_TRUE;
107 	boolean_t	is_verbose = B_FALSE;
108 	int		ipc_fd;
109 	int		c;
110 	struct rlimit	rl;
111 
112 	/*
113 	 * -l is ignored for compatibility with old agent.
114 	 */
115 
116 	while ((c = getopt(argc, argv, "vd:l:fa")) != EOF) {
117 
118 		switch (c) {
119 
120 		case 'a':
121 			do_adopt = B_TRUE;
122 			grandparent = getpid();
123 			break;
124 
125 		case 'd':
126 			debug_level = strtoul(optarg, NULL, 0);
127 			break;
128 
129 		case 'f':
130 			is_daemon = B_FALSE;
131 			break;
132 
133 		case 'v':
134 			is_verbose = B_TRUE;
135 			break;
136 
137 		case '?':
138 			(void) fprintf(stderr, "usage: %s [-a] [-d n] [-f] [-v]"
139 			    "\n", argv[0]);
140 			return (EXIT_FAILURE);
141 
142 		default:
143 			break;
144 		}
145 	}
146 
147 	(void) setlocale(LC_ALL, "");
148 	(void) textdomain(TEXT_DOMAIN);
149 
150 	if (geteuid() != 0) {
151 		dhcpmsg_init(argv[0], B_FALSE, is_verbose, debug_level);
152 		dhcpmsg(MSG_ERROR, "must be super-user");
153 		dhcpmsg_fini();
154 		return (EXIT_FAILURE);
155 	}
156 
157 	if (is_daemon && daemonize() == 0) {
158 		dhcpmsg_init(argv[0], B_FALSE, is_verbose, debug_level);
159 		dhcpmsg(MSG_ERR, "cannot become daemon, exiting");
160 		dhcpmsg_fini();
161 		return (EXIT_FAILURE);
162 	}
163 
164 	dhcpmsg_init(argv[0], is_daemon, is_verbose, debug_level);
165 	(void) atexit(dhcpmsg_fini);
166 
167 	tq = iu_tq_create();
168 	eh = iu_eh_create();
169 
170 	if (eh == NULL || tq == NULL) {
171 		errno = ENOMEM;
172 		dhcpmsg(MSG_ERR, "cannot create timer queue or event handler");
173 		return (EXIT_FAILURE);
174 	}
175 
176 	/*
177 	 * ignore most signals that could be reasonably generated.
178 	 */
179 
180 	(void) signal(SIGTERM, graceful_shutdown);
181 	(void) signal(SIGQUIT, graceful_shutdown);
182 	(void) signal(SIGPIPE, SIG_IGN);
183 	(void) signal(SIGUSR1, SIG_IGN);
184 	(void) signal(SIGUSR2, SIG_IGN);
185 	(void) signal(SIGINT,  SIG_IGN);
186 	(void) signal(SIGHUP,  SIG_IGN);
187 	(void) signal(SIGCHLD, SIG_IGN);
188 
189 	/*
190 	 * upon SIGTHAW we need to refresh any non-infinite leases.
191 	 */
192 
193 	(void) iu_eh_register_signal(eh, SIGTHAW, refresh_ifslist, NULL);
194 
195 	class_id = get_class_id();
196 	if (class_id != NULL)
197 		class_id_len = strlen(class_id);
198 	else
199 		dhcpmsg(MSG_WARNING, "get_class_id failed, continuing "
200 		    "with no vendor class id");
201 
202 	/*
203 	 * the inactivity timer is enabled any time there are no
204 	 * interfaces under DHCP control.  if DHCP_INACTIVITY_WAIT
205 	 * seconds transpire without an interface under DHCP control,
206 	 * the agent shuts down.
207 	 */
208 
209 	inactivity_id = iu_schedule_timer(tq, DHCP_INACTIVITY_WAIT,
210 	    inactivity_shutdown, NULL);
211 
212 	/*
213 	 * max out the number available descriptors, just in case..
214 	 */
215 
216 	rl.rlim_cur = RLIM_INFINITY;
217 	rl.rlim_max = RLIM_INFINITY;
218 	if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
219 		dhcpmsg(MSG_ERR, "setrlimit failed");
220 
221 	(void) enable_extended_FILE_stdio(-1, -1);
222 
223 	/*
224 	 * create the ipc channel that the agent will listen for
225 	 * requests on, and register it with the event handler so that
226 	 * `accept_event' will be called back.
227 	 */
228 
229 	switch (dhcp_ipc_init(&ipc_fd)) {
230 
231 	case 0:
232 		break;
233 
234 	case DHCP_IPC_E_BIND:
235 		dhcpmsg(MSG_ERROR, "dhcp_ipc_init: cannot bind to port "
236 		    "%i (agent already running?)", IPPORT_DHCPAGENT);
237 		return (EXIT_FAILURE);
238 
239 	default:
240 		dhcpmsg(MSG_ERROR, "dhcp_ipc_init failed");
241 		return (EXIT_FAILURE);
242 	}
243 
244 	if (iu_register_event(eh, ipc_fd, POLLIN, accept_event, 0) == -1) {
245 		dhcpmsg(MSG_ERR, "cannot register ipc fd for messages");
246 		return (EXIT_FAILURE);
247 	}
248 
249 	/*
250 	 * Create the global routing socket.  This is used for monitoring
251 	 * interface transitions, so that we learn about the kernel's Duplicate
252 	 * Address Detection status, and for inserting and removing default
253 	 * routes as learned from DHCP servers.
254 	 */
255 	rtsock_fd = socket(PF_ROUTE, SOCK_RAW, AF_INET);
256 	if (rtsock_fd == -1) {
257 		dhcpmsg(MSG_ERR, "cannot open routing socket");
258 		return (EXIT_FAILURE);
259 	}
260 	if (iu_register_event(eh, rtsock_fd, POLLIN, rtsock_event, 0) == -1) {
261 		dhcpmsg(MSG_ERR, "cannot register routing socket for messages");
262 		return (EXIT_FAILURE);
263 	}
264 
265 	/*
266 	 * if the -a (adopt) option was specified, try to adopt the
267 	 * kernel-managed interface before we start. Our grandparent
268 	 * will be waiting for us to finish this, so signal him when
269 	 * we're done.
270 	 */
271 
272 	if (do_adopt) {
273 		int result;
274 
275 		result = dhcp_adopt();
276 
277 		if (grandparent != (pid_t)0) {
278 			dhcpmsg(MSG_DEBUG, "adoption complete, signalling "
279 			    "parent (%i) to exit.", grandparent);
280 			(void) kill(grandparent, SIGALRM);
281 		}
282 
283 		if (result == 0)
284 			return (EXIT_FAILURE);
285 	}
286 
287 	/*
288 	 * enter the main event loop; this is where all the real work
289 	 * takes place (through registering events and scheduling timers).
290 	 * this function only returns when the agent is shutting down.
291 	 */
292 
293 	switch (iu_handle_events(eh, tq)) {
294 
295 	case -1:
296 		dhcpmsg(MSG_WARNING, "iu_handle_events exited abnormally");
297 		break;
298 
299 	case DHCP_REASON_INACTIVITY:
300 		dhcpmsg(MSG_INFO, "no interfaces to manage, shutting down...");
301 		break;
302 
303 	case DHCP_REASON_TERMINATE:
304 		dhcpmsg(MSG_INFO, "received SIGTERM, shutting down...");
305 		break;
306 
307 	case DHCP_REASON_SIGNAL:
308 		dhcpmsg(MSG_WARNING, "received unexpected signal, shutting "
309 		    "down...");
310 		break;
311 	}
312 
313 	(void) iu_eh_unregister_signal(eh, SIGTHAW, NULL);
314 
315 	iu_eh_destroy(eh);
316 	iu_tq_destroy(tq);
317 
318 	return (EXIT_SUCCESS);
319 }
320 
321 /*
322  * drain_script(): event loop callback during shutdown
323  *
324  *   input: eh_t *: unused
325  *	    void *: unused
326  *  output: boolean_t: B_TRUE if event loop should exit; B_FALSE otherwise
327  */
328 
329 /* ARGSUSED */
330 boolean_t
331 drain_script(iu_eh_t *ehp, void *arg)
332 {
333 	if (shutdown_started == B_FALSE) {
334 		shutdown_started = B_TRUE;
335 		if (do_adopt == B_FALSE)	/* see 4291141 */
336 			nuke_ifslist(B_TRUE);
337 	}
338 	return (script_count == 0);
339 }
340 
341 /*
342  * accept_event(): accepts a new connection on the ipc socket and registers
343  *		   to receive its messages with the event handler
344  *
345  *   input: iu_eh_t *: unused
346  *	    int: the file descriptor in the iu_eh_t * the connection came in on
347  *	    (other arguments unused)
348  *  output: void
349  */
350 
351 /* ARGSUSED */
352 static void
353 accept_event(iu_eh_t *ehp, int fd, short events, iu_event_id_t id, void *arg)
354 {
355 	int	client_fd;
356 	int	is_priv;
357 
358 	if (dhcp_ipc_accept(fd, &client_fd, &is_priv) != 0) {
359 		dhcpmsg(MSG_ERR, "accept_event: accept on ipc socket");
360 		return;
361 	}
362 
363 	if (iu_register_event(eh, client_fd, POLLIN, ipc_event,
364 	    (void *)is_priv) == -1) {
365 		dhcpmsg(MSG_ERROR, "accept_event: cannot register ipc socket "
366 		    "for callback");
367 	}
368 }
369 
370 /*
371  * ipc_event(): processes incoming ipc requests
372  *
373  *   input: iu_eh_t *: unused
374  *	    int: the file descriptor in the iu_eh_t * the request came in on
375  *	    short: unused
376  *	    iu_event_id_t: unused
377  *	    void *: indicates whether the request is from a privileged client
378  *  output: void
379  */
380 
381 /* ARGSUSED */
382 static void
383 ipc_event(iu_eh_t *ehp, int fd, short events, iu_event_id_t id, void *arg)
384 {
385 	dhcp_ipc_request_t	*request;
386 	struct ifslist		*ifsp, *primary_ifsp;
387 	int			error, is_priv = (int)arg;
388 	PKT_LIST 		*plp[2];
389 	dhcp_ipc_type_t		cmd;
390 
391 	(void) iu_unregister_event(eh, id, NULL);
392 
393 	if (dhcp_ipc_recv_request(fd, &request, DHCP_IPC_REQUEST_WAIT) != 0) {
394 		dhcpmsg(MSG_ERROR, "ipc_event: dhcp_ipc_recv_request failed");
395 		(void) dhcp_ipc_close(fd);
396 		return;
397 	}
398 
399 	cmd = DHCP_IPC_CMD(request->message_type);
400 	if (cmd >= DHCP_NIPC) {
401 		send_error_reply(request, DHCP_IPC_E_CMD_UNKNOWN, &fd);
402 		return;
403 	}
404 
405 	/* return EPERM for any of the privileged actions */
406 
407 	if (!is_priv) {
408 		switch (cmd) {
409 
410 		case DHCP_STATUS:
411 		case DHCP_PING:
412 		case DHCP_GET_TAG:
413 			break;
414 
415 		default:
416 			dhcpmsg(MSG_WARNING, "ipc_event: privileged ipc "
417 			    "command (%i) attempted on %s", cmd,
418 			    request->ifname);
419 
420 			send_error_reply(request, DHCP_IPC_E_PERM, &fd);
421 			return;
422 		}
423 	}
424 
425 	/*
426 	 * try to locate the ifs associated with this command.  if the
427 	 * command is DHCP_START or DHCP_INFORM, then if there isn't
428 	 * an ifs already, make one (there may already be one from a
429 	 * previous failed attempt to START or INFORM).  otherwise,
430 	 * verify the interface is still valid.
431 	 */
432 
433 	ifsp = lookup_ifs(request->ifname);
434 
435 	switch (cmd) {
436 
437 	case DHCP_START:			/* FALLTHRU */
438 	case DHCP_INFORM:
439 		/*
440 		 * it's possible that the interface already exists, but
441 		 * has been abandoned.  usually in those cases we should
442 		 * return DHCP_IPC_E_UNKIF, but that makes little sense
443 		 * in the case of "start" or "inform", so just ignore
444 		 * the abandoned interface and start over anew.
445 		 */
446 
447 		if (ifsp != NULL && verify_ifs(ifsp) == 0)
448 			ifsp = NULL;
449 
450 		/*
451 		 * as part of initializing the ifs, insert_ifs()
452 		 * creates a DLPI stream at ifsp->if_dlpi_fd.
453 		 */
454 
455 		if (ifsp == NULL) {
456 			ifsp = insert_ifs(request->ifname, B_FALSE, &error);
457 			if (ifsp == NULL) {
458 				send_error_reply(request, error, &fd);
459 				return;
460 			}
461 		}
462 		break;
463 
464 	default:
465 		if (ifsp == NULL) {
466 			if (request->ifname[0] == '\0')
467 				error = DHCP_IPC_E_NOPRIMARY;
468 			else
469 				error = DHCP_IPC_E_UNKIF;
470 
471 			send_error_reply(request, error, &fd);
472 			return;
473 		}
474 		break;
475 	}
476 
477 	if (verify_ifs(ifsp) == 0) {
478 		send_error_reply(request, DHCP_IPC_E_UNKIF, &fd);
479 		return;
480 	}
481 
482 	if (ifsp->if_dflags & DHCP_IF_BOOTP) {
483 		switch (cmd) {
484 
485 		case DHCP_EXTEND:
486 		case DHCP_RELEASE:
487 		case DHCP_INFORM:
488 			send_error_reply(request, DHCP_IPC_E_BOOTP, &fd);
489 			return;
490 
491 		default:
492 			break;
493 		}
494 	}
495 
496 	/*
497 	 * verify that the interface is in a state which will allow the
498 	 * command.  we do this up front so that we can return an error
499 	 * *before* needlessly cancelling an in-progress transaction.
500 	 */
501 
502 	if (!ipc_cmd_allowed[ifsp->if_state][cmd]) {
503 		send_error_reply(request, DHCP_IPC_E_OUTSTATE, &fd);
504 		return;
505 	}
506 
507 	if ((request->message_type & DHCP_PRIMARY) && is_priv) {
508 		if ((primary_ifsp = lookup_ifs("")) != NULL)
509 			primary_ifsp->if_dflags &= ~DHCP_IF_PRIMARY;
510 		ifsp->if_dflags |= DHCP_IF_PRIMARY;
511 	}
512 
513 	/*
514 	 * current design dictates that there can be only one
515 	 * outstanding transaction per interface -- this simplifies
516 	 * the code considerably and also fits well with RFC2131.
517 	 * it is worth classifying the different DHCP commands into
518 	 * synchronous (those which we will handle now and be done
519 	 * with) and asynchronous (those which require transactions
520 	 * and will be completed at an indeterminate time in the
521 	 * future):
522 	 *
523 	 *    DROP: removes the agent's management of an interface.
524 	 *	    asynchronous as the script program may be invoked.
525 	 *
526 	 *    PING: checks to see if the agent controls an interface.
527 	 *	    synchronous, since no packets need to be sent
528 	 *	    to the DHCP server.
529 	 *
530 	 *  STATUS: returns information about the an interface.
531 	 *	    synchronous, since no packets need to be sent
532 	 *	    to the DHCP server.
533 	 *
534 	 * RELEASE: releases the agent's management of an interface
535 	 *	    and brings the interface down.  asynchronous as
536 	 *	    the script program may be invoked.
537 	 *
538 	 *  EXTEND: renews a lease.  asynchronous, since the agent
539 	 *	    needs to wait for an ACK, etc.
540 	 *
541 	 *   START: starts DHCP on an interface.  asynchronous since
542 	 *	    the agent needs to wait for OFFERs, ACKs, etc.
543 	 *
544 	 *  INFORM: obtains configuration parameters for an externally
545 	 *	    configured interface.  asynchronous, since the
546 	 *	    agent needs to wait for an ACK.
547 	 *
548 	 * notice that EXTEND, INFORM, START, DROP and RELEASE are
549 	 * asynchronous. notice also that asynchronous commands may
550 	 * occur from within the agent -- for instance, the agent
551 	 * will need to do implicit EXTENDs to extend the lease. in
552 	 * order to make the code simpler, the following rules apply
553 	 * for asynchronous commands:
554 	 *
555 	 * there can only be one asynchronous command at a time per
556 	 * interface.  the current asynchronous command is managed by
557 	 * the async_* api: async_start(), async_finish(),
558 	 * async_timeout(), async_cancel(), and async_pending().
559 	 * async_start() starts management of a new asynchronous
560 	 * command on an interface, which should only be done after
561 	 * async_pending() is called to check that there are no
562 	 * pending asynchronous commands on that interface.  when the
563 	 * command is completed, async_finish() should be called.  all
564 	 * asynchronous commands have an associated timer, which calls
565 	 * async_timeout() when it times out.  if async_timeout()
566 	 * decides that the asynchronous command should be cancelled
567 	 * (see below), it calls async_cancel() to attempt
568 	 * cancellation.
569 	 *
570 	 * asynchronous commands started by a user command have an
571 	 * associated ipc_action which provides the agent with
572 	 * information for how to get in touch with the user command
573 	 * when the action completes.  these ipc_action records also
574 	 * have an associated timeout which may be infinite.
575 	 * ipc_action_start() should be called when starting an
576 	 * asynchronous command requested by a user, which sets up the
577 	 * timer and keeps track of the ipc information (file
578 	 * descriptor, request type).  when the asynchronous command
579 	 * completes, ipc_action_finish() should be called to return a
580 	 * command status code to the user and close the ipc
581 	 * connection).  if the command does not complete before the
582 	 * timer fires, ipc_action_timeout() is called which closes
583 	 * the ipc connection and returns DHCP_IPC_E_TIMEOUT to the
584 	 * user.  note that independent of ipc_action_timeout(),
585 	 * ipc_action_finish() should be called.
586 	 *
587 	 * on a case-by-case basis, here is what happens (per interface):
588 	 *
589 	 *    o when an asynchronous command is requested, then
590 	 *	async_pending() is called to see if there is already
591 	 *	an asynchronous event.  if so, the command does not
592 	 *	proceed, and if there is an associated ipc_action,
593 	 *	the user command is sent DHCP_IPC_E_PEND.
594 	 *
595 	 *    o otherwise, the the transaction is started with
596 	 *	async_start().  if the transaction is on behalf
597 	 *	of a user, ipc_action_start() is called to keep
598 	 *	track of the ipc information and set up the
599 	 *	ipc_action timer.
600 	 *
601 	 *    o if the command completes normally and before a
602 	 *	timeout fires, then async_finish() is called.
603 	 *	if there was an associated ipc_action,
604 	 *	ipc_action_finish() is called to complete it.
605 	 *
606 	 *    o if the command fails before a timeout fires, then
607 	 *	async_finish() is called, and the interface is
608 	 *	is returned to a known state based on the command.
609 	 *	if there was an associated ipc_action,
610 	 *	ipc_action_finish() is called to complete it.
611 	 *
612 	 *    o if the ipc_action timer fires before command
613 	 *	completion, then DHCP_IPC_E_TIMEOUT is returned to
614 	 *	the user.  however, the transaction continues to
615 	 *	be carried out asynchronously.
616 	 *
617 	 *    o if async_timeout() fires before command completion,
618 	 *	then if the command was internal to the agent, it
619 	 *	is cancelled.  otherwise, if it was a user command,
620 	 *	then if the user is still waiting for the command
621 	 *	to complete, the command continues and async_timeout()
622 	 *	is rescheduled.
623 	 */
624 
625 	switch (cmd) {
626 
627 	case DHCP_DROP:					/* FALLTHRU */
628 	case DHCP_RELEASE:				/* FALLTHRU */
629 	case DHCP_EXTEND:				/* FALLTHRU */
630 	case DHCP_INFORM:				/* FALLTHRU */
631 	case DHCP_START:
632 		/*
633 		 * if shutdown request has been received, send back an error.
634 		 */
635 		if (shutdown_started) {
636 			send_error_reply(request, DHCP_IPC_E_OUTSTATE, &fd);
637 			return;
638 		}
639 
640 		if (async_pending(ifsp)) {
641 			send_error_reply(request, DHCP_IPC_E_PEND, &fd);
642 			return;
643 		}
644 
645 		if (ipc_action_start(ifsp, request, fd) == 0) {
646 			dhcpmsg(MSG_WARNING, "ipc_event: ipc_action_start "
647 			    "failed for %s", ifsp->if_name);
648 			send_error_reply(request, DHCP_IPC_E_MEMORY, &fd);
649 			return;
650 		}
651 
652 		if (async_start(ifsp, cmd, B_TRUE) == 0) {
653 			ipc_action_finish(ifsp, DHCP_IPC_E_MEMORY);
654 			return;
655 		}
656 		break;
657 
658 	default:
659 		break;
660 	}
661 
662 	switch (cmd) {
663 
664 	case DHCP_DROP:
665 		(void) script_start(ifsp, EVENT_DROP, dhcp_drop, NULL, NULL);
666 		return;
667 
668 	case DHCP_EXTEND:
669 		(void) dhcp_extending(ifsp);
670 		break;
671 
672 	case DHCP_GET_TAG: {
673 		dhcp_optnum_t	optnum;
674 		DHCP_OPT	*opt = NULL;
675 		boolean_t	did_alloc = B_FALSE;
676 		PKT_LIST	*ack = ifsp->if_ack;
677 
678 		/*
679 		 * verify the request makes sense.
680 		 */
681 
682 		if (request->data_type   != DHCP_TYPE_OPTNUM ||
683 		    request->data_length != sizeof (dhcp_optnum_t)) {
684 			send_error_reply(request, DHCP_IPC_E_PROTO, &fd);
685 			return;
686 		}
687 
688 		(void) memcpy(&optnum, request->buffer, sizeof (dhcp_optnum_t));
689 load_option:
690 		switch (optnum.category) {
691 
692 		case DSYM_SITE:			/* FALLTHRU */
693 		case DSYM_STANDARD:
694 			if (optnum.code <= DHCP_LAST_OPT)
695 				opt = ack->opts[optnum.code];
696 			break;
697 
698 		case DSYM_VENDOR:
699 			/*
700 			 * the test against VS_OPTION_START is broken up into
701 			 * two tests to avoid compiler warnings under intel.
702 			 */
703 
704 			if ((optnum.code > VS_OPTION_START ||
705 			    optnum.code == VS_OPTION_START) &&
706 			    optnum.code <= VS_OPTION_END)
707 				opt = ack->vs[optnum.code];
708 			break;
709 
710 		case DSYM_FIELD:
711 			if (optnum.code + optnum.size > sizeof (PKT))
712 				break;
713 
714 			/* + 2 to account for option code and length byte */
715 			opt = malloc(optnum.size + 2);
716 			if (opt == NULL) {
717 				send_error_reply(request, DHCP_IPC_E_MEMORY,
718 				    &fd);
719 				return;
720 			}
721 
722 			did_alloc = B_TRUE;
723 			opt->len  = optnum.size;
724 			opt->code = optnum.code;
725 			(void) memcpy(&opt->value, (caddr_t)ack->pkt +
726 			    opt->code, opt->len);
727 
728 			break;
729 
730 		default:
731 			send_error_reply(request, DHCP_IPC_E_PROTO, &fd);
732 			return;
733 		}
734 
735 		/*
736 		 * return the option payload, if there was one.  the "+ 2"
737 		 * accounts for the option code number and length byte.
738 		 */
739 
740 		if (opt != NULL) {
741 			send_data_reply(request, &fd, 0, DHCP_TYPE_OPTION, opt,
742 			    opt->len + 2);
743 
744 			if (did_alloc)
745 				free(opt);
746 			return;
747 		} else if (ack != ifsp->if_orig_ack) {
748 			/*
749 			 * There wasn't any definition for the option in the
750 			 * current ack, so now retry with the original ack if
751 			 * the original ack is not the current ack.
752 			 */
753 			ack = ifsp->if_orig_ack;
754 			goto load_option;
755 		}
756 
757 		/*
758 		 * note that an "okay" response is returned either in
759 		 * the case of an unknown option or a known option
760 		 * with no payload.  this is okay (for now) since
761 		 * dhcpinfo checks whether an option is valid before
762 		 * ever performing ipc with the agent.
763 		 */
764 
765 		send_ok_reply(request, &fd);
766 		return;
767 	}
768 
769 	case DHCP_INFORM:
770 		dhcp_inform(ifsp);
771 		/* next destination: dhcp_acknak() */
772 		return;
773 
774 	case DHCP_PING:
775 		if (ifsp->if_dflags & DHCP_IF_FAILED)
776 			send_error_reply(request, DHCP_IPC_E_FAILEDIF, &fd);
777 		else
778 			send_ok_reply(request, &fd);
779 		return;
780 
781 	case DHCP_RELEASE:
782 		(void) script_start(ifsp, EVENT_RELEASE, dhcp_release,
783 		    "Finished with lease.", NULL);
784 		return;
785 
786 	case DHCP_START:
787 		(void) canonize_ifs(ifsp);
788 
789 		/*
790 		 * if we have a valid hostconf lying around, then jump
791 		 * into INIT_REBOOT.  if it fails, we'll end up going
792 		 * through the whole selecting() procedure again.
793 		 */
794 
795 		error = read_hostconf(ifsp->if_name, plp, 2);
796 		if (error != -1) {
797 			ifsp->if_orig_ack = ifsp->if_ack = plp[0];
798 			if (error > 1) {
799 				/*
800 				 * Return indicated we had more than one packet
801 				 * second one is the original ack.  Older
802 				 * versions of the agent wrote only one ack
803 				 * to the file, we now keep both the first
804 				 * ack as well as the last one.
805 				 */
806 				ifsp->if_orig_ack = plp[1];
807 			}
808 			dhcp_init_reboot(ifsp);
809 			/* next destination: dhcp_acknak() */
810 			return;
811 		}
812 
813 		/*
814 		 * if not debugging, wait for a few seconds before
815 		 * going into SELECTING.
816 		 */
817 
818 		if (debug_level == 0) {
819 			if (iu_schedule_timer_ms(tq,
820 			    lrand48() % DHCP_SELECT_WAIT, dhcp_start, ifsp)
821 			    != -1) {
822 				hold_ifs(ifsp);
823 				/* next destination: dhcp_start() */
824 				return;
825 			}
826 		}
827 
828 		dhcp_selecting(ifsp);
829 		/* next destination: dhcp_requesting() */
830 		return;
831 
832 	case DHCP_STATUS: {
833 		dhcp_status_t	status;
834 
835 		status.if_began = monosec_to_time(ifsp->if_curstart_monosec);
836 
837 		if (ifsp->if_lease == DHCP_PERM) {
838 			status.if_t1	= DHCP_PERM;
839 			status.if_t2	= DHCP_PERM;
840 			status.if_lease	= DHCP_PERM;
841 		} else {
842 			status.if_t1	= status.if_began + ifsp->if_t1;
843 			status.if_t2	= status.if_began + ifsp->if_t2;
844 			status.if_lease	= status.if_began + ifsp->if_lease;
845 		}
846 
847 		status.version		= DHCP_STATUS_VER;
848 		status.if_state		= ifsp->if_state;
849 		status.if_dflags	= ifsp->if_dflags;
850 		status.if_sent		= ifsp->if_sent;
851 		status.if_recv		= ifsp->if_received;
852 		status.if_bad_offers	= ifsp->if_bad_offers;
853 
854 		(void) strlcpy(status.if_name, ifsp->if_name, IFNAMSIZ);
855 
856 		send_data_reply(request, &fd, 0, DHCP_TYPE_STATUS, &status,
857 		    sizeof (dhcp_status_t));
858 		return;
859 	}
860 
861 	default:
862 		return;
863 	}
864 }
865 
866 /*
867  * check_rtm_addr(): determine if routing socket message matches interface
868  *		     address
869  *
870  *   input: struct if_msghdr *: pointer to routing socket message
871  *	    struct in_addr: IP address
872  *  output: boolean_t
873  */
874 static boolean_t
875 check_rtm_addr(struct ifa_msghdr *ifam, int msglen, struct in_addr addr)
876 {
877 	char *cp, *lim;
878 	uint_t flag;
879 	struct sockaddr *sa;
880 	struct sockaddr_in *sinp;
881 
882 	if (!(ifam->ifam_addrs & RTA_IFA))
883 		return (B_FALSE);
884 
885 	cp = (char *)(ifam + 1);
886 	lim = (char *)ifam + msglen;
887 	for (flag = 1; flag < RTA_IFA; flag <<= 1) {
888 		if (ifam->ifam_addrs & flag) {
889 			/* LINTED: alignment */
890 			sa = (struct sockaddr *)cp;
891 			if ((char *)(sa + 1) > lim)
892 				return (B_FALSE);
893 			switch (sa->sa_family) {
894 			case AF_UNIX:
895 				cp += sizeof (struct sockaddr_un);
896 				break;
897 			case AF_INET:
898 				cp += sizeof (struct sockaddr_in);
899 				break;
900 			case AF_LINK:
901 				cp += sizeof (struct sockaddr_dl);
902 				break;
903 			case AF_INET6:
904 				cp += sizeof (struct sockaddr_in6);
905 				break;
906 			default:
907 				cp += sizeof (struct sockaddr);
908 				break;
909 			}
910 		}
911 	}
912 	/* LINTED: alignment */
913 	sinp = (struct sockaddr_in *)cp;
914 	if ((char *)(sinp + 1) > lim)
915 		return (B_FALSE);
916 	return (sinp->sin_addr.s_addr == addr.s_addr);
917 }
918 
919 /*
920  * rtsock_event(): fetches routing socket messages and updates internal
921  *		   interface state based on those messages.
922  *
923  *   input: iu_eh_t *: unused
924  *	    int: the routing socket file descriptor
925  *	    (other arguments unused)
926  *  output: void
927  */
928 
929 /* ARGSUSED */
930 static void
931 rtsock_event(iu_eh_t *ehp, int fd, short events, iu_event_id_t id, void *arg)
932 {
933 	struct ifslist *ifs;
934 	union {
935 		struct ifa_msghdr ifam;
936 		char buf[1024];
937 	} msg;
938 	uint16_t ifindex;
939 	struct lifreq lifr;
940 	char *fail;
941 	int msglen;
942 
943 	if ((msglen = read(fd, &msg, sizeof (msg))) <= 0)
944 		return;
945 
946 	/*
947 	 * These are the messages that can identify a particular logical
948 	 * interface by local IP address.
949 	 */
950 	if (msg.ifam.ifam_type != RTM_DELADDR &&
951 	    msg.ifam.ifam_type != RTM_NEWADDR)
952 		return;
953 
954 	/* Note that ifam_index is just 16 bits */
955 	ifindex = msg.ifam.ifam_index;
956 
957 	for (ifs = lookup_ifs_by_uindex(ifindex, NULL);
958 	    ifs != NULL;
959 	    ifs = lookup_ifs_by_uindex(ifindex, ifs)) {
960 
961 		/*
962 		 * The if_sock_ip_fd is set to a non-negative integer by
963 		 * configure_bound().  If it's negative, then DHCP doesn't
964 		 * think we're bound.
965 		 *
966 		 * For pre-bound interfaces, we want to check to see if the
967 		 * IFF_UP bit has been reported.  This means that DAD is
968 		 * complete.
969 		 */
970 		if (ifs->if_sock_ip_fd == -1 && ifs->if_state != PRE_BOUND)
971 			continue;
972 
973 		/*
974 		 * Since we cannot trust the flags reported by the routing
975 		 * socket (they're just 32 bits -- and thus never include
976 		 * IFF_DUPLICATE), and we can't trust the ifindex (it's only 16
977 		 * bits and also doesn't reflect the alias in use), we get
978 		 * flags on all matching interfaces, and go by that.
979 		 */
980 		(void) strlcpy(lifr.lifr_name, ifs->if_name,
981 		    sizeof (lifr.lifr_name));
982 		if (ioctl(ifs->if_sock_fd, SIOCGLIFFLAGS, &lifr) == -1) {
983 			fail = "unable to retrieve interface flags";
984 		} else if (!check_rtm_addr(&msg.ifam, msglen, ifs->if_addr)) {
985 			/*
986 			 * If the message is not about this logical interface,
987 			 * then just ignore it.
988 			 */
989 			continue;
990 		} else if (lifr.lifr_flags & IFF_DUPLICATE) {
991 			fail = "interface has duplicate address";
992 		} else {
993 			/*
994 			 * If we're now up and we were waiting for that, then
995 			 * kick off this interface.  DAD is done.
996 			 */
997 			if ((lifr.lifr_flags & IFF_UP) &&
998 			    ifs->if_state == PRE_BOUND)
999 				dhcp_bound_complete(ifs);
1000 
1001 			continue;
1002 		}
1003 
1004 		if (ifs->if_sock_ip_fd != -1) {
1005 			(void) close(ifs->if_sock_ip_fd);
1006 			ifs->if_sock_ip_fd = -1;
1007 		}
1008 		dhcpmsg(MSG_ERROR, fail);
1009 
1010 		/*
1011 		 * The binding has evidently failed, so it's as though it never
1012 		 * happened.  We need to do switch back to PRE_BOUND state so
1013 		 * that send_pkt_internal() uses DLPI instead of sockets.  Our
1014 		 * logical interface has already been torn down by the kernel,
1015 		 * and thus we can't send DHCPDECLINE by way of regular IP.
1016 		 */
1017 		ifs->if_state = PRE_BOUND;
1018 
1019 		if (ifs->if_ack->opts[CD_DHCP_TYPE] != NULL)
1020 			send_decline(ifs, fail, &ifs->if_addr);
1021 
1022 		ifs->if_bad_offers++;
1023 		dhcp_restart(ifs);
1024 	}
1025 }
1026