1 /* $NetBSD: pppoectl.c,v 1.5 2002/01/07 12:22:02 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 static void print_error(const char *ifname, int error, const char * str); 51 static void print_vals(const char *ifname, int phase, struct spppauthcfg *sp, 52 int lcp_timeout, time_t idle_timeout, int authfailures, 53 int max_auth_failures); 54 const char *phase_name(int phase); 55 const char *proto_name(int proto); 56 const char *authflags(int flags); 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, dump = 0; 65 size_t off, len; 66 const char *ifname, *cp; 67 const char *eth_if_name, *access_concentrator, *service; 68 struct spppauthcfg spr; 69 struct sppplcpcfg lcp; 70 struct spppstatus status; 71 struct spppidletimeout timeout; 72 struct spppauthfailurestats authfailstats; 73 struct spppauthfailuresettings authfailset; 74 int mib[2]; 75 int set_auth = 0, set_lcp = 0, set_idle_to = 0, set_auth_failure = 0; 76 struct clockinfo clockinfo; 77 78 setprogname(argv[0]); 79 80 eth_if_name = NULL; 81 access_concentrator = NULL; 82 service = NULL; 83 while ((c = getopt(argc, argv, "vde:s:a:")) != -1) 84 switch (c) { 85 case 'v': 86 verbose++; 87 break; 88 89 case 'd': 90 dump++; 91 break; 92 93 case 'e': 94 eth_if_name = optarg; 95 break; 96 97 case 's': 98 service = optarg; 99 break; 100 101 case 'a': 102 access_concentrator = optarg; 103 break; 104 105 default: 106 errs++; 107 break; 108 } 109 argv += optind; 110 argc -= optind; 111 112 if (errs || argc < 1) 113 usage(); 114 115 ifname = argv[0]; 116 117 /* use a random AF to create the socket */ 118 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 119 err(EX_UNAVAILABLE, "ifconfig: socket"); 120 121 argc--; 122 argv++; 123 124 if (eth_if_name) { 125 struct pppoediscparms parms; 126 int e; 127 128 memset(&parms, 0, sizeof parms); 129 strncpy(parms.ifname, ifname, sizeof(parms.ifname)); 130 strncpy(parms.eth_ifname, eth_if_name, sizeof(parms.eth_ifname)); 131 if (access_concentrator) { 132 parms.ac_name = (char*)access_concentrator; 133 parms.ac_name_len = strlen(access_concentrator); 134 } 135 if (service) { 136 parms.service_name = (char*)service; 137 parms.service_name_len = strlen(service); 138 } 139 140 e = ioctl(s, PPPOESETPARMS, &parms); 141 if (e) 142 print_error(ifname, e, "PPPOESETPARMS"); 143 return 0; 144 } 145 146 if (dump) { 147 /* dump PPPoE session state */ 148 struct pppoeconnectionstate state; 149 int e; 150 151 memset(&state, 0, sizeof state); 152 strncpy(state.ifname, ifname, sizeof state.ifname); 153 e = ioctl(s, PPPOEGETSESSION, &state); 154 if (e) 155 print_error(ifname, e, "PPPOEGETSESSION,"); 156 157 printf("%s:\tstate = ", ifname); 158 switch(state.state) { 159 case PPPOE_STATE_INITIAL: 160 printf("initial\n"); break; 161 case PPPOE_STATE_PADI_SENT: 162 printf("PADI sent\n"); break; 163 case PPPOE_STATE_PADR_SENT: 164 printf("PADR sent\n"); break; 165 case PPPOE_STATE_SESSION: 166 printf("session\n"); break; 167 case PPPOE_STATE_CLOSING: 168 printf("closing\n"); break; 169 } 170 printf("\tSession ID: 0x%x\n", state.session_id); 171 printf("\tPADI retries: %d\n", state.padi_retry_no); 172 printf("\tPADR retries: %d\n", state.padr_retry_no); 173 174 return 0; 175 } 176 177 178 memset(&spr, 0, sizeof spr); 179 strncpy(spr.ifname, ifname, sizeof spr.ifname); 180 memset(&lcp, 0, sizeof lcp); 181 strncpy(lcp.ifname, ifname, sizeof lcp.ifname); 182 memset(&status, 0, sizeof status); 183 strncpy(status.ifname, ifname, sizeof status.ifname); 184 memset(&timeout, 0, sizeof timeout); 185 strncpy(timeout.ifname, ifname, sizeof timeout.ifname); 186 memset(&authfailstats, 0, sizeof &authfailstats); 187 strncpy(authfailstats.ifname, ifname, sizeof authfailstats.ifname); 188 memset(&authfailset, 0, sizeof authfailset); 189 strncpy(authfailset.ifname, ifname, sizeof authfailset.ifname); 190 191 mib[0] = CTL_KERN; 192 mib[1] = KERN_CLOCKRATE; 193 len = sizeof(clockinfo); 194 if(sysctl(mib, 2, &clockinfo, &len, NULL, 0) == -1) 195 { 196 fprintf(stderr, "error, cannot sysctl kern.clockrate!\n"); 197 exit(1); 198 } 199 200 hz = clockinfo.hz; 201 202 if (argc == 0) { 203 /* list only mode */ 204 205 /* first pass, get name lenghts */ 206 if (ioctl(s, SPPPGETAUTHCFG, &spr) == -1) 207 err(EX_OSERR, "SPPPGETAUTHCFG"); 208 /* now allocate buffers for strings */ 209 if (spr.myname_length) 210 spr.myname = malloc(spr.myname_length); 211 if (spr.hisname_length) 212 spr.hisname = malloc(spr.hisname_length); 213 /* second pass: get names too */ 214 if (ioctl(s, SPPPGETAUTHCFG, &spr) == -1) 215 err(EX_OSERR, "SPPPGETAUTHCFG"); 216 217 if (ioctl(s, SPPPGETLCPCFG, &lcp) == -1) 218 err(EX_OSERR, "SPPPGETLCPCFG"); 219 if (ioctl(s, SPPPGETSTATUS, &status) == -1) 220 err(EX_OSERR, "SPPPGETSTATUS"); 221 if (ioctl(s, SPPPGETIDLETO, &timeout) == -1) 222 err(EX_OSERR, "SPPPGETIDLETO"); 223 if (ioctl(s, SPPPGETAUTHFAILURES, &authfailstats) == -1) 224 err(EX_OSERR, "SPPPGETAUTHFAILURES"); 225 226 print_vals(ifname, status.phase, &spr, lcp.lcp_timeout, timeout.idle_seconds, authfailstats.auth_failures, authfailstats.max_failures); 227 228 if (spr.hisname) free(spr.hisname); 229 if (spr.myname) free(spr.myname); 230 return 0; 231 } 232 233 #define startswith(s) strncmp(argv[0], s, (off = strlen(s))) == 0 234 235 while (argc > 0) { 236 if (startswith("authproto=")) { 237 cp = argv[0] + off; 238 if (strcmp(cp, "pap") == 0) 239 spr.myauth = 240 spr.hisauth = SPPP_AUTHPROTO_PAP; 241 else if (strcmp(cp, "chap") == 0) 242 spr.myauth = spr.hisauth = SPPP_AUTHPROTO_CHAP; 243 else if (strcmp(cp, "none") == 0) 244 spr.myauth = spr.hisauth = SPPP_AUTHPROTO_NONE; 245 else 246 errx(EX_DATAERR, "bad auth proto: %s", cp); 247 set_auth = 1; 248 } else if (startswith("myauthproto=")) { 249 cp = argv[0] + off; 250 if (strcmp(cp, "pap") == 0) 251 spr.myauth = SPPP_AUTHPROTO_PAP; 252 else if (strcmp(cp, "chap") == 0) 253 spr.myauth = SPPP_AUTHPROTO_CHAP; 254 else if (strcmp(cp, "none") == 0) 255 spr.myauth = SPPP_AUTHPROTO_NONE; 256 else 257 errx(EX_DATAERR, "bad auth proto: %s", cp); 258 set_auth = 1; 259 } else if (startswith("myauthname=")) { 260 spr.myname = argv[0] + off; 261 spr.myname_length = strlen(spr.myname)+1; 262 set_auth = 1; 263 } else if (startswith("myauthsecret=") || startswith("myauthkey=")) { 264 spr.mysecret = argv[0] + off; 265 spr.mysecret_length = strlen(spr.mysecret)+1; 266 set_auth = 1; 267 } else if (startswith("hisauthproto=")) { 268 cp = argv[0] + off; 269 if (strcmp(cp, "pap") == 0) 270 spr.hisauth = SPPP_AUTHPROTO_PAP; 271 else if (strcmp(cp, "chap") == 0) 272 spr.hisauth = SPPP_AUTHPROTO_CHAP; 273 else if (strcmp(cp, "none") == 0) 274 spr.hisauth = SPPP_AUTHPROTO_NONE; 275 else 276 errx(EX_DATAERR, "bad auth proto: %s", cp); 277 set_auth = 1; 278 } else if (startswith("hisauthname=")) { 279 spr.hisname = argv[0] + off; 280 spr.hisname_length = strlen(spr.hisname)+1; 281 set_auth = 1; 282 } else if (startswith("hisauthsecret=") || startswith("hisauthkey=")) { 283 spr.hissecret = argv[0] + off; 284 spr.hissecret_length = strlen(spr.hissecret)+1; 285 set_auth = 1; 286 } else if (strcmp(argv[0], "callin") == 0) 287 spr.hisauthflags |= SPPP_AUTHFLAG_NOCALLOUT; 288 else if (strcmp(argv[0], "always") == 0) 289 spr.hisauthflags &= ~SPPP_AUTHFLAG_NOCALLOUT; 290 else if (strcmp(argv[0], "norechallenge") == 0) 291 spr.hisauthflags |= SPPP_AUTHFLAG_NORECHALLENGE; 292 else if (strcmp(argv[0], "rechallenge") == 0) 293 spr.hisauthflags &= ~SPPP_AUTHFLAG_NORECHALLENGE; 294 #ifndef __NetBSD__ 295 else if (strcmp(argv[0], "enable-vj") == 0) 296 spr.defs.enable_vj = 1; 297 else if (strcmp(argv[0], "disable-vj") == 0) 298 spr.defs.enable_vj = 0; 299 #endif 300 else if (startswith("lcp-timeout=")) { 301 int timeout_arg = atoi(argv[0]+off); 302 if ((timeout_arg > 20000) || (timeout_arg <= 0)) 303 errx(EX_DATAERR, "bad lcp timeout value: %s", 304 argv[0]+off); 305 lcp.lcp_timeout = timeout_arg * hz / 1000; 306 set_lcp = 1; 307 } else if (startswith("idle-timeout=")) { 308 timeout.idle_seconds = (time_t)atol(argv[0]+off); 309 set_idle_to = 1; 310 } else if (startswith("max-auth-failure=")) { 311 authfailset.max_failures = atoi(argv[0]+off); 312 set_auth_failure = 1; 313 } else 314 errx(EX_DATAERR, "bad parameter: \"%s\"", argv[0]); 315 316 argv++; 317 argc--; 318 } 319 320 if (set_auth) { 321 if (ioctl(s, SPPPSETAUTHCFG, &spr) == -1) 322 err(EX_OSERR, "SPPPSETAUTHCFG"); 323 } 324 if (set_lcp) { 325 if (ioctl(s, SPPPSETLCPCFG, &lcp) == -1) 326 err(EX_OSERR, "SPPPSETLCPCFG"); 327 } 328 if (set_idle_to) { 329 if (ioctl(s, SPPPSETIDLETO, &timeout) == -1) 330 err(EX_OSERR, "SPPPSETIDLETO"); 331 } 332 if (set_auth_failure) { 333 if (ioctl(s, SPPPSETAUTHFAILURE, &authfailset) == -1) 334 err(EX_OSERR, "SPPPSETAUTHFAILURE"); 335 } 336 337 if (verbose) { 338 if (ioctl(s, SPPPGETAUTHFAILURES, &authfailstats) == -1) 339 err(EX_OSERR, "SPPPGETAUTHFAILURES"); 340 print_vals(ifname, status.phase, &spr, lcp.lcp_timeout, timeout.idle_seconds, authfailstats.auth_failures, authfailstats.max_failures); 341 } 342 343 return 0; 344 } 345 346 static void 347 usage(void) 348 { 349 const char * prog = getprogname(); 350 fprintf(stderr, 351 "usage:\n" 352 " %s [-v] ifname [{my|his}auth{proto|name|secret}=...] \\\n" 353 " [callin] [always] [{no}rechallenge]\n" 354 " to set authentication names, passwords\n" 355 " and (optional) paramaters\n" 356 " %s [-v] ifname lcp-timeout=ms|idle-timeout=s|max-auth-failure=count\n" 357 " to set general parameters\n" 358 " or\n" 359 " %s -e ethernet-ifname ifname\n" 360 " to connect an ethernet interface for PPPoE\n" 361 " %s [-a access-concentrator-name] [-s service-name] ifname\n" 362 " to specify (optional) data for PPPoE sessions\n" 363 " %s -d ifname\n" 364 " to dump the current PPPoE session state\n" 365 , prog, prog, prog, prog, prog); 366 exit(EX_USAGE); 367 } 368 369 static void 370 print_vals(const char *ifname, int phase, struct spppauthcfg *sp, int lcp_timeout, 371 time_t idle_timeout, int authfailures, int max_auth_failures) 372 { 373 #ifndef __NetBSD__ 374 time_t send, recv; 375 #endif 376 377 printf("%s:\tphase=%s\n", ifname, phase_name(phase)); 378 if (sp->myauth) { 379 printf("\tmyauthproto=%s myauthname=\"%s\"\n", 380 proto_name(sp->myauth), 381 sp->myname); 382 } 383 if (sp->hisauth) { 384 printf("\thisauthproto=%s hisauthname=\"%s\"%s\n", 385 proto_name(sp->hisauth), 386 sp->hisname, 387 authflags(sp->hisauthflags)); 388 } 389 #ifndef __NetBSD__ 390 if (sp->defs.pp_phase > PHASE_DEAD) { 391 send = time(NULL) - sp->defs.pp_last_sent; 392 recv = time(NULL) - sp->defs.pp_last_recv; 393 printf("\tidle_time=%ld\n", (send<recv)? send : recv); 394 } 395 #endif 396 397 printf("\tlcp timeout: %.3f s\n", 398 (double)lcp_timeout / hz); 399 400 if (idle_timeout != 0) 401 printf("\tidle timeout = %lu s\n", (unsigned long)idle_timeout); 402 else 403 printf("\tidle timeout = disabled\n"); 404 405 if (authfailures != 0) 406 printf("\tauthentication failures = %d\n", authfailures); 407 printf("\tmax-auth-failure = %d\n", max_auth_failures); 408 409 #ifndef __NetBSD__ 410 printf("\tenable_vj: %s\n", 411 sp->defs.enable_vj ? "on" : "off"); 412 #endif 413 } 414 415 const char * 416 phase_name(int phase) 417 { 418 switch (phase) { 419 case SPPP_PHASE_DEAD: return "dead"; 420 case SPPP_PHASE_ESTABLISH: return "establish"; 421 case SPPP_PHASE_TERMINATE: return "terminate"; 422 case SPPP_PHASE_AUTHENTICATE: return "authenticate"; 423 case SPPP_PHASE_NETWORK: return "network"; 424 } 425 return "illegal"; 426 } 427 428 const char * 429 proto_name(int proto) 430 { 431 static char buf[12]; 432 switch (proto) { 433 case SPPP_AUTHPROTO_PAP: return "pap"; 434 case SPPP_AUTHPROTO_CHAP: return "chap"; 435 case SPPP_AUTHPROTO_NONE: return "none"; 436 } 437 sprintf(buf, "0x%x", (unsigned)proto); 438 return buf; 439 } 440 441 const char * 442 authflags(int flags) 443 { 444 static char buf[32]; 445 buf[0] = '\0'; 446 if (flags & SPPP_AUTHFLAG_NOCALLOUT) 447 strcat(buf, " callin"); 448 if (flags & SPPP_AUTHFLAG_NORECHALLENGE) 449 strcat(buf, " norechallenge"); 450 return buf; 451 } 452 453 static void 454 print_error(const char *ifname, int error, const char * str) 455 { 456 if (error == -1) 457 fprintf(stderr, "%s: interface not found\n", ifname); 458 else 459 fprintf(stderr, "%s: %s: %s\n", ifname, str, strerror(error)); 460 exit(EX_DATAERR); 461 } 462 463 464