xref: /onnv-gate/usr/src/cmd/cmd-inet/sbin/dhcpinfo/dhcpinfo.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright (c) 1999-2001 by Sun Microsystems, Inc.
24*0Sstevel@tonic-gate  * All rights reserved.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <sys/types.h>
30*0Sstevel@tonic-gate #include <stdlib.h>
31*0Sstevel@tonic-gate #include <stdio.h>
32*0Sstevel@tonic-gate #include <ctype.h>
33*0Sstevel@tonic-gate #include <dhcpagent_ipc.h>
34*0Sstevel@tonic-gate #include <dhcp_inittab.h>
35*0Sstevel@tonic-gate #include <dhcp_symbol.h>
36*0Sstevel@tonic-gate 
37*0Sstevel@tonic-gate #define	DHCP_INFO_VENDOR_START	256
38*0Sstevel@tonic-gate 
39*0Sstevel@tonic-gate static void
40*0Sstevel@tonic-gate usage(const char *program)
41*0Sstevel@tonic-gate {
42*0Sstevel@tonic-gate 	(void) fprintf(stderr,
43*0Sstevel@tonic-gate 	    "usage: %s [-i interface] [-n limit] [-c] code\n"
44*0Sstevel@tonic-gate 	    "       %s [-i interface] [-n limit] [-c] identifier\n",
45*0Sstevel@tonic-gate 	    program, program);
46*0Sstevel@tonic-gate 
47*0Sstevel@tonic-gate 	exit(DHCP_EXIT_BADARGS);
48*0Sstevel@tonic-gate }
49*0Sstevel@tonic-gate 
50*0Sstevel@tonic-gate int
51*0Sstevel@tonic-gate main(int argc, char **argv)
52*0Sstevel@tonic-gate {
53*0Sstevel@tonic-gate 	ssize_t			max_lines = -1;
54*0Sstevel@tonic-gate 	size_t			gran, n_spaces = 0;
55*0Sstevel@tonic-gate 	dhcp_optnum_t		optnum;
56*0Sstevel@tonic-gate 	dhcp_ipc_request_t	*request;
57*0Sstevel@tonic-gate 	dhcp_ipc_reply_t	*reply;
58*0Sstevel@tonic-gate 	int			c, error, i;
59*0Sstevel@tonic-gate 	char			*ifname = "";
60*0Sstevel@tonic-gate 	char			*value, *valuep;
61*0Sstevel@tonic-gate 	dhcp_symbol_t		*entry;
62*0Sstevel@tonic-gate 	DHCP_OPT		*opt;
63*0Sstevel@tonic-gate 	size_t			opt_len;
64*0Sstevel@tonic-gate 	boolean_t		is_canonical = B_FALSE;
65*0Sstevel@tonic-gate 
66*0Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "cn:i:")) != EOF) {
67*0Sstevel@tonic-gate 
68*0Sstevel@tonic-gate 		switch (c) {
69*0Sstevel@tonic-gate 
70*0Sstevel@tonic-gate 		case 'c':
71*0Sstevel@tonic-gate 			is_canonical = B_TRUE;
72*0Sstevel@tonic-gate 			break;
73*0Sstevel@tonic-gate 
74*0Sstevel@tonic-gate 		case 'i':
75*0Sstevel@tonic-gate 			ifname = optarg;
76*0Sstevel@tonic-gate 			break;
77*0Sstevel@tonic-gate 
78*0Sstevel@tonic-gate 		case 'n':
79*0Sstevel@tonic-gate 			max_lines = strtoul(optarg, NULL, 0);
80*0Sstevel@tonic-gate 			break;
81*0Sstevel@tonic-gate 
82*0Sstevel@tonic-gate 		case '?':
83*0Sstevel@tonic-gate 			usage(argv[0]);
84*0Sstevel@tonic-gate 
85*0Sstevel@tonic-gate 		default:
86*0Sstevel@tonic-gate 			break;
87*0Sstevel@tonic-gate 		}
88*0Sstevel@tonic-gate 	}
89*0Sstevel@tonic-gate 
90*0Sstevel@tonic-gate 	if (argc - optind != 1)
91*0Sstevel@tonic-gate 		usage(argv[0]);
92*0Sstevel@tonic-gate 
93*0Sstevel@tonic-gate 	/*
94*0Sstevel@tonic-gate 	 * we either have a code or an identifer.  if we have a code,
95*0Sstevel@tonic-gate 	 * then values over 256 indicate a vendor option.  if we have
96*0Sstevel@tonic-gate 	 * an identifier, then use inittab_getbyname() to turn the
97*0Sstevel@tonic-gate 	 * identifier into a code, then send the request over the wire.
98*0Sstevel@tonic-gate 	 */
99*0Sstevel@tonic-gate 
100*0Sstevel@tonic-gate 	if (isalpha(*argv[optind])) {
101*0Sstevel@tonic-gate 
102*0Sstevel@tonic-gate 		entry = inittab_getbyname(ITAB_CAT_SITE|ITAB_CAT_STANDARD|
103*0Sstevel@tonic-gate 		    ITAB_CAT_VENDOR|ITAB_CAT_FIELD, ITAB_CONS_INFO,
104*0Sstevel@tonic-gate 		    argv[optind]);
105*0Sstevel@tonic-gate 
106*0Sstevel@tonic-gate 		if (entry == NULL) {
107*0Sstevel@tonic-gate 			(void) fprintf(stderr, "%s: unknown identifier `%s'\n",
108*0Sstevel@tonic-gate 			    argv[0], argv[optind]);
109*0Sstevel@tonic-gate 			return (DHCP_EXIT_BADARGS);
110*0Sstevel@tonic-gate 		}
111*0Sstevel@tonic-gate 
112*0Sstevel@tonic-gate 		optnum.code	= entry->ds_code;
113*0Sstevel@tonic-gate 		optnum.category = entry->ds_category;
114*0Sstevel@tonic-gate 
115*0Sstevel@tonic-gate 	} else {
116*0Sstevel@tonic-gate 
117*0Sstevel@tonic-gate 		optnum.code	= strtoul(argv[optind], 0, 0);
118*0Sstevel@tonic-gate 		optnum.category = ITAB_CAT_STANDARD|ITAB_CAT_SITE;
119*0Sstevel@tonic-gate 
120*0Sstevel@tonic-gate 		/*
121*0Sstevel@tonic-gate 		 * sigh.  this is a hack, but it's needed for backward
122*0Sstevel@tonic-gate 		 * compatibility with the CA dhcpinfo program.
123*0Sstevel@tonic-gate 		 */
124*0Sstevel@tonic-gate 
125*0Sstevel@tonic-gate 		if (optnum.code > DHCP_INFO_VENDOR_START) {
126*0Sstevel@tonic-gate 			optnum.code    -= DHCP_INFO_VENDOR_START;
127*0Sstevel@tonic-gate 			optnum.category = ITAB_CAT_VENDOR;
128*0Sstevel@tonic-gate 		}
129*0Sstevel@tonic-gate 
130*0Sstevel@tonic-gate 		entry = inittab_getbycode(optnum.category, ITAB_CONS_INFO,
131*0Sstevel@tonic-gate 		    optnum.code);
132*0Sstevel@tonic-gate 
133*0Sstevel@tonic-gate 		if (entry == NULL) {
134*0Sstevel@tonic-gate 			(void) fprintf(stderr, "%s: unknown code `%s'\n",
135*0Sstevel@tonic-gate 			    argv[0], argv[optind]);
136*0Sstevel@tonic-gate 			return (DHCP_EXIT_BADARGS);
137*0Sstevel@tonic-gate 		}
138*0Sstevel@tonic-gate 		optnum.category = entry->ds_category;
139*0Sstevel@tonic-gate 	}
140*0Sstevel@tonic-gate 
141*0Sstevel@tonic-gate 	optnum.size = entry->ds_max * inittab_type_to_size(entry);
142*0Sstevel@tonic-gate 
143*0Sstevel@tonic-gate 	/*
144*0Sstevel@tonic-gate 	 * send the request to the agent and reap the reply
145*0Sstevel@tonic-gate 	 */
146*0Sstevel@tonic-gate 
147*0Sstevel@tonic-gate 	request = dhcp_ipc_alloc_request(DHCP_GET_TAG, ifname, &optnum,
148*0Sstevel@tonic-gate 	    sizeof (dhcp_optnum_t), DHCP_TYPE_OPTNUM);
149*0Sstevel@tonic-gate 
150*0Sstevel@tonic-gate 	if (request == NULL)
151*0Sstevel@tonic-gate 		return (DHCP_EXIT_SYSTEM);
152*0Sstevel@tonic-gate 
153*0Sstevel@tonic-gate 	error = dhcp_ipc_make_request(request, &reply, DHCP_IPC_WAIT_DEFAULT);
154*0Sstevel@tonic-gate 	if (error != 0 || reply->return_code != 0) {
155*0Sstevel@tonic-gate 
156*0Sstevel@tonic-gate 		if (error == 0)
157*0Sstevel@tonic-gate 			error = reply->return_code;
158*0Sstevel@tonic-gate 
159*0Sstevel@tonic-gate 		(void) fprintf(stderr, "%s: %s\n", argv[0],
160*0Sstevel@tonic-gate 		    dhcp_ipc_strerror(error));
161*0Sstevel@tonic-gate 
162*0Sstevel@tonic-gate 		if (error == DHCP_IPC_E_TIMEOUT)
163*0Sstevel@tonic-gate 			return (DHCP_EXIT_TIMEOUT);
164*0Sstevel@tonic-gate 
165*0Sstevel@tonic-gate 		return (DHCP_EXIT_FAILURE);
166*0Sstevel@tonic-gate 	}
167*0Sstevel@tonic-gate 
168*0Sstevel@tonic-gate 	opt = dhcp_ipc_get_data(reply, &opt_len, NULL);
169*0Sstevel@tonic-gate 
170*0Sstevel@tonic-gate 	/*
171*0Sstevel@tonic-gate 	 * no data means that the client has an ACK but has no information
172*0Sstevel@tonic-gate 	 * about the specified option; return success
173*0Sstevel@tonic-gate 	 */
174*0Sstevel@tonic-gate 
175*0Sstevel@tonic-gate 	if (opt_len == 0)
176*0Sstevel@tonic-gate 		return (DHCP_EXIT_SUCCESS);
177*0Sstevel@tonic-gate 
178*0Sstevel@tonic-gate 	/*
179*0Sstevel@tonic-gate 	 * check for protocol error
180*0Sstevel@tonic-gate 	 */
181*0Sstevel@tonic-gate 
182*0Sstevel@tonic-gate 	if (opt_len < 2 || (opt_len - 2 != opt->len))
183*0Sstevel@tonic-gate 		return (DHCP_EXIT_FAILURE);
184*0Sstevel@tonic-gate 
185*0Sstevel@tonic-gate 	if (is_canonical) {
186*0Sstevel@tonic-gate 
187*0Sstevel@tonic-gate 		value = malloc(opt->len * (sizeof ("0xNN") + 1));
188*0Sstevel@tonic-gate 		if (value == NULL) {
189*0Sstevel@tonic-gate 			(void) fprintf(stderr, "%s: out of memory\n", argv[0]);
190*0Sstevel@tonic-gate 			return (DHCP_EXIT_FAILURE);
191*0Sstevel@tonic-gate 		}
192*0Sstevel@tonic-gate 
193*0Sstevel@tonic-gate 		for (i = 0, valuep = value; i < opt->len; i++)
194*0Sstevel@tonic-gate 			valuep += sprintf(valuep, "0x%02X ", opt->value[i]);
195*0Sstevel@tonic-gate 
196*0Sstevel@tonic-gate 		valuep[-1] = '\0';
197*0Sstevel@tonic-gate 		gran = 1;
198*0Sstevel@tonic-gate 
199*0Sstevel@tonic-gate 	} else {
200*0Sstevel@tonic-gate 
201*0Sstevel@tonic-gate 		value = inittab_decode(entry, opt->value, opt->len, B_TRUE);
202*0Sstevel@tonic-gate 		if (value == NULL) {
203*0Sstevel@tonic-gate 			(void) fprintf(stderr, "%s: cannot decode agent's "
204*0Sstevel@tonic-gate 			    "reply\n", argv[0]);
205*0Sstevel@tonic-gate 			return (DHCP_EXIT_FAILURE);
206*0Sstevel@tonic-gate 		}
207*0Sstevel@tonic-gate 
208*0Sstevel@tonic-gate 		gran = entry->ds_gran;
209*0Sstevel@tonic-gate 	}
210*0Sstevel@tonic-gate 
211*0Sstevel@tonic-gate 	/*
212*0Sstevel@tonic-gate 	 * now display `gran' items per line, printing at most `max_lines'.
213*0Sstevel@tonic-gate 	 */
214*0Sstevel@tonic-gate 
215*0Sstevel@tonic-gate 	for (i = 0; value[i] != '\0'; i++) {
216*0Sstevel@tonic-gate 		if (value[i] == ' ') {
217*0Sstevel@tonic-gate 			if ((++n_spaces % gran) == 0) {
218*0Sstevel@tonic-gate 				value[i] = '\n';
219*0Sstevel@tonic-gate 				if (max_lines != -1 && --max_lines == 0) {
220*0Sstevel@tonic-gate 					value[i] = '\0';
221*0Sstevel@tonic-gate 					break;
222*0Sstevel@tonic-gate 				}
223*0Sstevel@tonic-gate 			}
224*0Sstevel@tonic-gate 		}
225*0Sstevel@tonic-gate 	}
226*0Sstevel@tonic-gate 
227*0Sstevel@tonic-gate 	(void) printf("%s\n", value);
228*0Sstevel@tonic-gate 
229*0Sstevel@tonic-gate 	return (DHCP_EXIT_SUCCESS);
230*0Sstevel@tonic-gate }
231