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