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