1 /* $NetBSD: pppoectl.c,v 1.1 2001/12/10 17:22:09 martin Exp $ */ 2 3 /* 4 * Copyright (c) 1997 Joerg Wunsch 5 * 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * From: spppcontrol.c,v 1.3 1998/01/07 07:55:26 charnier Exp 29 * From: ispppcontrol 30 */ 31 32 #include <sys/param.h> 33 #include <sys/callout.h> 34 #include <sys/ioctl.h> 35 #include <sys/mbuf.h> 36 #include <sys/socket.h> 37 #include <sys/time.h> 38 #include <sys/sysctl.h> 39 #include <net/if.h> 40 #include <net/if_sppp.h> 41 #include <net/if_pppoe.h> 42 #include <err.h> 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <string.h> 46 #include <sysexits.h> 47 #include <unistd.h> 48 49 static void usage(void); 50 void print_vals(const char *ifname, struct spppreq *sp); 51 const char *phase_name(enum ppp_phase phase); 52 const char *proto_name(u_short proto); 53 const char *authflags(u_short flags); 54 55 #define PPP_PAP 0xc023 56 #define PPP_CHAP 0xc223 57 58 int hz = 0; 59 60 int 61 main(int argc, char **argv) 62 { 63 int s, c; 64 int errs = 0, verbose = 0; 65 size_t off, len; 66 const char *ifname, *cp; 67 const char *eth_if_name, *access_concentrator, *service; 68 struct ifreq ifr; 69 struct spppreq spr; 70 int mib[2]; 71 struct clockinfo clockinfo; 72 73 eth_if_name = NULL; 74 access_concentrator = NULL; 75 service = NULL; 76 while ((c = getopt(argc, argv, "vde:s:a:")) != -1) 77 switch (c) { 78 case 'v': 79 verbose++; 80 break; 81 82 case 'e': 83 eth_if_name = optarg; 84 break; 85 86 case 's': 87 service = optarg; 88 break; 89 90 case 'a': 91 access_concentrator = optarg; 92 break; 93 94 default: 95 errs++; 96 break; 97 } 98 argv += optind; 99 argc -= optind; 100 101 if (errs || argc < 1) 102 usage(); 103 104 ifname = argv[0]; 105 106 strncpy(ifr.ifr_name, ifname, sizeof ifr.ifr_name); 107 108 /* use a random AF to create the socket */ 109 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 110 err(EX_UNAVAILABLE, "ifconfig: socket"); 111 112 argc--; 113 argv++; 114 115 if (eth_if_name) { 116 struct pppoediscparms parms; 117 int e; 118 119 memset(&parms, 0, sizeof parms); 120 strncpy(parms.ifname, ifname, sizeof(parms.ifname)); 121 strncpy(parms.eth_ifname, eth_if_name, sizeof(parms.eth_ifname)); 122 if (access_concentrator) { 123 parms.ac_name = (char*)access_concentrator; 124 parms.ac_name_len = strlen(access_concentrator); 125 } 126 if (service) { 127 parms.service_name = (char*)service; 128 parms.service_name_len = strlen(service); 129 } 130 131 e = ioctl(s, PPPOESETPARMS, &parms); 132 if (e) { 133 fprintf(stderr, "%s: ioctl(PPPOESETPARMS): %s\n", 134 ifname, strerror(e)); 135 } 136 return 0; 137 } 138 139 spr.cmd = (int)SPPPIOGDEFS; 140 ifr.ifr_data = (caddr_t)&spr; 141 142 if (ioctl(s, SIOCGIFGENERIC, &ifr) == -1) 143 err(EX_OSERR, "SIOCGIFGENERIC(SPPPIOGDEFS)"); 144 145 mib[0] = CTL_KERN; 146 mib[1] = KERN_CLOCKRATE; 147 len = sizeof(clockinfo); 148 if(sysctl(mib, 2, &clockinfo, &len, NULL, 0) == -1) 149 { 150 fprintf(stderr, "error, cannot sysctl kern.clockrate!\n"); 151 exit(1); 152 } 153 154 hz = clockinfo.hz; 155 156 if (argc == 0) { 157 /* list only mode */ 158 print_vals(ifname, &spr); 159 return 0; 160 } 161 162 #define startswith(s) strncmp(argv[0], s, (off = strlen(s))) == 0 163 164 while (argc > 0) { 165 if (startswith("authproto=")) { 166 cp = argv[0] + off; 167 if (strcmp(cp, "pap") == 0) 168 spr.defs.myauth.proto = 169 spr.defs.hisauth.proto = PPP_PAP; 170 else if (strcmp(cp, "chap") == 0) 171 spr.defs.myauth.proto = 172 spr.defs.hisauth.proto = PPP_CHAP; 173 else if (strcmp(cp, "none") == 0) 174 spr.defs.myauth.proto = 175 spr.defs.hisauth.proto = 0; 176 else 177 errx(EX_DATAERR, "bad auth proto: %s", cp); 178 } else if (startswith("myauthproto=")) { 179 cp = argv[0] + off; 180 if (strcmp(cp, "pap") == 0) 181 spr.defs.myauth.proto = PPP_PAP; 182 else if (strcmp(cp, "chap") == 0) 183 spr.defs.myauth.proto = PPP_CHAP; 184 else if (strcmp(cp, "none") == 0) 185 spr.defs.myauth.proto = 0; 186 else 187 errx(EX_DATAERR, "bad auth proto: %s", cp); 188 } else if (startswith("myauthname=")) 189 strncpy(spr.defs.myauth.name, argv[0] + off, 190 AUTHNAMELEN); 191 else if (startswith("myauthsecret=") || 192 startswith("myauthkey=")) 193 strncpy(spr.defs.myauth.secret, argv[0] + off, 194 AUTHKEYLEN); 195 else if (startswith("hisauthproto=")) { 196 cp = argv[0] + off; 197 if (strcmp(cp, "pap") == 0) 198 spr.defs.hisauth.proto = PPP_PAP; 199 else if (strcmp(cp, "chap") == 0) 200 spr.defs.hisauth.proto = PPP_CHAP; 201 else if (strcmp(cp, "none") == 0) 202 spr.defs.hisauth.proto = 0; 203 else 204 errx(EX_DATAERR, "bad auth proto: %s", cp); 205 } else if (startswith("hisauthname=")) 206 strncpy(spr.defs.hisauth.name, argv[0] + off, 207 AUTHNAMELEN); 208 else if (startswith("hisauthsecret=") || 209 startswith("hisauthkey=")) 210 strncpy(spr.defs.hisauth.secret, argv[0] + off, 211 AUTHKEYLEN); 212 else if (strcmp(argv[0], "callin") == 0) 213 spr.defs.hisauth.flags |= AUTHFLAG_NOCALLOUT; 214 else if (strcmp(argv[0], "always") == 0) 215 spr.defs.hisauth.flags &= ~AUTHFLAG_NOCALLOUT; 216 else if (strcmp(argv[0], "norechallenge") == 0) 217 spr.defs.hisauth.flags |= AUTHFLAG_NORECHALLENGE; 218 else if (strcmp(argv[0], "rechallenge") == 0) 219 spr.defs.hisauth.flags &= ~AUTHFLAG_NORECHALLENGE; 220 #ifndef __NetBSD__ 221 else if (strcmp(argv[0], "enable-vj") == 0) 222 spr.defs.enable_vj = 1; 223 else if (strcmp(argv[0], "disable-vj") == 0) 224 spr.defs.enable_vj = 0; 225 #endif 226 else if (startswith("lcp-timeout=")) { 227 int timeout_arg = atoi(argv[0]+off); 228 if ((timeout_arg > 20000) || (timeout_arg <= 0)) 229 errx(EX_DATAERR, "bad lcp timeout value: %s", 230 argv[0]+off); 231 spr.defs.lcp.timeout = timeout_arg * hz / 1000; 232 } else 233 errx(EX_DATAERR, "bad parameter: \"%s\"", argv[0]); 234 235 argv++; 236 argc--; 237 } 238 239 spr.cmd = (int)SPPPIOSDEFS; 240 241 if (ioctl(s, SIOCSIFGENERIC, &ifr) == -1) 242 err(EX_OSERR, "SIOCSIFGENERIC(SPPPIOSDEFS)"); 243 244 if (verbose) 245 print_vals(ifname, &spr); 246 247 return 0; 248 } 249 250 static void 251 usage(void) 252 { 253 fprintf(stderr, "%s\n%s\n", 254 "usage: ispppcontrol [-v] ifname [{my|his}auth{proto|name|secret}=...]", 255 " ispppcontrol [-v] ifname callin|always"); 256 exit(EX_USAGE); 257 } 258 259 void 260 print_vals(const char *ifname, struct spppreq *sp) 261 { 262 #ifndef __NetBSD__ 263 time_t send, recv; 264 #endif 265 266 printf("%s:\tphase=%s\n", ifname, phase_name(sp->defs.pp_phase)); 267 if (sp->defs.myauth.proto) { 268 printf("\tmyauthproto=%s myauthname=\"%.*s\"\n", 269 proto_name(sp->defs.myauth.proto), 270 AUTHNAMELEN, sp->defs.myauth.name); 271 } 272 if (sp->defs.hisauth.proto) { 273 printf("\thisauthproto=%s hisauthname=\"%.*s\"%s\n", 274 proto_name(sp->defs.hisauth.proto), 275 AUTHNAMELEN, sp->defs.hisauth.name, 276 authflags(sp->defs.hisauth.flags)); 277 } 278 #ifndef __NetBSD__ 279 if (sp->defs.pp_phase > PHASE_DEAD) { 280 send = time(NULL) - sp->defs.pp_last_sent; 281 recv = time(NULL) - sp->defs.pp_last_recv; 282 printf("\tidle_time=%ld\n", (send<recv)? send : recv); 283 } 284 #endif 285 printf("\tlcp timeout: %.3f s\n", 286 (double)sp->defs.lcp.timeout / hz); 287 #ifndef __NetBSD__ 288 printf("\tenable_vj: %s\n", 289 sp->defs.enable_vj ? "on" : "off"); 290 #endif 291 } 292 293 const char * 294 phase_name(enum ppp_phase phase) 295 { 296 switch (phase) { 297 case PHASE_DEAD: return "dead"; 298 case PHASE_ESTABLISH: return "establish"; 299 case PHASE_TERMINATE: return "terminate"; 300 case PHASE_AUTHENTICATE: return "authenticate"; 301 case PHASE_NETWORK: return "network"; 302 } 303 return "illegal"; 304 } 305 306 const char * 307 proto_name(u_short proto) 308 { 309 static char buf[12]; 310 switch (proto) { 311 case PPP_PAP: return "pap"; 312 case PPP_CHAP: return "chap"; 313 } 314 sprintf(buf, "0x%x", (unsigned)proto); 315 return buf; 316 } 317 318 const char * 319 authflags(u_short flags) 320 { 321 static char buf[32]; 322 buf[0] = '\0'; 323 if (flags & AUTHFLAG_NOCALLOUT) 324 strcat(buf, " callin"); 325 if (flags & AUTHFLAG_NORECHALLENGE) 326 strcat(buf, " norechallenge"); 327 return buf; 328 } 329