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