]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sbin/atm/atm/atm_subr.c
This commit was generated by cvs2svn to compensate for changes in r56889,
[FreeBSD/FreeBSD.git] / sbin / atm / atm / atm_subr.c
1 /*
2  *
3  * ===================================
4  * HARP  |  Host ATM Research Platform
5  * ===================================
6  *
7  *
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.
12  *
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.
20  *
21  * Copyright 1994-1998 Network Computing Services, Inc.
22  *
23  * Copies of this Software may be made, however, the above copyright
24  * notice must be reproduced on all copies.
25  *
26  *      @(#) $FreeBSD$
27  *
28  */
29
30 /*
31  * User configuration and display program
32  * --------------------------------------
33  *
34  * General subroutines
35  *
36  */
37
38 #include <sys/types.h>  
39 #include <sys/param.h>  
40 #include <sys/socket.h> 
41 #include <net/if.h>
42 #include <netinet/in.h>
43 #include <netatm/port.h>
44 #include <netatm/atm.h>
45 #include <netatm/atm_if.h> 
46 #include <netatm/atm_sap.h>
47 #include <netatm/atm_sys.h>
48 #include <netatm/atm_ioctl.h>
49 #include <arpa/inet.h>
50
51 #include <errno.h>
52 #include <libatm.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <string.h>
56
57 #include "atm.h"
58
59 #ifndef lint
60 __RCSID("@(#) $FreeBSD$");
61 #endif
62
63
64 /*
65  * Table entry definition
66  */
67 typedef struct {
68         int     type;
69         char    *name;
70 } tbl_ent;
71
72
73 /*
74  * Table to translate vendor codes to ASCII
75  */
76 tbl_ent vendors[] = {
77         { VENDAPI_UNKNOWN,      "Unknown" },
78         { VENDAPI_FORE_1,       "Fore" },
79         { VENDAPI_ENI_1,        "ENI" },
80         { 0,                    0 },
81 };
82
83
84 /*
85  * Table to translate adapter codes to ASCII
86  */
87 tbl_ent adapter_types[] = {
88         { DEV_UNKNOWN,          "Unknown" },
89         { DEV_FORE_SBA200E,     "SBA-200E" },
90         { DEV_FORE_SBA200,      "SBA-200" },
91         { DEV_FORE_PCA200E,     "PCA-200E" },
92         { DEV_ENI_155P,         "ENI-155p" },
93         { 0,                    0 },
94 };
95
96 /*
97  * Table to translate medium types to ASCII
98  */
99 tbl_ent media_types[] = {
100         { MEDIA_UNKNOWN,        "Unknown" },
101         { MEDIA_TAXI_100,       "100 Mbps 4B/5B" },
102         { MEDIA_TAXI_140,       "140 Mbps 4B/5B" },
103         { MEDIA_OC3C,           "OC-3c" },
104         { MEDIA_OC12C,          "OC-12c" },
105         { MEDIA_UTP155,         "155 Mbps UTP" },
106         { 0,                    0 },
107 };
108
109 /*
110  * Table to translate bus types to ASCII
111  */
112 tbl_ent bus_types[] = {
113         { BUS_UNKNOWN,  "Unknown" },
114         { BUS_SBUS_B16, "SBus" },
115         { BUS_SBUS_B32, "SBus" },
116         { BUS_PCI,      "PCI" },
117         { 0,                    0 },
118 };
119
120
121 /*
122  * Get interface vendor name
123  *
124  * Return a character string with a vendor name, given a vendor code.
125  * 
126  * Arguments:
127  *      vendor  vendor ID
128  *
129  * Returns:
130  *      char *  pointer to a string with the vendor name
131  *
132  */
133 char *
134 get_vendor(vendor)
135         int     vendor;
136 {
137         int     i;
138
139         for(i=0; vendors[i].name; i++) {
140                 if (vendors[i].type == vendor)
141                         return(vendors[i].name);
142         }
143
144         return("-");
145 }
146
147
148 /*
149  * Get adapter type
150  *
151  * Arguments:
152  *      dev     adapter code
153  *
154  * Returns:
155  *      char *  pointer to a string with the adapter type
156  *
157  */
158 char *
159 get_adapter(dev)
160         int     dev;
161 {
162         int     i;
163
164         for(i=0; adapter_types[i].name; i++) {
165                 if (adapter_types[i].type == dev)
166                         return(adapter_types[i].name);
167         }
168
169         return("-");
170 }
171
172
173 /*
174  * Get communication medium type
175  *
176  * Arguments:
177  *      media   medium code
178  *
179  * Returns:
180  *      char *  pointer to a string with the name of the medium
181  *
182  */
183 char *
184 get_media_type(media)
185         int     media;
186 {
187         int     i;
188
189         for(i=0; media_types[i].name; i++) {
190                 if (media_types[i].type == media)
191                         return(media_types[i].name);
192         }
193
194         return("-");
195 }
196
197
198 /*
199  * Get bus type
200  *
201  * Arguments:
202  *      bus     bus type code
203  *
204  * Returns:
205  *      char *  pointer to a string with the bus type
206  *
207  */
208 char *
209 get_bus_type(bus)
210         int     bus;
211 {
212         int     i;
213
214         for(i=0; bus_types[i].name; i++) {
215                 if (bus_types[i].type == bus)
216                         return(bus_types[i].name);
217         }
218
219         return("-");
220 }
221
222
223 /*
224  * Get adapter ID
225  *
226  * Get a string giving the adapter's vendor and type.
227  *
228  * Arguments:
229  *      intf    interface name
230  *
231  * Returns:
232  *      char *  pointer to a string identifying the adapter
233  *
234  */
235 char *
236 get_adapter_name(intf)
237         char    *intf;
238 {
239         int                     buf_len;
240         struct atminfreq        air;
241         struct air_cfg_rsp      *cfg;
242         static char             name[256];
243
244         /*
245          * Initialize
246          */
247         UM_ZERO(&air, sizeof(air));
248         UM_ZERO(name, sizeof(name));
249
250         /*
251          * Get configuration information from the kernel
252          */
253         air.air_opcode = AIOCS_INF_CFG;
254         strcpy(air.air_cfg_intf, intf);
255         buf_len = do_info_ioctl(&air, sizeof(struct air_cfg_rsp));
256         if (buf_len < sizeof(struct air_cfg_rsp))
257                 return("-");
258         cfg = (struct air_cfg_rsp *) air.air_buf_addr;
259
260         /*
261          * Build a string describing the adapter
262          */
263         strcpy(name, get_vendor(cfg->acp_vendor));
264         strcat(name, " ");
265         strcat(name, get_adapter(cfg->acp_device));
266
267         UM_FREE(cfg);
268
269         return(name);
270 }
271
272
273 /*
274  * Format a MAC address into a string
275  * 
276  * Arguments:
277  *      addr    pointer to a MAC address
278  *
279  * Returns:
280  *              the address of a string representing the MAC address
281  *
282  */
283 char *
284 format_mac_addr(addr)
285         Mac_addr *addr;
286 {
287         static char     str[256];
288
289         /*
290          * Check for null pointer
291          */
292         if (!addr)
293                 return("-");
294
295         /*
296          * Clear the returned string
297          */
298         UM_ZERO(str, sizeof(str));
299
300         /*
301          * Format the address
302          */
303         sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
304                         addr->ma_data[0],
305                         addr->ma_data[1],
306                         addr->ma_data[2],
307                         addr->ma_data[3],
308                         addr->ma_data[4],
309                         addr->ma_data[5]);
310
311         return(str);
312 }
313
314
315 /*
316  * Parse an IP prefix designation in the form nnn.nnn.nnn.nnn/mm
317  *
318  * Arguments:
319  *      cp      pointer to prefix designation string
320  *      op      pointer to a pair of in_addrs for the result
321  *
322  * Returns:
323  *      0       success
324  *      -1      prefix was invalid
325  *
326  */
327 int
328 parse_ip_prefix(cp, op)
329         char            *cp;
330         struct in_addr  *op;
331 {
332         int             len;
333         char            *mp;
334         struct in_addr  ip_addr;
335
336         static u_long   masks[33] = {
337                 0x0,
338                 0x80000000,
339                 0xc0000000,
340                 0xe0000000,
341                 0xf0000000,
342                 0xf8000000,
343                 0xfc000000,
344                 0xfe000000,
345                 0xff000000,
346                 0xff800000,
347                 0xffc00000,
348                 0xffe00000,
349                 0xfff00000,
350                 0xfff80000,
351                 0xfffc0000,
352                 0xfffe0000,
353                 0xffff0000,
354                 0xffff8000,
355                 0xffffc000,
356                 0xffffe000,
357                 0xfffff000,
358                 0xfffff800,
359                 0xfffffc00,
360                 0xfffffe00,
361                 0xffffff00,
362                 0xffffff80,
363                 0xffffffc0,
364                 0xffffffe0,
365                 0xfffffff0,
366                 0xfffffff8,
367                 0xfffffffc,
368                 0xfffffffe,
369                 0xffffffff
370         };
371
372         /*
373          * Find the slash that marks the start of the mask
374          */
375         mp = strchr(cp, '/');
376         if (mp) {
377                 *mp = '\0';
378                 mp++;
379         }
380
381         /*
382          * Convert the IP-address part of the prefix
383          */
384         ip_addr.s_addr = inet_addr(cp);
385         if (ip_addr.s_addr == -1)
386                 return(-1);
387
388         /*
389          * Set the default mask length
390          */
391         if (IN_CLASSA(ntohl(ip_addr.s_addr)))
392                 len = 8;
393         else if (IN_CLASSB(ntohl(ip_addr.s_addr)))
394                 len = 16;
395         else if (IN_CLASSC(ntohl(ip_addr.s_addr)))
396                 len = 24;
397         else
398                 return(-1);
399
400         /*
401          * Get the mask length
402          */
403         if (mp) {
404                 len = atoi(mp);
405                 if (len < 1 || len > 32)
406                         return(-1);
407         }
408
409         /*
410          * Select the mask and copy the IP address into the
411          * result buffer, ANDing it with the mask
412          */
413         op[1].s_addr = htonl(masks[len]);
414         op[0].s_addr = ip_addr.s_addr & op[1].s_addr;
415
416         return(0);
417 }
418
419
420 /*
421  * Compress a list of IP network prefixes
422  *
423  * Arguments:
424  *      ipp     pointer to list of IP address/mask pairs
425  *      ipc     length of list
426  *
427  * Returns:
428  *      length of compressed list
429  *
430  */
431 int
432 compress_prefix_list(ipp, ilen)
433         struct in_addr  *ipp;
434         int             ilen;
435 {
436         int             i, j, n;
437         struct in_addr  *ip1, *ip2, *m1, *m2;
438
439         /*
440          * Figure out how many pairs there are
441          */
442         n = ilen / (sizeof(struct in_addr) * 2);
443
444         /*
445          * Check each pair of address/mask pairs to make sure
446          * none contains the other
447          */
448         for (i = 0; i < n; i++) {
449                 ip1 = &ipp[i*2];
450                 m1 = &ipp[i*2+1];
451
452                 /*
453                  * If we've already eliminated this address,
454                  * skip the checks
455                  */
456                 if (ip1->s_addr == 0)
457                         continue;
458
459                 /*
460                  * Try all possible second members of the pair
461                  */
462                 for (j = i + 1; j < n; j++) {
463                         ip2 = &ipp[j*2];
464                         m2 = &ipp[j*2+1];
465
466                         /*
467                          * If we've already eliminated the second
468                          * address, just skip the checks
469                          */
470                         if (ip2->s_addr == 0)
471                                 continue;
472
473                         /*
474                          * Compare the address/mask pairs
475                          */
476                         if (m1->s_addr == m2->s_addr) {
477                                 /*
478                                  * Masks are equal
479                                  */
480                                 if (ip1->s_addr == ip2->s_addr) {
481                                         ip2->s_addr = 0;
482                                         m2->s_addr = 0;
483                                 }
484                         } else if (ntohl(m1->s_addr) <
485                                         ntohl(m2->s_addr)) {
486                                 /*
487                                  * m1 is shorter
488                                  */
489                                 if ((ip2->s_addr & m1->s_addr) ==
490                                                 ip1->s_addr) {
491                                         ip2->s_addr = 0;
492                                         m2->s_addr = 0;
493                                 }
494                         } else {
495                                 /*
496                                  * m1 is longer
497                                  */
498                                 if ((ip1->s_addr & m2->s_addr) ==
499                                                 ip2->s_addr) {
500                                         ip1->s_addr = 0;
501                                         m1->s_addr = 0;
502                                         break;
503                                 }
504                         }
505                 }
506         }
507
508         /*
509          * Now pull up the list, eliminating zeroed entries
510          */
511         for (i = 0, j = 0; i < n; i++) {
512                 ip1 = &ipp[i*2];
513                 m1 = &ipp[i*2+1];
514                 ip2 = &ipp[j*2];
515                 m2 = &ipp[j*2+1];
516                 if (ip1->s_addr != 0) {
517                         if (i != j) {
518                                 *ip2 = *ip1;
519                                 *m2 = *m1;
520                         }
521                         j++;
522                 }
523         }
524
525         return(j * sizeof(struct in_addr) * 2);
526 }
527
528
529 /*
530  * Make sure a user-supplied parameter is a valid network interface
531  * name
532  *
533  * When a socket call fails, print an error message and exit
534  * 
535  * Arguments:
536  *      nif     pointer to network interface name
537  *
538  * Returns:
539  *      none    exits if name is not valid
540  *
541  */
542 void
543 check_netif_name(nif)
544         char    *nif;
545 {
546         int     rc;
547
548         /*
549          * Look up the name in the kernel
550          */
551         rc = verify_nif_name(nif);
552
553         /*
554          * Check the result
555          */
556         if (rc > 0) {
557                 /*
558                  * Name is OK
559                  */
560                 return;
561         } else if (rc == 0) {
562                 /*
563                  * Name is not valid
564                  */
565                 fprintf(stderr, "%s: Invalid network interface name %s\n",
566                                 prog, nif);
567         } else {
568                 /*
569                  * Error performing IOCTL
570                  */
571                 fprintf(stderr, "%s: ", prog);
572                 switch(errno) {
573                 case ENOPROTOOPT:
574                 case EOPNOTSUPP:
575                         perror("Internal error");
576                         break;
577                 case ENXIO:
578                         fprintf(stderr, "%s is not an ATM device\n",
579                                         nif);
580                         break;
581                 default:
582                         perror("ioctl (AIOCINFO)");
583                         break;
584                 }
585         }
586
587         exit(1);
588 }
589
590
591 /*
592  * Socket error handler
593  *
594  * When a socket call fails, print an error message and exit
595  * 
596  * Arguments:
597  *      err     an errno describing the error
598  *
599  * Returns:
600  *      none
601  *
602  */
603 void
604 sock_error(err)
605         int     err;
606 {
607         fprintf(stderr, "%s: ", prog);
608
609         switch (err) {
610
611         case EPROTONOSUPPORT:
612                 fprintf(stderr, "ATM protocol support not loaded\n");
613                 break;
614
615         default:
616                 perror("socket");
617                 break;
618         }
619
620         exit(1);
621 }