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