1 /* 2 * Written by Eivind Eklund <eivind@yes.no> 3 * for Yes Interactive 4 * 5 * Copyright (C) 1998, Yes Interactive. All rights reserved. 6 * 7 * Redistribution and use in any form is permitted. Redistribution in 8 * source form should include the above copyright and this set of 9 * conditions, because large sections american law seems to have been 10 * created by a bunch of jerks on drugs that are now illegal, forcing 11 * me to include this copyright-stuff instead of placing this in the 12 * public domain. The name of of 'Yes Interactive' or 'Eivind Eklund' 13 * may not be used to endorse or promote products derived from this 14 * software without specific prior written permission. 15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 17 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 18 * 19 * $FreeBSD$ 20 * 21 */ 22 23 #include <sys/param.h> 24 #include <netinet/in.h> 25 #include <netinet/in_systm.h> 26 #include <netinet/ip.h> 27 #include <sys/socket.h> 28 #include <sys/time.h> 29 #include <sys/un.h> 30 31 #include <errno.h> 32 #include <fcntl.h> 33 #include <paths.h> 34 #ifdef NOSUID 35 #include <signal.h> 36 #endif 37 #include <stdarg.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <sys/uio.h> 42 #include <sysexits.h> 43 #include <termios.h> 44 #include <time.h> 45 #include <unistd.h> 46 #include <utmpx.h> 47 #if defined(__OpenBSD__) || defined(__NetBSD__) 48 #include <sys/ioctl.h> 49 #include <util.h> 50 #else 51 #include <libutil.h> 52 #endif 53 54 #include "layer.h" 55 #ifndef NONAT 56 #include "nat_cmd.h" 57 #endif 58 #include "proto.h" 59 #include "acf.h" 60 #include "vjcomp.h" 61 #include "defs.h" 62 #include "command.h" 63 #include "mbuf.h" 64 #include "log.h" 65 #include "id.h" 66 #include "timer.h" 67 #include "fsm.h" 68 #include "lqr.h" 69 #include "hdlc.h" 70 #include "lcp.h" 71 #include "throughput.h" 72 #include "sync.h" 73 #include "async.h" 74 #include "iplist.h" 75 #include "slcompress.h" 76 #include "ncpaddr.h" 77 #include "ipcp.h" 78 #include "filter.h" 79 #include "descriptor.h" 80 #include "ccp.h" 81 #include "link.h" 82 #include "physical.h" 83 #include "mp.h" 84 #ifndef NORADIUS 85 #include "radius.h" 86 #endif 87 #include "ipv6cp.h" 88 #include "ncp.h" 89 #include "bundle.h" 90 #include "prompt.h" 91 #include "chat.h" 92 #include "auth.h" 93 #include "main.h" 94 #include "chap.h" 95 #include "cbcp.h" 96 #include "datalink.h" 97 #include "tcp.h" 98 #include "udp.h" 99 #include "exec.h" 100 #include "tty.h" 101 #ifndef NONETGRAPH 102 #include "ether.h" 103 #include "netgraph.h" 104 #endif 105 #include "tcpmss.h" 106 107 static int physical_DescriptorWrite(struct fdescriptor *, struct bundle *, 108 const fd_set *); 109 110 static unsigned 111 physical_DeviceSize(void) 112 { 113 return sizeof(struct device); 114 } 115 116 struct { 117 struct device *(*create)(struct physical *); 118 struct device *(*iov2device)(int, struct physical *, struct iovec *, 119 int *, int, int *, int *); 120 unsigned (*DeviceSize)(void); 121 } devices[] = { 122 { tty_Create, tty_iov2device, tty_DeviceSize }, 123 #ifndef NONETGRAPH 124 /* 125 * This must come before ``udp'' so that the probe routine is 126 * able to identify it as a more specific type of SOCK_DGRAM. 127 */ 128 { ether_Create, ether_iov2device, ether_DeviceSize }, 129 #ifdef EXPERIMENTAL_NETGRAPH 130 { ng_Create, ng_iov2device, ng_DeviceSize }, 131 #endif 132 #endif 133 { tcp_Create, tcp_iov2device, tcp_DeviceSize }, 134 { udp_Create, udp_iov2device, udp_DeviceSize }, 135 { exec_Create, exec_iov2device, exec_DeviceSize } 136 }; 137 138 #define NDEVICES (sizeof devices / sizeof devices[0]) 139 140 static int 141 physical_UpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w, fd_set *e, 142 int *n) 143 { 144 return physical_doUpdateSet(d, r, w, e, n, 0); 145 } 146 147 void 148 physical_SetDescriptor(struct physical *p) 149 { 150 p->desc.type = PHYSICAL_DESCRIPTOR; 151 p->desc.UpdateSet = physical_UpdateSet; 152 p->desc.IsSet = physical_IsSet; 153 p->desc.Read = physical_DescriptorRead; 154 p->desc.Write = physical_DescriptorWrite; 155 } 156 157 struct physical * 158 physical_Create(struct datalink *dl, int type) 159 { 160 struct physical *p; 161 162 p = (struct physical *)malloc(sizeof(struct physical)); 163 if (!p) 164 return NULL; 165 166 p->link.type = PHYSICAL_LINK; 167 p->link.name = dl->name; 168 p->link.len = sizeof *p; 169 170 /* The sample period is fixed - see physical2iov() & iov2physical() */ 171 throughput_init(&p->link.stats.total, SAMPLE_PERIOD); 172 p->link.stats.parent = dl->bundle->ncp.mp.active ? 173 &dl->bundle->ncp.mp.link.stats.total : NULL; 174 p->link.stats.gather = 1; 175 176 memset(p->link.Queue, '\0', sizeof p->link.Queue); 177 memset(p->link.proto_in, '\0', sizeof p->link.proto_in); 178 memset(p->link.proto_out, '\0', sizeof p->link.proto_out); 179 link_EmptyStack(&p->link); 180 181 p->handler = NULL; 182 physical_SetDescriptor(p); 183 p->type = type; 184 185 hdlc_Init(&p->hdlc, &p->link.lcp); 186 async_Init(&p->async); 187 188 p->fd = -1; 189 p->out = NULL; 190 p->connect_count = 0; 191 p->dl = dl; 192 p->input.sz = 0; 193 *p->name.full = '\0'; 194 p->name.base = p->name.full; 195 196 p->Utmp = 0; 197 p->session_owner = (pid_t)-1; 198 199 p->cfg.rts_cts = MODEM_CTSRTS; 200 p->cfg.speed = MODEM_SPEED; 201 p->cfg.parity = CS8; 202 memcpy(p->cfg.devlist, MODEM_LIST, sizeof MODEM_LIST); 203 p->cfg.ndev = NMODEMS; 204 p->cfg.cd.necessity = CD_DEFAULT; 205 p->cfg.cd.delay = 0; /* reconfigured or device specific default */ 206 207 lcp_Init(&p->link.lcp, dl->bundle, &p->link, &dl->fsmp); 208 ccp_Init(&p->link.ccp, dl->bundle, &p->link, &dl->fsmp); 209 210 return p; 211 } 212 213 static const struct parity { 214 const char *name; 215 const char *name1; 216 int set; 217 } validparity[] = { 218 { "even", "P_EVEN", CS7 | PARENB }, 219 { "odd", "P_ODD", CS7 | PARENB | PARODD }, 220 { "none", "P_ZERO", CS8 }, 221 { NULL, NULL, 0 }, 222 }; 223 224 static int 225 GetParityValue(const char *str) 226 { 227 const struct parity *pp; 228 229 for (pp = validparity; pp->name; pp++) { 230 if (strcasecmp(pp->name, str) == 0 || 231 strcasecmp(pp->name1, str) == 0) { 232 return pp->set; 233 } 234 } 235 return (-1); 236 } 237 238 int 239 physical_SetParity(struct physical *p, const char *str) 240 { 241 struct termios rstio; 242 int val; 243 244 val = GetParityValue(str); 245 if (val > 0) { 246 p->cfg.parity = val; 247 if (p->fd >= 0) { 248 tcgetattr(p->fd, &rstio); 249 rstio.c_cflag &= ~(CSIZE | PARODD | PARENB); 250 rstio.c_cflag |= val; 251 tcsetattr(p->fd, TCSADRAIN, &rstio); 252 } 253 return 0; 254 } 255 log_Printf(LogWARN, "%s: %s: Invalid parity\n", p->link.name, str); 256 return -1; 257 } 258 259 unsigned 260 physical_GetSpeed(struct physical *p) 261 { 262 if (p->handler && p->handler->speed) 263 return (*p->handler->speed)(p); 264 265 return 0; 266 } 267 268 int 269 physical_SetSpeed(struct physical *p, unsigned speed) 270 { 271 if (UnsignedToSpeed(speed) != B0) { 272 p->cfg.speed = speed; 273 return 1; 274 } 275 276 return 0; 277 } 278 279 int 280 physical_Raw(struct physical *p) 281 { 282 if (p->handler && p->handler->raw) 283 return (*p->handler->raw)(p); 284 285 return 1; 286 } 287 288 void 289 physical_Offline(struct physical *p) 290 { 291 if (p->handler && p->handler->offline) 292 (*p->handler->offline)(p); 293 log_Printf(LogPHASE, "%s: Disconnected!\n", p->link.name); 294 } 295 296 static int 297 physical_Lock(struct physical *p) 298 { 299 int res; 300 301 if (*p->name.full == '/' && p->type != PHYS_DIRECT && 302 (res = ID0uu_lock(p->name.base)) != UU_LOCK_OK) { 303 if (res == UU_LOCK_INUSE) 304 log_Printf(LogPHASE, "%s: %s is in use\n", p->link.name, p->name.full); 305 else 306 log_Printf(LogPHASE, "%s: %s is in use: uu_lock: %s\n", 307 p->link.name, p->name.full, uu_lockerr(res)); 308 return 0; 309 } 310 311 return 1; 312 } 313 314 static void 315 physical_Unlock(struct physical *p) 316 { 317 if (*p->name.full == '/' && p->type != PHYS_DIRECT && 318 ID0uu_unlock(p->name.base) == -1) 319 log_Printf(LogALERT, "%s: Can't uu_unlock %s\n", p->link.name, 320 p->name.base); 321 } 322 323 void 324 physical_Close(struct physical *p) 325 { 326 int newsid; 327 char fn[PATH_MAX]; 328 struct utmpx ut; 329 330 if (p->fd < 0) 331 return; 332 333 log_Printf(LogDEBUG, "%s: Close\n", p->link.name); 334 335 if (p->handler && p->handler->cooked) 336 (*p->handler->cooked)(p); 337 338 physical_StopDeviceTimer(p); 339 if (p->Utmp) { 340 memset(&ut, 0, sizeof ut); 341 ut.ut_type = DEAD_PROCESS; 342 gettimeofday(&ut.ut_tv, NULL); 343 snprintf(ut.ut_id, sizeof ut.ut_id, "%xppp", (int)getpid()); 344 ID0logout(&ut); 345 p->Utmp = 0; 346 } 347 newsid = tcgetpgrp(p->fd) == getpgrp(); 348 close(p->fd); 349 p->fd = -1; 350 log_SetTtyCommandMode(p->dl); 351 352 throughput_stop(&p->link.stats.total); 353 throughput_log(&p->link.stats.total, LogPHASE, p->link.name); 354 355 if (p->session_owner != (pid_t)-1) { 356 log_Printf(LogPHASE, "%s: HUPing %ld\n", p->link.name, 357 (long)p->session_owner); 358 ID0kill(p->session_owner, SIGHUP); 359 p->session_owner = (pid_t)-1; 360 } 361 362 if (newsid) 363 bundle_setsid(p->dl->bundle, 0); 364 365 if (*p->name.full == '/') { 366 snprintf(fn, sizeof fn, "%s%s.if", _PATH_VARRUN, p->name.base); 367 #ifndef RELEASE_CRUNCH 368 if (ID0unlink(fn) == -1) 369 log_Printf(LogALERT, "%s: Can't remove %s: %s\n", 370 p->link.name, fn, strerror(errno)); 371 #else 372 ID0unlink(fn); 373 #endif 374 } 375 physical_Unlock(p); 376 if (p->handler && p->handler->destroy) 377 (*p->handler->destroy)(p); 378 p->handler = NULL; 379 p->name.base = p->name.full; 380 *p->name.full = '\0'; 381 } 382 383 void 384 physical_Destroy(struct physical *p) 385 { 386 physical_Close(p); 387 throughput_destroy(&p->link.stats.total); 388 free(p); 389 } 390 391 static int 392 physical_DescriptorWrite(struct fdescriptor *d, struct bundle *bundle __unused, 393 const fd_set *fdset __unused) 394 { 395 struct physical *p = descriptor2physical(d); 396 int nw, result = 0; 397 398 if (p->out == NULL) 399 p->out = link_Dequeue(&p->link); 400 401 if (p->out) { 402 nw = physical_Write(p, MBUF_CTOP(p->out), p->out->m_len); 403 log_Printf(LogDEBUG, "%s: DescriptorWrite: wrote %d(%lu) to %d\n", 404 p->link.name, nw, (unsigned long)p->out->m_len, p->fd); 405 if (nw > 0) { 406 p->out->m_len -= nw; 407 p->out->m_offset += nw; 408 if (p->out->m_len == 0) 409 p->out = m_free(p->out); 410 result = 1; 411 } else if (nw < 0) { 412 if (errno == EAGAIN) 413 result = 1; 414 else if (errno != ENOBUFS) { 415 log_Printf(LogPHASE, "%s: write (fd %d, len %zd): %s\n", p->link.name, 416 p->fd, p->out->m_len, strerror(errno)); 417 datalink_Down(p->dl, CLOSE_NORMAL); 418 } 419 } 420 /* else we shouldn't really have been called ! select() is broken ! */ 421 } 422 423 return result; 424 } 425 426 int 427 physical_ShowStatus(struct cmdargs const *arg) 428 { 429 struct physical *p = arg->cx->physical; 430 struct cd *cd; 431 const char *dev; 432 int n, slot; 433 434 prompt_Printf(arg->prompt, "Name: %s\n", p->link.name); 435 prompt_Printf(arg->prompt, " State: "); 436 if (p->fd < 0) 437 prompt_Printf(arg->prompt, "closed\n"); 438 else { 439 slot = physical_Slot(p); 440 if (p->handler && p->handler->openinfo) { 441 if (slot == -1) 442 prompt_Printf(arg->prompt, "open (%s)\n", (*p->handler->openinfo)(p)); 443 else 444 prompt_Printf(arg->prompt, "open (%s, port %d)\n", 445 (*p->handler->openinfo)(p), slot); 446 } else if (slot == -1) 447 prompt_Printf(arg->prompt, "open\n"); 448 else 449 prompt_Printf(arg->prompt, "open (port %d)\n", slot); 450 } 451 452 prompt_Printf(arg->prompt, " Device: %s", 453 *p->name.full ? p->name.full : 454 p->type == PHYS_DIRECT ? "unknown" : "N/A"); 455 if (p->session_owner != (pid_t)-1) 456 prompt_Printf(arg->prompt, " (session owner: %ld)", (long)p->session_owner); 457 458 prompt_Printf(arg->prompt, "\n Link Type: %s\n", mode2Nam(p->type)); 459 prompt_Printf(arg->prompt, " Connect Count: %d\n", p->connect_count); 460 #ifdef TIOCOUTQ 461 if (p->fd >= 0 && ioctl(p->fd, TIOCOUTQ, &n) >= 0) 462 prompt_Printf(arg->prompt, " Physical outq: %d\n", n); 463 #endif 464 465 prompt_Printf(arg->prompt, " Queued Packets: %lu\n", 466 (u_long)link_QueueLen(&p->link)); 467 prompt_Printf(arg->prompt, " Phone Number: %s\n", arg->cx->phone.chosen); 468 469 prompt_Printf(arg->prompt, "\nDefaults:\n"); 470 471 prompt_Printf(arg->prompt, " Device List: "); 472 dev = p->cfg.devlist; 473 for (n = 0; n < p->cfg.ndev; n++) { 474 if (n) 475 prompt_Printf(arg->prompt, ", "); 476 prompt_Printf(arg->prompt, "\"%s\"", dev); 477 dev += strlen(dev) + 1; 478 } 479 480 prompt_Printf(arg->prompt, "\n Characteristics: "); 481 if (physical_IsSync(arg->cx->physical)) 482 prompt_Printf(arg->prompt, "sync"); 483 else 484 prompt_Printf(arg->prompt, "%dbps", p->cfg.speed); 485 486 switch (p->cfg.parity & CSIZE) { 487 case CS7: 488 prompt_Printf(arg->prompt, ", cs7"); 489 break; 490 case CS8: 491 prompt_Printf(arg->prompt, ", cs8"); 492 break; 493 } 494 if (p->cfg.parity & PARENB) { 495 if (p->cfg.parity & PARODD) 496 prompt_Printf(arg->prompt, ", odd parity"); 497 else 498 prompt_Printf(arg->prompt, ", even parity"); 499 } else 500 prompt_Printf(arg->prompt, ", no parity"); 501 502 prompt_Printf(arg->prompt, ", CTS/RTS %s\n", (p->cfg.rts_cts ? "on" : "off")); 503 504 prompt_Printf(arg->prompt, " CD check delay: "); 505 cd = p->handler ? &p->handler->cd : &p->cfg.cd; 506 if (cd->necessity == CD_NOTREQUIRED) 507 prompt_Printf(arg->prompt, "no cd"); 508 else if (p->cfg.cd.necessity == CD_DEFAULT) { 509 prompt_Printf(arg->prompt, "device specific"); 510 } else { 511 prompt_Printf(arg->prompt, "%d second%s", p->cfg.cd.delay, 512 p->cfg.cd.delay == 1 ? "" : "s"); 513 if (p->cfg.cd.necessity == CD_REQUIRED) 514 prompt_Printf(arg->prompt, " (required!)"); 515 } 516 prompt_Printf(arg->prompt, "\n\n"); 517 518 throughput_disp(&p->link.stats.total, arg->prompt); 519 520 return 0; 521 } 522 523 void 524 physical_DescriptorRead(struct fdescriptor *d, struct bundle *bundle, 525 const fd_set *fdset __unused) 526 { 527 struct physical *p = descriptor2physical(d); 528 u_char *rbuff; 529 int n, found; 530 531 rbuff = p->input.buf + p->input.sz; 532 533 /* something to read */ 534 n = physical_Read(p, rbuff, sizeof p->input.buf - p->input.sz); 535 log_Printf(LogDEBUG, "%s: DescriptorRead: read %d/%d from %d\n", 536 p->link.name, n, (int)(sizeof p->input.buf - p->input.sz), p->fd); 537 if (n <= 0) { 538 if (n < 0) 539 log_Printf(LogPHASE, "%s: read (%d): %s\n", p->link.name, p->fd, 540 strerror(errno)); 541 else 542 log_Printf(LogPHASE, "%s: read (%d): Got zero bytes\n", 543 p->link.name, p->fd); 544 datalink_Down(p->dl, CLOSE_NORMAL); 545 return; 546 } 547 548 rbuff -= p->input.sz; 549 n += p->input.sz; 550 551 if (p->link.lcp.fsm.state <= ST_CLOSED) { 552 if (p->type != PHYS_DEDICATED) { 553 found = hdlc_Detect((u_char const **)&rbuff, n, physical_IsSync(p)); 554 if (rbuff != p->input.buf) 555 log_WritePrompts(p->dl, "%.*s", (int)(rbuff - p->input.buf), 556 p->input.buf); 557 p->input.sz = n - (rbuff - p->input.buf); 558 559 if (found) { 560 /* LCP packet is detected. Turn ourselves into packet mode */ 561 log_Printf(LogPHASE, "%s: PPP packet detected, coming up\n", 562 p->link.name); 563 log_SetTtyCommandMode(p->dl); 564 datalink_Up(p->dl, 0, 1); 565 link_PullPacket(&p->link, rbuff, p->input.sz, bundle); 566 p->input.sz = 0; 567 } else 568 bcopy(rbuff, p->input.buf, p->input.sz); 569 } else 570 /* In -dedicated mode, we just discard input until LCP is started */ 571 p->input.sz = 0; 572 } else if (n > 0) 573 link_PullPacket(&p->link, rbuff, n, bundle); 574 } 575 576 struct physical * 577 iov2physical(struct datalink *dl, struct iovec *iov, int *niov, int maxiov, 578 int fd, int *auxfd, int *nauxfd) 579 { 580 struct physical *p; 581 int type; 582 unsigned h; 583 584 p = (struct physical *)iov[(*niov)++].iov_base; 585 p->link.name = dl->name; 586 memset(p->link.Queue, '\0', sizeof p->link.Queue); 587 588 p->desc.UpdateSet = physical_UpdateSet; 589 p->desc.IsSet = physical_IsSet; 590 p->desc.Read = physical_DescriptorRead; 591 p->desc.Write = physical_DescriptorWrite; 592 p->type = PHYS_DIRECT; 593 p->dl = dl; 594 p->out = NULL; 595 p->connect_count = 1; 596 597 physical_SetDevice(p, p->name.full); 598 599 p->link.lcp.fsm.bundle = dl->bundle; 600 p->link.lcp.fsm.link = &p->link; 601 memset(&p->link.lcp.fsm.FsmTimer, '\0', sizeof p->link.lcp.fsm.FsmTimer); 602 memset(&p->link.lcp.fsm.OpenTimer, '\0', sizeof p->link.lcp.fsm.OpenTimer); 603 memset(&p->link.lcp.fsm.StoppedTimer, '\0', 604 sizeof p->link.lcp.fsm.StoppedTimer); 605 p->link.lcp.fsm.parent = &dl->fsmp; 606 lcp_SetupCallbacks(&p->link.lcp); 607 608 p->link.ccp.fsm.bundle = dl->bundle; 609 p->link.ccp.fsm.link = &p->link; 610 /* Our in.state & out.state are NULL (no link-level ccp yet) */ 611 memset(&p->link.ccp.fsm.FsmTimer, '\0', sizeof p->link.ccp.fsm.FsmTimer); 612 memset(&p->link.ccp.fsm.OpenTimer, '\0', sizeof p->link.ccp.fsm.OpenTimer); 613 memset(&p->link.ccp.fsm.StoppedTimer, '\0', 614 sizeof p->link.ccp.fsm.StoppedTimer); 615 p->link.ccp.fsm.parent = &dl->fsmp; 616 ccp_SetupCallbacks(&p->link.ccp); 617 618 p->hdlc.lqm.owner = &p->link.lcp; 619 p->hdlc.ReportTimer.state = TIMER_STOPPED; 620 p->hdlc.lqm.timer.state = TIMER_STOPPED; 621 622 p->fd = fd; 623 p->link.stats.total.in.SampleOctets = (long long *)iov[(*niov)++].iov_base; 624 p->link.stats.total.out.SampleOctets = (long long *)iov[(*niov)++].iov_base; 625 p->link.stats.parent = dl->bundle->ncp.mp.active ? 626 &dl->bundle->ncp.mp.link.stats.total : NULL; 627 p->link.stats.gather = 1; 628 629 type = (long)p->handler; 630 p->handler = NULL; 631 for (h = 0; h < NDEVICES && p->handler == NULL; h++) 632 p->handler = (*devices[h].iov2device)(type, p, iov, niov, maxiov, 633 auxfd, nauxfd); 634 if (p->handler == NULL) { 635 log_Printf(LogPHASE, "%s: Unknown link type\n", p->link.name); 636 free(iov[(*niov)++].iov_base); 637 physical_SetupStack(p, "unknown", PHYSICAL_NOFORCE); 638 } else 639 log_Printf(LogPHASE, "%s: Device %s, link type is %s\n", 640 p->link.name, p->name.full, p->handler->name); 641 642 if (p->hdlc.lqm.method && p->hdlc.lqm.timer.load) 643 lqr_reStart(&p->link.lcp); 644 hdlc_StartTimer(&p->hdlc); 645 646 throughput_restart(&p->link.stats.total, "physical throughput", 647 Enabled(dl->bundle, OPT_THROUGHPUT)); 648 649 return p; 650 } 651 652 unsigned 653 physical_MaxDeviceSize() 654 { 655 unsigned biggest, sz, n; 656 657 biggest = sizeof(struct device); 658 for (n = 0; n < NDEVICES; n++) 659 if (devices[n].DeviceSize) { 660 sz = (*devices[n].DeviceSize)(); 661 if (biggest < sz) 662 biggest = sz; 663 } 664 665 return biggest; 666 } 667 668 int 669 physical2iov(struct physical *p, struct iovec *iov, int *niov, int maxiov, 670 int *auxfd, int *nauxfd) 671 { 672 struct device *h; 673 int sz; 674 675 h = NULL; 676 if (p) { 677 hdlc_StopTimer(&p->hdlc); 678 lqr_StopTimer(p); 679 timer_Stop(&p->link.lcp.fsm.FsmTimer); 680 timer_Stop(&p->link.ccp.fsm.FsmTimer); 681 timer_Stop(&p->link.lcp.fsm.OpenTimer); 682 timer_Stop(&p->link.ccp.fsm.OpenTimer); 683 timer_Stop(&p->link.lcp.fsm.StoppedTimer); 684 timer_Stop(&p->link.ccp.fsm.StoppedTimer); 685 if (p->handler) { 686 h = p->handler; 687 p->handler = (struct device *)(long)p->handler->type; 688 } 689 690 if (Enabled(p->dl->bundle, OPT_KEEPSESSION) || 691 tcgetpgrp(p->fd) == getpgrp()) 692 p->session_owner = getpid(); /* So I'll eventually get HUP'd */ 693 else 694 p->session_owner = (pid_t)-1; 695 timer_Stop(&p->link.stats.total.Timer); 696 } 697 698 if (*niov + 2 >= maxiov) { 699 log_Printf(LogERROR, "physical2iov: No room for physical + throughput" 700 " + device !\n"); 701 if (p) 702 free(p); 703 return -1; 704 } 705 706 iov[*niov].iov_base = (void *)p; 707 iov[*niov].iov_len = sizeof *p; 708 (*niov)++; 709 710 iov[*niov].iov_base = p ? (void *)p->link.stats.total.in.SampleOctets : NULL; 711 iov[*niov].iov_len = SAMPLE_PERIOD * sizeof(long long); 712 (*niov)++; 713 iov[*niov].iov_base = p ? (void *)p->link.stats.total.out.SampleOctets : NULL; 714 iov[*niov].iov_len = SAMPLE_PERIOD * sizeof(long long); 715 (*niov)++; 716 717 sz = physical_MaxDeviceSize(); 718 if (p) { 719 if (h && h->device2iov) 720 (*h->device2iov)(h, iov, niov, maxiov, auxfd, nauxfd); 721 else { 722 if ((iov[*niov].iov_base = malloc(sz)) == NULL) { 723 log_Printf(LogALERT, "physical2iov: Out of memory (%d bytes)\n", sz); 724 AbortProgram(EX_OSERR); 725 } 726 if (h) 727 memcpy(iov[*niov].iov_base, h, sizeof *h); 728 iov[*niov].iov_len = sz; 729 (*niov)++; 730 } 731 } else { 732 iov[*niov].iov_base = NULL; 733 iov[*niov].iov_len = sz; 734 (*niov)++; 735 } 736 737 return p ? p->fd : 0; 738 } 739 740 const char * 741 physical_LockedDevice(struct physical *p) 742 { 743 if (p->fd >= 0 && *p->name.full == '/' && p->type != PHYS_DIRECT) 744 return p->name.base; 745 746 return NULL; 747 } 748 749 void 750 physical_ChangedPid(struct physical *p, pid_t newpid) 751 { 752 if (physical_LockedDevice(p)) { 753 int res; 754 755 if ((res = ID0uu_lock_txfr(p->name.base, newpid)) != UU_LOCK_OK) 756 log_Printf(LogPHASE, "uu_lock_txfr: %s\n", uu_lockerr(res)); 757 } 758 } 759 760 int 761 physical_IsSync(struct physical *p) 762 { 763 return p->cfg.speed == 0; 764 } 765 766 u_short 767 physical_DeviceMTU(struct physical *p) 768 { 769 return p->handler ? p->handler->mtu : 0; 770 } 771 772 const char *physical_GetDevice(struct physical *p) 773 { 774 return p->name.full; 775 } 776 777 void 778 physical_SetDeviceList(struct physical *p, int argc, const char *const *argv) 779 { 780 unsigned pos; 781 int f; 782 783 p->cfg.devlist[sizeof p->cfg.devlist - 1] = '\0'; 784 for (f = 0, pos = 0; f < argc && pos < sizeof p->cfg.devlist - 1; f++) { 785 if (pos) 786 p->cfg.devlist[pos++] = '\0'; 787 strncpy(p->cfg.devlist + pos, argv[f], sizeof p->cfg.devlist - pos - 1); 788 pos += strlen(p->cfg.devlist + pos); 789 } 790 p->cfg.ndev = f; 791 } 792 793 void 794 physical_SetSync(struct physical *p) 795 { 796 p->cfg.speed = 0; 797 } 798 799 int 800 physical_SetRtsCts(struct physical *p, int enable) 801 { 802 p->cfg.rts_cts = enable ? 1 : 0; 803 return 1; 804 } 805 806 ssize_t 807 physical_Read(struct physical *p, void *buf, size_t nbytes) 808 { 809 ssize_t ret; 810 811 if (p->handler && p->handler->read) 812 ret = (*p->handler->read)(p, buf, nbytes); 813 else 814 ret = read(p->fd, buf, nbytes); 815 816 log_DumpBuff(LogPHYSICAL, "read", buf, ret); 817 818 return ret; 819 } 820 821 ssize_t 822 physical_Write(struct physical *p, const void *buf, size_t nbytes) 823 { 824 log_DumpBuff(LogPHYSICAL, "write", buf, nbytes); 825 826 if (p->handler && p->handler->write) 827 return (*p->handler->write)(p, buf, nbytes); 828 829 return write(p->fd, buf, nbytes); 830 } 831 832 int 833 physical_doUpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w, fd_set *e, 834 int *n, int force) 835 { 836 struct physical *p = descriptor2physical(d); 837 int sets; 838 839 sets = 0; 840 if (p->fd >= 0) { 841 if (r) { 842 FD_SET(p->fd, r); 843 log_Printf(LogTIMER, "%s: fdset(r) %d\n", p->link.name, p->fd); 844 sets++; 845 } 846 if (e) { 847 FD_SET(p->fd, e); 848 log_Printf(LogTIMER, "%s: fdset(e) %d\n", p->link.name, p->fd); 849 sets++; 850 } 851 if (w && (force || link_QueueLen(&p->link) || p->out)) { 852 FD_SET(p->fd, w); 853 log_Printf(LogTIMER, "%s: fdset(w) %d\n", p->link.name, p->fd); 854 sets++; 855 } 856 if (sets && *n < p->fd + 1) 857 *n = p->fd + 1; 858 } 859 860 return sets; 861 } 862 863 int 864 physical_RemoveFromSet(struct physical *p, fd_set *r, fd_set *w, fd_set *e) 865 { 866 if (p->handler && p->handler->removefromset) 867 return (*p->handler->removefromset)(p, r, w, e); 868 else { 869 int sets; 870 871 sets = 0; 872 if (p->fd >= 0) { 873 if (r && FD_ISSET(p->fd, r)) { 874 FD_CLR(p->fd, r); 875 log_Printf(LogTIMER, "%s: fdunset(r) %d\n", p->link.name, p->fd); 876 sets++; 877 } 878 if (e && FD_ISSET(p->fd, e)) { 879 FD_CLR(p->fd, e); 880 log_Printf(LogTIMER, "%s: fdunset(e) %d\n", p->link.name, p->fd); 881 sets++; 882 } 883 if (w && FD_ISSET(p->fd, w)) { 884 FD_CLR(p->fd, w); 885 log_Printf(LogTIMER, "%s: fdunset(w) %d\n", p->link.name, p->fd); 886 sets++; 887 } 888 } 889 890 return sets; 891 } 892 } 893 894 int 895 physical_IsSet(struct fdescriptor *d, const fd_set *fdset) 896 { 897 struct physical *p = descriptor2physical(d); 898 return p->fd >= 0 && FD_ISSET(p->fd, fdset); 899 } 900 901 void 902 physical_Login(struct physical *p, const char *name) 903 { 904 if (p->type == PHYS_DIRECT && *p->name.base && !p->Utmp) { 905 struct utmpx ut; 906 const char *connstr; 907 char *colon; 908 909 memset(&ut, 0, sizeof ut); 910 ut.ut_type = USER_PROCESS; 911 gettimeofday(&ut.ut_tv, NULL); 912 snprintf(ut.ut_id, sizeof ut.ut_id, "%xppp", (int)getpid()); 913 strncpy(ut.ut_user, name, sizeof ut.ut_user); 914 if (p->handler && (p->handler->type == TCP_DEVICE || 915 p->handler->type == UDP_DEVICE)) { 916 strncpy(ut.ut_host, p->name.base, sizeof ut.ut_host); 917 colon = memchr(ut.ut_host, ':', sizeof ut.ut_host); 918 if (colon) 919 *colon = '\0'; 920 } else 921 strncpy(ut.ut_line, p->name.base, sizeof ut.ut_line); 922 if ((connstr = getenv("CONNECT"))) 923 /* mgetty sets this to the connection speed */ 924 strncpy(ut.ut_host, connstr, sizeof ut.ut_host); 925 ID0login(&ut); 926 p->Utmp = 1; 927 } 928 } 929 930 int 931 physical_SetMode(struct physical *p, int mode) 932 { 933 if ((p->type & (PHYS_DIRECT|PHYS_DEDICATED) || 934 mode & (PHYS_DIRECT|PHYS_DEDICATED)) && 935 (!(p->type & PHYS_DIRECT) || !(mode & PHYS_BACKGROUND))) { 936 /* Note: The -direct -> -background is for callback ! */ 937 log_Printf(LogWARN, "%s: Cannot change mode %s to %s\n", p->link.name, 938 mode2Nam(p->type), mode2Nam(mode)); 939 return 0; 940 } 941 p->type = mode; 942 return 1; 943 } 944 945 void 946 physical_DeleteQueue(struct physical *p) 947 { 948 if (p->out) { 949 m_freem(p->out); 950 p->out = NULL; 951 } 952 link_DeleteQueue(&p->link); 953 } 954 955 void 956 physical_SetDevice(struct physical *p, const char *name) 957 { 958 int len = strlen(_PATH_DEV); 959 960 if (name != p->name.full) { 961 strncpy(p->name.full, name, sizeof p->name.full - 1); 962 p->name.full[sizeof p->name.full - 1] = '\0'; 963 } 964 p->name.base = *p->name.full == '!' ? p->name.full + 1 : 965 strncmp(p->name.full, _PATH_DEV, len) ? 966 p->name.full : p->name.full + len; 967 } 968 969 static void 970 physical_Found(struct physical *p) 971 { 972 FILE *lockfile; 973 char fn[PATH_MAX]; 974 975 if (*p->name.full == '/') { 976 snprintf(fn, sizeof fn, "%s%s.if", _PATH_VARRUN, p->name.base); 977 lockfile = ID0fopen(fn, "w"); 978 if (lockfile != NULL) { 979 fprintf(lockfile, "%s%d\n", TUN_NAME, p->dl->bundle->unit); 980 fclose(lockfile); 981 } 982 #ifndef RELEASE_CRUNCH 983 else 984 log_Printf(LogALERT, "%s: Can't create %s: %s\n", 985 p->link.name, fn, strerror(errno)); 986 #endif 987 } 988 989 throughput_start(&p->link.stats.total, "physical throughput", 990 Enabled(p->dl->bundle, OPT_THROUGHPUT)); 991 p->connect_count++; 992 p->input.sz = 0; 993 994 log_Printf(LogPHASE, "%s: Connected!\n", p->link.name); 995 } 996 997 int 998 physical_Open(struct physical *p) 999 { 1000 char *dev; 1001 int devno, wasfd, err; 1002 unsigned h; 1003 1004 if (p->fd >= 0) 1005 log_Printf(LogDEBUG, "%s: Open: Modem is already open!\n", p->link.name); 1006 /* We're going back into "term" mode */ 1007 else if (p->type == PHYS_DIRECT) { 1008 physical_SetDevice(p, ""); 1009 p->fd = STDIN_FILENO; 1010 for (h = 0; h < NDEVICES && p->handler == NULL && p->fd >= 0; h++) 1011 p->handler = (*devices[h].create)(p); 1012 close(STDOUT_FILENO); 1013 if (p->fd >= 0) { 1014 if (p->handler == NULL) { 1015 physical_SetupStack(p, "unknown", PHYSICAL_NOFORCE); 1016 log_Printf(LogDEBUG, "%s: stdin is unidentified\n", p->link.name); 1017 } 1018 physical_Found(p); 1019 } 1020 } else { 1021 dev = p->cfg.devlist; 1022 devno = 0; 1023 while (devno < p->cfg.ndev && p->fd < 0) { 1024 physical_SetDevice(p, dev); 1025 if (physical_Lock(p)) { 1026 err = 0; 1027 1028 if (*p->name.full == '/') { 1029 p->fd = ID0open(p->name.full, O_RDWR | O_NONBLOCK); 1030 if (p->fd < 0) 1031 err = errno; 1032 } 1033 1034 wasfd = p->fd; 1035 for (h = 0; h < NDEVICES && p->handler == NULL; h++) 1036 if ((p->handler = (*devices[h].create)(p)) == NULL && wasfd != p->fd) 1037 break; 1038 1039 if (p->fd < 0) { 1040 if (h == NDEVICES) { 1041 if (err) 1042 log_Printf(LogWARN, "%s: %s: %s\n", p->link.name, p->name.full, 1043 strerror(errno)); 1044 else 1045 log_Printf(LogWARN, "%s: Device (%s) must begin with a '/'," 1046 " a '!' or contain at least one ':'\n", p->link.name, 1047 p->name.full); 1048 } 1049 physical_Unlock(p); 1050 } else 1051 physical_Found(p); 1052 } 1053 dev += strlen(dev) + 1; 1054 devno++; 1055 } 1056 } 1057 1058 return p->fd; 1059 } 1060 1061 void 1062 physical_SetupStack(struct physical *p, const char *who, int how) 1063 { 1064 link_EmptyStack(&p->link); 1065 if (how == PHYSICAL_FORCE_SYNC || how == PHYSICAL_FORCE_SYNCNOACF || 1066 (how == PHYSICAL_NOFORCE && physical_IsSync(p))) 1067 link_Stack(&p->link, &synclayer); 1068 else { 1069 link_Stack(&p->link, &asynclayer); 1070 link_Stack(&p->link, &hdlclayer); 1071 } 1072 if (how != PHYSICAL_FORCE_SYNCNOACF) 1073 link_Stack(&p->link, &acflayer); 1074 link_Stack(&p->link, &protolayer); 1075 link_Stack(&p->link, &lqrlayer); 1076 link_Stack(&p->link, &ccplayer); 1077 link_Stack(&p->link, &vjlayer); 1078 link_Stack(&p->link, &tcpmsslayer); 1079 #ifndef NONAT 1080 link_Stack(&p->link, &natlayer); 1081 #endif 1082 if (how == PHYSICAL_FORCE_ASYNC && physical_IsSync(p)) { 1083 log_Printf(LogWARN, "Sync device setting ignored for ``%s'' device\n", who); 1084 p->cfg.speed = MODEM_SPEED; 1085 } else if (how == PHYSICAL_FORCE_SYNC && !physical_IsSync(p)) { 1086 log_Printf(LogWARN, "Async device setting ignored for ``%s'' device\n", 1087 who); 1088 physical_SetSync(p); 1089 } 1090 } 1091 1092 void 1093 physical_StopDeviceTimer(struct physical *p) 1094 { 1095 if (p->handler && p->handler->stoptimer) 1096 (*p->handler->stoptimer)(p); 1097 } 1098 1099 int 1100 physical_AwaitCarrier(struct physical *p) 1101 { 1102 if (p->handler && p->handler->awaitcarrier) 1103 return (*p->handler->awaitcarrier)(p); 1104 1105 return CARRIER_OK; 1106 } 1107 1108 1109 void 1110 physical_SetAsyncParams(struct physical *p, u_int32_t mymap, u_int32_t hismap) 1111 { 1112 if (p->handler && p->handler->setasyncparams) 1113 return (*p->handler->setasyncparams)(p, mymap, hismap); 1114 1115 async_SetLinkParams(&p->async, mymap, hismap); 1116 } 1117 1118 int 1119 physical_Slot(struct physical *p) 1120 { 1121 if (p->handler && p->handler->slot) 1122 return (*p->handler->slot)(p); 1123 1124 return -1; 1125 } 1126 1127 int 1128 physical_SetPPPoEnonstandard(struct physical *p, int enable) 1129 { 1130 p->cfg.nonstandard_pppoe = enable ? 1 : 0; 1131 p->cfg.pppoe_configured = 1; 1132 return 1; 1133 } 1134