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