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