1 /* $NetBSD: pppoectl.c,v 1.26 2020/11/25 10:32:54 yamaguchi 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 #include <sys/cdefs.h> 32 33 #ifndef lint 34 __RCSID("$NetBSD: pppoectl.c,v 1.26 2020/11/25 10:32:54 yamaguchi Exp $"); 35 #endif 36 37 38 #include <sys/param.h> 39 #include <sys/callout.h> 40 #include <sys/ioctl.h> 41 #include <sys/socket.h> 42 #include <sys/time.h> 43 #include <sys/sysctl.h> 44 #include <net/if.h> 45 #include <net/if_sppp.h> 46 #include <net/if_pppoe.h> 47 #include <arpa/inet.h> 48 #include <err.h> 49 #include <stdio.h> 50 #include <stdlib.h> 51 #include <string.h> 52 #include <sysexits.h> 53 #include <unistd.h> 54 55 __dead static void usage(void); 56 __dead static void print_error(const char *ifname, int error, const char * str); 57 static void print_vals(const char *ifname, int phase, struct spppauthcfg *sp, 58 int lcp_timeout, time_t idle_timeout, int authfailures, 59 int max_auth_failures, u_int maxalive, time_t max_noreceive); 60 static void print_dns(const char *ifname, int dns1, int dns2, int s, int tabs); 61 static void print_stats(const char *ifname, int s, int dump); 62 static const char *phase_name(int phase); 63 static const char *proto_name(int proto); 64 static const char *authflags(int flags); 65 static const char *pppoe_state_name(int state); 66 static const char *ppp_state_name(int state); 67 static void pppoectl_argument(char *arg); 68 69 #define ISSET(x, a) ((x) & (a)) 70 #define PPPOECTL_IOCTL(_ifname, _s, _cmd, _st) do { \ 71 int __e; \ 72 memset((_st), 0, sizeof(*(_st))); \ 73 strncpy((_st)->ifname, (_ifname), \ 74 sizeof((_st)->ifname)); \ 75 __e = ioctl((_s), (_cmd), (_st)); \ 76 if (__e != 0) \ 77 print_error((_ifname), __e, #_cmd); \ 78 } while (0) 79 80 static int hz = 0; 81 82 static int set_auth, set_lcp, set_idle_to, set_auth_failure, set_dns, 83 clear_auth_failure_count, set_keepalive; 84 static int maxalive = -1; 85 static int max_noreceive = -1; 86 static struct spppauthcfg spr; 87 static struct sppplcpcfg lcp; 88 static struct spppstatus status; 89 static struct spppidletimeout timeout; 90 static struct spppauthfailurestats authfailstats; 91 static struct spppauthfailuresettings authfailset; 92 static struct spppdnssettings dnssettings; 93 static struct spppkeepalivesettings keepalivesettings; 94 95 int 96 main(int argc, char **argv) 97 { 98 FILE *fp; 99 int s, c; 100 int errs = 0, verbose = 0, dump = 0, dns1 = 0, dns2 = 0; 101 size_t len; 102 const char *eth_if_name, *access_concentrator, *service; 103 const char *ifname, *configname; 104 char *line; 105 int mib[2]; 106 struct clockinfo clockinfo; 107 setprogname(argv[0]); 108 109 eth_if_name = NULL; 110 access_concentrator = NULL; 111 service = NULL; 112 configname = NULL; 113 while ((c = getopt(argc, argv, "vde:f:s:a:n:")) != -1) 114 switch (c) { 115 case 'v': 116 verbose++; 117 break; 118 119 case 'd': 120 dump++; 121 break; 122 123 case 'e': 124 eth_if_name = optarg; 125 break; 126 127 case 'f': 128 configname = optarg; 129 break; 130 131 case 's': 132 service = optarg; 133 break; 134 135 case 'a': 136 access_concentrator = optarg; 137 break; 138 139 case 'n': 140 if (strcmp(optarg, "1") == 0) 141 dns1 = 1; 142 else if (strcmp(optarg, "2") == 0) 143 dns2 = 1; 144 else { 145 fprintf(stderr, "bad argument \"%s\" to -n (only 1 or two allowed)\n", 146 optarg); 147 errs++; 148 } 149 break; 150 151 default: 152 errs++; 153 break; 154 } 155 argv += optind; 156 argc -= optind; 157 158 if (errs || argc < 1) 159 usage(); 160 161 ifname = argv[0]; 162 163 /* use a random AF to create the socket */ 164 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 165 err(EX_UNAVAILABLE, "ifconfig: socket"); 166 167 argc--; 168 argv++; 169 170 if (eth_if_name) { 171 struct pppoediscparms parms; 172 int e; 173 174 memset(&parms, 0, sizeof parms); 175 strncpy(parms.ifname, ifname, sizeof(parms.ifname)); 176 strncpy(parms.eth_ifname, eth_if_name, sizeof(parms.eth_ifname)); 177 if (access_concentrator) { 178 parms.ac_name = access_concentrator; 179 parms.ac_name_len = strlen(access_concentrator); 180 } 181 if (service) { 182 parms.service_name = service; 183 parms.service_name_len = strlen(service); 184 } 185 186 e = ioctl(s, PPPOESETPARMS, &parms); 187 if (e) 188 print_error(ifname, e, "PPPOESETPARMS"); 189 return 0; 190 } 191 192 if (dns1 || dns2) { 193 print_dns(ifname, dns1, dns2, s, 0); 194 } 195 196 if (dump) { 197 print_stats(ifname, s, dump); 198 return 0; 199 } 200 201 memset(&spr, 0, sizeof spr); 202 strncpy(spr.ifname, ifname, sizeof spr.ifname); 203 memset(&lcp, 0, sizeof lcp); 204 strncpy(lcp.ifname, ifname, sizeof lcp.ifname); 205 memset(&status, 0, sizeof status); 206 strncpy(status.ifname, ifname, sizeof status.ifname); 207 memset(&timeout, 0, sizeof timeout); 208 strncpy(timeout.ifname, ifname, sizeof timeout.ifname); 209 memset(&authfailstats, 0, sizeof authfailstats); 210 strncpy(authfailstats.ifname, ifname, sizeof authfailstats.ifname); 211 memset(&authfailset, 0, sizeof authfailset); 212 strncpy(authfailset.ifname, ifname, sizeof authfailset.ifname); 213 memset(&dnssettings, 0, sizeof dnssettings); 214 strncpy(dnssettings.ifname, ifname, sizeof dnssettings.ifname); 215 memset(&keepalivesettings, 0, sizeof keepalivesettings); 216 strncpy(keepalivesettings.ifname, ifname, sizeof keepalivesettings.ifname); 217 218 mib[0] = CTL_KERN; 219 mib[1] = KERN_CLOCKRATE; 220 len = sizeof(clockinfo); 221 if(sysctl(mib, 2, &clockinfo, &len, NULL, 0) == -1) 222 { 223 fprintf(stderr, "error, cannot sysctl kern.clockrate!\n"); 224 exit(1); 225 } 226 227 hz = clockinfo.hz; 228 229 if (argc == 0 && !(dns1||dns2) && !configname) { 230 /* list only mode */ 231 232 /* first pass, get name lengths */ 233 if (ioctl(s, SPPPGETAUTHCFG, &spr) == -1) 234 err(EX_OSERR, "SPPPGETAUTHCFG"); 235 /* now allocate buffers for strings */ 236 if (spr.myname_length) 237 if ((spr.myname = malloc(spr.myname_length)) == NULL) 238 err(1, NULL); 239 if (spr.hisname_length) 240 if ((spr.hisname = malloc(spr.hisname_length)) == NULL) 241 err(1, NULL); 242 /* second pass: get names too */ 243 if (ioctl(s, SPPPGETAUTHCFG, &spr) == -1) 244 err(EX_OSERR, "SPPPGETAUTHCFG"); 245 246 if (ioctl(s, SPPPGETLCPCFG, &lcp) == -1) 247 err(EX_OSERR, "SPPPGETLCPCFG"); 248 if (ioctl(s, SPPPGETSTATUS, &status) == -1) 249 err(EX_OSERR, "SPPPGETSTATUS"); 250 if (ioctl(s, SPPPGETIDLETO, &timeout) == -1) 251 err(EX_OSERR, "SPPPGETIDLETO"); 252 if (ioctl(s, SPPPGETAUTHFAILURES, &authfailstats) == -1) 253 err(EX_OSERR, "SPPPGETAUTHFAILURES"); 254 if (ioctl(s, SPPPGETKEEPALIVE, &keepalivesettings) == -1) 255 err(EX_OSERR, "SPPPGETKEEPALIVE"); 256 257 print_vals(ifname, status.phase, &spr, lcp.lcp_timeout, 258 timeout.idle_seconds, authfailstats.auth_failures, 259 authfailstats.max_failures, 260 keepalivesettings.maxalive, 261 keepalivesettings.max_noreceive); 262 263 if (spr.hisname) free(spr.hisname); 264 if (spr.myname) free(spr.myname); 265 return 0; 266 } 267 268 /* first load the config file, then parse command line args */ 269 if (configname && (fp = fopen(configname, "r"))) 270 while ((line = fparseln(fp, NULL, NULL, NULL, 271 FPARSELN_UNESCALL)) != NULL) { 272 if (line[0] != '\0') 273 pppoectl_argument(line); 274 /* 275 * We do not free(line) here, because we 276 * still have references to parts of the 277 * string collected in the various ioctl 278 * argument structures (and need those). 279 * Yes, this is a memory leak. 280 * We could copy the partial strings instead, 281 * and free those later - but this is a one-shot 282 * program and memory will be freed at process 283 * exit time anyway. 284 */ 285 } 286 287 288 while (argc > 0) { 289 pppoectl_argument(argv[0]); 290 291 argv++; 292 argc--; 293 } 294 295 if (set_auth) { 296 if (ioctl(s, SPPPSETAUTHCFG, &spr) == -1) 297 err(EX_OSERR, "SPPPSETAUTHCFG"); 298 } 299 if (set_lcp) { 300 if (ioctl(s, SPPPSETLCPCFG, &lcp) == -1) 301 err(EX_OSERR, "SPPPSETLCPCFG"); 302 } 303 if (set_idle_to) { 304 if (ioctl(s, SPPPSETIDLETO, &timeout) == -1) 305 err(EX_OSERR, "SPPPSETIDLETO"); 306 } 307 if (set_auth_failure) { 308 if (ioctl(s, SPPPSETAUTHFAILURE, &authfailset) == -1) 309 err(EX_OSERR, "SPPPSETAUTHFAILURE"); 310 } 311 if (clear_auth_failure_count && !(set_auth || set_auth_failure)) { 312 /* 313 * We want to clear the auth failure count, but did not 314 * do that implicitly by setting authentication - so 315 * do a zero-effect auth setting change 316 */ 317 if (ioctl(s, SPPPGETAUTHFAILURES, &authfailstats) == -1) 318 err(EX_OSERR, "SPPPGETAUTHFAILURES"); 319 authfailset.max_failures = authfailstats.max_failures; 320 if (ioctl(s, SPPPSETAUTHFAILURE, &authfailset) == -1) 321 err(EX_OSERR, "SPPPSETAUTHFAILURE"); 322 } 323 if (set_dns) { 324 if (ioctl(s, SPPPSETDNSOPTS, &dnssettings) == -1) 325 err(EX_OSERR, "SPPPSETDNSOPTS"); 326 } 327 if (set_keepalive) { 328 if (ioctl(s, SPPPGETKEEPALIVE, &keepalivesettings) == -1) 329 err(EX_OSERR, "SPPPGETKEEPALIVE"); 330 if (max_noreceive >= 0) 331 keepalivesettings.max_noreceive = max_noreceive; 332 if (maxalive >= 0) 333 keepalivesettings.maxalive = maxalive; 334 if (ioctl(s, SPPPSETKEEPALIVE, &keepalivesettings) == -1) 335 err(EX_OSERR, "SPPPSETKEEPALIVE"); 336 } 337 338 if (verbose) { 339 if (ioctl(s, SPPPGETAUTHFAILURES, &authfailstats) == -1) 340 err(EX_OSERR, "SPPPGETAUTHFAILURES"); 341 if (ioctl(s, SPPPGETKEEPALIVE, &keepalivesettings) == -1) 342 err(EX_OSERR, "SPPPGETKEEPALIVE"); 343 print_vals(ifname, status.phase, &spr, lcp.lcp_timeout, 344 timeout.idle_seconds, authfailstats.auth_failures, 345 authfailstats.max_failures, 346 keepalivesettings.maxalive, 347 keepalivesettings.max_noreceive); 348 } 349 350 return 0; 351 } 352 353 static void 354 pppoectl_argument(char *arg) 355 { 356 size_t off; 357 const char *cp; 358 359 #define startswith(a,s) strncmp(a, s, (off = strlen(s))) == 0 360 if (startswith(arg, "authproto=")) { 361 cp = arg + off; 362 if (strcmp(cp, "pap") == 0) 363 spr.myauth = 364 spr.hisauth = SPPP_AUTHPROTO_PAP; 365 else if (strcmp(cp, "chap") == 0) 366 spr.myauth = spr.hisauth = SPPP_AUTHPROTO_CHAP; 367 else if (strcmp(cp, "none") == 0) 368 spr.myauth = spr.hisauth = SPPP_AUTHPROTO_NONE; 369 else 370 errx(EX_DATAERR, "bad auth proto: %s", cp); 371 set_auth = 1; 372 } else if (startswith(arg, "myauthproto=")) { 373 cp = arg + off; 374 if (strcmp(cp, "pap") == 0) 375 spr.myauth = SPPP_AUTHPROTO_PAP; 376 else if (strcmp(cp, "chap") == 0) 377 spr.myauth = SPPP_AUTHPROTO_CHAP; 378 else if (strcmp(cp, "none") == 0) 379 spr.myauth = SPPP_AUTHPROTO_NONE; 380 else 381 errx(EX_DATAERR, "bad auth proto: %s", cp); 382 set_auth = 1; 383 } else if (startswith(arg, "myauthname=")) { 384 spr.myname = arg + off; 385 spr.myname_length = strlen(spr.myname)+1; 386 set_auth = 1; 387 } else if (startswith(arg, "myauthsecret=") || startswith(arg, "myauthkey=")) { 388 spr.mysecret = arg + off; 389 spr.mysecret_length = strlen(spr.mysecret)+1; 390 set_auth = 1; 391 } else if (startswith(arg, "hisauthproto=")) { 392 cp = arg + off; 393 if (strcmp(cp, "pap") == 0) 394 spr.hisauth = SPPP_AUTHPROTO_PAP; 395 else if (strcmp(cp, "chap") == 0) 396 spr.hisauth = SPPP_AUTHPROTO_CHAP; 397 else if (strcmp(cp, "none") == 0) 398 spr.hisauth = SPPP_AUTHPROTO_NONE; 399 else 400 errx(EX_DATAERR, "bad auth proto: %s", cp); 401 set_auth = 1; 402 } else if (startswith(arg, "hisauthname=")) { 403 spr.hisname = arg + off; 404 spr.hisname_length = strlen(spr.hisname)+1; 405 set_auth = 1; 406 } else if (startswith(arg, "hisauthsecret=") || startswith(arg, "hisauthkey=")) { 407 spr.hissecret = arg + off; 408 spr.hissecret_length = strlen(spr.hissecret)+1; 409 set_auth = 1; 410 } else if (startswith(arg, "max-noreceive=")) { 411 max_noreceive = atoi(arg+off); 412 if (max_noreceive < 0) { 413 fprintf(stderr, 414 "max-noreceive value must be at least 0\n"); 415 max_noreceive = -1; 416 } else { 417 set_keepalive = 1; 418 } 419 } else if (startswith(arg, "max-alive-missed=")) { 420 maxalive = atoi(arg+off); 421 if (maxalive < 0) { 422 fprintf(stderr, 423 "max-alive-missed value must be at least 0\n"); 424 maxalive = -1; 425 } else { 426 set_keepalive = 1; 427 } 428 } else if (strcmp(arg, "callin") == 0) 429 spr.hisauthflags |= SPPP_AUTHFLAG_NOCALLOUT; 430 else if (strcmp(arg, "always") == 0) 431 spr.hisauthflags &= ~SPPP_AUTHFLAG_NOCALLOUT; 432 else if (strcmp(arg, "norechallenge") == 0) 433 spr.hisauthflags |= SPPP_AUTHFLAG_NORECHALLENGE; 434 else if (strcmp(arg, "rechallenge") == 0) 435 spr.hisauthflags &= ~SPPP_AUTHFLAG_NORECHALLENGE; 436 #ifndef __NetBSD__ 437 else if (strcmp(arg, "enable-vj") == 0) 438 spr.defs.enable_vj = 1; 439 else if (strcmp(arg, "disable-vj") == 0) 440 spr.defs.enable_vj = 0; 441 #endif 442 else if (startswith(arg, "lcp-timeout=")) { 443 int timeout_arg = atoi(arg+off); 444 if ((timeout_arg > 20000) || (timeout_arg <= 0)) 445 errx(EX_DATAERR, "bad lcp timeout value: %s", 446 arg+off); 447 lcp.lcp_timeout = timeout_arg * hz / 1000; 448 set_lcp = 1; 449 } else if (startswith(arg, "idle-timeout=")) { 450 timeout.idle_seconds = (time_t)atol(arg+off); 451 set_idle_to = 1; 452 } else if (startswith(arg, "max-auth-failure=")) { 453 authfailset.max_failures = atoi(arg+off); 454 set_auth_failure = 1; 455 } else if (strcmp(arg, "clear-auth-failure") == 0) { 456 clear_auth_failure_count = 1; 457 } else if (startswith(arg, "query-dns=")) { 458 dnssettings.query_dns = atoi(arg+off); 459 set_dns = 1; 460 } else 461 errx(EX_DATAERR, "bad parameter: \"%s\"", arg); 462 } 463 464 static void 465 usage(void) 466 { 467 const char * prog = getprogname(); 468 fprintf(stderr, 469 "usage:\n" 470 " %s [-f config] ifname [...]\n" 471 " %s [-v] ifname [{my|his}auth{proto|name|secret}=...] \\\n" 472 " [callin] [always] [{no}rechallenge]\n" 473 " [query-dns=3]\n" 474 " to set authentication names, passwords\n" 475 " and (optional) paramaters\n" 476 " %s [-v] ifname lcp-timeout=ms|idle-timeout=s|\n" 477 " max-noreceive=s|max-alive-missed=cnt|\n" 478 " max-auth-failure=count|clear-auth-failure\n" 479 " to set general parameters\n" 480 " or\n" 481 " %s -e ethernet-ifname ifname\n" 482 " to connect an ethernet interface for PPPoE\n" 483 " %s [-a access-concentrator-name] [-s service-name] ifname\n" 484 " to specify (optional) data for PPPoE sessions\n" 485 " %s -d ifname\n" 486 " to dump the current PPPoE session state\n" 487 " %s -n (1|2) ifname\n" 488 " to print DNS addresses retrieved via query-dns\n" 489 , prog, prog, prog, prog, prog, prog, prog); 490 exit(EX_USAGE); 491 } 492 493 static void 494 print_vals(const char *ifname, int phase, struct spppauthcfg *sp, int lcp_timeout, 495 time_t idle_timeout, int authfailures, int max_auth_failures, 496 u_int maxalive_cnt, time_t max_noreceive_time) 497 { 498 #ifndef __NetBSD__ 499 time_t send, recv; 500 #endif 501 502 printf("%s:\tphase=%s\n", ifname, phase_name(phase)); 503 if (sp->myauth) { 504 printf("\tmyauthproto=%s myauthname=\"%s\"\n", 505 proto_name(sp->myauth), 506 sp->myname); 507 } 508 if (sp->hisauth) { 509 printf("\thisauthproto=%s hisauthname=\"%s\"%s\n", 510 proto_name(sp->hisauth), 511 sp->hisname, 512 authflags(sp->hisauthflags)); 513 } 514 #ifndef __NetBSD__ 515 if (sp->defs.pp_phase > PHASE_DEAD) { 516 send = time(NULL) - sp->defs.pp_last_sent; 517 recv = time(NULL) - sp->defs.pp_last_recv; 518 printf("\tidle_time=%ld\n", (send<recv)? send : recv); 519 } 520 #endif 521 522 printf("\tlcp timeout: %.3f s\n", 523 (double)lcp_timeout / hz); 524 525 if (idle_timeout != 0) 526 printf("\tidle timeout = %lu s\n", (unsigned long)idle_timeout); 527 else 528 printf("\tidle timeout = disabled\n"); 529 530 if (authfailures != 0) 531 printf("\tauthentication failures = %d\n", authfailures); 532 printf("\tmax-auth-failure = %d\n", max_auth_failures); 533 534 printf("\tmax-noreceive = %ld seconds\n", (long)max_noreceive_time); 535 printf("\tmax-alive-missed = %u unanswered echo requests\n", maxalive_cnt); 536 537 #ifndef __NetBSD__ 538 printf("\tenable_vj: %s\n", 539 sp->defs.enable_vj ? "on" : "off"); 540 #endif 541 } 542 543 static void 544 print_dns(const char *ifname, int dns1, int dns2, int s, int tabs) 545 { 546 int i; 547 struct spppdnsaddrs addrs; 548 549 if (!dns1 && !dns2) 550 return; 551 552 PPPOECTL_IOCTL(ifname, s, SPPPGETDNSADDRS, &addrs); 553 if (dns1) { 554 for (i = 0; i < tabs; i++) 555 printf("\t"); 556 if (tabs > 0) 557 printf("primary dns address "); 558 printf("%d.%d.%d.%d\n", 559 (addrs.dns[0] >> 24) & 0xff, 560 (addrs.dns[0] >> 16) & 0xff, 561 (addrs.dns[0] >> 8) & 0xff, 562 addrs.dns[0] & 0xff); 563 } 564 if (dns2) { 565 for (i = 0; i < tabs; i++) 566 printf("\t"); 567 if (tabs > 0) 568 printf("secondary dns address "); 569 printf("%d.%d.%d.%d\n", 570 (addrs.dns[1] >> 24) & 0xff, 571 (addrs.dns[1] >> 16) & 0xff, 572 (addrs.dns[1] >> 8) & 0xff, 573 addrs.dns[1] & 0xff); 574 } 575 } 576 577 static void 578 print_stats(const char *ifname, int s, int dump) 579 { 580 struct pppoeconnectionstate state; 581 struct sppplcpstatus lcpst; 582 struct spppipcpstatus ipcpst; 583 struct spppipv6cpstatus ipv6cpst; 584 struct in_addr addr; 585 586 PPPOECTL_IOCTL(ifname, s, PPPOEGETSESSION, &state); 587 588 /* dump PPPoE session state */ 589 printf("%s:\t%s %s\n", ifname, 590 dump > 1 ? "PPPoE state:" : "state =", 591 pppoe_state_name(state.state)); 592 printf("\tSession ID: 0x%x\n", state.session_id); 593 printf("\tPADI retries: %d\n", state.padi_retry_no); 594 printf("\tPADR retries: %d\n", state.padr_retry_no); 595 596 if (dump > 1) { 597 PPPOECTL_IOCTL(ifname, s, SPPPGETLCPSTATUS, &lcpst); 598 PPPOECTL_IOCTL(ifname, s, SPPPGETIPCPSTATUS, &ipcpst); 599 PPPOECTL_IOCTL(ifname, s, SPPPGETIPV6CPSTATUS, &ipv6cpst); 600 601 printf("\tLCP state: %s\n", 602 ppp_state_name(lcpst.state)); 603 printf("\tIPCP state: %s\n", 604 ppp_state_name(ipcpst.state)); 605 printf("\tIPv6CP state: %s\n", 606 ppp_state_name(ipv6cpst.state)); 607 608 if (lcpst.state == SPPP_STATE_OPENED) { 609 printf("\tLCP negotiated options:\n"); 610 printf("\t\tmru %lu\n", lcpst.mru); 611 printf("\t\tmagic number 0x%lx\n", 612 lcpst.magic); 613 } 614 615 if (ipcpst.state == SPPP_STATE_OPENED) { 616 addr.s_addr = ipcpst.myaddr; 617 618 printf("\tIPCP negotiated options:\n"); 619 printf("\t\taddress %s\n", inet_ntoa(addr)); 620 print_dns(ifname, 621 ISSET(ipcpst.opts, SPPP_IPCP_OPT_PRIMDNS), 622 ISSET(ipcpst.opts, SPPP_IPCP_OPT_SECDNS), 623 s, 2); 624 } 625 626 if (ipv6cpst.state == SPPP_STATE_OPENED) { 627 printf("\tIPv6CP negotiated options:\n"); 628 if (ISSET(ipv6cpst.opts, SPPP_IPV6CP_OPT_COMPRESSION)) 629 printf("\t\tcompression\n"); 630 if (ISSET(ipv6cpst.opts, SPPP_IPV6CP_OPT_IFID)) { 631 printf("\t\tifid: " 632 "my_ifid=0x%02x%02x%02x%02x%02x%02x%02x%02x, " 633 "his_ifid=0x%02x%02x%02x%02x%02x%02x%02x%02x\n", 634 ipv6cpst.my_ifid[0], ipv6cpst.my_ifid[1], 635 ipv6cpst.my_ifid[2], ipv6cpst.my_ifid[3], 636 ipv6cpst.my_ifid[4], ipv6cpst.my_ifid[5], 637 ipv6cpst.my_ifid[6], ipv6cpst.my_ifid[7], 638 ipv6cpst.his_ifid[0], ipv6cpst.his_ifid[1], 639 ipv6cpst.his_ifid[2], ipv6cpst.his_ifid[3], 640 ipv6cpst.his_ifid[4], ipv6cpst.his_ifid[5], 641 ipv6cpst.his_ifid[6], ipv6cpst.his_ifid[7]); 642 } 643 } 644 } 645 } 646 647 static const char * 648 phase_name(int phase) 649 { 650 switch (phase) { 651 case SPPP_PHASE_DEAD: return "dead"; 652 case SPPP_PHASE_ESTABLISH: return "establish"; 653 case SPPP_PHASE_TERMINATE: return "terminate"; 654 case SPPP_PHASE_AUTHENTICATE: return "authenticate"; 655 case SPPP_PHASE_NETWORK: return "network"; 656 } 657 return "illegal"; 658 } 659 660 static const char * 661 proto_name(int proto) 662 { 663 static char buf[12]; 664 switch (proto) { 665 case SPPP_AUTHPROTO_PAP: return "pap"; 666 case SPPP_AUTHPROTO_CHAP: return "chap"; 667 case SPPP_AUTHPROTO_NONE: return "none"; 668 } 669 snprintf(buf, sizeof(buf), "0x%x", (unsigned)proto); 670 return buf; 671 } 672 673 static const char * 674 authflags(int flags) 675 { 676 static char buf[32]; 677 buf[0] = '\0'; 678 if (flags & SPPP_AUTHFLAG_NOCALLOUT) 679 strlcat(buf, " callin", sizeof(buf)); 680 if (flags & SPPP_AUTHFLAG_NORECHALLENGE) 681 strlcat(buf, " norechallenge", sizeof(buf)); 682 return buf; 683 } 684 685 static const char * 686 pppoe_state_name(int state) 687 { 688 689 switch(state) { 690 case PPPOE_STATE_INITIAL: 691 return "initial"; 692 case PPPOE_STATE_PADI_SENT: 693 return "PADI sent"; 694 case PPPOE_STATE_PADR_SENT: 695 return "PADR sent"; 696 case PPPOE_STATE_SESSION: 697 return "session"; 698 case PPPOE_STATE_CLOSING: 699 return "closing"; 700 } 701 702 return "unknown"; 703 } 704 static const char * 705 ppp_state_name(int state) 706 { 707 708 switch (state) { 709 case SPPP_STATE_INITIAL: return "initial"; 710 case SPPP_STATE_STARTING: return "starting"; 711 case SPPP_STATE_CLOSED: return "closed"; 712 case SPPP_STATE_STOPPED: return "stopped"; 713 case SPPP_STATE_CLOSING: return "closing"; 714 case SPPP_STATE_STOPPING: return "stopping"; 715 case SPPP_STATE_REQ_SENT: return "req-sent"; 716 case SPPP_STATE_ACK_RCVD: return "ack-rcvd"; 717 case SPPP_STATE_ACK_SENT: return "ack-sent"; 718 case SPPP_STATE_OPENED: return "opened"; 719 } 720 721 return "unknown"; 722 } 723 724 static void 725 print_error(const char *ifname, int error, const char * str) 726 { 727 if (error == -1) 728 fprintf(stderr, "%s: interface not found\n", ifname); 729 else 730 fprintf(stderr, "%s: %s: %s\n", ifname, str, strerror(error)); 731 exit(EX_DATAERR); 732 } 733