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