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