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