BUS_CONFIG_INTR takes 2 devices now: parent and child
[dragonfly.git] / sbin / atm / atm / atm_subr.c
blob577997111006b1257623a8179ac8ca4df3ff3b01
1 /*
3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
8 * This Host ATM Research Platform ("HARP") file (the "Software") is
9 * made available by Network Computing Services, Inc. ("NetworkCS")
10 * "AS IS". NetworkCS does not provide maintenance, improvements or
11 * support of any kind.
13 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17 * In no event shall NetworkCS be responsible for any damages, including
18 * but not limited to consequential damages, arising from or relating to
19 * any use of the Software or related support.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
26 * @(#) $FreeBSD: src/sbin/atm/atm/atm_subr.c,v 1.3.2.1 2000/07/01 06:02:14 ps Exp $
27 * @(#) $DragonFly: src/sbin/atm/atm/atm_subr.c,v 1.4 2006/10/16 00:15:35 pavalos Exp $
31 * User configuration and display program
32 * --------------------------------------
34 * General subroutines
38 #include <sys/param.h>
39 #include <sys/socket.h>
40 #include <net/if.h>
41 #include <netinet/in.h>
42 #include <netatm/port.h>
43 #include <netatm/atm.h>
44 #include <netatm/atm_if.h>
45 #include <netatm/atm_sap.h>
46 #include <netatm/atm_sys.h>
47 #include <netatm/atm_ioctl.h>
48 #include <arpa/inet.h>
50 #include <errno.h>
51 #include <libatm.h>
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <string.h>
56 #include "atm.h"
59 * Table entry definition
61 typedef struct {
62 int type;
63 const char *name;
64 } tbl_ent;
68 * Table to translate vendor codes to ASCII
70 static const tbl_ent vendors[] = {
71 { VENDAPI_UNKNOWN, "Unknown" },
72 { VENDAPI_FORE_1, "Fore" },
73 { VENDAPI_ENI_1, "ENI" },
74 { 0, 0 },
79 * Table to translate adapter codes to ASCII
81 static const tbl_ent adapter_types[] = {
82 { DEV_UNKNOWN, "Unknown" },
83 { DEV_FORE_SBA200E, "SBA-200E" },
84 { DEV_FORE_SBA200, "SBA-200" },
85 { DEV_FORE_PCA200E, "PCA-200E" },
86 { DEV_ENI_155P, "ENI-155p" },
87 { 0, 0 },
91 * Table to translate medium types to ASCII
93 static const tbl_ent media_types[] = {
94 { MEDIA_UNKNOWN, "Unknown" },
95 { MEDIA_TAXI_100, "100 Mbps 4B/5B" },
96 { MEDIA_TAXI_140, "140 Mbps 4B/5B" },
97 { MEDIA_OC3C, "OC-3c" },
98 { MEDIA_OC12C, "OC-12c" },
99 { MEDIA_UTP155, "155 Mbps UTP" },
100 { 0, 0 },
104 * Table to translate bus types to ASCII
106 static const tbl_ent bus_types[] = {
107 { BUS_UNKNOWN, "Unknown" },
108 { BUS_SBUS_B16, "SBus" },
109 { BUS_SBUS_B32, "SBus" },
110 { BUS_PCI, "PCI" },
111 { 0, 0 },
116 * Get interface vendor name
118 * Return a character string with a vendor name, given a vendor code.
120 * Arguments:
121 * vendor vendor ID
123 * Returns:
124 * char * pointer to a string with the vendor name
127 const char *
128 get_vendor(int vendor)
130 int i;
132 for(i=0; vendors[i].name; i++) {
133 if (vendors[i].type == vendor)
134 return(vendors[i].name);
137 return("-");
142 * Get adapter type
144 * Arguments:
145 * dev adapter code
147 * Returns:
148 * char * pointer to a string with the adapter type
151 const char *
152 get_adapter(int dev)
154 int i;
156 for(i=0; adapter_types[i].name; i++) {
157 if (adapter_types[i].type == dev)
158 return(adapter_types[i].name);
161 return("-");
166 * Get communication medium type
168 * Arguments:
169 * media medium code
171 * Returns:
172 * char * pointer to a string with the name of the medium
175 const char *
176 get_media_type(int media)
178 int i;
180 for(i=0; media_types[i].name; i++) {
181 if (media_types[i].type == media)
182 return(media_types[i].name);
185 return("-");
190 * Get bus type
192 * Arguments:
193 * bus bus type code
195 * Returns:
196 * char * pointer to a string with the bus type
199 const char *
200 get_bus_type(int bus)
202 int i;
204 for(i=0; bus_types[i].name; i++) {
205 if (bus_types[i].type == bus)
206 return(bus_types[i].name);
209 return("-");
214 * Get adapter ID
216 * Get a string giving the adapter's vendor and type.
218 * Arguments:
219 * intf interface name
221 * Returns:
222 * char * pointer to a string identifying the adapter
225 const char *
226 get_adapter_name(char *intf)
228 int buf_len;
229 struct atminfreq air;
230 struct air_cfg_rsp *cfg;
231 static char name[256];
234 * Initialize
236 UM_ZERO(&air, sizeof(air));
237 UM_ZERO(name, sizeof(name));
240 * Get configuration information from the kernel
242 air.air_opcode = AIOCS_INF_CFG;
243 strcpy(air.air_cfg_intf, intf);
244 buf_len = do_info_ioctl(&air, sizeof(struct air_cfg_rsp));
245 if ((size_t)buf_len < sizeof(struct air_cfg_rsp))
246 return("-");
247 cfg = (struct air_cfg_rsp *) air.air_buf_addr;
250 * Build a string describing the adapter
252 strcpy(name, get_vendor(cfg->acp_vendor));
253 strcat(name, " ");
254 strcat(name, get_adapter(cfg->acp_device));
256 UM_FREE(cfg);
258 return(name);
263 * Format a MAC address into a string
265 * Arguments:
266 * addr pointer to a MAC address
268 * Returns:
269 * the address of a string representing the MAC address
272 const char *
273 format_mac_addr(Mac_addr *addr)
275 static char str[256];
278 * Check for null pointer
280 if (!addr)
281 return("-");
284 * Clear the returned string
286 UM_ZERO(str, sizeof(str));
289 * Format the address
291 sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
292 addr->ma_data[0],
293 addr->ma_data[1],
294 addr->ma_data[2],
295 addr->ma_data[3],
296 addr->ma_data[4],
297 addr->ma_data[5]);
299 return(str);
304 * Parse an IP prefix designation in the form nnn.nnn.nnn.nnn/mm
306 * Arguments:
307 * cp pointer to prefix designation string
308 * op pointer to a pair of in_addrs for the result
310 * Returns:
311 * 0 success
312 * -1 prefix was invalid
316 parse_ip_prefix(char *cp, struct in_addr *op)
318 int len;
319 char *mp;
320 struct in_addr ip_addr;
322 static u_long masks[33] = {
323 0x0,
324 0x80000000,
325 0xc0000000,
326 0xe0000000,
327 0xf0000000,
328 0xf8000000,
329 0xfc000000,
330 0xfe000000,
331 0xff000000,
332 0xff800000,
333 0xffc00000,
334 0xffe00000,
335 0xfff00000,
336 0xfff80000,
337 0xfffc0000,
338 0xfffe0000,
339 0xffff0000,
340 0xffff8000,
341 0xffffc000,
342 0xffffe000,
343 0xfffff000,
344 0xfffff800,
345 0xfffffc00,
346 0xfffffe00,
347 0xffffff00,
348 0xffffff80,
349 0xffffffc0,
350 0xffffffe0,
351 0xfffffff0,
352 0xfffffff8,
353 0xfffffffc,
354 0xfffffffe,
355 0xffffffff
359 * Find the slash that marks the start of the mask
361 mp = strchr(cp, '/');
362 if (mp) {
363 *mp = '\0';
364 mp++;
368 * Convert the IP-address part of the prefix
370 ip_addr.s_addr = inet_addr(cp);
371 if (ip_addr.s_addr == INADDR_NONE)
372 return(-1);
375 * Set the default mask length
377 if (IN_CLASSA(ntohl(ip_addr.s_addr)))
378 len = 8;
379 else if (IN_CLASSB(ntohl(ip_addr.s_addr)))
380 len = 16;
381 else if (IN_CLASSC(ntohl(ip_addr.s_addr)))
382 len = 24;
383 else
384 return(-1);
387 * Get the mask length
389 if (mp) {
390 len = atoi(mp);
391 if (len < 1 || len > 32)
392 return(-1);
396 * Select the mask and copy the IP address into the
397 * result buffer, ANDing it with the mask
399 op[1].s_addr = htonl(masks[len]);
400 op[0].s_addr = ip_addr.s_addr & op[1].s_addr;
402 return(0);
407 * Compress a list of IP network prefixes
409 * Arguments:
410 * ipp pointer to list of IP address/mask pairs
411 * ipc length of list
413 * Returns:
414 * length of compressed list
418 compress_prefix_list(struct in_addr *ipp, int ilen)
420 int i, j, n;
421 struct in_addr *ip1, *ip2, *m1, *m2;
424 * Figure out how many pairs there are
426 n = ilen / (sizeof(struct in_addr) * 2);
429 * Check each pair of address/mask pairs to make sure
430 * none contains the other
432 for (i = 0; i < n; i++) {
433 ip1 = &ipp[i*2];
434 m1 = &ipp[i*2+1];
437 * If we've already eliminated this address,
438 * skip the checks
440 if (ip1->s_addr == 0)
441 continue;
444 * Try all possible second members of the pair
446 for (j = i + 1; j < n; j++) {
447 ip2 = &ipp[j*2];
448 m2 = &ipp[j*2+1];
451 * If we've already eliminated the second
452 * address, just skip the checks
454 if (ip2->s_addr == 0)
455 continue;
458 * Compare the address/mask pairs
460 if (m1->s_addr == m2->s_addr) {
462 * Masks are equal
464 if (ip1->s_addr == ip2->s_addr) {
465 ip2->s_addr = 0;
466 m2->s_addr = 0;
468 } else if (ntohl(m1->s_addr) <
469 ntohl(m2->s_addr)) {
471 * m1 is shorter
473 if ((ip2->s_addr & m1->s_addr) ==
474 ip1->s_addr) {
475 ip2->s_addr = 0;
476 m2->s_addr = 0;
478 } else {
480 * m1 is longer
482 if ((ip1->s_addr & m2->s_addr) ==
483 ip2->s_addr) {
484 ip1->s_addr = 0;
485 m1->s_addr = 0;
486 break;
493 * Now pull up the list, eliminating zeroed entries
495 for (i = 0, j = 0; i < n; i++) {
496 ip1 = &ipp[i*2];
497 m1 = &ipp[i*2+1];
498 ip2 = &ipp[j*2];
499 m2 = &ipp[j*2+1];
500 if (ip1->s_addr != 0) {
501 if (i != j) {
502 *ip2 = *ip1;
503 *m2 = *m1;
505 j++;
509 return(j * sizeof(struct in_addr) * 2);
514 * Make sure a user-supplied parameter is a valid network interface
515 * name
517 * When a socket call fails, print an error message and exit
519 * Arguments:
520 * nif pointer to network interface name
522 * Returns:
523 * none exits if name is not valid
526 void
527 check_netif_name(char *nif)
529 int rc;
532 * Look up the name in the kernel
534 rc = verify_nif_name(nif);
537 * Check the result
539 if (rc > 0) {
541 * Name is OK
543 return;
544 } else if (rc == 0) {
546 * Name is not valid
548 fprintf(stderr, "%s: Invalid network interface name %s\n",
549 prog, nif);
550 } else {
552 * Error performing IOCTL
554 fprintf(stderr, "%s: ", prog);
555 switch(errno) {
556 case ENOPROTOOPT:
557 case EOPNOTSUPP:
558 perror("Internal error");
559 break;
560 case ENXIO:
561 fprintf(stderr, "%s is not an ATM device\n",
562 nif);
563 break;
564 default:
565 perror("ioctl (AIOCINFO)");
566 break;
570 exit(1);
575 * Socket error handler
577 * When a socket call fails, print an error message and exit
579 * Arguments:
580 * err an errno describing the error
582 * Returns:
583 * none
586 void
587 sock_error(int err)
589 fprintf(stderr, "%s: ", prog);
591 switch (err) {
593 case EPROTONOSUPPORT:
594 fprintf(stderr, "ATM protocol support not loaded\n");
595 break;
597 default:
598 perror("socket");
599 break;
602 exit(1);