/* * 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)); } }
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); }