Ejemplo n.º 1
0
/*
 * Start up DHCPv6 on a given physical interface. Does not wait for
 * a message to be returned from the daemon.
 */
void
start_dhcp(struct phyint *pi)
{
	int	error;
	int	type;

	if (dhcp_start_agent(DHCP_IPC_MAX_WAIT) == -1) {
		logmsg(LOG_ERR, "unable to start %s\n", DHCP_AGENT_PATH);
		/* make sure we try again next time there's a chance */
		pi->pi_ra_flags &= ~ND_RA_FLAG_MANAGED & ~ND_RA_FLAG_OTHER;
		return;
	}

	else if (pi->pi_ra_flags & ND_RA_FLAG_MANAGED)
		type = DHCP_START;
	else
		type = DHCP_INFORM;

	error = dhcp_op(pi, type);
	/*
	 * Timeout is considered to be "success" because we don't wait for DHCP
	 * to do its exchange.
	 */
	if (error != DHCP_IPC_SUCCESS && error != DHCP_IPC_E_RUNNING &&
	    error != DHCP_IPC_E_TIMEOUT) {
		logmsg(LOG_ERR, "Error in dhcpagent: %s: %s\n",
		    pi->pi_name, dhcp_ipc_strerror(error));
	}
}
Ejemplo n.º 2
0
int
dhcp_ipc_getinfo(dhcp_optnum_t *optnum, DHCP_OPT **result, int32_t timeout)
{
	dhcp_ipc_request_t	*request;
	dhcp_ipc_reply_t	*reply;
	char			*ifnames, *ifnames_copy, *ifnames_head;
	int			retval;
	time_t			start_time = time(NULL);

	if (timeout == DHCP_IPC_WAIT_DEFAULT)
		timeout = DHCP_IPC_DEFAULT_WAIT;

	/*
	 * wait at most 5 seconds for the agent to start.
	 */

	if (dhcp_start_agent((timeout > 5 || timeout < 0) ? 5 : timeout) == -1)
		return (DHCP_IPC_E_INT);

	/*
	 * check the primary interface for the option value first.
	 */

	retval = getinfo_ifnames("", optnum, result);
	if ((retval != 0) || (retval == 0 && *result != NULL))
		return (retval);

	/*
	 * no luck.  get a list of the interfaces under DHCP control
	 * and perform a GET_TAG on each one.
	 */

	ifnames = get_ifnames(IFF_DHCPRUNNING, 0);
	if (ifnames != NULL && strlen(ifnames) != 0) {
		retval = getinfo_ifnames(ifnames, optnum, result);
		if ((retval != 0) || (retval == 0 && *result != NULL)) {
			free(ifnames);
			return (retval);
		}
	}
	free(ifnames);

	/*
	 * still no luck.  retrieve a list of all interfaces on the
	 * system that could use DHCP but aren't.  send INFORMs out on
	 * each one. after that, sit in a loop for the next `timeout'
	 * seconds, trying every second to see if a response for the
	 * option we want has come in on one of the interfaces.
	 */

	ifnames = get_ifnames(IFF_UP|IFF_RUNNING, IFF_LOOPBACK|IFF_DHCPRUNNING);
	if (ifnames == NULL || strlen(ifnames) == 0) {
		free(ifnames);
		return (DHCP_IPC_E_NOVALUE);
	}

	ifnames_head = ifnames_copy = strdup(ifnames);
	if (ifnames_copy == NULL) {
		free(ifnames);
		return (DHCP_IPC_E_MEMORY);
	}

	request = dhcp_ipc_alloc_request(DHCP_INFORM, "", NULL, 0,
	    DHCP_TYPE_NONE);
	if (request == NULL) {
		free(ifnames);
		free(ifnames_head);
		return (DHCP_IPC_E_MEMORY);
	}

	ifnames_copy = strtok(ifnames_copy, " ");
	for (; ifnames_copy != NULL; ifnames_copy = strtok(NULL, " ")) {
		(void) strlcpy(request->ifname, ifnames_copy, IFNAMSIZ);
		if (dhcp_ipc_make_request(request, &reply, 0) == 0)
			free(reply);
	}

	for (;;) {
		if ((timeout != DHCP_IPC_WAIT_FOREVER) &&
		    (time(NULL) - start_time > timeout)) {
			retval = DHCP_IPC_E_TIMEOUT;
			break;
		}

		retval = getinfo_ifnames(ifnames, optnum, result);
		if (retval != 0 || (retval == 0 && *result != NULL))
			break;

		(void) sleep(1);
	}

	/*
	 * drop any interfaces that weren't under DHCP control before
	 * we got here; this keeps this function more of a black box
	 * and the behavior more consistent from call to call.
	 */

	request->message_type = DHCP_DROP;

	ifnames_copy = strcpy(ifnames_head, ifnames);
	ifnames_copy = strtok(ifnames_copy, " ");
	for (; ifnames_copy != NULL; ifnames_copy = strtok(NULL, " ")) {
		(void) strlcpy(request->ifname, ifnames_copy, IFNAMSIZ);
		if (dhcp_ipc_make_request(request, &reply, 0) == 0)
			free(reply);
	}

	free(request);
	free(ifnames_head);
	free(ifnames);
	return (retval);
}