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 2007 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 <sys/socket.h> 30 #include <sys/time.h> 31 #include <unistd.h> 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include "dhcpagent_ipc.h" 36 #include "dhcpagent_util.h" 37 38 /* 39 * Strings returned by dhcp_status_hdr_string() and 40 * dhcp_status_reply_to_string(). The first define is the header line, and 41 * the second defines line printed underneath. 42 * The spacing of fields must match. 43 */ 44 #define DHCP_STATUS_HDR "Interface State Sent Recv Declined Flags\n" 45 #define DHCP_STATUS_STR "%-10s %-12s %5d %5d %9d " 46 47 static const char *time_to_string(time_t abs_time); 48 49 /* 50 * dhcp_state_to_string(): given a state, provides the state's name 51 * 52 * input: DHCPSTATE: the state to get the name of 53 * output: const char *: the state's name 54 */ 55 56 const char * 57 dhcp_state_to_string(DHCPSTATE state) 58 { 59 const char *states[] = { 60 "INIT", 61 "SELECTING", 62 "REQUESTING", 63 "PRE_BOUND", 64 "BOUND", 65 "RENEWING", 66 "REBINDING", 67 "INFORMATION", 68 "INIT_REBOOT", 69 "ADOPTING", 70 "INFORM_SENT", 71 "DECLINING", 72 "RELEASING" 73 }; 74 75 if (state < 0 || state >= DHCP_NSTATES) 76 return ("<unknown>"); 77 78 return (states[state]); 79 } 80 81 /* 82 * dhcp_start_agent(): starts the agent if not already running 83 * 84 * input: int: number of seconds to wait for agent to start (-1 is forever) 85 * output: int: 0 on success, -1 on failure 86 */ 87 88 int 89 dhcp_start_agent(int timeout) 90 { 91 int error; 92 time_t start_time = time(NULL); 93 dhcp_ipc_request_t *request; 94 dhcp_ipc_reply_t *reply; 95 96 /* 97 * just send a dummy request to the agent to find out if it's 98 * up. we do this instead of directly connecting to it since 99 * we want to make sure we follow its IPC conventions 100 * (otherwise, it will log warnings to syslog). 101 */ 102 103 request = dhcp_ipc_alloc_request(DHCP_PING, "", NULL, 0, 104 DHCP_TYPE_NONE); 105 if (request == NULL) 106 return (-1); 107 108 error = dhcp_ipc_make_request(request, &reply, 0); 109 if (error == 0) { 110 free(reply); 111 free(request); 112 return (0); 113 } 114 if (error != DHCP_IPC_E_CONNECT) { 115 free(request); 116 return (-1); 117 } 118 119 switch (fork()) { 120 121 case -1: 122 free(request); 123 return (-1); 124 125 case 0: 126 (void) execl(DHCP_AGENT_PATH, DHCP_AGENT_PATH, (char *)0); 127 _exit(EXIT_FAILURE); 128 129 default: 130 break; 131 } 132 133 while ((timeout != -1) && (time(NULL) - start_time < timeout)) { 134 error = dhcp_ipc_make_request(request, &reply, 0); 135 if (error == 0) { 136 free(reply); 137 free(request); 138 return (0); 139 } else if (error != DHCP_IPC_E_CONNECT) 140 break; 141 (void) sleep(1); 142 } 143 144 free(request); 145 return (-1); 146 } 147 148 /* 149 * dhcp_status_hdr_string(): Return a string suitable to use as the header 150 * when printing DHCP_STATUS reply. 151 * output: const char *: newline terminated printable string 152 */ 153 const char * 154 dhcp_status_hdr_string(void) 155 { 156 return (DHCP_STATUS_HDR); 157 } 158 159 /* 160 * time_to_string(): Utility routine for printing time 161 * 162 * input: time_t *: time_t to stringify 163 * output: const char *: printable time 164 */ 165 static const char * 166 time_to_string(time_t abs_time) 167 { 168 static char time_buf[24]; 169 time_t tm = abs_time; 170 171 if (tm == DHCP_PERM) 172 return ("Never"); 173 174 if (strftime(time_buf, sizeof (time_buf), "%m/%d/%Y %R", 175 localtime(&tm)) == 0) 176 return ("<unknown>"); 177 178 return (time_buf); 179 } 180 181 /* 182 * dhcp_status_reply_to_string(): Return DHCP IPC reply of type DHCP_STATUS 183 * as a printable string 184 * 185 * input: dhcp_reply_t *: contains the status structure to print 186 * output: const char *: newline terminated printable string 187 */ 188 const char * 189 dhcp_status_reply_to_string(dhcp_ipc_reply_t *reply) 190 { 191 static char str[1024]; 192 size_t reply_size; 193 dhcp_status_t *status; 194 195 status = dhcp_ipc_get_data(reply, &reply_size, NULL); 196 if (reply_size < DHCP_STATUS_VER1_SIZE) 197 return ("<Internal error: status msg size>\n"); 198 199 (void) snprintf(str, sizeof (str), DHCP_STATUS_STR, 200 status->if_name, dhcp_state_to_string(status->if_state), 201 status->if_sent, status->if_recv, status->if_bad_offers); 202 203 if (status->if_dflags & DHCP_IF_PRIMARY) 204 (void) strlcat(str, "[PRIMARY] ", sizeof (str)); 205 206 if (status->if_dflags & DHCP_IF_BOOTP) 207 (void) strlcat(str, "[BOOTP] ", sizeof (str)); 208 209 if (status->if_dflags & DHCP_IF_FAILED) 210 (void) strlcat(str, "[FAILED] ", sizeof (str)); 211 212 if (status->if_dflags & DHCP_IF_BUSY) 213 (void) strlcat(str, "[BUSY] ", sizeof (str)); 214 215 if (status->if_dflags & DHCP_IF_V6) 216 (void) strlcat(str, "[V6] ", sizeof (str)); 217 218 (void) strlcat(str, "\n", sizeof (str)); 219 220 switch (status->if_state) { 221 case BOUND: 222 case RENEWING: 223 case REBINDING: 224 break; 225 default: 226 return (str); 227 } 228 229 (void) strlcat(str, "(Began, Expires, Renew) = (", sizeof (str)); 230 (void) strlcat(str, time_to_string(status->if_began), sizeof (str)); 231 (void) strlcat(str, ", ", sizeof (str)); 232 (void) strlcat(str, time_to_string(status->if_lease), sizeof (str)); 233 (void) strlcat(str, ", ", sizeof (str)); 234 (void) strlcat(str, time_to_string(status->if_t1), sizeof (str)); 235 (void) strlcat(str, ")\n", sizeof (str)); 236 return (str); 237 } 238