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