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