Exemplo n.º 1
0
/*
 * Function that sends commands to dhcpagent daemon.
 */
int
dhcp_op(struct phyint *pi, int type)
{
	dhcp_ipc_request_t	*request;
	dhcp_ipc_reply_t	*reply	= NULL;
	int			error;

	request = dhcp_ipc_alloc_request(type | DHCP_V6, pi->pi_name, NULL, 0,
	    DHCP_TYPE_NONE);
	if (request == NULL) {
		logmsg(LOG_ERR, "dhcp_op: out of memory\n");
		/* make sure we try again next time there's a chance */
		if (type != DHCP_RELEASE) {
			pi->pi_ra_flags &=
			    ~ND_RA_FLAG_MANAGED & ~ND_RA_FLAG_OTHER;
		}
		return (DHCP_IPC_E_MEMORY);
	}

	error = dhcp_ipc_make_request(request, &reply, 0);
	free(request);
	if (error != 0) {
		logmsg(LOG_ERR, "could not send request to dhcpagent: "
		    "%s: %s\n", pi->pi_name, dhcp_ipc_strerror(error));
		return (error);
	}

	error = reply->return_code;
	free(reply);

	return (error);
}
Exemplo n.º 2
0
static int
getinfo_ifnames(const char *ifn, dhcp_optnum_t *optnum, DHCP_OPT **result)
{
	dhcp_ipc_request_t	*request;
	dhcp_ipc_reply_t	*reply;
	char			*ifnames, *ifnames_head;
	DHCP_OPT		*opt;
	size_t			opt_size;
	int			retval = 0;

	*result = NULL;
	ifnames_head = ifnames = strdup(ifn);
	if (ifnames == NULL)
		return (DHCP_IPC_E_MEMORY);

	request = dhcp_ipc_alloc_request(DHCP_GET_TAG, "", optnum,
	    sizeof (dhcp_optnum_t), DHCP_TYPE_OPTNUM);

	if (request == NULL) {
		free(ifnames_head);
		return (DHCP_IPC_E_MEMORY);
	}

	ifnames = strtok(ifnames, " ");
	if (ifnames == NULL)
		ifnames = "";

	for (; ifnames != NULL; ifnames = strtok(NULL, " ")) {

		(void) strlcpy(request->ifname, ifnames, IFNAMSIZ);
		retval = dhcp_ipc_make_request(request, &reply, 0);
		if (retval != 0)
			break;

		if (reply->return_code == 0) {
			opt = dhcp_ipc_get_data(reply, &opt_size, NULL);
			if (opt_size > 2 && (opt->len == opt_size - 2)) {
				*result = malloc(opt_size);
				if (*result == NULL)
					retval = DHCP_IPC_E_MEMORY;
				else
					(void) memcpy(*result, opt, opt_size);

				free(reply);
				break;
			}
		}

		free(reply);
		if (ifnames[0] == '\0')
			break;
	}

	free(request);
	free(ifnames_head);

	return (retval);
}
Exemplo n.º 3
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);
}