1 /* $NetBSD: pppoectl.c,v 1.16 2004/09/01 19:38:09 jdolecek 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.16 2004/09/01 19:38:09 jdolecek 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 static void usage(void); 56 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 const char *phase_name(int phase); 61 const char *proto_name(int proto); 62 const char *authflags(int flags); 63 static void pppoectl_argument(char *arg); 64 65 int hz = 0; 66 67 int set_auth, set_lcp, set_idle_to, set_auth_failure, set_dns, 68 clear_auth_failure_count, set_keepalive; 69 int maxalive = -1; 70 int max_noreceive = -1; 71 struct spppauthcfg spr; 72 struct sppplcpcfg lcp; 73 struct spppstatus status; 74 struct spppidletimeout timeout; 75 struct spppauthfailurestats authfailstats; 76 struct spppauthfailuresettings authfailset; 77 struct spppdnssettings dnssettings; 78 struct spppkeepalivesettings keepalivesettings; 79 80 int 81 main(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 = (char*)access_concentrator; 164 parms.ac_name_len = strlen(access_concentrator); 165 } 166 if (service) { 167 parms.service_name = (char*)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 spr.myname = malloc(spr.myname_length); 269 if (spr.hisname_length) 270 spr.hisname = malloc(spr.hisname_length); 271 /* second pass: get names too */ 272 if (ioctl(s, SPPPGETAUTHCFG, &spr) == -1) 273 err(EX_OSERR, "SPPPGETAUTHCFG"); 274 275 if (ioctl(s, SPPPGETLCPCFG, &lcp) == -1) 276 err(EX_OSERR, "SPPPGETLCPCFG"); 277 if (ioctl(s, SPPPGETSTATUS, &status) == -1) 278 err(EX_OSERR, "SPPPGETSTATUS"); 279 if (ioctl(s, SPPPGETIDLETO, &timeout) == -1) 280 err(EX_OSERR, "SPPPGETIDLETO"); 281 if (ioctl(s, SPPPGETAUTHFAILURES, &authfailstats) == -1) 282 err(EX_OSERR, "SPPPGETAUTHFAILURES"); 283 if (ioctl(s, SPPPGETKEEPALIVE, &keepalivesettings) == -1) 284 err(EX_OSERR, "SPPPGETKEEPALIVE"); 285 286 print_vals(ifname, status.phase, &spr, lcp.lcp_timeout, 287 timeout.idle_seconds, authfailstats.auth_failures, 288 authfailstats.max_failures, 289 keepalivesettings.maxalive, 290 keepalivesettings.max_noreceive); 291 292 if (spr.hisname) free(spr.hisname); 293 if (spr.myname) free(spr.myname); 294 return 0; 295 } 296 297 /* first load the config file, then parse command line args */ 298 if (configname && (fp = fopen(configname, "r"))) 299 while ((line = fparseln(fp, NULL, NULL, NULL, 0))) 300 pppoectl_argument(line); 301 302 while (argc > 0) { 303 pppoectl_argument(argv[0]); 304 305 argv++; 306 argc--; 307 } 308 309 if (set_auth) { 310 if (ioctl(s, SPPPSETAUTHCFG, &spr) == -1) 311 err(EX_OSERR, "SPPPSETAUTHCFG"); 312 } 313 if (set_lcp) { 314 if (ioctl(s, SPPPSETLCPCFG, &lcp) == -1) 315 err(EX_OSERR, "SPPPSETLCPCFG"); 316 } 317 if (set_idle_to) { 318 if (ioctl(s, SPPPSETIDLETO, &timeout) == -1) 319 err(EX_OSERR, "SPPPSETIDLETO"); 320 } 321 if (set_auth_failure) { 322 if (ioctl(s, SPPPSETAUTHFAILURE, &authfailset) == -1) 323 err(EX_OSERR, "SPPPSETAUTHFAILURE"); 324 } 325 if (clear_auth_failure_count && !(set_auth || set_auth_failure)) { 326 /* 327 * We want to clear the auth failure count, but did not 328 * do that implicitly by setting authentication - so 329 * do a zero-effect auth setting change 330 */ 331 if (ioctl(s, SPPPGETAUTHFAILURES, &authfailstats) == -1) 332 err(EX_OSERR, "SPPPGETAUTHFAILURES"); 333 authfailset.max_failures = authfailstats.max_failures; 334 if (ioctl(s, SPPPSETAUTHFAILURE, &authfailset) == -1) 335 err(EX_OSERR, "SPPPSETAUTHFAILURE"); 336 } 337 if (set_dns) { 338 if (ioctl(s, SPPPSETDNSOPTS, &dnssettings) == -1) 339 err(EX_OSERR, "SPPPSETDNSOPTS"); 340 } 341 if (set_keepalive) { 342 if (ioctl(s, SPPPGETKEEPALIVE, &keepalivesettings) == -1) 343 err(EX_OSERR, "SPPPGETKEEPALIVE"); 344 if (max_noreceive >= 0) 345 keepalivesettings.max_noreceive = max_noreceive; 346 if (maxalive >= 0) 347 keepalivesettings.maxalive = maxalive; 348 if (ioctl(s, SPPPSETKEEPALIVE, &keepalivesettings) == -1) 349 err(EX_OSERR, "SPPPSETKEEPALIVE"); 350 } 351 352 if (verbose) { 353 if (ioctl(s, SPPPGETAUTHFAILURES, &authfailstats) == -1) 354 err(EX_OSERR, "SPPPGETAUTHFAILURES"); 355 if (ioctl(s, SPPPGETKEEPALIVE, &keepalivesettings) == -1) 356 err(EX_OSERR, "SPPPGETKEEPALIVE"); 357 print_vals(ifname, status.phase, &spr, lcp.lcp_timeout, 358 timeout.idle_seconds, authfailstats.auth_failures, 359 authfailstats.max_failures, 360 keepalivesettings.maxalive, 361 keepalivesettings.max_noreceive); 362 } 363 364 return 0; 365 } 366 367 static void 368 pppoectl_argument(char *arg) 369 { 370 size_t off; 371 const char *cp; 372 373 #define startswith(a,s) strncmp(a, s, (off = strlen(s))) == 0 374 if (startswith(arg, "authproto=")) { 375 cp = arg + off; 376 if (strcmp(cp, "pap") == 0) 377 spr.myauth = 378 spr.hisauth = SPPP_AUTHPROTO_PAP; 379 else if (strcmp(cp, "chap") == 0) 380 spr.myauth = spr.hisauth = SPPP_AUTHPROTO_CHAP; 381 else if (strcmp(cp, "none") == 0) 382 spr.myauth = spr.hisauth = SPPP_AUTHPROTO_NONE; 383 else 384 errx(EX_DATAERR, "bad auth proto: %s", cp); 385 set_auth = 1; 386 } else if (startswith(arg, "myauthproto=")) { 387 cp = arg + off; 388 if (strcmp(cp, "pap") == 0) 389 spr.myauth = SPPP_AUTHPROTO_PAP; 390 else if (strcmp(cp, "chap") == 0) 391 spr.myauth = SPPP_AUTHPROTO_CHAP; 392 else if (strcmp(cp, "none") == 0) 393 spr.myauth = SPPP_AUTHPROTO_NONE; 394 else 395 errx(EX_DATAERR, "bad auth proto: %s", cp); 396 set_auth = 1; 397 } else if (startswith(arg, "myauthname=")) { 398 spr.myname = arg + off; 399 spr.myname_length = strlen(spr.myname)+1; 400 set_auth = 1; 401 } else if (startswith(arg, "myauthsecret=") || startswith(arg, "myauthkey=")) { 402 spr.mysecret = arg + off; 403 spr.mysecret_length = strlen(spr.mysecret)+1; 404 set_auth = 1; 405 } else if (startswith(arg, "hisauthproto=")) { 406 cp = arg + off; 407 if (strcmp(cp, "pap") == 0) 408 spr.hisauth = SPPP_AUTHPROTO_PAP; 409 else if (strcmp(cp, "chap") == 0) 410 spr.hisauth = SPPP_AUTHPROTO_CHAP; 411 else if (strcmp(cp, "none") == 0) 412 spr.hisauth = SPPP_AUTHPROTO_NONE; 413 else 414 errx(EX_DATAERR, "bad auth proto: %s", cp); 415 set_auth = 1; 416 } else if (startswith(arg, "hisauthname=")) { 417 spr.hisname = arg + off; 418 spr.hisname_length = strlen(spr.hisname)+1; 419 set_auth = 1; 420 } else if (startswith(arg, "hisauthsecret=") || startswith(arg, "hisauthkey=")) { 421 spr.hissecret = arg + off; 422 spr.hissecret_length = strlen(spr.hissecret)+1; 423 set_auth = 1; 424 } else if (startswith(arg, "max-noreceive=")) { 425 max_noreceive = atoi(arg+off); 426 if (max_noreceive < 0) { 427 fprintf(stderr, 428 "max-noreceive value must be at least 0\n"); 429 max_noreceive = -1; 430 } else { 431 set_keepalive = 1; 432 } 433 } else if (startswith(arg, "max-alive-missed=")) { 434 maxalive = atoi(arg+off); 435 if (maxalive < 0) { 436 fprintf(stderr, 437 "max-alive-missed value must be at least 0\n"); 438 maxalive = -1; 439 } else { 440 set_keepalive = 1; 441 } 442 } else if (strcmp(arg, "callin") == 0) 443 spr.hisauthflags |= SPPP_AUTHFLAG_NOCALLOUT; 444 else if (strcmp(arg, "always") == 0) 445 spr.hisauthflags &= ~SPPP_AUTHFLAG_NOCALLOUT; 446 else if (strcmp(arg, "norechallenge") == 0) 447 spr.hisauthflags |= SPPP_AUTHFLAG_NORECHALLENGE; 448 else if (strcmp(arg, "rechallenge") == 0) 449 spr.hisauthflags &= ~SPPP_AUTHFLAG_NORECHALLENGE; 450 #ifndef __NetBSD__ 451 else if (strcmp(arg, "enable-vj") == 0) 452 spr.defs.enable_vj = 1; 453 else if (strcmp(arg, "disable-vj") == 0) 454 spr.defs.enable_vj = 0; 455 #endif 456 else if (startswith(arg, "lcp-timeout=")) { 457 int timeout_arg = atoi(arg+off); 458 if ((timeout_arg > 20000) || (timeout_arg <= 0)) 459 errx(EX_DATAERR, "bad lcp timeout value: %s", 460 arg+off); 461 lcp.lcp_timeout = timeout_arg * hz / 1000; 462 set_lcp = 1; 463 } else if (startswith(arg, "idle-timeout=")) { 464 timeout.idle_seconds = (time_t)atol(arg+off); 465 set_idle_to = 1; 466 } else if (startswith(arg, "max-auth-failure=")) { 467 authfailset.max_failures = atoi(arg+off); 468 set_auth_failure = 1; 469 } else if (strcmp(arg, "clear-auth-failure") == 0) { 470 clear_auth_failure_count = 1; 471 } else if (startswith(arg, "query-dns=")) { 472 dnssettings.query_dns = atoi(arg+off); 473 set_dns = 1; 474 } else 475 errx(EX_DATAERR, "bad parameter: \"%s\"", arg); 476 } 477 478 static void 479 usage(void) 480 { 481 const char * prog = getprogname(); 482 fprintf(stderr, 483 "usage:\n" 484 " %s [-f config] ifname [...]\n" 485 " %s [-v] ifname [{my|his}auth{proto|name|secret}=...] \\\n" 486 " [callin] [always] [{no}rechallenge]\n" 487 " [query-dns=3]\n" 488 " to set authentication names, passwords\n" 489 " and (optional) paramaters\n" 490 " %s [-v] ifname lcp-timeout=ms|idle-timeout=s|\n" 491 " max-noreceive=s|max-alive-missed=cnt|\n" 492 " max-auth-failure=count|clear-auth-failure\n" 493 " to set general parameters\n" 494 " or\n" 495 " %s -e ethernet-ifname ifname\n" 496 " to connect an ethernet interface for PPPoE\n" 497 " %s [-a access-concentrator-name] [-s service-name] ifname\n" 498 " to specify (optional) data for PPPoE sessions\n" 499 " %s -d ifname\n" 500 " to dump the current PPPoE session state\n" 501 " %s -n (1|2) ifname\n" 502 " to print DNS addresses retrieved via query-dns\n" 503 , prog, prog, prog, prog, prog, prog, prog); 504 exit(EX_USAGE); 505 } 506 507 static void 508 print_vals(const char *ifname, int phase, struct spppauthcfg *sp, int lcp_timeout, 509 time_t idle_timeout, int authfailures, int max_auth_failures, 510 u_int maxalive_cnt, time_t max_noreceive_time) 511 { 512 #ifndef __NetBSD__ 513 time_t send, recv; 514 #endif 515 516 printf("%s:\tphase=%s\n", ifname, phase_name(phase)); 517 if (sp->myauth) { 518 printf("\tmyauthproto=%s myauthname=\"%s\"\n", 519 proto_name(sp->myauth), 520 sp->myname); 521 } 522 if (sp->hisauth) { 523 printf("\thisauthproto=%s hisauthname=\"%s\"%s\n", 524 proto_name(sp->hisauth), 525 sp->hisname, 526 authflags(sp->hisauthflags)); 527 } 528 #ifndef __NetBSD__ 529 if (sp->defs.pp_phase > PHASE_DEAD) { 530 send = time(NULL) - sp->defs.pp_last_sent; 531 recv = time(NULL) - sp->defs.pp_last_recv; 532 printf("\tidle_time=%ld\n", (send<recv)? send : recv); 533 } 534 #endif 535 536 printf("\tlcp timeout: %.3f s\n", 537 (double)lcp_timeout / hz); 538 539 if (idle_timeout != 0) 540 printf("\tidle timeout = %lu s\n", (unsigned long)idle_timeout); 541 else 542 printf("\tidle timeout = disabled\n"); 543 544 if (authfailures != 0) 545 printf("\tauthentication failures = %d\n", authfailures); 546 printf("\tmax-auth-failure = %d\n", max_auth_failures); 547 548 printf("\tmax-noreceive = %ld seconds\n", (long)max_noreceive_time); 549 printf("\tmax-alive-missed = %u unanswered echo requests\n", maxalive_cnt); 550 551 #ifndef __NetBSD__ 552 printf("\tenable_vj: %s\n", 553 sp->defs.enable_vj ? "on" : "off"); 554 #endif 555 } 556 557 const char * 558 phase_name(int phase) 559 { 560 switch (phase) { 561 case SPPP_PHASE_DEAD: return "dead"; 562 case SPPP_PHASE_ESTABLISH: return "establish"; 563 case SPPP_PHASE_TERMINATE: return "terminate"; 564 case SPPP_PHASE_AUTHENTICATE: return "authenticate"; 565 case SPPP_PHASE_NETWORK: return "network"; 566 } 567 return "illegal"; 568 } 569 570 const char * 571 proto_name(int proto) 572 { 573 static char buf[12]; 574 switch (proto) { 575 case SPPP_AUTHPROTO_PAP: return "pap"; 576 case SPPP_AUTHPROTO_CHAP: return "chap"; 577 case SPPP_AUTHPROTO_NONE: return "none"; 578 } 579 snprintf(buf, sizeof(buf), "0x%x", (unsigned)proto); 580 return buf; 581 } 582 583 const char * 584 authflags(int flags) 585 { 586 static char buf[32]; 587 buf[0] = '\0'; 588 if (flags & SPPP_AUTHFLAG_NOCALLOUT) 589 strlcat(buf, " callin", sizeof(buf)); 590 if (flags & SPPP_AUTHFLAG_NORECHALLENGE) 591 strlcat(buf, " norechallenge", sizeof(buf)); 592 return buf; 593 } 594 595 static void 596 print_error(const char *ifname, int error, const char * str) 597 { 598 if (error == -1) 599 fprintf(stderr, "%s: interface not found\n", ifname); 600 else 601 fprintf(stderr, "%s: %s: %s\n", ifname, str, strerror(error)); 602 exit(EX_DATAERR); 603 } 604 605 606