xref: /NextBSD/sbin/atm/atmconfig/atmconfig_device.c (revision eb1a5f8de9f7ea602c373a710f531abbf81141c4)
1 /*
2  * Copyright (c) 2001-2002
3  *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4  * 	All rights reserved.
5  * Copyright (c) 2003-2004
6  *	Hartmut Brandt.
7  * 	All rights reserved.
8  *
9  * Author: Hartmut Brandt <harti@freebsd.org>
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35 
36 #include "atmconfig.h"
37 #include "atmconfig_device.h"
38 #include "private.h"
39 #include "oid.h"
40 
41 #include <bsnmp/asn1.h>
42 #include <bsnmp/snmp.h>
43 #include <bsnmp/snmpclient.h>
44 
45 /*
46  * Description of the begemotAtmIfTable
47  */
48 static const struct snmp_table atmif_table = {
49 	OIDX_begemotAtmIfTable,
50 	OIDX_begemotAtmIfTableLastChange, 2,
51 	sizeof(struct atmif),
52 	1, 0x7ffULL,
53 	{
54 	  { 0,
55 	    SNMP_SYNTAX_INTEGER, offsetof(struct atmif, index) },
56 	  { OID_begemotAtmIfName,
57 	    SNMP_SYNTAX_OCTETSTRING, offsetof(struct atmif, ifname) },
58 	  { OID_begemotAtmIfPcr,
59 	    SNMP_SYNTAX_GAUGE, offsetof(struct atmif, pcr) },
60 	  { OID_begemotAtmIfMedia,
61 	    SNMP_SYNTAX_INTEGER, offsetof(struct atmif, media) },
62 	  { OID_begemotAtmIfVpiBits,
63 	    SNMP_SYNTAX_GAUGE, offsetof(struct atmif, vpi_bits) },
64 	  { OID_begemotAtmIfVciBits,
65 	    SNMP_SYNTAX_GAUGE, offsetof(struct atmif, vci_bits) },
66 	  { OID_begemotAtmIfMaxVpcs,
67 	    SNMP_SYNTAX_GAUGE, offsetof(struct atmif, max_vpcs) },
68 	  { OID_begemotAtmIfMaxVccs,
69 	    SNMP_SYNTAX_GAUGE, offsetof(struct atmif, max_vccs) },
70 	  { OID_begemotAtmIfEsi,
71 	    SNMP_SYNTAX_OCTETSTRING, offsetof(struct atmif, esi) },
72 	  { OID_begemotAtmIfCarrierStatus,
73 	    SNMP_SYNTAX_INTEGER, offsetof(struct atmif, carrier) },
74 	  { OID_begemotAtmIfMode,
75 	    SNMP_SYNTAX_INTEGER, offsetof(struct atmif, mode) },
76           { 0, SNMP_SYNTAX_NULL, 0 }
77 	}
78 };
79 
80 /* List of all ATM interfaces */
81 struct atmif_list atmif_list = TAILQ_HEAD_INITIALIZER(atmif_list);
82 
83 /*
84  * ATM hardware table
85  */
86 struct atmhw {
87 	TAILQ_ENTRY(atmhw) link;
88 	uint64_t	found;
89 	int32_t		index;
90 	u_char		*vendor;
91 	size_t		vendorlen;
92 	u_char		*device;
93 	size_t		devicelen;
94 	uint32_t	serial;
95 	uint32_t	version;
96 	uint32_t	soft_version;
97 };
98 TAILQ_HEAD(atmhw_list, atmhw);
99 
100 /* list of ATM hardware */
101 static struct atmhw_list atmhw_list;
102 
103 /*
104  * Read ATM hardware table
105  */
106 static const struct snmp_table atmhw_table = {
107 	OIDX_begemotAtmHWTable,
108 	OIDX_begemotAtmIfTableLastChange, 2,
109 	sizeof(struct atmhw),
110 	1, 0x3fULL,
111 	{
112 	  { 0,
113 	    SNMP_SYNTAX_INTEGER, offsetof(struct atmhw, index) },
114 	  { OID_begemotAtmHWVendor,
115 	    SNMP_SYNTAX_OCTETSTRING, offsetof(struct atmhw, vendor) },
116 	  { OID_begemotAtmHWDevice,
117 	    SNMP_SYNTAX_OCTETSTRING, offsetof(struct atmhw, device) },
118 	  { OID_begemotAtmHWSerial,
119 	    SNMP_SYNTAX_GAUGE, offsetof(struct atmhw, serial) },
120 	  { OID_begemotAtmHWVersion,
121 	    SNMP_SYNTAX_GAUGE, offsetof(struct atmhw, version) },
122 	  { OID_begemotAtmHWSoftVersion,
123 	    SNMP_SYNTAX_GAUGE, offsetof(struct atmhw, soft_version) },
124           { 0, SNMP_SYNTAX_NULL, 0 }
125 	}
126 };
127 
128 static void device_status(int, char *[]);
129 static void device_hardware(int, char *[]);
130 static void device_modify(int, char *[]);
131 
132 static const struct cmdtab device_tab[] = {
133 	{ "hardware",	NULL,	device_hardware },
134  	{ "status",	NULL,	device_status },
135  	{ "modify",	NULL,	device_modify },
136 	{ NULL,		NULL,	NULL }
137 };
138 
139 static const struct cmdtab entry =
140 	{ "device",	device_tab,	NULL };
141 
142 static DEF_MODULE(&entry);
143 
144 /*
145  * Carrier state to string
146  */
147 static const struct penum strcarrier[] = {
148 	{ 1, "on" },
149 	{ 2, "off" },
150 	{ 3, "unknown" },
151 	{ 4, "none" },
152 	{ 0, NULL }
153 };
154 /*
155  * SUNI mode to string
156  */
157 static const struct penum strsunimode[] = {
158 	{ 1, "sonet" },
159 	{ 2, "sdh" },
160 	{ 3, "unknown" },
161 	{ 0, NULL }
162 };
163 
164 /*
165  * OIDs
166  */
167 static const struct asn_oid
168 	oid_begemotAtmIfMode = OIDX_begemotAtmIfMode;
169 
170 /*
171  * Print 1st status line
172  */
173 static void
dev_status1(const struct atmif * aif)174 dev_status1(const struct atmif *aif)
175 {
176 	char buf[100];
177 
178 	printf("%-5u %-8s %-6u %-4u %-5u %-4u %-5u "
179 	    "%02x:%02x:%02x:%02x:%02x:%02x %s\n", aif->index,
180 	    aif->ifname, aif->pcr,
181 	    (1 << aif->vpi_bits) - 1, (1 << aif->vci_bits) - 1,
182 	    aif->max_vpcs, aif->max_vccs, aif->esi[0],
183 	    aif->esi[1], aif->esi[2], aif->esi[3], aif->esi[4], aif->esi[5],
184 	    penum(aif->carrier, strcarrier, buf));
185 }
186 
187 /*
188  * Print 2nd status line
189  */
190 static void
dev_status2(const struct atmif * aif)191 dev_status2(const struct atmif *aif)
192 {
193 	char buf[100];
194 
195 	printf("%-5u %-8s %s\n", aif->index, aif->ifname,
196 	    penum(aif->mode, strsunimode, buf));
197 }
198 
199 /*
200  * Implement the 'device status' command
201  */
202 static void
device_status(int argc,char * argv[])203 device_status(int argc, char *argv[])
204 {
205 	int opt, i;
206 	struct atmif *aif;
207 	static const struct option opts[] = {
208 	    { NULL, 0, NULL }
209 	};
210 
211 	const char dev1[] =
212 	    "Interface             Max        Max\n"
213 	    "Index Name     PCR    VPI  VCI   VPCs VCCs  ESI               Carrier\n";
214 	const char dev2[] =
215 	    "Interface\n"
216 	    "Index Name     Mode\n";
217 
218 	while ((opt = parse_options(&argc, &argv, opts)) != -1)
219 		switch (opt) {
220 		}
221 
222 	snmp_open(NULL, NULL, NULL, NULL);
223 	atexit(snmp_close);
224 
225 	atmif_fetchtable();
226 
227 	if (TAILQ_EMPTY(&atmif_list))
228 		errx(1, "no ATM interfaces found");
229 
230 	if (argc > 0) {
231 		heading_init();
232 		for (i = 0; i < argc; i++) {
233 			if ((aif = atmif_find_name(argv[i])) == NULL) {
234 				warnx("%s: no such ATM interface", argv[i]);
235 				continue;
236 			}
237 			heading(dev1);
238 			dev_status1(aif);
239 		}
240 		heading_init();
241 		for (i = 0; i < argc; i++) {
242 			if ((aif = atmif_find_name(argv[i])) == NULL)
243 				continue;
244 			heading(dev2);
245 			dev_status2(aif);
246 		}
247 	} else {
248 		heading_init();
249 		TAILQ_FOREACH(aif, &atmif_list, link) {
250 			heading(dev1);
251 			dev_status1(aif);
252 		}
253 		heading_init();
254 		TAILQ_FOREACH(aif, &atmif_list, link) {
255 			heading(dev2);
256 			dev_status2(aif);
257 		}
258 	}
259 }
260 
261 /*
262  * Print hardware info line
263  */
264 static void
dev_hardware(const struct atmif * aif)265 dev_hardware(const struct atmif *aif)
266 {
267 	const struct atmhw *hw;
268 
269 	TAILQ_FOREACH(hw, &atmhw_list, link)
270 		if (aif->index == hw->index)
271 			break;
272 	if (hw == NULL) {
273 		warnx("hardware info not found for '%s'", aif->ifname);
274 		return;
275 	}
276 
277 	printf("%-5u %-8s %-16s%-10s %-10u %-10u %u\n", aif->index,
278 	    aif->ifname, hw->vendor, hw->device, hw->serial,
279 	    hw->version, hw->soft_version);
280 }
281 
282 /*
283  * Show hardware configuration
284  */
285 static void
device_hardware(int argc,char * argv[])286 device_hardware(int argc, char *argv[])
287 {
288 	int opt, i;
289 	struct atmif *aif;
290 
291 	static const struct option opts[] = {
292 	    { NULL, 0, NULL }
293 	};
294 
295 	static const char headline[] =
296 	    "Interface      \n"
297 	    "Index Name     Vendor          Card       Serial     HW         SW\n";
298 
299 	while ((opt = parse_options(&argc, &argv, opts)) != -1)
300 		switch (opt) {
301 		}
302 
303 	snmp_open(NULL, NULL, NULL, NULL);
304 	atexit(snmp_close);
305 
306 	atmif_fetchtable();
307 
308 	if (snmp_table_fetch(&atmhw_table, &atmhw_list) != 0)
309 		errx(1, "AtmHW table: %s", snmp_client.error);
310 
311 	if (argc > 0) {
312 		heading_init();
313 		for (i = 0; i < argc; i++) {
314 			if ((aif = atmif_find_name(argv[i])) == NULL) {
315 				warnx("interface not found '%s'", argv[i]);
316 				continue;
317 			}
318 			heading(headline);
319 			dev_hardware(aif);
320 		}
321 	} else {
322 		heading_init();
323 		TAILQ_FOREACH(aif, &atmif_list, link) {
324 			heading(headline);
325 			dev_hardware(aif);
326 		}
327 	}
328 }
329 
330 /*
331  * Change device parameters
332  */
333 static void
device_modify(int argc,char * argv[])334 device_modify(int argc, char *argv[])
335 {
336 	int opt;
337 	struct atmif *aif;
338 	int mode = 0;
339 	int n;
340 	struct snmp_pdu pdu, resp;
341 
342 	static const struct option opts[] = {
343 #define MODIFY_MODE	0
344 	    { "mode", OPT_STRING, NULL },
345 	    { NULL, 0, NULL }
346 	};
347 
348 	while ((opt = parse_options(&argc, &argv, opts)) != -1)
349 		switch (opt) {
350 
351 		  case MODIFY_MODE:
352 			if (pparse(&mode, strsunimode, optarg) == -1 ||
353 			    mode == 3)
354 				errx(1, "illegal mode for -m '%s'", optarg);
355 			break;
356 		}
357 
358 	if (argc != 1)
359 		errx(1, "device modify needs one argument");
360 
361 	snmp_open(NULL, NULL, NULL, NULL);
362 
363 	atexit(snmp_close);
364 	atmif_fetchtable();
365 
366 	if ((aif = atmif_find_name(argv[0])) == NULL)
367 		errx(1, "%s: no such ATM interface", argv[0]);
368 
369 	snmp_pdu_create(&pdu, SNMP_PDU_SET);
370 	if (mode != 0) {
371 		n = snmp_add_binding(&pdu,
372 		    &oid_begemotAtmIfMode, SNMP_SYNTAX_INTEGER,
373 		    NULL);
374 		snmp_oid_append(&pdu.bindings[n + 0].var, "i",
375 		    (asn_subid_t)aif->index);
376 		pdu.bindings[n + 0].v.integer = mode;
377 	}
378 
379 	if (pdu.nbindings == 0)
380 		errx(1, "must specify something to modify");
381 
382 	if (snmp_dialog(&pdu, &resp))
383 		errx(1, "No response from '%s': %s", snmp_client.chost,
384 		    snmp_client.error);
385 
386 	if (snmp_pdu_check(&pdu, &resp) <= 0)
387 		errx(1, "Error modifying device");
388 
389 	snmp_pdu_free(&resp);
390 	snmp_pdu_free(&pdu);
391 }
392 
393 /* XXX while this is compiled in */
394 void
device_register(void)395 device_register(void)
396 {
397 	register_module(&amodule_1);
398 }
399 
400 /*
401  * Fetch the ATM interface table
402  */
403 void
atmif_fetchtable(void)404 atmif_fetchtable(void)
405 {
406 	struct atmif *aif;
407 
408 	while ((aif = TAILQ_FIRST(&atmif_list)) != NULL) {
409 		free(aif->ifname);
410 		free(aif->esi);
411 		TAILQ_REMOVE(&atmif_list, aif, link);
412 		free(aif);
413 	}
414 
415 	if (snmp_table_fetch(&atmif_table, &atmif_list) != 0)
416 		errx(1, "AtmIf table: %s", snmp_client.error);
417 }
418 
419 /*
420  * Find a named ATM interface
421  */
422 struct atmif *
atmif_find_name(const char * ifname)423 atmif_find_name(const char *ifname)
424 {
425 	struct atmif *atmif;
426 
427 	TAILQ_FOREACH(atmif, &atmif_list, link)
428 		if (strcmp(atmif->ifname, ifname) == 0)
429 			return (atmif);
430 	return (NULL);
431 }
432 /*
433  * find an ATM interface by index
434  */
435 struct atmif *
atmif_find(u_int idx)436 atmif_find(u_int idx)
437 {
438 	struct atmif *atmif;
439 
440 	TAILQ_FOREACH(atmif, &atmif_list, link)
441 		if (atmif->index == (int32_t)idx)
442 			return (atmif);
443 	return (NULL);
444 }
445