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