Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / sbin / atm / atm / atm_set.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: src/sbin/atm/atm/atm_set.c,v 1.3.2.1 2000/07/01 06:02:14 ps Exp $
27  *      @(#) $DragonFly: src/sbin/atm/atm/atm_set.c,v 1.2 2003/06/17 04:27:32 dillon Exp $
28  */
29
30 /*
31  * User configuration and display program
32  * --------------------------------------
33  *
34  * Routines for "set" subcommand
35  *
36  */
37
38 #include <sys/param.h>  
39 #include <sys/socket.h> 
40 #include <sys/sockio.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
50 #include <errno.h>
51 #include <libatm.h>
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <string.h>
55 #include <unistd.h>
56
57 #include "atm.h"
58
59 /*
60  * Process ATM ARP server set command
61  *
62  * Command format:
63  *      atm set arpserver <interface_name> <atm-address> <IP prefix> ...
64  *
65  * Arguments:
66  *      argc    number of arguments to command
67  *      argv    pointer to argument strings
68  *      cmdp    pointer to command description
69  *
70  * Returns:
71  *      none
72  *
73  */
74 void
75 set_arpserver(argc, argv, cmdp)
76         int             argc;
77         char            **argv;
78         struct cmd      *cmdp;
79 {
80         int                     i, len, prefix_len = 0, rc, s;
81         char                    *intf;
82         Atm_addr                server;
83         struct sockaddr_in      *lis;
84         struct sockaddr_in      if_mask;
85         struct atmsetreq        asr;
86         struct atminfreq        air;
87         struct air_netif_rsp    *int_info;
88         struct {
89                 struct in_addr  ip_addr;
90                 struct in_addr  ip_mask;
91         } prefix_buf[64];;
92
93         /*
94          * Validate interface name
95          */
96         check_netif_name(argv[0]);
97         intf = argv[0];
98         argc--; argv++;
99
100         /*
101          * Get the ARP server's ATM address
102          */
103         UM_ZERO(&server, sizeof(server));
104         if (strcasecmp(argv[0], "local")) {
105                 /*
106                  * ARP server NSAP address is provided
107                  */
108                 server.address_format = T_ATM_ENDSYS_ADDR;
109                 server.address_length = sizeof(Atm_addr_nsap);
110                 if (get_hex_atm_addr(argv[0],
111                                         (u_char *)server.address,
112                                         sizeof(Atm_addr_nsap)) !=
113                                 sizeof(Atm_addr_nsap)) {
114                         fprintf(stderr, "%s: Invalid ARP server address\n",
115                                         prog);
116                         exit(1);
117                 }
118                 if (argc > 1) {
119                         fprintf(stderr, "%s: Invalid number of arguments\n",
120                                         prog);
121                         exit(1);
122                 }
123                 prefix_len = 0;
124         } else {
125                 argc--; argv++;
126
127                 /*
128                  * This host is the ARP server
129                  */
130                 server.address_format = T_ATM_ABSENT;
131                 server.address_length = 0;
132
133                 /*
134                  * Get interface information from the kernel.  We need
135                  * to get the IP address and the subnet mask associated
136                  * with the network interface and insert them into the
137                  * list of permitted LIS prefixes.
138                  */
139                 len = sizeof(struct air_netif_rsp);
140                 UM_ZERO(&air, sizeof(air));
141                 air.air_opcode = AIOCS_INF_NIF;
142                 strcpy(air.air_int_intf, intf);
143                 len = do_info_ioctl(&air, len);
144                 if (len < 0) {
145                         fprintf(stderr, "%s: ", prog);
146                         switch (errno) {
147                         case ENOPROTOOPT:
148                         case EOPNOTSUPP:
149                                 perror("Internal error");
150                                 break;
151                         case ENXIO:
152                                 fprintf(stderr, "%s is not an ATM device\n",
153                                                 intf);
154                                 break;
155                         default:
156                                 perror("ioctl (AIOCINFO)");
157                                 break;
158                         }
159                         exit(1);
160                 }
161                 int_info = (struct air_netif_rsp *) air.air_buf_addr;
162                 lis = (struct sockaddr_in *)&int_info->anp_proto_addr;
163                 prefix_buf[0].ip_addr = lis->sin_addr;
164                 UM_FREE(int_info);
165         
166                 rc = get_subnet_mask(intf, &if_mask);
167                 if (rc) {
168                         fprintf(stderr, "%s: Can't get subnet mask for %s\n",
169                                         prog, intf);
170                 }
171                 prefix_buf[0].ip_mask = if_mask.sin_addr;
172                 prefix_buf[0].ip_addr.s_addr &=
173                                 prefix_buf[0].ip_mask.s_addr;
174
175                 /*
176                  * Get the prefixes of the LISs that we'll support
177                  */
178                 for (i = 1; argc; i++, argc--, argv++) {
179                         rc = parse_ip_prefix(argv[0],
180                                         (struct in_addr *)&prefix_buf[i]);
181                         if (rc != 0) {
182                                 fprintf(stderr, "%s: Invalid IP prefix value \'%s\'\n",
183                                         prog, argv[0]);
184                                 exit(1);
185                         }
186                 }
187
188                 /*
189                  * Compress the prefix list
190                  */
191                 prefix_len = compress_prefix_list((struct in_addr *)prefix_buf,
192                                 i * sizeof(struct in_addr) * 2);
193         }
194
195         /*
196          * Build ioctl request
197          */
198         UM_ZERO(&asr, sizeof(asr));
199         asr.asr_opcode = AIOCS_SET_ASV;
200         strncpy(asr.asr_arp_intf, intf, sizeof(asr.asr_arp_intf));
201         asr.asr_arp_addr = server;
202         asr.asr_arp_subaddr.address_format = T_ATM_ABSENT;
203         asr.asr_arp_subaddr.address_length = 0;
204         if (prefix_len)
205                 asr.asr_arp_pbuf = (caddr_t)prefix_buf;
206         else
207                 asr.asr_arp_pbuf = (caddr_t)0;
208         asr.asr_arp_plen = prefix_len;
209
210         /*
211          * Pass the new ARP server address to the kernel
212          */
213         s = socket(AF_ATM, SOCK_DGRAM, 0);
214         if (s < 0) {
215                 sock_error(errno);
216         }
217         if (ioctl(s, AIOCSET, (caddr_t)&asr) < 0) {
218                 fprintf(stderr, "%s: ", prog);
219                 switch (errno) {
220                 case EOPNOTSUPP:
221                 case EPROTONOSUPPORT:
222                         perror("Internal error");
223                         break;
224                 case EINVAL:
225                         fprintf(stderr, "Invalid parameter\n");
226                         break;
227                 case ENOMEM:
228                         fprintf(stderr, "Kernel memory exhausted\n");
229                         break;
230                 case ENETDOWN:
231                         fprintf(stderr, "ATM network is inoperable\n");
232                         break;
233                 case EPERM:
234                         fprintf(stderr, "Must be super user to use set subcommand\n");
235                         break;
236                 case ENXIO:
237                         fprintf(stderr, "%s is not an ATM interface\n", intf);
238                         break;
239                 case ENOENT:
240                         fprintf(stderr, "Signalling manager not attached\n");
241                         break;
242                 case ENOPROTOOPT:
243                         fprintf(stderr,
244                                 "%s does not have an IP address configured\n",
245                                 intf);
246                         break;
247                 default:
248                         perror("Ioctl (AIOCSET) ARPSERVER address");
249                         break;
250                 }
251                 exit(1);
252         }
253
254         (void)close(s);
255 }
256
257
258 /*
259  * Process set MAC address command
260  *
261  * Command format:
262  *      atm set mac <interface_name> <MAC address>
263  *
264  * Arguments:
265  *      argc    number of remaining arguments to command
266  *      argv    pointer to remaining argument strings
267  *      cmdp    pointer to command description
268  *
269  * Returns:
270  *      none
271  *
272  */
273 void
274 set_macaddr(argc, argv, cmdp)
275         int             argc;
276         char            **argv;
277         struct cmd      *cmdp;
278 {
279         int                     s;
280         char                    *intf;
281         struct mac_addr         mac;
282         struct atmsetreq        asr;
283
284         /*
285          * Validate interface name
286          */
287         if (strlen(argv[0]) > sizeof(asr.asr_mac_intf) - 1) {
288                 fprintf(stderr, "%s: Illegal interface name\n", prog);
289                 exit(1);
290         }
291         intf = argv[0];
292         argc--; argv++;
293
294         /*
295          * Get the MAC address provided by the user
296          */
297         if (get_hex_atm_addr(argv[0], (u_char *)&mac, sizeof(mac)) !=
298                         sizeof(mac)) {
299                 fprintf(stderr, "%s: Invalid MAC address\n", prog);
300                 exit(1);
301         }
302
303         /*
304          * Build ioctl request
305          */
306         asr.asr_opcode = AIOCS_SET_MAC;
307         strncpy(asr.asr_mac_intf, intf, sizeof(asr.asr_mac_intf));
308         UM_COPY(&mac, &asr.asr_mac_addr, sizeof(asr.asr_mac_addr));
309
310         /*
311          * Pass the new address to the kernel
312          */
313         s = socket(AF_ATM, SOCK_DGRAM, 0);
314         if (s < 0) {
315                 sock_error(errno);
316         }
317         if (ioctl(s, AIOCSET, (caddr_t)&asr) < 0) {
318                 fprintf(stderr, "%s: ", prog);
319                 switch (errno) {
320                 case EOPNOTSUPP:
321                 case EPROTONOSUPPORT:
322                         perror("Internal error");
323                         break;
324                 case EADDRINUSE:
325                         fprintf(stderr, "Interface must be detached to set MAC addres\n");
326                         break;
327                 case EINVAL:
328                         fprintf(stderr, "Invalid parameter\n");
329                         break;
330                 case ENOMEM:
331                         fprintf(stderr, "Kernel memory exhausted\n");
332                         break;
333                 case ENETDOWN:
334                         fprintf(stderr, "ATM network is inoperable\n");
335                         break;
336                 case EPERM:
337                         fprintf(stderr, "Must be super user to use set subcommand\n");
338                         break;
339                 case ENXIO:
340                         fprintf(stderr, "%s is not an ATM device\n",
341                                         argv[0]);
342                         break;
343                 default:
344                         perror("Ioctl (AIOCSET) MAC address");
345                         break;
346                 }
347                 exit(1);
348         }
349
350         (void)close(s);
351 }
352
353
354 /*
355  * Process network interface set command
356  *
357  * Command format:
358  *      atm set netif <interface_name> <prefix_name> <count>
359  *
360  * Arguments:
361  *      argc    number of arguments to command
362  *      argv    pointer to argument strings
363  *      cmdp    pointer to command description
364  *
365  * Returns:
366  *      none
367  *
368  */
369 void
370 set_netif(argc, argv, cmdp)
371         int             argc;
372         char            **argv;
373         struct cmd      *cmdp;
374 {
375         struct atmsetreq        anr;
376         char                    str[16];
377         char                    *cp;
378         int                     nifs, s;
379
380         /*
381          * Set IOCTL opcode
382          */
383         anr.asr_opcode = AIOCS_SET_NIF;
384
385         /*
386          * Validate interface name
387          */
388         if (strlen(argv[0]) > sizeof(anr.asr_nif_intf) - 1) {
389                 fprintf(stderr, "%s: Illegal interface name\n", prog);
390                 exit(1);
391         }
392         strcpy(anr.asr_nif_intf, argv[0]);
393         argc--; argv++;
394
395         /*
396          * Validate network interface name prefix
397          */
398         if ((strlen(argv[0]) > sizeof(anr.asr_nif_pref) - 1) ||
399                         (strpbrk(argv[0], "0123456789"))) {
400                 fprintf(stderr, "%s: Illegal network interface prefix\n", prog);
401                 exit(1);
402         }
403         strcpy(anr.asr_nif_pref, argv[0]);
404         argc--; argv++;
405
406         /*
407          * Validate interface count
408          */
409         nifs = (int) strtol(argv[0], &cp, 0);
410         if ((*cp != '\0') || (nifs < 0) || (nifs > MAX_NIFS)) {
411                 fprintf(stderr, "%s: Invalid interface count\n", prog);
412                 exit(1);
413         }
414         anr.asr_nif_cnt = nifs;
415
416         /*
417          * Make sure the resulting name won't be too long
418          */
419         sprintf(str, "%d", nifs - 1);
420         if ((strlen(str) + strlen(anr.asr_nif_pref)) >
421                         sizeof(anr.asr_nif_intf) - 1) {
422                 fprintf(stderr, "%s: Network interface prefix too long\n", prog);
423                 exit(1);
424         }
425
426         /*
427          * Tell the kernel to do it
428          */
429         s = socket(AF_ATM, SOCK_DGRAM, 0);
430         if (s < 0) {
431                 sock_error(errno);
432         }
433         if (ioctl(s, AIOCSET, (caddr_t)&anr) < 0) {
434                 fprintf(stderr, "%s: ", prog);
435                 perror("ioctl (AIOCSET) set NIF");
436                 exit(1);
437         }
438         (void)close(s);
439 }
440
441
442 /*
443  * Process set NSAP prefix command
444  *
445  * Command format:
446  *      atm set nsap <interface_name> <NSAP prefix>
447  *
448  * Arguments:
449  *      argc    number of remaining arguments to command
450  *      argv    pointer to remaining argument strings
451  *      cmdp    pointer to command description
452  *
453  * Returns:
454  *      none
455  *
456  */
457 void
458 set_prefix(argc, argv, cmdp)
459         int             argc;
460         char            **argv;
461         struct cmd      *cmdp;
462 {
463         int                     s;
464         char                    *intf;
465         u_char                  prefix[13];
466         struct atmsetreq        asr;
467
468         /*
469          * Validate interface name
470          */
471         if (strlen(argv[0]) > sizeof(asr.asr_prf_intf) - 1) {
472                 fprintf(stderr, "%s: Illegal interface name\n", prog);
473                 exit(1);
474         }
475         intf = argv[0];
476         argc--; argv++;
477
478         /*
479          * Get the prefix provided by the user
480          */
481         if (get_hex_atm_addr(argv[0], prefix, sizeof(prefix)) !=
482                         sizeof(prefix)) {
483                 fprintf(stderr, "%s: Invalid NSAP prefix\n", prog);
484                 exit(1);
485         }
486
487         /*
488          * Build ioctl request
489          */
490         asr.asr_opcode = AIOCS_SET_PRF;
491         strncpy(asr.asr_prf_intf, intf, sizeof(asr.asr_prf_intf));
492         UM_COPY(prefix, asr.asr_prf_pref, sizeof(asr.asr_prf_pref));
493
494         /*
495          * Pass the new prefix to the kernel
496          */
497         s = socket(AF_ATM, SOCK_DGRAM, 0);
498         if (s < 0) {
499                 sock_error(errno);
500         }
501         if (ioctl(s, AIOCSET, (caddr_t)&asr) < 0) {
502                 fprintf(stderr, "%s: ", prog);
503                 switch (errno) {
504                 case EOPNOTSUPP:
505                 case EPROTONOSUPPORT:
506                         perror("Internal error");
507                         break;
508                 case EALREADY:
509                         fprintf(stderr, "NSAP prefix is already set\n");
510                         break;
511                 case EINVAL:
512                         fprintf(stderr, "Invalid parameter\n");
513                         break;
514                 case ENOMEM:
515                         fprintf(stderr, "Kernel memory exhausted\n");
516                         break;
517                 case ENETDOWN:
518                         fprintf(stderr, "ATM network is inoperable\n");
519                         break;
520                 case EPERM:
521                         fprintf(stderr, "Must be super user to use set subcommand\n");
522                         break;
523                 case ENXIO:
524                         fprintf(stderr, "%s is not an ATM device\n",
525                                         argv[0]);
526                         break;
527                 default:
528                         perror("Ioctl (AIOCSET) NSAP prefix");
529                         break;
530                 }
531                 exit(1);
532         }
533
534         (void)close(s);
535 }