physical.c revision 179568
136285Sbrian/* 236285Sbrian * Written by Eivind Eklund <eivind@yes.no> 336285Sbrian * for Yes Interactive 436285Sbrian * 536285Sbrian * Copyright (C) 1998, Yes Interactive. All rights reserved. 636285Sbrian * 736285Sbrian * Redistribution and use in any form is permitted. Redistribution in 836285Sbrian * source form should include the above copyright and this set of 936285Sbrian * conditions, because large sections american law seems to have been 1036285Sbrian * created by a bunch of jerks on drugs that are now illegal, forcing 1136285Sbrian * me to include this copyright-stuff instead of placing this in the 1236285Sbrian * public domain. The name of of 'Yes Interactive' or 'Eivind Eklund' 1336285Sbrian * may not be used to endorse or promote products derived from this 1436285Sbrian * software without specific prior written permission. 1536285Sbrian * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1636285Sbrian * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1736285Sbrian * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1836285Sbrian * 1950479Speter * $FreeBSD: head/usr.sbin/ppp/physical.c 179568 2008-06-05 17:46:32Z ed $ 2036285Sbrian * 2136285Sbrian */ 2236285Sbrian 2346686Sbrian#include <sys/param.h> 2446686Sbrian#include <netinet/in.h> 2546686Sbrian#include <netinet/in_systm.h> 2646686Sbrian#include <netinet/ip.h> 2781634Sbrian#include <sys/socket.h> 2846686Sbrian#include <sys/un.h> 2946686Sbrian 3046686Sbrian#include <errno.h> 3146686Sbrian#include <fcntl.h> 3246686Sbrian#include <paths.h> 33134789Sbrian#ifdef NOSUID 34134789Sbrian#include <signal.h> 35134789Sbrian#endif 36102500Sbrian#include <stdarg.h> 3736285Sbrian#include <stdio.h> 3836285Sbrian#include <stdlib.h> 3936285Sbrian#include <string.h> 4046686Sbrian#include <sys/uio.h> 41136375Sbrian#include <sysexits.h> 42179568Sed#include <termios.h> 4336285Sbrian#include <time.h> 4436285Sbrian#include <unistd.h> 4536285Sbrian#include <utmp.h> 4646686Sbrian#if defined(__OpenBSD__) || defined(__NetBSD__) 4746686Sbrian#include <sys/ioctl.h> 4846686Sbrian#include <util.h> 4946686Sbrian#else 5046686Sbrian#include <libutil.h> 5146686Sbrian#endif 5236285Sbrian 5346686Sbrian#include "layer.h" 5450059Sbrian#ifndef NONAT 5551075Sbrian#include "nat_cmd.h" 5646686Sbrian#endif 5746686Sbrian#include "proto.h" 5846686Sbrian#include "acf.h" 5946686Sbrian#include "vjcomp.h" 6036285Sbrian#include "defs.h" 6146686Sbrian#include "command.h" 6236285Sbrian#include "mbuf.h" 6346686Sbrian#include "log.h" 6446686Sbrian#include "id.h" 6536285Sbrian#include "timer.h" 6646686Sbrian#include "fsm.h" 6736285Sbrian#include "lqr.h" 6836285Sbrian#include "hdlc.h" 6946686Sbrian#include "lcp.h" 7036285Sbrian#include "throughput.h" 7146686Sbrian#include "sync.h" 7236285Sbrian#include "async.h" 7346686Sbrian#include "iplist.h" 7446686Sbrian#include "slcompress.h" 7581634Sbrian#include "ncpaddr.h" 7646686Sbrian#include "ipcp.h" 7746686Sbrian#include "filter.h" 7846686Sbrian#include "descriptor.h" 7936285Sbrian#include "ccp.h" 8036285Sbrian#include "link.h" 8136285Sbrian#include "physical.h" 8246686Sbrian#include "mp.h" 8346686Sbrian#ifndef NORADIUS 8446686Sbrian#include "radius.h" 8546686Sbrian#endif 8681634Sbrian#include "ipv6cp.h" 8781634Sbrian#include "ncp.h" 8846686Sbrian#include "bundle.h" 8946686Sbrian#include "prompt.h" 9046686Sbrian#include "chat.h" 9146686Sbrian#include "auth.h" 92136375Sbrian#include "main.h" 9346686Sbrian#include "chap.h" 9446686Sbrian#include "cbcp.h" 9546686Sbrian#include "datalink.h" 9646686Sbrian#include "tcp.h" 9747061Sbrian#include "udp.h" 9846686Sbrian#include "exec.h" 9946686Sbrian#include "tty.h" 10052942Sbrian#ifndef NONETGRAPH 10152942Sbrian#include "ether.h" 10293418Sbrian#include "netgraph.h" 10352942Sbrian#endif 10465862Sbrian#ifndef NOATM 10565862Sbrian#include "atm.h" 10665862Sbrian#endif 10769303Sbrian#include "tcpmss.h" 10836285Sbrian 10952429Sbrian#define PPPOTCPLINE "ppp" 11052429Sbrian 11158028Sbrianstatic int physical_DescriptorWrite(struct fdescriptor *, struct bundle *, 11246686Sbrian const fd_set *); 11336285Sbrian 114134789Sbrianstatic unsigned 11547769Sbrianphysical_DeviceSize(void) 11647769Sbrian{ 11747769Sbrian return sizeof(struct device); 11847769Sbrian} 11947769Sbrian 12047061Sbrianstruct { 12147061Sbrian struct device *(*create)(struct physical *); 12252942Sbrian struct device *(*iov2device)(int, struct physical *, struct iovec *, 12352942Sbrian int *, int, int *, int *); 124134789Sbrian unsigned (*DeviceSize)(void); 12547061Sbrian} devices[] = { 12647769Sbrian { tty_Create, tty_iov2device, tty_DeviceSize }, 12752942Sbrian#ifndef NONETGRAPH 12871006Sbrian /* 12971006Sbrian * This must come before ``udp'' so that the probe routine is 13071006Sbrian * able to identify it as a more specific type of SOCK_DGRAM. 13171006Sbrian */ 13252942Sbrian { ether_Create, ether_iov2device, ether_DeviceSize }, 13393418Sbrian#ifdef EXPERIMENTAL_NETGRAPH 13493418Sbrian { ng_Create, ng_iov2device, ng_DeviceSize }, 13552942Sbrian#endif 13693418Sbrian#endif 13765862Sbrian#ifndef NOATM 13871006Sbrian /* Ditto for ATM devices */ 13965862Sbrian { atm_Create, atm_iov2device, atm_DeviceSize }, 14065862Sbrian#endif 14147769Sbrian { tcp_Create, tcp_iov2device, tcp_DeviceSize }, 14247769Sbrian { udp_Create, udp_iov2device, udp_DeviceSize }, 14347769Sbrian { exec_Create, exec_iov2device, exec_DeviceSize } 14446686Sbrian}; 14546686Sbrian 14647061Sbrian#define NDEVICES (sizeof devices / sizeof devices[0]) 14746686Sbrian 14846686Sbrianstatic int 14958028Sbrianphysical_UpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w, fd_set *e, 15046686Sbrian int *n) 15146686Sbrian{ 15246686Sbrian return physical_doUpdateSet(d, r, w, e, n, 0); 15346686Sbrian} 15446686Sbrian 15552942Sbrianvoid 15652942Sbrianphysical_SetDescriptor(struct physical *p) 15752942Sbrian{ 15852942Sbrian p->desc.type = PHYSICAL_DESCRIPTOR; 15952942Sbrian p->desc.UpdateSet = physical_UpdateSet; 16052942Sbrian p->desc.IsSet = physical_IsSet; 16152942Sbrian p->desc.Read = physical_DescriptorRead; 16252942Sbrian p->desc.Write = physical_DescriptorWrite; 16352942Sbrian} 16452942Sbrian 16546686Sbrianstruct physical * 16646686Sbrianphysical_Create(struct datalink *dl, int type) 16746686Sbrian{ 16846686Sbrian struct physical *p; 16946686Sbrian 17046686Sbrian p = (struct physical *)malloc(sizeof(struct physical)); 17146686Sbrian if (!p) 17246686Sbrian return NULL; 17346686Sbrian 17446686Sbrian p->link.type = PHYSICAL_LINK; 17546686Sbrian p->link.name = dl->name; 17646686Sbrian p->link.len = sizeof *p; 17746686Sbrian 17849434Sbrian /* The sample period is fixed - see physical2iov() & iov2physical() */ 17964652Sbrian throughput_init(&p->link.stats.total, SAMPLE_PERIOD); 18064652Sbrian p->link.stats.parent = dl->bundle->ncp.mp.active ? 18164652Sbrian &dl->bundle->ncp.mp.link.stats.total : NULL; 18264652Sbrian p->link.stats.gather = 1; 18349434Sbrian 18446686Sbrian memset(p->link.Queue, '\0', sizeof p->link.Queue); 18546686Sbrian memset(p->link.proto_in, '\0', sizeof p->link.proto_in); 18646686Sbrian memset(p->link.proto_out, '\0', sizeof p->link.proto_out); 18746686Sbrian link_EmptyStack(&p->link); 18846686Sbrian 18946686Sbrian p->handler = NULL; 19052942Sbrian physical_SetDescriptor(p); 19146686Sbrian p->type = type; 19246686Sbrian 19346686Sbrian hdlc_Init(&p->hdlc, &p->link.lcp); 19446686Sbrian async_Init(&p->async); 19546686Sbrian 19646686Sbrian p->fd = -1; 19746686Sbrian p->out = NULL; 19846686Sbrian p->connect_count = 0; 19946686Sbrian p->dl = dl; 20046686Sbrian p->input.sz = 0; 20146686Sbrian *p->name.full = '\0'; 20246686Sbrian p->name.base = p->name.full; 20346686Sbrian 20446686Sbrian p->Utmp = 0; 20546686Sbrian p->session_owner = (pid_t)-1; 20646686Sbrian 20746686Sbrian p->cfg.rts_cts = MODEM_CTSRTS; 20846686Sbrian p->cfg.speed = MODEM_SPEED; 20946686Sbrian p->cfg.parity = CS8; 21046686Sbrian memcpy(p->cfg.devlist, MODEM_LIST, sizeof MODEM_LIST); 21146686Sbrian p->cfg.ndev = NMODEMS; 21253733Sbrian p->cfg.cd.necessity = CD_DEFAULT; 21353733Sbrian p->cfg.cd.delay = 0; /* reconfigured or device specific default */ 21446686Sbrian 21546686Sbrian lcp_Init(&p->link.lcp, dl->bundle, &p->link, &dl->fsmp); 21646686Sbrian ccp_Init(&p->link.ccp, dl->bundle, &p->link, &dl->fsmp); 21746686Sbrian 21846686Sbrian return p; 21946686Sbrian} 22046686Sbrian 22146686Sbrianstatic const struct parity { 22246686Sbrian const char *name; 22346686Sbrian const char *name1; 22446686Sbrian int set; 22546686Sbrian} validparity[] = { 22646686Sbrian { "even", "P_EVEN", CS7 | PARENB }, 22746686Sbrian { "odd", "P_ODD", CS7 | PARENB | PARODD }, 22846686Sbrian { "none", "P_ZERO", CS8 }, 229134789Sbrian { NULL, NULL, 0 }, 23046686Sbrian}; 23146686Sbrian 23246686Sbrianstatic int 23346686SbrianGetParityValue(const char *str) 23446686Sbrian{ 23546686Sbrian const struct parity *pp; 23646686Sbrian 23746686Sbrian for (pp = validparity; pp->name; pp++) { 23846686Sbrian if (strcasecmp(pp->name, str) == 0 || 23946686Sbrian strcasecmp(pp->name1, str) == 0) { 24046686Sbrian return pp->set; 24146686Sbrian } 24246686Sbrian } 24346686Sbrian return (-1); 24446686Sbrian} 24546686Sbrian 24636285Sbrianint 24746686Sbrianphysical_SetParity(struct physical *p, const char *str) 24846686Sbrian{ 24946686Sbrian struct termios rstio; 25046686Sbrian int val; 25146686Sbrian 25246686Sbrian val = GetParityValue(str); 25346686Sbrian if (val > 0) { 25446686Sbrian p->cfg.parity = val; 25546686Sbrian if (p->fd >= 0) { 25646686Sbrian tcgetattr(p->fd, &rstio); 25746686Sbrian rstio.c_cflag &= ~(CSIZE | PARODD | PARENB); 25846686Sbrian rstio.c_cflag |= val; 25946686Sbrian tcsetattr(p->fd, TCSADRAIN, &rstio); 26046686Sbrian } 26146686Sbrian return 0; 26246686Sbrian } 26346686Sbrian log_Printf(LogWARN, "%s: %s: Invalid parity\n", p->link.name, str); 26446686Sbrian return -1; 26536285Sbrian} 26636285Sbrian 267134789Sbrianunsigned 26846686Sbrianphysical_GetSpeed(struct physical *p) 26946686Sbrian{ 27046686Sbrian if (p->handler && p->handler->speed) 27146686Sbrian return (*p->handler->speed)(p); 27246686Sbrian 27349434Sbrian return 0; 27436285Sbrian} 27536285Sbrian 27646686Sbrianint 277134789Sbrianphysical_SetSpeed(struct physical *p, unsigned speed) 27836285Sbrian{ 279134789Sbrian if (UnsignedToSpeed(speed) != B0) { 28046686Sbrian p->cfg.speed = speed; 28146686Sbrian return 1; 28246686Sbrian } 28346686Sbrian 28446686Sbrian return 0; 28536285Sbrian} 28636285Sbrian 28746686Sbrianint 28846686Sbrianphysical_Raw(struct physical *p) 28946686Sbrian{ 29046686Sbrian if (p->handler && p->handler->raw) 29146686Sbrian return (*p->handler->raw)(p); 29246686Sbrian 29346686Sbrian return 1; 29446686Sbrian} 29546686Sbrian 29636285Sbrianvoid 29746686Sbrianphysical_Offline(struct physical *p) 29846686Sbrian{ 29946686Sbrian if (p->handler && p->handler->offline) 30046686Sbrian (*p->handler->offline)(p); 30146686Sbrian log_Printf(LogPHASE, "%s: Disconnected!\n", p->link.name); 30246686Sbrian} 30346686Sbrian 30447286Sbrianstatic int 30547286Sbrianphysical_Lock(struct physical *p) 30646686Sbrian{ 30747286Sbrian int res; 30846686Sbrian 30947286Sbrian if (*p->name.full == '/' && p->type != PHYS_DIRECT && 31047286Sbrian (res = ID0uu_lock(p->name.base)) != UU_LOCK_OK) { 31147286Sbrian if (res == UU_LOCK_INUSE) 31247286Sbrian log_Printf(LogPHASE, "%s: %s is in use\n", p->link.name, p->name.full); 31347286Sbrian else 31447286Sbrian log_Printf(LogPHASE, "%s: %s is in use: uu_lock: %s\n", 31547286Sbrian p->link.name, p->name.full, uu_lockerr(res)); 31647286Sbrian return 0; 31746686Sbrian } 31847286Sbrian 31947286Sbrian return 1; 32046686Sbrian} 32146686Sbrian 32247286Sbrianstatic void 32347286Sbrianphysical_Unlock(struct physical *p) 32447286Sbrian{ 32547286Sbrian if (*p->name.full == '/' && p->type != PHYS_DIRECT && 32647286Sbrian ID0uu_unlock(p->name.base) == -1) 32774001Sbrian log_Printf(LogALERT, "%s: Can't uu_unlock %s\n", p->link.name, 32874001Sbrian p->name.base); 32947286Sbrian} 33047286Sbrian 33146686Sbrianvoid 33246686Sbrianphysical_Close(struct physical *p) 33346686Sbrian{ 33447286Sbrian int newsid; 33574001Sbrian char fn[PATH_MAX]; 33647286Sbrian 33746686Sbrian if (p->fd < 0) 33846686Sbrian return; 33946686Sbrian 34046686Sbrian log_Printf(LogDEBUG, "%s: Close\n", p->link.name); 34146686Sbrian 34246686Sbrian if (p->handler && p->handler->cooked) 34346686Sbrian (*p->handler->cooked)(p); 34446686Sbrian 34547286Sbrian physical_StopDeviceTimer(p); 34647286Sbrian if (p->Utmp) { 34752429Sbrian if (p->handler && (p->handler->type == TCP_DEVICE || 34852487Sbrian p->handler->type == UDP_DEVICE)) 34952487Sbrian /* Careful - we logged in on line ``ppp'' with IP as our host */ 35052487Sbrian ID0logout(PPPOTCPLINE, 1); 35152487Sbrian else 35252487Sbrian ID0logout(p->name.base, 0); 35347286Sbrian p->Utmp = 0; 35447286Sbrian } 35547286Sbrian newsid = tcgetpgrp(p->fd) == getpgrp(); 35647286Sbrian close(p->fd); 35747286Sbrian p->fd = -1; 35847286Sbrian log_SetTtyCommandMode(p->dl); 35947286Sbrian 36064652Sbrian throughput_stop(&p->link.stats.total); 36164652Sbrian throughput_log(&p->link.stats.total, LogPHASE, p->link.name); 36247286Sbrian 36347286Sbrian if (p->session_owner != (pid_t)-1) { 36497360Sbrian log_Printf(LogPHASE, "%s: HUPing %ld\n", p->link.name, 36597360Sbrian (long)p->session_owner); 36647286Sbrian ID0kill(p->session_owner, SIGHUP); 36747286Sbrian p->session_owner = (pid_t)-1; 36847286Sbrian } 36947286Sbrian 37047286Sbrian if (newsid) 37147286Sbrian bundle_setsid(p->dl->bundle, 0); 37247286Sbrian 37347286Sbrian if (*p->name.full == '/') { 37447286Sbrian snprintf(fn, sizeof fn, "%s%s.if", _PATH_VARRUN, p->name.base); 37547286Sbrian#ifndef RELEASE_CRUNCH 37647286Sbrian if (ID0unlink(fn) == -1) 37747286Sbrian log_Printf(LogALERT, "%s: Can't remove %s: %s\n", 37847286Sbrian p->link.name, fn, strerror(errno)); 37947286Sbrian#else 38047286Sbrian ID0unlink(fn); 38147286Sbrian#endif 38247286Sbrian } 38347286Sbrian physical_Unlock(p); 38447286Sbrian if (p->handler && p->handler->destroy) 38547286Sbrian (*p->handler->destroy)(p); 38647286Sbrian p->handler = NULL; 38747286Sbrian p->name.base = p->name.full; 38847286Sbrian *p->name.full = '\0'; 38946686Sbrian} 39046686Sbrian 39146686Sbrianvoid 39246686Sbrianphysical_Destroy(struct physical *p) 39346686Sbrian{ 39446686Sbrian physical_Close(p); 39564652Sbrian throughput_destroy(&p->link.stats.total); 39646686Sbrian free(p); 39746686Sbrian} 39846686Sbrian 39946686Sbrianstatic int 400134789Sbrianphysical_DescriptorWrite(struct fdescriptor *d, struct bundle *bundle __unused, 401134789Sbrian const fd_set *fdset __unused) 40246686Sbrian{ 40346686Sbrian struct physical *p = descriptor2physical(d); 40446686Sbrian int nw, result = 0; 40546686Sbrian 40646686Sbrian if (p->out == NULL) 40746686Sbrian p->out = link_Dequeue(&p->link); 40846686Sbrian 40946686Sbrian if (p->out) { 41054912Sbrian nw = physical_Write(p, MBUF_CTOP(p->out), p->out->m_len); 41158042Sbrian log_Printf(LogDEBUG, "%s: DescriptorWrite: wrote %d(%lu) to %d\n", 41258042Sbrian p->link.name, nw, (unsigned long)p->out->m_len, p->fd); 41346686Sbrian if (nw > 0) { 41454912Sbrian p->out->m_len -= nw; 41554912Sbrian p->out->m_offset += nw; 41654912Sbrian if (p->out->m_len == 0) 41754912Sbrian p->out = m_free(p->out); 41846686Sbrian result = 1; 41946686Sbrian } else if (nw < 0) { 42066900Sbrian if (errno == EAGAIN) 42166900Sbrian result = 1; 42266900Sbrian else if (errno != ENOBUFS) { 423134833Smarcel log_Printf(LogPHASE, "%s: write (fd %d, len %zd): %s\n", p->link.name, 424132423Sbrian p->fd, p->out->m_len, strerror(errno)); 42546686Sbrian datalink_Down(p->dl, CLOSE_NORMAL); 42646686Sbrian } 42746686Sbrian } 42846686Sbrian /* else we shouldn't really have been called ! select() is broken ! */ 42946686Sbrian } 43046686Sbrian 43146686Sbrian return result; 43246686Sbrian} 43346686Sbrian 43446686Sbrianint 43546686Sbrianphysical_ShowStatus(struct cmdargs const *arg) 43646686Sbrian{ 43746686Sbrian struct physical *p = arg->cx->physical; 43853733Sbrian struct cd *cd; 43946686Sbrian const char *dev; 44099097Sbrian int n, slot; 44146686Sbrian 44246686Sbrian prompt_Printf(arg->prompt, "Name: %s\n", p->link.name); 44346686Sbrian prompt_Printf(arg->prompt, " State: "); 44446686Sbrian if (p->fd < 0) 44546686Sbrian prompt_Printf(arg->prompt, "closed\n"); 44699097Sbrian else { 44799097Sbrian slot = physical_Slot(p); 44899097Sbrian if (p->handler && p->handler->openinfo) { 44999097Sbrian if (slot == -1) 45099097Sbrian prompt_Printf(arg->prompt, "open (%s)\n", (*p->handler->openinfo)(p)); 45199097Sbrian else 45299097Sbrian prompt_Printf(arg->prompt, "open (%s, port %d)\n", 45399097Sbrian (*p->handler->openinfo)(p), slot); 45499097Sbrian } else if (slot == -1) 45599097Sbrian prompt_Printf(arg->prompt, "open\n"); 45699097Sbrian else 45799097Sbrian prompt_Printf(arg->prompt, "open (port %d)\n", slot); 45899097Sbrian } 45946686Sbrian 46046686Sbrian prompt_Printf(arg->prompt, " Device: %s", 46146686Sbrian *p->name.full ? p->name.full : 46246686Sbrian p->type == PHYS_DIRECT ? "unknown" : "N/A"); 46346686Sbrian if (p->session_owner != (pid_t)-1) 46497360Sbrian prompt_Printf(arg->prompt, " (session owner: %ld)", (long)p->session_owner); 46546686Sbrian 46646686Sbrian prompt_Printf(arg->prompt, "\n Link Type: %s\n", mode2Nam(p->type)); 46746686Sbrian prompt_Printf(arg->prompt, " Connect Count: %d\n", p->connect_count); 46846686Sbrian#ifdef TIOCOUTQ 46946686Sbrian if (p->fd >= 0 && ioctl(p->fd, TIOCOUTQ, &n) >= 0) 47046686Sbrian prompt_Printf(arg->prompt, " Physical outq: %d\n", n); 47146686Sbrian#endif 47246686Sbrian 47354912Sbrian prompt_Printf(arg->prompt, " Queued Packets: %lu\n", 47454912Sbrian (u_long)link_QueueLen(&p->link)); 47546686Sbrian prompt_Printf(arg->prompt, " Phone Number: %s\n", arg->cx->phone.chosen); 47646686Sbrian 47746686Sbrian prompt_Printf(arg->prompt, "\nDefaults:\n"); 47846686Sbrian 47946686Sbrian prompt_Printf(arg->prompt, " Device List: "); 48046686Sbrian dev = p->cfg.devlist; 48146686Sbrian for (n = 0; n < p->cfg.ndev; n++) { 48246686Sbrian if (n) 48346686Sbrian prompt_Printf(arg->prompt, ", "); 48446686Sbrian prompt_Printf(arg->prompt, "\"%s\"", dev); 48546686Sbrian dev += strlen(dev) + 1; 48646686Sbrian } 48798243Sbrian 48846686Sbrian prompt_Printf(arg->prompt, "\n Characteristics: "); 48946686Sbrian if (physical_IsSync(arg->cx->physical)) 49046686Sbrian prompt_Printf(arg->prompt, "sync"); 49146686Sbrian else 49246686Sbrian prompt_Printf(arg->prompt, "%dbps", p->cfg.speed); 49346686Sbrian 49446686Sbrian switch (p->cfg.parity & CSIZE) { 49546686Sbrian case CS7: 49646686Sbrian prompt_Printf(arg->prompt, ", cs7"); 49746686Sbrian break; 49846686Sbrian case CS8: 49946686Sbrian prompt_Printf(arg->prompt, ", cs8"); 50046686Sbrian break; 50146686Sbrian } 50246686Sbrian if (p->cfg.parity & PARENB) { 50346686Sbrian if (p->cfg.parity & PARODD) 50446686Sbrian prompt_Printf(arg->prompt, ", odd parity"); 50546686Sbrian else 50646686Sbrian prompt_Printf(arg->prompt, ", even parity"); 50746686Sbrian } else 50846686Sbrian prompt_Printf(arg->prompt, ", no parity"); 50946686Sbrian 51046686Sbrian prompt_Printf(arg->prompt, ", CTS/RTS %s\n", (p->cfg.rts_cts ? "on" : "off")); 51146686Sbrian 51251699Sbrian prompt_Printf(arg->prompt, " CD check delay: "); 51353733Sbrian cd = p->handler ? &p->handler->cd : &p->cfg.cd; 51453733Sbrian if (cd->necessity == CD_NOTREQUIRED) 51551699Sbrian prompt_Printf(arg->prompt, "no cd"); 51653733Sbrian else if (p->cfg.cd.necessity == CD_DEFAULT) { 51753733Sbrian prompt_Printf(arg->prompt, "device specific"); 51853733Sbrian } else { 51951699Sbrian prompt_Printf(arg->prompt, "%d second%s", p->cfg.cd.delay, 52051699Sbrian p->cfg.cd.delay == 1 ? "" : "s"); 52151699Sbrian if (p->cfg.cd.necessity == CD_REQUIRED) 52251699Sbrian prompt_Printf(arg->prompt, " (required!)"); 52351699Sbrian } 52451699Sbrian prompt_Printf(arg->prompt, "\n\n"); 52546686Sbrian 52664652Sbrian throughput_disp(&p->link.stats.total, arg->prompt); 52746686Sbrian 52846686Sbrian return 0; 52946686Sbrian} 53046686Sbrian 53152942Sbrianvoid 53258028Sbrianphysical_DescriptorRead(struct fdescriptor *d, struct bundle *bundle, 533134789Sbrian const fd_set *fdset __unused) 53446686Sbrian{ 53546686Sbrian struct physical *p = descriptor2physical(d); 53646686Sbrian u_char *rbuff; 53746686Sbrian int n, found; 53846686Sbrian 53946686Sbrian rbuff = p->input.buf + p->input.sz; 54046686Sbrian 54146686Sbrian /* something to read */ 54246686Sbrian n = physical_Read(p, rbuff, sizeof p->input.buf - p->input.sz); 54346686Sbrian log_Printf(LogDEBUG, "%s: DescriptorRead: read %d/%d from %d\n", 54446686Sbrian p->link.name, n, (int)(sizeof p->input.buf - p->input.sz), p->fd); 54546686Sbrian if (n <= 0) { 54646686Sbrian if (n < 0) 54746686Sbrian log_Printf(LogPHASE, "%s: read (%d): %s\n", p->link.name, p->fd, 54846686Sbrian strerror(errno)); 54946686Sbrian else 55046686Sbrian log_Printf(LogPHASE, "%s: read (%d): Got zero bytes\n", 55146686Sbrian p->link.name, p->fd); 55246686Sbrian datalink_Down(p->dl, CLOSE_NORMAL); 55346686Sbrian return; 55446686Sbrian } 55546686Sbrian 55646686Sbrian rbuff -= p->input.sz; 55746686Sbrian n += p->input.sz; 55846686Sbrian 55946686Sbrian if (p->link.lcp.fsm.state <= ST_CLOSED) { 56046686Sbrian if (p->type != PHYS_DEDICATED) { 56146686Sbrian found = hdlc_Detect((u_char const **)&rbuff, n, physical_IsSync(p)); 56246686Sbrian if (rbuff != p->input.buf) 56346686Sbrian log_WritePrompts(p->dl, "%.*s", (int)(rbuff - p->input.buf), 56446686Sbrian p->input.buf); 56546686Sbrian p->input.sz = n - (rbuff - p->input.buf); 56646686Sbrian 56746686Sbrian if (found) { 56846686Sbrian /* LCP packet is detected. Turn ourselves into packet mode */ 56946686Sbrian log_Printf(LogPHASE, "%s: PPP packet detected, coming up\n", 57046686Sbrian p->link.name); 57146686Sbrian log_SetTtyCommandMode(p->dl); 57246686Sbrian datalink_Up(p->dl, 0, 1); 57346686Sbrian link_PullPacket(&p->link, rbuff, p->input.sz, bundle); 57446686Sbrian p->input.sz = 0; 57546686Sbrian } else 57646686Sbrian bcopy(rbuff, p->input.buf, p->input.sz); 57746686Sbrian } else 57846686Sbrian /* In -dedicated mode, we just discard input until LCP is started */ 57946686Sbrian p->input.sz = 0; 58046686Sbrian } else if (n > 0) 58146686Sbrian link_PullPacket(&p->link, rbuff, n, bundle); 58246686Sbrian} 58346686Sbrian 58446686Sbrianstruct physical * 58546686Sbrianiov2physical(struct datalink *dl, struct iovec *iov, int *niov, int maxiov, 58652942Sbrian int fd, int *auxfd, int *nauxfd) 58746686Sbrian{ 58846686Sbrian struct physical *p; 589134789Sbrian int len, type; 590134789Sbrian unsigned h; 59146686Sbrian 59246686Sbrian p = (struct physical *)iov[(*niov)++].iov_base; 59346686Sbrian p->link.name = dl->name; 59446686Sbrian memset(p->link.Queue, '\0', sizeof p->link.Queue); 59546686Sbrian 59646686Sbrian p->desc.UpdateSet = physical_UpdateSet; 59746686Sbrian p->desc.IsSet = physical_IsSet; 59846686Sbrian p->desc.Read = physical_DescriptorRead; 59946686Sbrian p->desc.Write = physical_DescriptorWrite; 60046686Sbrian p->type = PHYS_DIRECT; 60146686Sbrian p->dl = dl; 60246686Sbrian len = strlen(_PATH_DEV); 60346686Sbrian p->out = NULL; 60446686Sbrian p->connect_count = 1; 60546686Sbrian 60647682Sbrian physical_SetDevice(p, p->name.full); 60747682Sbrian 60846686Sbrian p->link.lcp.fsm.bundle = dl->bundle; 60946686Sbrian p->link.lcp.fsm.link = &p->link; 61046686Sbrian memset(&p->link.lcp.fsm.FsmTimer, '\0', sizeof p->link.lcp.fsm.FsmTimer); 61146686Sbrian memset(&p->link.lcp.fsm.OpenTimer, '\0', sizeof p->link.lcp.fsm.OpenTimer); 61246686Sbrian memset(&p->link.lcp.fsm.StoppedTimer, '\0', 61346686Sbrian sizeof p->link.lcp.fsm.StoppedTimer); 61446686Sbrian p->link.lcp.fsm.parent = &dl->fsmp; 61546686Sbrian lcp_SetupCallbacks(&p->link.lcp); 61646686Sbrian 61746686Sbrian p->link.ccp.fsm.bundle = dl->bundle; 61846686Sbrian p->link.ccp.fsm.link = &p->link; 61946686Sbrian /* Our in.state & out.state are NULL (no link-level ccp yet) */ 62046686Sbrian memset(&p->link.ccp.fsm.FsmTimer, '\0', sizeof p->link.ccp.fsm.FsmTimer); 62146686Sbrian memset(&p->link.ccp.fsm.OpenTimer, '\0', sizeof p->link.ccp.fsm.OpenTimer); 62246686Sbrian memset(&p->link.ccp.fsm.StoppedTimer, '\0', 62346686Sbrian sizeof p->link.ccp.fsm.StoppedTimer); 62446686Sbrian p->link.ccp.fsm.parent = &dl->fsmp; 62546686Sbrian ccp_SetupCallbacks(&p->link.ccp); 62646686Sbrian 62746686Sbrian p->hdlc.lqm.owner = &p->link.lcp; 62846686Sbrian p->hdlc.ReportTimer.state = TIMER_STOPPED; 62946686Sbrian p->hdlc.lqm.timer.state = TIMER_STOPPED; 63046686Sbrian 63146686Sbrian p->fd = fd; 63264670Sbrian p->link.stats.total.in.SampleOctets = (long long *)iov[(*niov)++].iov_base; 63364670Sbrian p->link.stats.total.out.SampleOctets = (long long *)iov[(*niov)++].iov_base; 63464652Sbrian p->link.stats.parent = dl->bundle->ncp.mp.active ? 63564652Sbrian &dl->bundle->ncp.mp.link.stats.total : NULL; 63664652Sbrian p->link.stats.gather = 1; 63746686Sbrian 63847769Sbrian type = (long)p->handler; 63947769Sbrian p->handler = NULL; 64047769Sbrian for (h = 0; h < NDEVICES && p->handler == NULL; h++) 64152942Sbrian p->handler = (*devices[h].iov2device)(type, p, iov, niov, maxiov, 64252942Sbrian auxfd, nauxfd); 64347769Sbrian if (p->handler == NULL) { 64452942Sbrian log_Printf(LogPHASE, "%s: Unknown link type\n", p->link.name); 64547769Sbrian free(iov[(*niov)++].iov_base); 64647769Sbrian physical_SetupStack(p, "unknown", PHYSICAL_NOFORCE); 64747769Sbrian } else 64847769Sbrian log_Printf(LogPHASE, "%s: Device %s, link type is %s\n", 64947769Sbrian p->link.name, p->name.full, p->handler->name); 65047769Sbrian 65146686Sbrian if (p->hdlc.lqm.method && p->hdlc.lqm.timer.load) 65246686Sbrian lqr_reStart(&p->link.lcp); 65346686Sbrian hdlc_StartTimer(&p->hdlc); 65446686Sbrian 65564652Sbrian throughput_restart(&p->link.stats.total, "physical throughput", 65649434Sbrian Enabled(dl->bundle, OPT_THROUGHPUT)); 65746686Sbrian 65847769Sbrian return p; 65947769Sbrian} 66047061Sbrian 661134789Sbrianunsigned 66247769Sbrianphysical_MaxDeviceSize() 66347769Sbrian{ 664134789Sbrian unsigned biggest, sz, n; 66547061Sbrian 66647769Sbrian biggest = sizeof(struct device); 667134789Sbrian for (n = 0; n < NDEVICES; n++) 66847769Sbrian if (devices[n].DeviceSize) { 66947769Sbrian sz = (*devices[n].DeviceSize)(); 67047769Sbrian if (biggest < sz) 67147769Sbrian biggest = sz; 67247769Sbrian } 67347769Sbrian 67447769Sbrian return biggest; 67546686Sbrian} 67646686Sbrian 67746686Sbrianint 67846686Sbrianphysical2iov(struct physical *p, struct iovec *iov, int *niov, int maxiov, 67953684Sbrian int *auxfd, int *nauxfd) 68046686Sbrian{ 68147769Sbrian struct device *h; 68247769Sbrian int sz; 68347769Sbrian 68447769Sbrian h = NULL; 68546686Sbrian if (p) { 68646686Sbrian hdlc_StopTimer(&p->hdlc); 68746686Sbrian lqr_StopTimer(p); 68846686Sbrian timer_Stop(&p->link.lcp.fsm.FsmTimer); 68946686Sbrian timer_Stop(&p->link.ccp.fsm.FsmTimer); 69046686Sbrian timer_Stop(&p->link.lcp.fsm.OpenTimer); 69146686Sbrian timer_Stop(&p->link.ccp.fsm.OpenTimer); 69246686Sbrian timer_Stop(&p->link.lcp.fsm.StoppedTimer); 69346686Sbrian timer_Stop(&p->link.ccp.fsm.StoppedTimer); 69447061Sbrian if (p->handler) { 69553684Sbrian h = p->handler; 69647061Sbrian p->handler = (struct device *)(long)p->handler->type; 69746686Sbrian } 69847061Sbrian 69947689Sbrian if (Enabled(p->dl->bundle, OPT_KEEPSESSION) || 70047689Sbrian tcgetpgrp(p->fd) == getpgrp()) 70146686Sbrian p->session_owner = getpid(); /* So I'll eventually get HUP'd */ 70247689Sbrian else 70347689Sbrian p->session_owner = (pid_t)-1; 70464652Sbrian timer_Stop(&p->link.stats.total.Timer); 70546686Sbrian } 70646686Sbrian 70749434Sbrian if (*niov + 2 >= maxiov) { 70849434Sbrian log_Printf(LogERROR, "physical2iov: No room for physical + throughput" 70949434Sbrian " + device !\n"); 71046686Sbrian if (p) 71146686Sbrian free(p); 71246686Sbrian return -1; 71346686Sbrian } 71446686Sbrian 71553684Sbrian iov[*niov].iov_base = (void *)p; 71646686Sbrian iov[*niov].iov_len = sizeof *p; 71746686Sbrian (*niov)++; 71846686Sbrian 71964670Sbrian iov[*niov].iov_base = p ? (void *)p->link.stats.total.in.SampleOctets : NULL; 72049434Sbrian iov[*niov].iov_len = SAMPLE_PERIOD * sizeof(long long); 72149434Sbrian (*niov)++; 72264670Sbrian iov[*niov].iov_base = p ? (void *)p->link.stats.total.out.SampleOctets : NULL; 72364670Sbrian iov[*niov].iov_len = SAMPLE_PERIOD * sizeof(long long); 72464670Sbrian (*niov)++; 72549434Sbrian 72647769Sbrian sz = physical_MaxDeviceSize(); 72747769Sbrian if (p) { 72853684Sbrian if (h && h->device2iov) 72953684Sbrian (*h->device2iov)(h, iov, niov, maxiov, auxfd, nauxfd); 73047769Sbrian else { 731136375Sbrian if ((iov[*niov].iov_base = malloc(sz)) == NULL) { 732136375Sbrian log_Printf(LogALERT, "physical2iov: Out of memory (%d bytes)\n", sz); 733136375Sbrian AbortProgram(EX_OSERR); 734136375Sbrian } 73553684Sbrian if (h) 73653684Sbrian memcpy(iov[*niov].iov_base, h, sizeof *h); 73747769Sbrian iov[*niov].iov_len = sz; 73847769Sbrian (*niov)++; 73947769Sbrian } 74047769Sbrian } else { 74153684Sbrian iov[*niov].iov_base = NULL; 74247769Sbrian iov[*niov].iov_len = sz; 74347769Sbrian (*niov)++; 74447769Sbrian } 74547769Sbrian 74646686Sbrian return p ? p->fd : 0; 74746686Sbrian} 74846686Sbrian 74953684Sbrianconst char * 75053684Sbrianphysical_LockedDevice(struct physical *p) 75153684Sbrian{ 75253684Sbrian if (p->fd >= 0 && *p->name.full == '/' && p->type != PHYS_DIRECT) 75353684Sbrian return p->name.base; 75453684Sbrian 75553684Sbrian return NULL; 75653684Sbrian} 75753684Sbrian 75846686Sbrianvoid 75946686Sbrianphysical_ChangedPid(struct physical *p, pid_t newpid) 76046686Sbrian{ 76153684Sbrian if (physical_LockedDevice(p)) { 76246686Sbrian int res; 76346686Sbrian 76446686Sbrian if ((res = ID0uu_lock_txfr(p->name.base, newpid)) != UU_LOCK_OK) 76546686Sbrian log_Printf(LogPHASE, "uu_lock_txfr: %s\n", uu_lockerr(res)); 76646686Sbrian } 76746686Sbrian} 76846686Sbrian 76946686Sbrianint 77046686Sbrianphysical_IsSync(struct physical *p) 77146686Sbrian{ 77246686Sbrian return p->cfg.speed == 0; 77346686Sbrian} 77446686Sbrian 77578410Sbrianu_short 77678410Sbrianphysical_DeviceMTU(struct physical *p) 77778410Sbrian{ 77878410Sbrian return p->handler ? p->handler->mtu : 0; 77978410Sbrian} 78078410Sbrian 78146686Sbrianconst char *physical_GetDevice(struct physical *p) 78246686Sbrian{ 78346686Sbrian return p->name.full; 78446686Sbrian} 78546686Sbrian 78646686Sbrianvoid 78736285Sbrianphysical_SetDeviceList(struct physical *p, int argc, const char *const *argv) 78836285Sbrian{ 789134789Sbrian unsigned pos; 790134789Sbrian int f; 79136285Sbrian 79236285Sbrian p->cfg.devlist[sizeof p->cfg.devlist - 1] = '\0'; 79336285Sbrian for (f = 0, pos = 0; f < argc && pos < sizeof p->cfg.devlist - 1; f++) { 79436285Sbrian if (pos) 79546102Sbrian p->cfg.devlist[pos++] = '\0'; 79636285Sbrian strncpy(p->cfg.devlist + pos, argv[f], sizeof p->cfg.devlist - pos - 1); 79736285Sbrian pos += strlen(p->cfg.devlist + pos); 79836285Sbrian } 79946102Sbrian p->cfg.ndev = f; 80036285Sbrian} 80136285Sbrian 80236285Sbrianvoid 80346686Sbrianphysical_SetSync(struct physical *p) 80446686Sbrian{ 80546686Sbrian p->cfg.speed = 0; 80636285Sbrian} 80736285Sbrian 80836285Sbrianint 80946686Sbrianphysical_SetRtsCts(struct physical *p, int enable) 81046686Sbrian{ 81146686Sbrian p->cfg.rts_cts = enable ? 1 : 0; 81236285Sbrian return 1; 81336285Sbrian} 81436285Sbrian 81536285Sbrianssize_t 81646686Sbrianphysical_Read(struct physical *p, void *buf, size_t nbytes) 81746686Sbrian{ 81847061Sbrian ssize_t ret; 81947061Sbrian 82047061Sbrian if (p->handler && p->handler->read) 82147061Sbrian ret = (*p->handler->read)(p, buf, nbytes); 82247061Sbrian else 82347061Sbrian ret = read(p->fd, buf, nbytes); 82447061Sbrian 82547061Sbrian log_DumpBuff(LogPHYSICAL, "read", buf, ret); 82647061Sbrian 82747061Sbrian return ret; 82836285Sbrian} 82936285Sbrian 83036285Sbrianssize_t 83146686Sbrianphysical_Write(struct physical *p, const void *buf, size_t nbytes) 83246686Sbrian{ 83347061Sbrian log_DumpBuff(LogPHYSICAL, "write", buf, nbytes); 83447061Sbrian 83547061Sbrian if (p->handler && p->handler->write) 83647061Sbrian return (*p->handler->write)(p, buf, nbytes); 83747061Sbrian 83847061Sbrian return write(p->fd, buf, nbytes); 83936285Sbrian} 84036285Sbrian 84136285Sbrianint 84258028Sbrianphysical_doUpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w, fd_set *e, 84346686Sbrian int *n, int force) 84436285Sbrian{ 84536285Sbrian struct physical *p = descriptor2physical(d); 84636285Sbrian int sets; 84736285Sbrian 84836285Sbrian sets = 0; 84936285Sbrian if (p->fd >= 0) { 85036285Sbrian if (r) { 85136285Sbrian FD_SET(p->fd, r); 85236285Sbrian log_Printf(LogTIMER, "%s: fdset(r) %d\n", p->link.name, p->fd); 85336285Sbrian sets++; 85436285Sbrian } 85536285Sbrian if (e) { 85636285Sbrian FD_SET(p->fd, e); 85736285Sbrian log_Printf(LogTIMER, "%s: fdset(e) %d\n", p->link.name, p->fd); 85836285Sbrian sets++; 85936285Sbrian } 86036314Sbrian if (w && (force || link_QueueLen(&p->link) || p->out)) { 86136285Sbrian FD_SET(p->fd, w); 86236285Sbrian log_Printf(LogTIMER, "%s: fdset(w) %d\n", p->link.name, p->fd); 86336285Sbrian sets++; 86436285Sbrian } 86536285Sbrian if (sets && *n < p->fd + 1) 86636285Sbrian *n = p->fd + 1; 86736285Sbrian } 86836285Sbrian 86936285Sbrian return sets; 87036285Sbrian} 87136285Sbrian 87236285Sbrianint 87336285Sbrianphysical_RemoveFromSet(struct physical *p, fd_set *r, fd_set *w, fd_set *e) 87436285Sbrian{ 87552942Sbrian if (p->handler && p->handler->removefromset) 87652942Sbrian return (*p->handler->removefromset)(p, r, w, e); 87752942Sbrian else { 87852942Sbrian int sets; 87936285Sbrian 88052942Sbrian sets = 0; 88152942Sbrian if (p->fd >= 0) { 88252942Sbrian if (r && FD_ISSET(p->fd, r)) { 88352942Sbrian FD_CLR(p->fd, r); 88452942Sbrian log_Printf(LogTIMER, "%s: fdunset(r) %d\n", p->link.name, p->fd); 88552942Sbrian sets++; 88652942Sbrian } 88752942Sbrian if (e && FD_ISSET(p->fd, e)) { 88852942Sbrian FD_CLR(p->fd, e); 88952942Sbrian log_Printf(LogTIMER, "%s: fdunset(e) %d\n", p->link.name, p->fd); 89052942Sbrian sets++; 89152942Sbrian } 89252942Sbrian if (w && FD_ISSET(p->fd, w)) { 89352942Sbrian FD_CLR(p->fd, w); 89452942Sbrian log_Printf(LogTIMER, "%s: fdunset(w) %d\n", p->link.name, p->fd); 89552942Sbrian sets++; 89652942Sbrian } 89736285Sbrian } 89852942Sbrian 89952942Sbrian return sets; 90036285Sbrian } 90136285Sbrian} 90236285Sbrian 90336285Sbrianint 90458028Sbrianphysical_IsSet(struct fdescriptor *d, const fd_set *fdset) 90536285Sbrian{ 90636285Sbrian struct physical *p = descriptor2physical(d); 90736285Sbrian return p->fd >= 0 && FD_ISSET(p->fd, fdset); 90836285Sbrian} 90936285Sbrian 91036285Sbrianvoid 91146686Sbrianphysical_Login(struct physical *p, const char *name) 91236285Sbrian{ 91346830Sbrian if (p->type == PHYS_DIRECT && *p->name.base && !p->Utmp) { 91446686Sbrian struct utmp ut; 91546686Sbrian const char *connstr; 91652413Sbrian char *colon; 91736285Sbrian 91846686Sbrian memset(&ut, 0, sizeof ut); 919106966Speter ut.ut_time = time(NULL); 92046686Sbrian strncpy(ut.ut_name, name, sizeof ut.ut_name); 92152413Sbrian if (p->handler && (p->handler->type == TCP_DEVICE || 92252413Sbrian p->handler->type == UDP_DEVICE)) { 92352429Sbrian strncpy(ut.ut_line, PPPOTCPLINE, sizeof ut.ut_line); 92452413Sbrian strncpy(ut.ut_host, p->name.base, sizeof ut.ut_host); 92552413Sbrian colon = memchr(ut.ut_host, ':', sizeof ut.ut_host); 92652413Sbrian if (colon) 92752413Sbrian *colon = '\0'; 92852413Sbrian } else 92952413Sbrian strncpy(ut.ut_line, p->name.base, sizeof ut.ut_line); 93046686Sbrian if ((connstr = getenv("CONNECT"))) 93146686Sbrian /* mgetty sets this to the connection speed */ 93246686Sbrian strncpy(ut.ut_host, connstr, sizeof ut.ut_host); 93346686Sbrian ID0login(&ut); 93452429Sbrian p->Utmp = ut.ut_time; 93536285Sbrian } 93636285Sbrian} 93736285Sbrian 93836285Sbrianint 93936285Sbrianphysical_SetMode(struct physical *p, int mode) 94036285Sbrian{ 94138174Sbrian if ((p->type & (PHYS_DIRECT|PHYS_DEDICATED) || 94238174Sbrian mode & (PHYS_DIRECT|PHYS_DEDICATED)) && 94338174Sbrian (!(p->type & PHYS_DIRECT) || !(mode & PHYS_BACKGROUND))) { 94453830Sbrian /* Note: The -direct -> -background is for callback ! */ 94536285Sbrian log_Printf(LogWARN, "%s: Cannot change mode %s to %s\n", p->link.name, 94636285Sbrian mode2Nam(p->type), mode2Nam(mode)); 94736285Sbrian return 0; 94836285Sbrian } 94936285Sbrian p->type = mode; 95036285Sbrian return 1; 95136285Sbrian} 95238544Sbrian 95338544Sbrianvoid 95438544Sbrianphysical_DeleteQueue(struct physical *p) 95538544Sbrian{ 95638544Sbrian if (p->out) { 95754912Sbrian m_freem(p->out); 95838544Sbrian p->out = NULL; 95938544Sbrian } 96038544Sbrian link_DeleteQueue(&p->link); 96138544Sbrian} 96246686Sbrian 96346686Sbrianvoid 96446686Sbrianphysical_SetDevice(struct physical *p, const char *name) 96546686Sbrian{ 96646686Sbrian int len = strlen(_PATH_DEV); 96746686Sbrian 96847682Sbrian if (name != p->name.full) { 96947682Sbrian strncpy(p->name.full, name, sizeof p->name.full - 1); 97047682Sbrian p->name.full[sizeof p->name.full - 1] = '\0'; 97147682Sbrian } 97246686Sbrian p->name.base = *p->name.full == '!' ? p->name.full + 1 : 97346686Sbrian strncmp(p->name.full, _PATH_DEV, len) ? 97446686Sbrian p->name.full : p->name.full + len; 97546686Sbrian} 97646686Sbrian 97746686Sbrianstatic void 97846686Sbrianphysical_Found(struct physical *p) 97946686Sbrian{ 98047286Sbrian FILE *lockfile; 98174001Sbrian char fn[PATH_MAX]; 98247286Sbrian 98347286Sbrian if (*p->name.full == '/') { 98447286Sbrian snprintf(fn, sizeof fn, "%s%s.if", _PATH_VARRUN, p->name.base); 98547286Sbrian lockfile = ID0fopen(fn, "w"); 98647286Sbrian if (lockfile != NULL) { 98747286Sbrian fprintf(lockfile, "%s%d\n", TUN_NAME, p->dl->bundle->unit); 98847286Sbrian fclose(lockfile); 98947286Sbrian } 99047286Sbrian#ifndef RELEASE_CRUNCH 99147286Sbrian else 99247286Sbrian log_Printf(LogALERT, "%s: Can't create %s: %s\n", 99347286Sbrian p->link.name, fn, strerror(errno)); 99447286Sbrian#endif 99547286Sbrian } 99647286Sbrian 99764652Sbrian throughput_start(&p->link.stats.total, "physical throughput", 99846686Sbrian Enabled(p->dl->bundle, OPT_THROUGHPUT)); 99946686Sbrian p->connect_count++; 100046686Sbrian p->input.sz = 0; 100146686Sbrian 100246686Sbrian log_Printf(LogPHASE, "%s: Connected!\n", p->link.name); 100346686Sbrian} 100446686Sbrian 100546686Sbrianint 1006134789Sbrianphysical_Open(struct physical *p) 100746686Sbrian{ 100846686Sbrian char *dev; 1009134789Sbrian int devno, wasfd, err; 1010134789Sbrian unsigned h; 101146686Sbrian 101246686Sbrian if (p->fd >= 0) 101346686Sbrian log_Printf(LogDEBUG, "%s: Open: Modem is already open!\n", p->link.name); 101446686Sbrian /* We're going back into "term" mode */ 101546686Sbrian else if (p->type == PHYS_DIRECT) { 101647061Sbrian physical_SetDevice(p, ""); 101747061Sbrian p->fd = STDIN_FILENO; 101847061Sbrian for (h = 0; h < NDEVICES && p->handler == NULL && p->fd >= 0; h++) 101952942Sbrian p->handler = (*devices[h].create)(p); 102047061Sbrian if (p->fd >= 0) { 102147124Sbrian if (p->handler == NULL) { 102247461Sbrian physical_SetupStack(p, "unknown", PHYSICAL_NOFORCE); 102347124Sbrian log_Printf(LogDEBUG, "%s: stdin is unidentified\n", p->link.name); 102447124Sbrian } 102546686Sbrian physical_Found(p); 102646686Sbrian } 102746686Sbrian } else { 102846686Sbrian dev = p->cfg.devlist; 102946686Sbrian devno = 0; 103046686Sbrian while (devno < p->cfg.ndev && p->fd < 0) { 103146686Sbrian physical_SetDevice(p, dev); 103247286Sbrian if (physical_Lock(p)) { 103347878Sbrian err = 0; 103447878Sbrian 103547878Sbrian if (*p->name.full == '/') { 103647286Sbrian p->fd = ID0open(p->name.full, O_RDWR | O_NONBLOCK); 103747878Sbrian if (p->fd < 0) 103847878Sbrian err = errno; 103947878Sbrian } 104046686Sbrian 104152942Sbrian wasfd = p->fd; 104247286Sbrian for (h = 0; h < NDEVICES && p->handler == NULL; h++) 104352942Sbrian if ((p->handler = (*devices[h].create)(p)) == NULL && wasfd != p->fd) 104447286Sbrian break; 104546686Sbrian 104647286Sbrian if (p->fd < 0) { 104747878Sbrian if (h == NDEVICES) { 104847878Sbrian if (err) 104947878Sbrian log_Printf(LogWARN, "%s: %s: %s\n", p->link.name, p->name.full, 105047878Sbrian strerror(errno)); 105147878Sbrian else 105247878Sbrian log_Printf(LogWARN, "%s: Device (%s) must begin with a '/'," 105352942Sbrian " a '!' or contain at least one ':'\n", p->link.name, 105447878Sbrian p->name.full); 105547878Sbrian } 105647286Sbrian physical_Unlock(p); 105747286Sbrian } else 105847286Sbrian physical_Found(p); 105947286Sbrian } 106046686Sbrian dev += strlen(dev) + 1; 106146686Sbrian devno++; 106246686Sbrian } 106346686Sbrian } 106446686Sbrian 106546686Sbrian return p->fd; 106646686Sbrian} 106746686Sbrian 106846686Sbrianvoid 106947461Sbrianphysical_SetupStack(struct physical *p, const char *who, int how) 107046686Sbrian{ 107146686Sbrian link_EmptyStack(&p->link); 107252942Sbrian if (how == PHYSICAL_FORCE_SYNC || how == PHYSICAL_FORCE_SYNCNOACF || 107347061Sbrian (how == PHYSICAL_NOFORCE && physical_IsSync(p))) 107446686Sbrian link_Stack(&p->link, &synclayer); 107546686Sbrian else { 107646686Sbrian link_Stack(&p->link, &asynclayer); 107746686Sbrian link_Stack(&p->link, &hdlclayer); 107846686Sbrian } 107952942Sbrian if (how != PHYSICAL_FORCE_SYNCNOACF) 108052942Sbrian link_Stack(&p->link, &acflayer); 108146686Sbrian link_Stack(&p->link, &protolayer); 108246686Sbrian link_Stack(&p->link, &lqrlayer); 108346686Sbrian link_Stack(&p->link, &ccplayer); 108446686Sbrian link_Stack(&p->link, &vjlayer); 108569303Sbrian link_Stack(&p->link, &tcpmsslayer); 108650059Sbrian#ifndef NONAT 108750059Sbrian link_Stack(&p->link, &natlayer); 108846686Sbrian#endif 108947061Sbrian if (how == PHYSICAL_FORCE_ASYNC && physical_IsSync(p)) { 109047461Sbrian log_Printf(LogWARN, "Sync device setting ignored for ``%s'' device\n", who); 109147061Sbrian p->cfg.speed = MODEM_SPEED; 109247061Sbrian } else if (how == PHYSICAL_FORCE_SYNC && !physical_IsSync(p)) { 109347061Sbrian log_Printf(LogWARN, "Async device setting ignored for ``%s'' device\n", 109447461Sbrian who); 109547061Sbrian physical_SetSync(p); 109647061Sbrian } 109746686Sbrian} 109847061Sbrian 109947061Sbrianvoid 110047061Sbrianphysical_StopDeviceTimer(struct physical *p) 110147061Sbrian{ 110247061Sbrian if (p->handler && p->handler->stoptimer) 110347061Sbrian (*p->handler->stoptimer)(p); 110447061Sbrian} 110549472Sbrian 110649472Sbrianint 110749472Sbrianphysical_AwaitCarrier(struct physical *p) 110849472Sbrian{ 110949472Sbrian if (p->handler && p->handler->awaitcarrier) 111049472Sbrian return (*p->handler->awaitcarrier)(p); 111149472Sbrian 111249472Sbrian return CARRIER_OK; 111349472Sbrian} 111493418Sbrian 111593418Sbrian 111693418Sbrianvoid 111793418Sbrianphysical_SetAsyncParams(struct physical *p, u_int32_t mymap, u_int32_t hismap) 111893418Sbrian{ 111993418Sbrian if (p->handler && p->handler->setasyncparams) 112093418Sbrian return (*p->handler->setasyncparams)(p, mymap, hismap); 112193418Sbrian 112293418Sbrian async_SetLinkParams(&p->async, mymap, hismap); 112393418Sbrian} 112496582Sbrian 112596582Sbrianint 112696582Sbrianphysical_Slot(struct physical *p) 112796582Sbrian{ 112896582Sbrian if (p->handler && p->handler->slot) 112996582Sbrian return (*p->handler->slot)(p); 113096582Sbrian 113196582Sbrian return -1; 113296582Sbrian} 1133132818Sglebius 1134132818Sglebiusint 1135132818Sglebiusphysical_SetPPPoEnonstandard(struct physical *p, int enable) 1136132818Sglebius{ 1137132818Sglebius p->cfg.nonstandard_pppoe = enable ? 1 : 0; 1138132818Sglebius p->cfg.pppoe_configured = 1; 1139132818Sglebius return 1; 1140132818Sglebius} 1141