Initial import from FreeBSD RELENG_4:
[dragonfly.git] / sbin / spppcontrol / spppcontrol.c
1 /*
2  * Copyright (c) 1997, 2001 Joerg Wunsch
3  *
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #ifndef lint
28 static const char rcsid[] =
29   "$FreeBSD: src/sbin/spppcontrol/spppcontrol.c,v 1.7.2.2 2002/04/24 18:47:22 joerg Exp $";
30 #endif /* not lint */
31
32 #include <sys/types.h>
33 #include <sys/ioctl.h>
34 #include <sys/socket.h>
35
36 #include <net/if.h>
37 #include <net/if_var.h>
38 #include <net/if_sppp.h>
39
40 #include <err.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <sysexits.h>
45 #include <unistd.h>
46
47 static void usage(void);
48 void    print_vals(const char *ifname, struct spppreq *sp);
49 const char *phase_name(enum ppp_phase phase);
50 const char *proto_name(u_short proto);
51 const char *authflags(u_short flags);
52
53 #define PPP_PAP         0xc023
54 #define PPP_CHAP        0xc223
55
56 int
57 main(int argc, char **argv)
58 {
59         int s, c;
60         int errs = 0, verbose = 0;
61         size_t off;
62         long to;
63         char *endp;
64         const char *ifname, *cp;
65         struct ifreq ifr;
66         struct spppreq spr;
67
68         while ((c = getopt(argc, argv, "v")) != -1)
69                 switch (c) {
70                 case 'v':
71                         verbose++;
72                         break;
73
74                 default:
75                         errs++;
76                         break;
77                 }
78         argv += optind;
79         argc -= optind;
80
81         if (errs || argc < 1)
82                 usage();
83
84         ifname = argv[0];
85         strncpy(ifr.ifr_name, ifname, sizeof ifr.ifr_name);
86
87         /* use a random AF to create the socket */
88         if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
89                 err(EX_UNAVAILABLE, "ifconfig: socket");
90
91         argc--;
92         argv++;
93
94         spr.cmd = (int)SPPPIOGDEFS;
95         ifr.ifr_data = (caddr_t)&spr;
96
97         if (ioctl(s, SIOCGIFGENERIC, &ifr) == -1)
98                 err(EX_OSERR, "SIOCGIFGENERIC(SPPPIOGDEFS)");
99
100         if (argc == 0) {
101                 /* list only mode */
102                 print_vals(ifname, &spr);
103                 return 0;
104         }
105
106 #define startswith(s) strncmp(argv[0], s, (off = strlen(s))) == 0
107
108         while (argc > 0) {
109                 if (startswith("authproto=")) {
110                         cp = argv[0] + off;
111                         if (strcmp(cp, "pap") == 0)
112                                 spr.defs.myauth.proto =
113                                         spr.defs.hisauth.proto = PPP_PAP;
114                         else if (strcmp(cp, "chap") == 0)
115                                 spr.defs.myauth.proto =
116                                         spr.defs.hisauth.proto = PPP_CHAP;
117                         else if (strcmp(cp, "none") == 0)
118                                 spr.defs.myauth.proto =
119                                         spr.defs.hisauth.proto = 0;
120                         else
121                                 errx(EX_DATAERR, "bad auth proto: %s", cp);
122                 } else if (startswith("myauthproto=")) {
123                         cp = argv[0] + off;
124                         if (strcmp(cp, "pap") == 0)
125                                 spr.defs.myauth.proto = PPP_PAP;
126                         else if (strcmp(cp, "chap") == 0)
127                                 spr.defs.myauth.proto = PPP_CHAP;
128                         else if (strcmp(cp, "none") == 0)
129                                 spr.defs.myauth.proto = 0;
130                         else
131                                 errx(EX_DATAERR, "bad auth proto: %s", cp);
132                 } else if (startswith("myauthname="))
133                         strncpy(spr.defs.myauth.name, argv[0] + off,
134                                 AUTHNAMELEN);
135                 else if (startswith("myauthsecret=") ||
136                          startswith("myauthkey="))
137                         strncpy(spr.defs.myauth.secret, argv[0] + off,
138                                 AUTHKEYLEN);
139                 else if (startswith("hisauthproto=")) {
140                         cp = argv[0] + off;
141                         if (strcmp(cp, "pap") == 0)
142                                 spr.defs.hisauth.proto = PPP_PAP;
143                         else if (strcmp(cp, "chap") == 0)
144                                 spr.defs.hisauth.proto = PPP_CHAP;
145                         else if (strcmp(cp, "none") == 0)
146                                 spr.defs.hisauth.proto = 0;
147                         else
148                                 errx(EX_DATAERR, "bad auth proto: %s", cp);
149                 } else if (startswith("hisauthname="))
150                         strncpy(spr.defs.hisauth.name, argv[0] + off,
151                                 AUTHNAMELEN);
152                 else if (startswith("hisauthsecret=") ||
153                          startswith("hisauthkey="))
154                         strncpy(spr.defs.hisauth.secret, argv[0] + off,
155                                 AUTHKEYLEN);
156                 else if (strcmp(argv[0], "callin") == 0)
157                         spr.defs.hisauth.flags |= AUTHFLAG_NOCALLOUT;
158                 else if (strcmp(argv[0], "always") == 0)
159                         spr.defs.hisauth.flags &= ~AUTHFLAG_NOCALLOUT;
160                 else if (strcmp(argv[0], "norechallenge") == 0)
161                         spr.defs.hisauth.flags |= AUTHFLAG_NORECHALLENGE;
162                 else if (strcmp(argv[0], "rechallenge") == 0)
163                         spr.defs.hisauth.flags &= ~AUTHFLAG_NORECHALLENGE;
164                 else if (startswith("lcp-timeout=")) {
165                         cp = argv[0] + off;
166                         to = strtol(cp, &endp, 10);
167                         if (*cp == '\0' || *endp != '\0' ||
168                             /*
169                              * NB: 10 ms is the minimal possible value for
170                              * hz=100.  We assume no kernel has less clock
171                              * frequency than that...
172                              */
173                             to < 10 || to > 20000)
174                                 errx(EX_DATAERR, "bad lcp timeout value: %s",
175                                      cp);
176                         spr.defs.lcp.timeout = to;
177                 } else if (strcmp(argv[0], "enable-vj") == 0)
178                         spr.defs.enable_vj = 1;
179                 else if (strcmp(argv[0], "disable-vj") == 0)
180                         spr.defs.enable_vj = 0;
181                 else if (strcmp(argv[0], "enable-ipv6") == 0)
182                         spr.defs.enable_ipv6 = 1;
183                 else if (strcmp(argv[0], "disable-ipv6") == 0)
184                         spr.defs.enable_ipv6 = 0;
185                 else
186                         errx(EX_DATAERR, "bad parameter: \"%s\"", argv[0]);
187
188                 argv++;
189                 argc--;
190         }
191
192         spr.cmd = (int)SPPPIOSDEFS;
193
194         if (ioctl(s, SIOCSIFGENERIC, &ifr) == -1)
195                 err(EX_OSERR, "SIOCSIFGENERIC(SPPPIOSDEFS)");
196
197         if (verbose)
198                 print_vals(ifname, &spr);
199
200         return 0;
201 }
202
203 static void
204 usage(void)
205 {
206         fprintf(stderr, "%s\n%s\n",
207         "usage: spppcontrol [-v] ifname [{my|his}auth{proto|name|secret}=...]",
208         "       spppcontrol [-v] ifname callin|always");
209         exit(EX_USAGE);
210 }
211
212 void
213 print_vals(const char *ifname, struct spppreq *sp)
214 {
215         printf("%s:\tphase=%s\n", ifname, phase_name(sp->defs.pp_phase));
216         if (sp->defs.myauth.proto) {
217                 printf("\tmyauthproto=%s myauthname=\"%.*s\"\n",
218                        proto_name(sp->defs.myauth.proto),
219                        AUTHNAMELEN, sp->defs.myauth.name);
220         }
221         if (sp->defs.hisauth.proto) {
222                 printf("\thisauthproto=%s hisauthname=\"%.*s\"%s\n",
223                        proto_name(sp->defs.hisauth.proto),
224                        AUTHNAMELEN, sp->defs.hisauth.name,
225                        authflags(sp->defs.hisauth.flags));
226         }
227         printf("\tlcp-timeout=%d ms\n", sp->defs.lcp.timeout);
228         printf("\t%sable-vj\n", sp->defs.enable_vj? "en": "dis");
229         printf("\t%sable-ipv6\n", sp->defs.enable_ipv6? "en": "dis");
230 }
231
232 const char *
233 phase_name(enum ppp_phase phase)
234 {
235         switch (phase) {
236         case PHASE_DEAD:        return "dead";
237         case PHASE_ESTABLISH:   return "establish";
238         case PHASE_TERMINATE:   return "terminate";
239         case PHASE_AUTHENTICATE: return "authenticate";
240         case PHASE_NETWORK:     return "network";
241         }
242         return "illegal";
243 }
244
245 const char *
246 proto_name(u_short proto)
247 {
248         static char buf[12];
249         switch (proto) {
250         case PPP_PAP:   return "pap";
251         case PPP_CHAP:  return "chap";
252         }
253         sprintf(buf, "0x%x", (unsigned)proto);
254         return buf;
255 }
256
257 const char *
258 authflags(u_short flags)
259 {
260         static char buf[30];
261         buf[0] = '\0';
262         if (flags & AUTHFLAG_NOCALLOUT)
263                 strcat(buf, " callin");
264         if (flags & AUTHFLAG_NORECHALLENGE)
265                 strcat(buf, " norechallenge");
266         return buf;
267 }