physical.c revision 78410
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 78410 2001-06-18 14:59:36Z brian $ 2036285Sbrian * 2136285Sbrian */ 2236285Sbrian 2346686Sbrian#include <sys/param.h> 2446686Sbrian#include <netinet/in.h> 2546686Sbrian#include <netinet/in_systm.h> 2646686Sbrian#include <netinet/ip.h> 2746686Sbrian#include <sys/un.h> 2846686Sbrian 2946686Sbrian#include <errno.h> 3046686Sbrian#include <fcntl.h> 3146686Sbrian#include <paths.h> 3264802Sbrian#ifdef NOSUID 3364802Sbrian#include <signal.h> 3464802Sbrian#endif 3536285Sbrian#include <stdio.h> 3636285Sbrian#include <stdlib.h> 3736285Sbrian#include <string.h> 3846686Sbrian#include <sys/tty.h> /* TIOCOUTQ */ 3946686Sbrian#include <sys/uio.h> 4036285Sbrian#include <time.h> 4136285Sbrian#include <unistd.h> 4236285Sbrian#include <utmp.h> 4346686Sbrian#if defined(__OpenBSD__) || defined(__NetBSD__) 4446686Sbrian#include <sys/ioctl.h> 4546686Sbrian#include <util.h> 4646686Sbrian#else 4746686Sbrian#include <libutil.h> 4846686Sbrian#endif 4936285Sbrian 5046686Sbrian#include "layer.h" 5150059Sbrian#ifndef NONAT 5251075Sbrian#include "nat_cmd.h" 5346686Sbrian#endif 5446686Sbrian#include "proto.h" 5546686Sbrian#include "acf.h" 5646686Sbrian#include "vjcomp.h" 5736285Sbrian#include "defs.h" 5846686Sbrian#include "command.h" 5936285Sbrian#include "mbuf.h" 6046686Sbrian#include "log.h" 6146686Sbrian#include "id.h" 6236285Sbrian#include "timer.h" 6346686Sbrian#include "fsm.h" 6436285Sbrian#include "lqr.h" 6536285Sbrian#include "hdlc.h" 6646686Sbrian#include "lcp.h" 6736285Sbrian#include "throughput.h" 6846686Sbrian#include "sync.h" 6936285Sbrian#include "async.h" 7046686Sbrian#include "iplist.h" 7146686Sbrian#include "slcompress.h" 7246686Sbrian#include "ipcp.h" 7346686Sbrian#include "filter.h" 7446686Sbrian#include "descriptor.h" 7536285Sbrian#include "ccp.h" 7636285Sbrian#include "link.h" 7736285Sbrian#include "physical.h" 7846686Sbrian#include "mp.h" 7946686Sbrian#ifndef NORADIUS 8046686Sbrian#include "radius.h" 8146686Sbrian#endif 8246686Sbrian#include "bundle.h" 8346686Sbrian#include "prompt.h" 8446686Sbrian#include "chat.h" 8546686Sbrian#include "auth.h" 8646686Sbrian#include "chap.h" 8746686Sbrian#include "cbcp.h" 8846686Sbrian#include "datalink.h" 8946686Sbrian#include "tcp.h" 9047061Sbrian#include "udp.h" 9146686Sbrian#include "exec.h" 9246686Sbrian#include "tty.h" 9349472Sbrian#ifndef NOI4B 9449472Sbrian#include "i4b.h" 9549472Sbrian#endif 9652942Sbrian#ifndef NONETGRAPH 9752942Sbrian#include "ether.h" 9852942Sbrian#endif 9965862Sbrian#ifndef NOATM 10065862Sbrian#include "atm.h" 10165862Sbrian#endif 10269303Sbrian#include "tcpmss.h" 10336285Sbrian 10452429Sbrian#define PPPOTCPLINE "ppp" 10552429Sbrian 10658028Sbrianstatic int physical_DescriptorWrite(struct fdescriptor *, struct bundle *, 10746686Sbrian const fd_set *); 10836285Sbrian 10947769Sbrianstatic int 11047769Sbrianphysical_DeviceSize(void) 11147769Sbrian{ 11247769Sbrian return sizeof(struct device); 11347769Sbrian} 11447769Sbrian 11547061Sbrianstruct { 11647061Sbrian struct device *(*create)(struct physical *); 11752942Sbrian struct device *(*iov2device)(int, struct physical *, struct iovec *, 11852942Sbrian int *, int, int *, int *); 11947769Sbrian int (*DeviceSize)(void); 12047061Sbrian} devices[] = { 12149472Sbrian#ifndef NOI4B 12271006Sbrian /* 12371006Sbrian * This must come before ``tty'' so that the probe routine is 12471006Sbrian * able to identify it as a more specific type of terminal device. 12571006Sbrian */ 12649472Sbrian { i4b_Create, i4b_iov2device, i4b_DeviceSize }, 12749472Sbrian#endif 12847769Sbrian { tty_Create, tty_iov2device, tty_DeviceSize }, 12952942Sbrian#ifndef NONETGRAPH 13071006Sbrian /* 13171006Sbrian * This must come before ``udp'' so that the probe routine is 13271006Sbrian * able to identify it as a more specific type of SOCK_DGRAM. 13371006Sbrian */ 13452942Sbrian { ether_Create, ether_iov2device, ether_DeviceSize }, 13552942Sbrian#endif 13665862Sbrian#ifndef NOATM 13771006Sbrian /* Ditto for ATM devices */ 13865862Sbrian { atm_Create, atm_iov2device, atm_DeviceSize }, 13965862Sbrian#endif 14047769Sbrian { tcp_Create, tcp_iov2device, tcp_DeviceSize }, 14147769Sbrian { udp_Create, udp_iov2device, udp_DeviceSize }, 14247769Sbrian { exec_Create, exec_iov2device, exec_DeviceSize } 14346686Sbrian}; 14446686Sbrian 14547061Sbrian#define NDEVICES (sizeof devices / sizeof devices[0]) 14646686Sbrian 14746686Sbrianstatic int 14858028Sbrianphysical_UpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w, fd_set *e, 14946686Sbrian int *n) 15046686Sbrian{ 15146686Sbrian return physical_doUpdateSet(d, r, w, e, n, 0); 15246686Sbrian} 15346686Sbrian 15452942Sbrianvoid 15552942Sbrianphysical_SetDescriptor(struct physical *p) 15652942Sbrian{ 15752942Sbrian p->desc.type = PHYSICAL_DESCRIPTOR; 15852942Sbrian p->desc.UpdateSet = physical_UpdateSet; 15952942Sbrian p->desc.IsSet = physical_IsSet; 16052942Sbrian p->desc.Read = physical_DescriptorRead; 16152942Sbrian p->desc.Write = physical_DescriptorWrite; 16252942Sbrian} 16352942Sbrian 16446686Sbrianstruct physical * 16546686Sbrianphysical_Create(struct datalink *dl, int type) 16646686Sbrian{ 16746686Sbrian struct physical *p; 16846686Sbrian 16946686Sbrian p = (struct physical *)malloc(sizeof(struct physical)); 17046686Sbrian if (!p) 17146686Sbrian return NULL; 17246686Sbrian 17346686Sbrian p->link.type = PHYSICAL_LINK; 17446686Sbrian p->link.name = dl->name; 17546686Sbrian p->link.len = sizeof *p; 17646686Sbrian 17749434Sbrian /* The sample period is fixed - see physical2iov() & iov2physical() */ 17864652Sbrian throughput_init(&p->link.stats.total, SAMPLE_PERIOD); 17964652Sbrian p->link.stats.parent = dl->bundle->ncp.mp.active ? 18064652Sbrian &dl->bundle->ncp.mp.link.stats.total : NULL; 18164652Sbrian p->link.stats.gather = 1; 18249434Sbrian 18346686Sbrian memset(p->link.Queue, '\0', sizeof p->link.Queue); 18446686Sbrian memset(p->link.proto_in, '\0', sizeof p->link.proto_in); 18546686Sbrian memset(p->link.proto_out, '\0', sizeof p->link.proto_out); 18646686Sbrian link_EmptyStack(&p->link); 18746686Sbrian 18846686Sbrian p->handler = NULL; 18952942Sbrian physical_SetDescriptor(p); 19046686Sbrian p->type = type; 19146686Sbrian 19246686Sbrian hdlc_Init(&p->hdlc, &p->link.lcp); 19346686Sbrian async_Init(&p->async); 19446686Sbrian 19546686Sbrian p->fd = -1; 19646686Sbrian p->out = NULL; 19746686Sbrian p->connect_count = 0; 19846686Sbrian p->dl = dl; 19946686Sbrian p->input.sz = 0; 20046686Sbrian *p->name.full = '\0'; 20146686Sbrian p->name.base = p->name.full; 20246686Sbrian 20346686Sbrian p->Utmp = 0; 20446686Sbrian p->session_owner = (pid_t)-1; 20546686Sbrian 20646686Sbrian p->cfg.rts_cts = MODEM_CTSRTS; 20746686Sbrian p->cfg.speed = MODEM_SPEED; 20846686Sbrian p->cfg.parity = CS8; 20946686Sbrian memcpy(p->cfg.devlist, MODEM_LIST, sizeof MODEM_LIST); 21046686Sbrian p->cfg.ndev = NMODEMS; 21153733Sbrian p->cfg.cd.necessity = CD_DEFAULT; 21253733Sbrian p->cfg.cd.delay = 0; /* reconfigured or device specific default */ 21346686Sbrian 21446686Sbrian lcp_Init(&p->link.lcp, dl->bundle, &p->link, &dl->fsmp); 21546686Sbrian ccp_Init(&p->link.ccp, dl->bundle, &p->link, &dl->fsmp); 21646686Sbrian 21746686Sbrian return p; 21846686Sbrian} 21946686Sbrian 22046686Sbrianstatic const struct parity { 22146686Sbrian const char *name; 22246686Sbrian const char *name1; 22346686Sbrian int set; 22446686Sbrian} validparity[] = { 22546686Sbrian { "even", "P_EVEN", CS7 | PARENB }, 22646686Sbrian { "odd", "P_ODD", CS7 | PARENB | PARODD }, 22746686Sbrian { "none", "P_ZERO", CS8 }, 22846686Sbrian { NULL, 0 }, 22946686Sbrian}; 23046686Sbrian 23146686Sbrianstatic int 23246686SbrianGetParityValue(const char *str) 23346686Sbrian{ 23446686Sbrian const struct parity *pp; 23546686Sbrian 23646686Sbrian for (pp = validparity; pp->name; pp++) { 23746686Sbrian if (strcasecmp(pp->name, str) == 0 || 23846686Sbrian strcasecmp(pp->name1, str) == 0) { 23946686Sbrian return pp->set; 24046686Sbrian } 24146686Sbrian } 24246686Sbrian return (-1); 24346686Sbrian} 24446686Sbrian 24536285Sbrianint 24646686Sbrianphysical_SetParity(struct physical *p, const char *str) 24746686Sbrian{ 24846686Sbrian struct termios rstio; 24946686Sbrian int val; 25046686Sbrian 25146686Sbrian val = GetParityValue(str); 25246686Sbrian if (val > 0) { 25346686Sbrian p->cfg.parity = val; 25446686Sbrian if (p->fd >= 0) { 25546686Sbrian tcgetattr(p->fd, &rstio); 25646686Sbrian rstio.c_cflag &= ~(CSIZE | PARODD | PARENB); 25746686Sbrian rstio.c_cflag |= val; 25846686Sbrian tcsetattr(p->fd, TCSADRAIN, &rstio); 25946686Sbrian } 26046686Sbrian return 0; 26146686Sbrian } 26246686Sbrian log_Printf(LogWARN, "%s: %s: Invalid parity\n", p->link.name, str); 26346686Sbrian return -1; 26436285Sbrian} 26536285Sbrian 26636285Sbrianint 26746686Sbrianphysical_GetSpeed(struct physical *p) 26846686Sbrian{ 26946686Sbrian if (p->handler && p->handler->speed) 27046686Sbrian return (*p->handler->speed)(p); 27146686Sbrian 27249434Sbrian return 0; 27336285Sbrian} 27436285Sbrian 27546686Sbrianint 27646686Sbrianphysical_SetSpeed(struct physical *p, int speed) 27736285Sbrian{ 27846686Sbrian if (IntToSpeed(speed) != B0) { 27946686Sbrian p->cfg.speed = speed; 28046686Sbrian return 1; 28146686Sbrian } 28246686Sbrian 28346686Sbrian return 0; 28436285Sbrian} 28536285Sbrian 28646686Sbrianint 28746686Sbrianphysical_Raw(struct physical *p) 28846686Sbrian{ 28946686Sbrian if (p->handler && p->handler->raw) 29046686Sbrian return (*p->handler->raw)(p); 29146686Sbrian 29246686Sbrian return 1; 29346686Sbrian} 29446686Sbrian 29536285Sbrianvoid 29646686Sbrianphysical_Offline(struct physical *p) 29746686Sbrian{ 29846686Sbrian if (p->handler && p->handler->offline) 29946686Sbrian (*p->handler->offline)(p); 30046686Sbrian log_Printf(LogPHASE, "%s: Disconnected!\n", p->link.name); 30146686Sbrian} 30246686Sbrian 30347286Sbrianstatic int 30447286Sbrianphysical_Lock(struct physical *p) 30546686Sbrian{ 30647286Sbrian int res; 30746686Sbrian 30847286Sbrian if (*p->name.full == '/' && p->type != PHYS_DIRECT && 30947286Sbrian (res = ID0uu_lock(p->name.base)) != UU_LOCK_OK) { 31047286Sbrian if (res == UU_LOCK_INUSE) 31147286Sbrian log_Printf(LogPHASE, "%s: %s is in use\n", p->link.name, p->name.full); 31247286Sbrian else 31347286Sbrian log_Printf(LogPHASE, "%s: %s is in use: uu_lock: %s\n", 31447286Sbrian p->link.name, p->name.full, uu_lockerr(res)); 31547286Sbrian return 0; 31646686Sbrian } 31747286Sbrian 31847286Sbrian return 1; 31946686Sbrian} 32046686Sbrian 32147286Sbrianstatic void 32247286Sbrianphysical_Unlock(struct physical *p) 32347286Sbrian{ 32447286Sbrian if (*p->name.full == '/' && p->type != PHYS_DIRECT && 32547286Sbrian ID0uu_unlock(p->name.base) == -1) 32674001Sbrian log_Printf(LogALERT, "%s: Can't uu_unlock %s\n", p->link.name, 32774001Sbrian p->name.base); 32847286Sbrian} 32947286Sbrian 33046686Sbrianvoid 33146686Sbrianphysical_Close(struct physical *p) 33246686Sbrian{ 33347286Sbrian int newsid; 33474001Sbrian char fn[PATH_MAX]; 33547286Sbrian 33646686Sbrian if (p->fd < 0) 33746686Sbrian return; 33846686Sbrian 33946686Sbrian log_Printf(LogDEBUG, "%s: Close\n", p->link.name); 34046686Sbrian 34146686Sbrian if (p->handler && p->handler->cooked) 34246686Sbrian (*p->handler->cooked)(p); 34346686Sbrian 34447286Sbrian physical_StopDeviceTimer(p); 34547286Sbrian if (p->Utmp) { 34652429Sbrian if (p->handler && (p->handler->type == TCP_DEVICE || 34752487Sbrian p->handler->type == UDP_DEVICE)) 34852487Sbrian /* Careful - we logged in on line ``ppp'' with IP as our host */ 34952487Sbrian ID0logout(PPPOTCPLINE, 1); 35052487Sbrian else 35152487Sbrian ID0logout(p->name.base, 0); 35247286Sbrian p->Utmp = 0; 35347286Sbrian } 35447286Sbrian newsid = tcgetpgrp(p->fd) == getpgrp(); 35547286Sbrian close(p->fd); 35647286Sbrian p->fd = -1; 35747286Sbrian log_SetTtyCommandMode(p->dl); 35847286Sbrian 35964652Sbrian throughput_stop(&p->link.stats.total); 36064652Sbrian throughput_log(&p->link.stats.total, LogPHASE, p->link.name); 36147286Sbrian 36247286Sbrian if (p->session_owner != (pid_t)-1) { 36360863Sbrian log_Printf(LogPHASE, "%s: HUPing %d\n", p->link.name, 36460863Sbrian (int)p->session_owner); 36547286Sbrian ID0kill(p->session_owner, SIGHUP); 36647286Sbrian p->session_owner = (pid_t)-1; 36747286Sbrian } 36847286Sbrian 36947286Sbrian if (newsid) 37047286Sbrian bundle_setsid(p->dl->bundle, 0); 37147286Sbrian 37247286Sbrian if (*p->name.full == '/') { 37347286Sbrian snprintf(fn, sizeof fn, "%s%s.if", _PATH_VARRUN, p->name.base); 37447286Sbrian#ifndef RELEASE_CRUNCH 37547286Sbrian if (ID0unlink(fn) == -1) 37647286Sbrian log_Printf(LogALERT, "%s: Can't remove %s: %s\n", 37747286Sbrian p->link.name, fn, strerror(errno)); 37847286Sbrian#else 37947286Sbrian ID0unlink(fn); 38047286Sbrian#endif 38147286Sbrian } 38247286Sbrian physical_Unlock(p); 38347286Sbrian if (p->handler && p->handler->destroy) 38447286Sbrian (*p->handler->destroy)(p); 38547286Sbrian p->handler = NULL; 38647286Sbrian p->name.base = p->name.full; 38747286Sbrian *p->name.full = '\0'; 38846686Sbrian} 38946686Sbrian 39046686Sbrianvoid 39146686Sbrianphysical_Destroy(struct physical *p) 39246686Sbrian{ 39346686Sbrian physical_Close(p); 39464652Sbrian throughput_destroy(&p->link.stats.total); 39546686Sbrian free(p); 39646686Sbrian} 39746686Sbrian 39846686Sbrianstatic int 39958028Sbrianphysical_DescriptorWrite(struct fdescriptor *d, struct bundle *bundle, 40046686Sbrian const fd_set *fdset) 40146686Sbrian{ 40246686Sbrian struct physical *p = descriptor2physical(d); 40346686Sbrian int nw, result = 0; 40446686Sbrian 40546686Sbrian if (p->out == NULL) 40646686Sbrian p->out = link_Dequeue(&p->link); 40746686Sbrian 40846686Sbrian if (p->out) { 40954912Sbrian nw = physical_Write(p, MBUF_CTOP(p->out), p->out->m_len); 41058042Sbrian log_Printf(LogDEBUG, "%s: DescriptorWrite: wrote %d(%lu) to %d\n", 41158042Sbrian p->link.name, nw, (unsigned long)p->out->m_len, p->fd); 41246686Sbrian if (nw > 0) { 41354912Sbrian p->out->m_len -= nw; 41454912Sbrian p->out->m_offset += nw; 41554912Sbrian if (p->out->m_len == 0) 41654912Sbrian p->out = m_free(p->out); 41746686Sbrian result = 1; 41846686Sbrian } else if (nw < 0) { 41966900Sbrian if (errno == EAGAIN) 42066900Sbrian result = 1; 42166900Sbrian else if (errno != ENOBUFS) { 42246686Sbrian log_Printf(LogPHASE, "%s: write (%d): %s\n", p->link.name, 42346686Sbrian p->fd, strerror(errno)); 42446686Sbrian datalink_Down(p->dl, CLOSE_NORMAL); 42546686Sbrian } 42646686Sbrian } 42746686Sbrian /* else we shouldn't really have been called ! select() is broken ! */ 42846686Sbrian } 42946686Sbrian 43046686Sbrian return result; 43146686Sbrian} 43246686Sbrian 43346686Sbrianint 43446686Sbrianphysical_ShowStatus(struct cmdargs const *arg) 43546686Sbrian{ 43646686Sbrian struct physical *p = arg->cx->physical; 43753733Sbrian struct cd *cd; 43846686Sbrian const char *dev; 43946686Sbrian int n; 44046686Sbrian 44146686Sbrian prompt_Printf(arg->prompt, "Name: %s\n", p->link.name); 44246686Sbrian prompt_Printf(arg->prompt, " State: "); 44346686Sbrian if (p->fd < 0) 44446686Sbrian prompt_Printf(arg->prompt, "closed\n"); 44546686Sbrian else if (p->handler && p->handler->openinfo) 44646686Sbrian prompt_Printf(arg->prompt, "open (%s)\n", (*p->handler->openinfo)(p)); 44746686Sbrian else 44846686Sbrian prompt_Printf(arg->prompt, "open\n"); 44946686Sbrian 45046686Sbrian prompt_Printf(arg->prompt, " Device: %s", 45146686Sbrian *p->name.full ? p->name.full : 45246686Sbrian p->type == PHYS_DIRECT ? "unknown" : "N/A"); 45346686Sbrian if (p->session_owner != (pid_t)-1) 45446686Sbrian prompt_Printf(arg->prompt, " (session owner: %d)", (int)p->session_owner); 45546686Sbrian 45646686Sbrian prompt_Printf(arg->prompt, "\n Link Type: %s\n", mode2Nam(p->type)); 45746686Sbrian prompt_Printf(arg->prompt, " Connect Count: %d\n", p->connect_count); 45846686Sbrian#ifdef TIOCOUTQ 45946686Sbrian if (p->fd >= 0 && ioctl(p->fd, TIOCOUTQ, &n) >= 0) 46046686Sbrian prompt_Printf(arg->prompt, " Physical outq: %d\n", n); 46146686Sbrian#endif 46246686Sbrian 46354912Sbrian prompt_Printf(arg->prompt, " Queued Packets: %lu\n", 46454912Sbrian (u_long)link_QueueLen(&p->link)); 46546686Sbrian prompt_Printf(arg->prompt, " Phone Number: %s\n", arg->cx->phone.chosen); 46646686Sbrian 46746686Sbrian prompt_Printf(arg->prompt, "\nDefaults:\n"); 46846686Sbrian 46946686Sbrian prompt_Printf(arg->prompt, " Device List: "); 47046686Sbrian dev = p->cfg.devlist; 47146686Sbrian for (n = 0; n < p->cfg.ndev; n++) { 47246686Sbrian if (n) 47346686Sbrian prompt_Printf(arg->prompt, ", "); 47446686Sbrian prompt_Printf(arg->prompt, "\"%s\"", dev); 47546686Sbrian dev += strlen(dev) + 1; 47646686Sbrian } 47746686Sbrian 47846686Sbrian prompt_Printf(arg->prompt, "\n Characteristics: "); 47946686Sbrian if (physical_IsSync(arg->cx->physical)) 48046686Sbrian prompt_Printf(arg->prompt, "sync"); 48146686Sbrian else 48246686Sbrian prompt_Printf(arg->prompt, "%dbps", p->cfg.speed); 48346686Sbrian 48446686Sbrian switch (p->cfg.parity & CSIZE) { 48546686Sbrian case CS7: 48646686Sbrian prompt_Printf(arg->prompt, ", cs7"); 48746686Sbrian break; 48846686Sbrian case CS8: 48946686Sbrian prompt_Printf(arg->prompt, ", cs8"); 49046686Sbrian break; 49146686Sbrian } 49246686Sbrian if (p->cfg.parity & PARENB) { 49346686Sbrian if (p->cfg.parity & PARODD) 49446686Sbrian prompt_Printf(arg->prompt, ", odd parity"); 49546686Sbrian else 49646686Sbrian prompt_Printf(arg->prompt, ", even parity"); 49746686Sbrian } else 49846686Sbrian prompt_Printf(arg->prompt, ", no parity"); 49946686Sbrian 50046686Sbrian prompt_Printf(arg->prompt, ", CTS/RTS %s\n", (p->cfg.rts_cts ? "on" : "off")); 50146686Sbrian 50251699Sbrian prompt_Printf(arg->prompt, " CD check delay: "); 50353733Sbrian cd = p->handler ? &p->handler->cd : &p->cfg.cd; 50453733Sbrian if (cd->necessity == CD_NOTREQUIRED) 50551699Sbrian prompt_Printf(arg->prompt, "no cd"); 50653733Sbrian else if (p->cfg.cd.necessity == CD_DEFAULT) { 50753733Sbrian prompt_Printf(arg->prompt, "device specific"); 50853733Sbrian } else { 50951699Sbrian prompt_Printf(arg->prompt, "%d second%s", p->cfg.cd.delay, 51051699Sbrian p->cfg.cd.delay == 1 ? "" : "s"); 51151699Sbrian if (p->cfg.cd.necessity == CD_REQUIRED) 51251699Sbrian prompt_Printf(arg->prompt, " (required!)"); 51351699Sbrian } 51451699Sbrian prompt_Printf(arg->prompt, "\n\n"); 51546686Sbrian 51664652Sbrian throughput_disp(&p->link.stats.total, arg->prompt); 51746686Sbrian 51846686Sbrian return 0; 51946686Sbrian} 52046686Sbrian 52152942Sbrianvoid 52258028Sbrianphysical_DescriptorRead(struct fdescriptor *d, struct bundle *bundle, 52346686Sbrian const fd_set *fdset) 52446686Sbrian{ 52546686Sbrian struct physical *p = descriptor2physical(d); 52646686Sbrian u_char *rbuff; 52746686Sbrian int n, found; 52846686Sbrian 52946686Sbrian rbuff = p->input.buf + p->input.sz; 53046686Sbrian 53146686Sbrian /* something to read */ 53246686Sbrian n = physical_Read(p, rbuff, sizeof p->input.buf - p->input.sz); 53346686Sbrian log_Printf(LogDEBUG, "%s: DescriptorRead: read %d/%d from %d\n", 53446686Sbrian p->link.name, n, (int)(sizeof p->input.buf - p->input.sz), p->fd); 53546686Sbrian if (n <= 0) { 53646686Sbrian if (n < 0) 53746686Sbrian log_Printf(LogPHASE, "%s: read (%d): %s\n", p->link.name, p->fd, 53846686Sbrian strerror(errno)); 53946686Sbrian else 54046686Sbrian log_Printf(LogPHASE, "%s: read (%d): Got zero bytes\n", 54146686Sbrian p->link.name, p->fd); 54246686Sbrian datalink_Down(p->dl, CLOSE_NORMAL); 54346686Sbrian return; 54446686Sbrian } 54546686Sbrian 54646686Sbrian rbuff -= p->input.sz; 54746686Sbrian n += p->input.sz; 54846686Sbrian 54946686Sbrian if (p->link.lcp.fsm.state <= ST_CLOSED) { 55046686Sbrian if (p->type != PHYS_DEDICATED) { 55146686Sbrian found = hdlc_Detect((u_char const **)&rbuff, n, physical_IsSync(p)); 55246686Sbrian if (rbuff != p->input.buf) 55346686Sbrian log_WritePrompts(p->dl, "%.*s", (int)(rbuff - p->input.buf), 55446686Sbrian p->input.buf); 55546686Sbrian p->input.sz = n - (rbuff - p->input.buf); 55646686Sbrian 55746686Sbrian if (found) { 55846686Sbrian /* LCP packet is detected. Turn ourselves into packet mode */ 55946686Sbrian log_Printf(LogPHASE, "%s: PPP packet detected, coming up\n", 56046686Sbrian p->link.name); 56146686Sbrian log_SetTtyCommandMode(p->dl); 56246686Sbrian datalink_Up(p->dl, 0, 1); 56346686Sbrian link_PullPacket(&p->link, rbuff, p->input.sz, bundle); 56446686Sbrian p->input.sz = 0; 56546686Sbrian } else 56646686Sbrian bcopy(rbuff, p->input.buf, p->input.sz); 56746686Sbrian } else 56846686Sbrian /* In -dedicated mode, we just discard input until LCP is started */ 56946686Sbrian p->input.sz = 0; 57046686Sbrian } else if (n > 0) 57146686Sbrian link_PullPacket(&p->link, rbuff, n, bundle); 57246686Sbrian} 57346686Sbrian 57446686Sbrianstruct physical * 57546686Sbrianiov2physical(struct datalink *dl, struct iovec *iov, int *niov, int maxiov, 57652942Sbrian int fd, int *auxfd, int *nauxfd) 57746686Sbrian{ 57846686Sbrian struct physical *p; 57947061Sbrian int len, h, type; 58046686Sbrian 58146686Sbrian p = (struct physical *)iov[(*niov)++].iov_base; 58246686Sbrian p->link.name = dl->name; 58346686Sbrian memset(p->link.Queue, '\0', sizeof p->link.Queue); 58446686Sbrian 58546686Sbrian p->desc.UpdateSet = physical_UpdateSet; 58646686Sbrian p->desc.IsSet = physical_IsSet; 58746686Sbrian p->desc.Read = physical_DescriptorRead; 58846686Sbrian p->desc.Write = physical_DescriptorWrite; 58946686Sbrian p->type = PHYS_DIRECT; 59046686Sbrian p->dl = dl; 59146686Sbrian len = strlen(_PATH_DEV); 59246686Sbrian p->out = NULL; 59346686Sbrian p->connect_count = 1; 59446686Sbrian 59547682Sbrian physical_SetDevice(p, p->name.full); 59647682Sbrian 59746686Sbrian p->link.lcp.fsm.bundle = dl->bundle; 59846686Sbrian p->link.lcp.fsm.link = &p->link; 59946686Sbrian memset(&p->link.lcp.fsm.FsmTimer, '\0', sizeof p->link.lcp.fsm.FsmTimer); 60046686Sbrian memset(&p->link.lcp.fsm.OpenTimer, '\0', sizeof p->link.lcp.fsm.OpenTimer); 60146686Sbrian memset(&p->link.lcp.fsm.StoppedTimer, '\0', 60246686Sbrian sizeof p->link.lcp.fsm.StoppedTimer); 60346686Sbrian p->link.lcp.fsm.parent = &dl->fsmp; 60446686Sbrian lcp_SetupCallbacks(&p->link.lcp); 60546686Sbrian 60646686Sbrian p->link.ccp.fsm.bundle = dl->bundle; 60746686Sbrian p->link.ccp.fsm.link = &p->link; 60846686Sbrian /* Our in.state & out.state are NULL (no link-level ccp yet) */ 60946686Sbrian memset(&p->link.ccp.fsm.FsmTimer, '\0', sizeof p->link.ccp.fsm.FsmTimer); 61046686Sbrian memset(&p->link.ccp.fsm.OpenTimer, '\0', sizeof p->link.ccp.fsm.OpenTimer); 61146686Sbrian memset(&p->link.ccp.fsm.StoppedTimer, '\0', 61246686Sbrian sizeof p->link.ccp.fsm.StoppedTimer); 61346686Sbrian p->link.ccp.fsm.parent = &dl->fsmp; 61446686Sbrian ccp_SetupCallbacks(&p->link.ccp); 61546686Sbrian 61646686Sbrian p->hdlc.lqm.owner = &p->link.lcp; 61746686Sbrian p->hdlc.ReportTimer.state = TIMER_STOPPED; 61846686Sbrian p->hdlc.lqm.timer.state = TIMER_STOPPED; 61946686Sbrian 62046686Sbrian p->fd = fd; 62164670Sbrian p->link.stats.total.in.SampleOctets = (long long *)iov[(*niov)++].iov_base; 62264670Sbrian p->link.stats.total.out.SampleOctets = (long long *)iov[(*niov)++].iov_base; 62364652Sbrian p->link.stats.parent = dl->bundle->ncp.mp.active ? 62464652Sbrian &dl->bundle->ncp.mp.link.stats.total : NULL; 62564652Sbrian p->link.stats.gather = 1; 62646686Sbrian 62747769Sbrian type = (long)p->handler; 62847769Sbrian p->handler = NULL; 62947769Sbrian for (h = 0; h < NDEVICES && p->handler == NULL; h++) 63052942Sbrian p->handler = (*devices[h].iov2device)(type, p, iov, niov, maxiov, 63152942Sbrian auxfd, nauxfd); 63247769Sbrian if (p->handler == NULL) { 63352942Sbrian log_Printf(LogPHASE, "%s: Unknown link type\n", p->link.name); 63447769Sbrian free(iov[(*niov)++].iov_base); 63547769Sbrian physical_SetupStack(p, "unknown", PHYSICAL_NOFORCE); 63647769Sbrian } else 63747769Sbrian log_Printf(LogPHASE, "%s: Device %s, link type is %s\n", 63847769Sbrian p->link.name, p->name.full, p->handler->name); 63947769Sbrian 64046686Sbrian if (p->hdlc.lqm.method && p->hdlc.lqm.timer.load) 64146686Sbrian lqr_reStart(&p->link.lcp); 64246686Sbrian hdlc_StartTimer(&p->hdlc); 64346686Sbrian 64464652Sbrian throughput_restart(&p->link.stats.total, "physical throughput", 64549434Sbrian Enabled(dl->bundle, OPT_THROUGHPUT)); 64646686Sbrian 64747769Sbrian return p; 64847769Sbrian} 64947061Sbrian 65047769Sbrianint 65147769Sbrianphysical_MaxDeviceSize() 65247769Sbrian{ 65347769Sbrian int biggest, sz, n; 65447061Sbrian 65547769Sbrian biggest = sizeof(struct device); 65647769Sbrian for (sz = n = 0; n < NDEVICES; n++) 65747769Sbrian if (devices[n].DeviceSize) { 65847769Sbrian sz = (*devices[n].DeviceSize)(); 65947769Sbrian if (biggest < sz) 66047769Sbrian biggest = sz; 66147769Sbrian } 66247769Sbrian 66347769Sbrian return biggest; 66446686Sbrian} 66546686Sbrian 66646686Sbrianint 66746686Sbrianphysical2iov(struct physical *p, struct iovec *iov, int *niov, int maxiov, 66853684Sbrian int *auxfd, int *nauxfd) 66946686Sbrian{ 67047769Sbrian struct device *h; 67147769Sbrian int sz; 67247769Sbrian 67347769Sbrian h = NULL; 67446686Sbrian if (p) { 67546686Sbrian hdlc_StopTimer(&p->hdlc); 67646686Sbrian lqr_StopTimer(p); 67746686Sbrian timer_Stop(&p->link.lcp.fsm.FsmTimer); 67846686Sbrian timer_Stop(&p->link.ccp.fsm.FsmTimer); 67946686Sbrian timer_Stop(&p->link.lcp.fsm.OpenTimer); 68046686Sbrian timer_Stop(&p->link.ccp.fsm.OpenTimer); 68146686Sbrian timer_Stop(&p->link.lcp.fsm.StoppedTimer); 68246686Sbrian timer_Stop(&p->link.ccp.fsm.StoppedTimer); 68347061Sbrian if (p->handler) { 68453684Sbrian h = p->handler; 68547061Sbrian p->handler = (struct device *)(long)p->handler->type; 68646686Sbrian } 68747061Sbrian 68847689Sbrian if (Enabled(p->dl->bundle, OPT_KEEPSESSION) || 68947689Sbrian tcgetpgrp(p->fd) == getpgrp()) 69046686Sbrian p->session_owner = getpid(); /* So I'll eventually get HUP'd */ 69147689Sbrian else 69247689Sbrian p->session_owner = (pid_t)-1; 69364652Sbrian timer_Stop(&p->link.stats.total.Timer); 69446686Sbrian } 69546686Sbrian 69649434Sbrian if (*niov + 2 >= maxiov) { 69749434Sbrian log_Printf(LogERROR, "physical2iov: No room for physical + throughput" 69849434Sbrian " + device !\n"); 69946686Sbrian if (p) 70046686Sbrian free(p); 70146686Sbrian return -1; 70246686Sbrian } 70346686Sbrian 70453684Sbrian iov[*niov].iov_base = (void *)p; 70546686Sbrian iov[*niov].iov_len = sizeof *p; 70646686Sbrian (*niov)++; 70746686Sbrian 70864670Sbrian iov[*niov].iov_base = p ? (void *)p->link.stats.total.in.SampleOctets : NULL; 70949434Sbrian iov[*niov].iov_len = SAMPLE_PERIOD * sizeof(long long); 71049434Sbrian (*niov)++; 71164670Sbrian iov[*niov].iov_base = p ? (void *)p->link.stats.total.out.SampleOctets : NULL; 71264670Sbrian iov[*niov].iov_len = SAMPLE_PERIOD * sizeof(long long); 71364670Sbrian (*niov)++; 71449434Sbrian 71547769Sbrian sz = physical_MaxDeviceSize(); 71647769Sbrian if (p) { 71753684Sbrian if (h && h->device2iov) 71853684Sbrian (*h->device2iov)(h, iov, niov, maxiov, auxfd, nauxfd); 71947769Sbrian else { 72047769Sbrian iov[*niov].iov_base = malloc(sz); 72153684Sbrian if (h) 72253684Sbrian memcpy(iov[*niov].iov_base, h, sizeof *h); 72347769Sbrian iov[*niov].iov_len = sz; 72447769Sbrian (*niov)++; 72547769Sbrian } 72647769Sbrian } else { 72753684Sbrian iov[*niov].iov_base = NULL; 72847769Sbrian iov[*niov].iov_len = sz; 72947769Sbrian (*niov)++; 73047769Sbrian } 73147769Sbrian 73246686Sbrian return p ? p->fd : 0; 73346686Sbrian} 73446686Sbrian 73553684Sbrianconst char * 73653684Sbrianphysical_LockedDevice(struct physical *p) 73753684Sbrian{ 73853684Sbrian if (p->fd >= 0 && *p->name.full == '/' && p->type != PHYS_DIRECT) 73953684Sbrian return p->name.base; 74053684Sbrian 74153684Sbrian return NULL; 74253684Sbrian} 74353684Sbrian 74446686Sbrianvoid 74546686Sbrianphysical_ChangedPid(struct physical *p, pid_t newpid) 74646686Sbrian{ 74753684Sbrian if (physical_LockedDevice(p)) { 74846686Sbrian int res; 74946686Sbrian 75046686Sbrian if ((res = ID0uu_lock_txfr(p->name.base, newpid)) != UU_LOCK_OK) 75146686Sbrian log_Printf(LogPHASE, "uu_lock_txfr: %s\n", uu_lockerr(res)); 75246686Sbrian } 75346686Sbrian} 75446686Sbrian 75546686Sbrianint 75646686Sbrianphysical_IsSync(struct physical *p) 75746686Sbrian{ 75846686Sbrian return p->cfg.speed == 0; 75946686Sbrian} 76046686Sbrian 76178410Sbrianu_short 76278410Sbrianphysical_DeviceMTU(struct physical *p) 76378410Sbrian{ 76478410Sbrian return p->handler ? p->handler->mtu : 0; 76578410Sbrian} 76678410Sbrian 76746686Sbrianconst char *physical_GetDevice(struct physical *p) 76846686Sbrian{ 76946686Sbrian return p->name.full; 77046686Sbrian} 77146686Sbrian 77246686Sbrianvoid 77336285Sbrianphysical_SetDeviceList(struct physical *p, int argc, const char *const *argv) 77436285Sbrian{ 77536285Sbrian int f, pos; 77636285Sbrian 77736285Sbrian p->cfg.devlist[sizeof p->cfg.devlist - 1] = '\0'; 77836285Sbrian for (f = 0, pos = 0; f < argc && pos < sizeof p->cfg.devlist - 1; f++) { 77936285Sbrian if (pos) 78046102Sbrian p->cfg.devlist[pos++] = '\0'; 78136285Sbrian strncpy(p->cfg.devlist + pos, argv[f], sizeof p->cfg.devlist - pos - 1); 78236285Sbrian pos += strlen(p->cfg.devlist + pos); 78336285Sbrian } 78446102Sbrian p->cfg.ndev = f; 78536285Sbrian} 78636285Sbrian 78736285Sbrianvoid 78846686Sbrianphysical_SetSync(struct physical *p) 78946686Sbrian{ 79046686Sbrian p->cfg.speed = 0; 79136285Sbrian} 79236285Sbrian 79336285Sbrianint 79446686Sbrianphysical_SetRtsCts(struct physical *p, int enable) 79546686Sbrian{ 79646686Sbrian p->cfg.rts_cts = enable ? 1 : 0; 79736285Sbrian return 1; 79836285Sbrian} 79936285Sbrian 80036285Sbrianssize_t 80146686Sbrianphysical_Read(struct physical *p, void *buf, size_t nbytes) 80246686Sbrian{ 80347061Sbrian ssize_t ret; 80447061Sbrian 80547061Sbrian if (p->handler && p->handler->read) 80647061Sbrian ret = (*p->handler->read)(p, buf, nbytes); 80747061Sbrian else 80847061Sbrian ret = read(p->fd, buf, nbytes); 80947061Sbrian 81047061Sbrian log_DumpBuff(LogPHYSICAL, "read", buf, ret); 81147061Sbrian 81247061Sbrian return ret; 81336285Sbrian} 81436285Sbrian 81536285Sbrianssize_t 81646686Sbrianphysical_Write(struct physical *p, const void *buf, size_t nbytes) 81746686Sbrian{ 81847061Sbrian log_DumpBuff(LogPHYSICAL, "write", buf, nbytes); 81947061Sbrian 82047061Sbrian if (p->handler && p->handler->write) 82147061Sbrian return (*p->handler->write)(p, buf, nbytes); 82247061Sbrian 82347061Sbrian return write(p->fd, buf, nbytes); 82436285Sbrian} 82536285Sbrian 82636285Sbrianint 82758028Sbrianphysical_doUpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w, fd_set *e, 82846686Sbrian int *n, int force) 82936285Sbrian{ 83036285Sbrian struct physical *p = descriptor2physical(d); 83136285Sbrian int sets; 83236285Sbrian 83336285Sbrian sets = 0; 83436285Sbrian if (p->fd >= 0) { 83536285Sbrian if (r) { 83636285Sbrian FD_SET(p->fd, r); 83736285Sbrian log_Printf(LogTIMER, "%s: fdset(r) %d\n", p->link.name, p->fd); 83836285Sbrian sets++; 83936285Sbrian } 84036285Sbrian if (e) { 84136285Sbrian FD_SET(p->fd, e); 84236285Sbrian log_Printf(LogTIMER, "%s: fdset(e) %d\n", p->link.name, p->fd); 84336285Sbrian sets++; 84436285Sbrian } 84536314Sbrian if (w && (force || link_QueueLen(&p->link) || p->out)) { 84636285Sbrian FD_SET(p->fd, w); 84736285Sbrian log_Printf(LogTIMER, "%s: fdset(w) %d\n", p->link.name, p->fd); 84836285Sbrian sets++; 84936285Sbrian } 85036285Sbrian if (sets && *n < p->fd + 1) 85136285Sbrian *n = p->fd + 1; 85236285Sbrian } 85336285Sbrian 85436285Sbrian return sets; 85536285Sbrian} 85636285Sbrian 85736285Sbrianint 85836285Sbrianphysical_RemoveFromSet(struct physical *p, fd_set *r, fd_set *w, fd_set *e) 85936285Sbrian{ 86052942Sbrian if (p->handler && p->handler->removefromset) 86152942Sbrian return (*p->handler->removefromset)(p, r, w, e); 86252942Sbrian else { 86352942Sbrian int sets; 86436285Sbrian 86552942Sbrian sets = 0; 86652942Sbrian if (p->fd >= 0) { 86752942Sbrian if (r && FD_ISSET(p->fd, r)) { 86852942Sbrian FD_CLR(p->fd, r); 86952942Sbrian log_Printf(LogTIMER, "%s: fdunset(r) %d\n", p->link.name, p->fd); 87052942Sbrian sets++; 87152942Sbrian } 87252942Sbrian if (e && FD_ISSET(p->fd, e)) { 87352942Sbrian FD_CLR(p->fd, e); 87452942Sbrian log_Printf(LogTIMER, "%s: fdunset(e) %d\n", p->link.name, p->fd); 87552942Sbrian sets++; 87652942Sbrian } 87752942Sbrian if (w && FD_ISSET(p->fd, w)) { 87852942Sbrian FD_CLR(p->fd, w); 87952942Sbrian log_Printf(LogTIMER, "%s: fdunset(w) %d\n", p->link.name, p->fd); 88052942Sbrian sets++; 88152942Sbrian } 88236285Sbrian } 88352942Sbrian 88452942Sbrian return sets; 88536285Sbrian } 88636285Sbrian} 88736285Sbrian 88836285Sbrianint 88958028Sbrianphysical_IsSet(struct fdescriptor *d, const fd_set *fdset) 89036285Sbrian{ 89136285Sbrian struct physical *p = descriptor2physical(d); 89236285Sbrian return p->fd >= 0 && FD_ISSET(p->fd, fdset); 89336285Sbrian} 89436285Sbrian 89536285Sbrianvoid 89646686Sbrianphysical_Login(struct physical *p, const char *name) 89736285Sbrian{ 89846830Sbrian if (p->type == PHYS_DIRECT && *p->name.base && !p->Utmp) { 89946686Sbrian struct utmp ut; 90046686Sbrian const char *connstr; 90152413Sbrian char *colon; 90236285Sbrian 90346686Sbrian memset(&ut, 0, sizeof ut); 90446686Sbrian time(&ut.ut_time); 90546686Sbrian strncpy(ut.ut_name, name, sizeof ut.ut_name); 90652413Sbrian if (p->handler && (p->handler->type == TCP_DEVICE || 90752413Sbrian p->handler->type == UDP_DEVICE)) { 90852429Sbrian strncpy(ut.ut_line, PPPOTCPLINE, sizeof ut.ut_line); 90952413Sbrian strncpy(ut.ut_host, p->name.base, sizeof ut.ut_host); 91052413Sbrian colon = memchr(ut.ut_host, ':', sizeof ut.ut_host); 91152413Sbrian if (colon) 91252413Sbrian *colon = '\0'; 91352413Sbrian } else 91452413Sbrian strncpy(ut.ut_line, p->name.base, sizeof ut.ut_line); 91546686Sbrian if ((connstr = getenv("CONNECT"))) 91646686Sbrian /* mgetty sets this to the connection speed */ 91746686Sbrian strncpy(ut.ut_host, connstr, sizeof ut.ut_host); 91846686Sbrian ID0login(&ut); 91952429Sbrian p->Utmp = ut.ut_time; 92036285Sbrian } 92136285Sbrian} 92236285Sbrian 92336285Sbrianint 92436285Sbrianphysical_SetMode(struct physical *p, int mode) 92536285Sbrian{ 92638174Sbrian if ((p->type & (PHYS_DIRECT|PHYS_DEDICATED) || 92738174Sbrian mode & (PHYS_DIRECT|PHYS_DEDICATED)) && 92838174Sbrian (!(p->type & PHYS_DIRECT) || !(mode & PHYS_BACKGROUND))) { 92953830Sbrian /* Note: The -direct -> -background is for callback ! */ 93036285Sbrian log_Printf(LogWARN, "%s: Cannot change mode %s to %s\n", p->link.name, 93136285Sbrian mode2Nam(p->type), mode2Nam(mode)); 93236285Sbrian return 0; 93336285Sbrian } 93436285Sbrian p->type = mode; 93536285Sbrian return 1; 93636285Sbrian} 93738544Sbrian 93838544Sbrianvoid 93938544Sbrianphysical_DeleteQueue(struct physical *p) 94038544Sbrian{ 94138544Sbrian if (p->out) { 94254912Sbrian m_freem(p->out); 94338544Sbrian p->out = NULL; 94438544Sbrian } 94538544Sbrian link_DeleteQueue(&p->link); 94638544Sbrian} 94746686Sbrian 94846686Sbrianvoid 94946686Sbrianphysical_SetDevice(struct physical *p, const char *name) 95046686Sbrian{ 95146686Sbrian int len = strlen(_PATH_DEV); 95246686Sbrian 95347682Sbrian if (name != p->name.full) { 95447682Sbrian strncpy(p->name.full, name, sizeof p->name.full - 1); 95547682Sbrian p->name.full[sizeof p->name.full - 1] = '\0'; 95647682Sbrian } 95746686Sbrian p->name.base = *p->name.full == '!' ? p->name.full + 1 : 95846686Sbrian strncmp(p->name.full, _PATH_DEV, len) ? 95946686Sbrian p->name.full : p->name.full + len; 96046686Sbrian} 96146686Sbrian 96246686Sbrianstatic void 96346686Sbrianphysical_Found(struct physical *p) 96446686Sbrian{ 96547286Sbrian FILE *lockfile; 96674001Sbrian char fn[PATH_MAX]; 96747286Sbrian 96847286Sbrian if (*p->name.full == '/') { 96947286Sbrian snprintf(fn, sizeof fn, "%s%s.if", _PATH_VARRUN, p->name.base); 97047286Sbrian lockfile = ID0fopen(fn, "w"); 97147286Sbrian if (lockfile != NULL) { 97247286Sbrian fprintf(lockfile, "%s%d\n", TUN_NAME, p->dl->bundle->unit); 97347286Sbrian fclose(lockfile); 97447286Sbrian } 97547286Sbrian#ifndef RELEASE_CRUNCH 97647286Sbrian else 97747286Sbrian log_Printf(LogALERT, "%s: Can't create %s: %s\n", 97847286Sbrian p->link.name, fn, strerror(errno)); 97947286Sbrian#endif 98047286Sbrian } 98147286Sbrian 98264652Sbrian throughput_start(&p->link.stats.total, "physical throughput", 98346686Sbrian Enabled(p->dl->bundle, OPT_THROUGHPUT)); 98446686Sbrian p->connect_count++; 98546686Sbrian p->input.sz = 0; 98646686Sbrian 98746686Sbrian log_Printf(LogPHASE, "%s: Connected!\n", p->link.name); 98846686Sbrian} 98946686Sbrian 99046686Sbrianint 99146686Sbrianphysical_Open(struct physical *p, struct bundle *bundle) 99246686Sbrian{ 99352942Sbrian int devno, h, wasfd, err; 99446686Sbrian char *dev; 99546686Sbrian 99646686Sbrian if (p->fd >= 0) 99746686Sbrian log_Printf(LogDEBUG, "%s: Open: Modem is already open!\n", p->link.name); 99846686Sbrian /* We're going back into "term" mode */ 99946686Sbrian else if (p->type == PHYS_DIRECT) { 100047061Sbrian physical_SetDevice(p, ""); 100147061Sbrian p->fd = STDIN_FILENO; 100247061Sbrian for (h = 0; h < NDEVICES && p->handler == NULL && p->fd >= 0; h++) 100352942Sbrian p->handler = (*devices[h].create)(p); 100447061Sbrian if (p->fd >= 0) { 100547124Sbrian if (p->handler == NULL) { 100647461Sbrian physical_SetupStack(p, "unknown", PHYSICAL_NOFORCE); 100747124Sbrian log_Printf(LogDEBUG, "%s: stdin is unidentified\n", p->link.name); 100847124Sbrian } 100946686Sbrian physical_Found(p); 101046686Sbrian } 101146686Sbrian } else { 101246686Sbrian dev = p->cfg.devlist; 101346686Sbrian devno = 0; 101446686Sbrian while (devno < p->cfg.ndev && p->fd < 0) { 101546686Sbrian physical_SetDevice(p, dev); 101647286Sbrian if (physical_Lock(p)) { 101747878Sbrian err = 0; 101847878Sbrian 101947878Sbrian if (*p->name.full == '/') { 102047286Sbrian p->fd = ID0open(p->name.full, O_RDWR | O_NONBLOCK); 102147878Sbrian if (p->fd < 0) 102247878Sbrian err = errno; 102347878Sbrian } 102446686Sbrian 102552942Sbrian wasfd = p->fd; 102647286Sbrian for (h = 0; h < NDEVICES && p->handler == NULL; h++) 102752942Sbrian if ((p->handler = (*devices[h].create)(p)) == NULL && wasfd != p->fd) 102847286Sbrian break; 102946686Sbrian 103047286Sbrian if (p->fd < 0) { 103147878Sbrian if (h == NDEVICES) { 103247878Sbrian if (err) 103347878Sbrian log_Printf(LogWARN, "%s: %s: %s\n", p->link.name, p->name.full, 103447878Sbrian strerror(errno)); 103547878Sbrian else 103647878Sbrian log_Printf(LogWARN, "%s: Device (%s) must begin with a '/'," 103752942Sbrian " a '!' or contain at least one ':'\n", p->link.name, 103847878Sbrian p->name.full); 103947878Sbrian } 104047286Sbrian physical_Unlock(p); 104147286Sbrian } else 104247286Sbrian physical_Found(p); 104347286Sbrian } 104446686Sbrian dev += strlen(dev) + 1; 104546686Sbrian devno++; 104646686Sbrian } 104746686Sbrian } 104846686Sbrian 104946686Sbrian return p->fd; 105046686Sbrian} 105146686Sbrian 105246686Sbrianvoid 105347461Sbrianphysical_SetupStack(struct physical *p, const char *who, int how) 105446686Sbrian{ 105546686Sbrian link_EmptyStack(&p->link); 105652942Sbrian if (how == PHYSICAL_FORCE_SYNC || how == PHYSICAL_FORCE_SYNCNOACF || 105747061Sbrian (how == PHYSICAL_NOFORCE && physical_IsSync(p))) 105846686Sbrian link_Stack(&p->link, &synclayer); 105946686Sbrian else { 106046686Sbrian link_Stack(&p->link, &asynclayer); 106146686Sbrian link_Stack(&p->link, &hdlclayer); 106246686Sbrian } 106352942Sbrian if (how != PHYSICAL_FORCE_SYNCNOACF) 106452942Sbrian link_Stack(&p->link, &acflayer); 106546686Sbrian link_Stack(&p->link, &protolayer); 106646686Sbrian link_Stack(&p->link, &lqrlayer); 106746686Sbrian link_Stack(&p->link, &ccplayer); 106846686Sbrian link_Stack(&p->link, &vjlayer); 106969303Sbrian link_Stack(&p->link, &tcpmsslayer); 107050059Sbrian#ifndef NONAT 107150059Sbrian link_Stack(&p->link, &natlayer); 107246686Sbrian#endif 107347061Sbrian if (how == PHYSICAL_FORCE_ASYNC && physical_IsSync(p)) { 107447461Sbrian log_Printf(LogWARN, "Sync device setting ignored for ``%s'' device\n", who); 107547061Sbrian p->cfg.speed = MODEM_SPEED; 107647061Sbrian } else if (how == PHYSICAL_FORCE_SYNC && !physical_IsSync(p)) { 107747061Sbrian log_Printf(LogWARN, "Async device setting ignored for ``%s'' device\n", 107847461Sbrian who); 107947061Sbrian physical_SetSync(p); 108047061Sbrian } 108146686Sbrian} 108247061Sbrian 108347061Sbrianvoid 108447061Sbrianphysical_StopDeviceTimer(struct physical *p) 108547061Sbrian{ 108647061Sbrian if (p->handler && p->handler->stoptimer) 108747061Sbrian (*p->handler->stoptimer)(p); 108847061Sbrian} 108949472Sbrian 109049472Sbrianint 109149472Sbrianphysical_AwaitCarrier(struct physical *p) 109249472Sbrian{ 109349472Sbrian if (p->handler && p->handler->awaitcarrier) 109449472Sbrian return (*p->handler->awaitcarrier)(p); 109549472Sbrian 109649472Sbrian return CARRIER_OK; 109749472Sbrian} 1098