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