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.
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.
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]
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
28 #include <sys/types.h>
33 #include <dhcpagent_ipc.h>
34 #include <dhcp_inittab.h>
35 #include <dhcp_symbol.h>
37 #define DHCP_INFO_VENDOR_START_V4 256
38 #define DHCP_INFO_VENDOR_START_V6 65536
41 usage(const char *program
)
43 (void) fprintf(stderr
,
44 "usage: %s [-c] [-i interface] [-n limit] [-v {4|6}] code\n"
45 " %s [-c] [-i interface] [-n limit] [-v {4|6}] identifier\n",
48 exit(DHCP_EXIT_BADARGS
);
52 main(int argc
, char **argv
)
54 ssize_t max_lines
= -1;
55 size_t gran
, n_spaces
= 0;
57 dhcp_ipc_request_t
*request
;
58 dhcp_ipc_reply_t
*reply
;
65 boolean_t is_canonical
= B_FALSE
;
70 while ((c
= getopt(argc
, argv
, "ci:n:v:")) != EOF
) {
75 is_canonical
= B_TRUE
;
83 max_lines
= strtoul(optarg
, NULL
, 0);
87 version
= strtol(optarg
, NULL
, 0);
88 if (version
!= 4 && version
!= 6)
100 if (argc
- optind
!= 1)
104 * we either have a code or an identifer. if we have a code,
105 * then values over 256 indicate a vendor option. if we have
106 * an identifier, then use inittab_getbyname() to turn the
107 * identifier into a code, then send the request over the wire.
110 isv6
= (version
== 6);
112 if (isalpha(*argv
[optind
])) {
114 entry
= inittab_getbyname(ITAB_CAT_SITE
| ITAB_CAT_STANDARD
|
115 ITAB_CAT_VENDOR
| ITAB_CAT_FIELD
|
116 (isv6
? ITAB_CAT_V6
: 0), ITAB_CONS_INFO
,
120 (void) fprintf(stderr
, "%s: unknown identifier `%s'\n",
121 argv
[0], argv
[optind
]);
122 return (DHCP_EXIT_BADARGS
);
125 optnum
.code
= entry
->ds_code
;
126 optnum
.category
= entry
->ds_category
;
131 optnum
.code
= strtoul(argv
[optind
], 0, 0);
132 optnum
.category
= ITAB_CAT_STANDARD
| ITAB_CAT_SITE
;
135 * sigh. this is a hack, but it's needed for backward
136 * compatibility with the CA dhcpinfo program.
139 start
= isv6
? DHCP_INFO_VENDOR_START_V6
:
140 DHCP_INFO_VENDOR_START_V4
;
141 if (optnum
.code
> start
) {
142 optnum
.code
-= start
;
143 optnum
.category
= ITAB_CAT_VENDOR
;
147 optnum
.category
|= ITAB_CAT_V6
;
149 entry
= inittab_getbycode(optnum
.category
, ITAB_CONS_INFO
,
153 (void) fprintf(stderr
, "%s: unknown code `%s'\n",
154 argv
[0], argv
[optind
]);
155 return (DHCP_EXIT_BADARGS
);
157 optnum
.category
= entry
->ds_category
;
160 optnum
.size
= entry
->ds_max
* inittab_type_to_size(entry
);
163 * send the request to the agent and reap the reply
166 request
= dhcp_ipc_alloc_request(DHCP_GET_TAG
| (isv6
? DHCP_V6
: 0),
167 ifname
, &optnum
, sizeof (dhcp_optnum_t
), DHCP_TYPE_OPTNUM
);
170 return (DHCP_EXIT_SYSTEM
);
172 error
= dhcp_ipc_make_request(request
, &reply
, DHCP_IPC_WAIT_DEFAULT
);
173 if (error
!= 0 || reply
->return_code
!= 0) {
176 error
= reply
->return_code
;
178 (void) fprintf(stderr
, "%s: %s\n", argv
[0],
179 dhcp_ipc_strerror(error
));
181 if (error
== DHCP_IPC_E_TIMEOUT
)
182 return (DHCP_EXIT_TIMEOUT
);
184 return (DHCP_EXIT_FAILURE
);
187 opt
= dhcp_ipc_get_data(reply
, &opt_len
, NULL
);
190 * no data means that the client has an ACK but has no information
191 * about the specified option; return success
195 return (DHCP_EXIT_SUCCESS
);
198 * check for protocol error
204 if (opt_len
< sizeof (d6o
))
205 return (DHCP_EXIT_FAILURE
);
206 (void) memcpy(&d6o
, opt
, sizeof (d6o
));
207 if (opt_len
!= ntohs(d6o
.d6o_len
) + sizeof (d6o
))
208 return (DHCP_EXIT_FAILURE
);
209 valptr
= (uint8_t *)opt
+ sizeof (d6o
);
210 opt_len
-= sizeof (d6o
);
212 if (opt_len
< 2 || (opt_len
- 2 != opt
->len
))
213 return (DHCP_EXIT_FAILURE
);
220 value
= malloc(opt_len
* (sizeof ("0xNN") + 1));
222 (void) fprintf(stderr
, "%s: out of memory\n", argv
[0]);
223 return (DHCP_EXIT_FAILURE
);
226 for (i
= 0, valuep
= value
; i
< opt_len
; i
++)
227 valuep
+= sprintf(valuep
, "0x%02X ", valptr
[i
]);
234 value
= inittab_decode(entry
, valptr
, opt_len
, B_TRUE
);
236 (void) fprintf(stderr
, "%s: cannot decode agent's "
238 return (DHCP_EXIT_FAILURE
);
241 gran
= entry
->ds_gran
;
245 * now display `gran' items per line, printing at most `max_lines'.
248 for (i
= 0; value
[i
] != '\0'; i
++) {
249 if (value
[i
] == ' ') {
250 if ((++n_spaces
% gran
) == 0) {
252 if (max_lines
!= -1 && --max_lines
== 0) {
260 (void) printf("%s\n", value
);
262 return (DHCP_EXIT_SUCCESS
);