physical.c revision 53830
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 53830 1999-11-28 15:50:08Z 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> 3236285Sbrian#include <stdio.h> 3336285Sbrian#include <stdlib.h> 3436285Sbrian#include <string.h> 3546686Sbrian#include <sys/tty.h> /* TIOCOUTQ */ 3646686Sbrian#include <sys/uio.h> 3736285Sbrian#include <time.h> 3836285Sbrian#include <unistd.h> 3936285Sbrian#include <utmp.h> 4046686Sbrian#if defined(__OpenBSD__) || defined(__NetBSD__) 4146686Sbrian#include <sys/ioctl.h> 4246686Sbrian#include <util.h> 4346686Sbrian#else 4446686Sbrian#include <libutil.h> 4546686Sbrian#endif 4636285Sbrian 4746686Sbrian#include "layer.h" 4850059Sbrian#ifndef NONAT 4951075Sbrian#include "nat_cmd.h" 5046686Sbrian#endif 5146686Sbrian#include "proto.h" 5246686Sbrian#include "acf.h" 5346686Sbrian#include "vjcomp.h" 5436285Sbrian#include "defs.h" 5546686Sbrian#include "command.h" 5636285Sbrian#include "mbuf.h" 5746686Sbrian#include "log.h" 5846686Sbrian#include "id.h" 5936285Sbrian#include "timer.h" 6046686Sbrian#include "fsm.h" 6136285Sbrian#include "lqr.h" 6236285Sbrian#include "hdlc.h" 6346686Sbrian#include "lcp.h" 6436285Sbrian#include "throughput.h" 6546686Sbrian#include "sync.h" 6636285Sbrian#include "async.h" 6746686Sbrian#include "iplist.h" 6846686Sbrian#include "slcompress.h" 6946686Sbrian#include "ipcp.h" 7046686Sbrian#include "filter.h" 7146686Sbrian#include "descriptor.h" 7236285Sbrian#include "ccp.h" 7336285Sbrian#include "link.h" 7436285Sbrian#include "physical.h" 7546686Sbrian#include "mp.h" 7646686Sbrian#ifndef NORADIUS 7746686Sbrian#include "radius.h" 7846686Sbrian#endif 7946686Sbrian#include "bundle.h" 8046686Sbrian#include "prompt.h" 8146686Sbrian#include "chat.h" 8246686Sbrian#include "auth.h" 8346686Sbrian#include "chap.h" 8446686Sbrian#include "cbcp.h" 8546686Sbrian#include "datalink.h" 8646686Sbrian#include "tcp.h" 8747061Sbrian#include "udp.h" 8846686Sbrian#include "exec.h" 8946686Sbrian#include "tty.h" 9049472Sbrian#ifndef NOI4B 9149472Sbrian#include "i4b.h" 9249472Sbrian#endif 9352942Sbrian#ifndef NONETGRAPH 9452942Sbrian#include "ether.h" 9552942Sbrian#endif 9636285Sbrian 9736285Sbrian 9852429Sbrian#define PPPOTCPLINE "ppp" 9952429Sbrian 10046686Sbrianstatic int physical_DescriptorWrite(struct descriptor *, struct bundle *, 10146686Sbrian const fd_set *); 10236285Sbrian 10347769Sbrianstatic int 10447769Sbrianphysical_DeviceSize(void) 10547769Sbrian{ 10647769Sbrian return sizeof(struct device); 10747769Sbrian} 10847769Sbrian 10947061Sbrianstruct { 11047061Sbrian struct device *(*create)(struct physical *); 11152942Sbrian struct device *(*iov2device)(int, struct physical *, struct iovec *, 11252942Sbrian int *, int, int *, int *); 11347769Sbrian int (*DeviceSize)(void); 11447061Sbrian} devices[] = { 11549472Sbrian#ifndef NOI4B 11649472Sbrian { i4b_Create, i4b_iov2device, i4b_DeviceSize }, 11749472Sbrian#endif 11847769Sbrian { tty_Create, tty_iov2device, tty_DeviceSize }, 11952942Sbrian#ifndef NONETGRAPH 12052942Sbrian /* This must come before ``udp'' & ``tcp'' */ 12152942Sbrian { ether_Create, ether_iov2device, ether_DeviceSize }, 12252942Sbrian#endif 12347769Sbrian { tcp_Create, tcp_iov2device, tcp_DeviceSize }, 12447769Sbrian { udp_Create, udp_iov2device, udp_DeviceSize }, 12547769Sbrian { exec_Create, exec_iov2device, exec_DeviceSize } 12646686Sbrian}; 12746686Sbrian 12847061Sbrian#define NDEVICES (sizeof devices / sizeof devices[0]) 12946686Sbrian 13046686Sbrianstatic int 13146686Sbrianphysical_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, 13246686Sbrian int *n) 13346686Sbrian{ 13446686Sbrian return physical_doUpdateSet(d, r, w, e, n, 0); 13546686Sbrian} 13646686Sbrian 13752942Sbrianvoid 13852942Sbrianphysical_SetDescriptor(struct physical *p) 13952942Sbrian{ 14052942Sbrian p->desc.type = PHYSICAL_DESCRIPTOR; 14152942Sbrian p->desc.UpdateSet = physical_UpdateSet; 14252942Sbrian p->desc.IsSet = physical_IsSet; 14352942Sbrian p->desc.Read = physical_DescriptorRead; 14452942Sbrian p->desc.Write = physical_DescriptorWrite; 14552942Sbrian} 14652942Sbrian 14746686Sbrianstruct physical * 14846686Sbrianphysical_Create(struct datalink *dl, int type) 14946686Sbrian{ 15046686Sbrian struct physical *p; 15146686Sbrian 15246686Sbrian p = (struct physical *)malloc(sizeof(struct physical)); 15346686Sbrian if (!p) 15446686Sbrian return NULL; 15546686Sbrian 15646686Sbrian p->link.type = PHYSICAL_LINK; 15746686Sbrian p->link.name = dl->name; 15846686Sbrian p->link.len = sizeof *p; 15946686Sbrian 16049434Sbrian /* The sample period is fixed - see physical2iov() & iov2physical() */ 16149434Sbrian throughput_init(&p->link.throughput, SAMPLE_PERIOD); 16249434Sbrian 16346686Sbrian memset(p->link.Queue, '\0', sizeof p->link.Queue); 16446686Sbrian memset(p->link.proto_in, '\0', sizeof p->link.proto_in); 16546686Sbrian memset(p->link.proto_out, '\0', sizeof p->link.proto_out); 16646686Sbrian link_EmptyStack(&p->link); 16746686Sbrian 16846686Sbrian p->handler = NULL; 16952942Sbrian physical_SetDescriptor(p); 17046686Sbrian p->type = type; 17146686Sbrian 17246686Sbrian hdlc_Init(&p->hdlc, &p->link.lcp); 17346686Sbrian async_Init(&p->async); 17446686Sbrian 17546686Sbrian p->fd = -1; 17646686Sbrian p->out = NULL; 17746686Sbrian p->connect_count = 0; 17846686Sbrian p->dl = dl; 17946686Sbrian p->input.sz = 0; 18046686Sbrian *p->name.full = '\0'; 18146686Sbrian p->name.base = p->name.full; 18246686Sbrian 18346686Sbrian p->Utmp = 0; 18446686Sbrian p->session_owner = (pid_t)-1; 18546686Sbrian 18646686Sbrian p->cfg.rts_cts = MODEM_CTSRTS; 18746686Sbrian p->cfg.speed = MODEM_SPEED; 18846686Sbrian p->cfg.parity = CS8; 18946686Sbrian memcpy(p->cfg.devlist, MODEM_LIST, sizeof MODEM_LIST); 19046686Sbrian p->cfg.ndev = NMODEMS; 19153733Sbrian p->cfg.cd.necessity = CD_DEFAULT; 19253733Sbrian p->cfg.cd.delay = 0; /* reconfigured or device specific default */ 19346686Sbrian 19446686Sbrian lcp_Init(&p->link.lcp, dl->bundle, &p->link, &dl->fsmp); 19546686Sbrian ccp_Init(&p->link.ccp, dl->bundle, &p->link, &dl->fsmp); 19646686Sbrian 19746686Sbrian return p; 19846686Sbrian} 19946686Sbrian 20046686Sbrianstatic const struct parity { 20146686Sbrian const char *name; 20246686Sbrian const char *name1; 20346686Sbrian int set; 20446686Sbrian} validparity[] = { 20546686Sbrian { "even", "P_EVEN", CS7 | PARENB }, 20646686Sbrian { "odd", "P_ODD", CS7 | PARENB | PARODD }, 20746686Sbrian { "none", "P_ZERO", CS8 }, 20846686Sbrian { NULL, 0 }, 20946686Sbrian}; 21046686Sbrian 21146686Sbrianstatic int 21246686SbrianGetParityValue(const char *str) 21346686Sbrian{ 21446686Sbrian const struct parity *pp; 21546686Sbrian 21646686Sbrian for (pp = validparity; pp->name; pp++) { 21746686Sbrian if (strcasecmp(pp->name, str) == 0 || 21846686Sbrian strcasecmp(pp->name1, str) == 0) { 21946686Sbrian return pp->set; 22046686Sbrian } 22146686Sbrian } 22246686Sbrian return (-1); 22346686Sbrian} 22446686Sbrian 22536285Sbrianint 22646686Sbrianphysical_SetParity(struct physical *p, const char *str) 22746686Sbrian{ 22846686Sbrian struct termios rstio; 22946686Sbrian int val; 23046686Sbrian 23146686Sbrian val = GetParityValue(str); 23246686Sbrian if (val > 0) { 23346686Sbrian p->cfg.parity = val; 23446686Sbrian if (p->fd >= 0) { 23546686Sbrian tcgetattr(p->fd, &rstio); 23646686Sbrian rstio.c_cflag &= ~(CSIZE | PARODD | PARENB); 23746686Sbrian rstio.c_cflag |= val; 23846686Sbrian tcsetattr(p->fd, TCSADRAIN, &rstio); 23946686Sbrian } 24046686Sbrian return 0; 24146686Sbrian } 24246686Sbrian log_Printf(LogWARN, "%s: %s: Invalid parity\n", p->link.name, str); 24346686Sbrian return -1; 24436285Sbrian} 24536285Sbrian 24636285Sbrianint 24746686Sbrianphysical_GetSpeed(struct physical *p) 24846686Sbrian{ 24946686Sbrian if (p->handler && p->handler->speed) 25046686Sbrian return (*p->handler->speed)(p); 25146686Sbrian 25249434Sbrian return 0; 25336285Sbrian} 25436285Sbrian 25546686Sbrianint 25646686Sbrianphysical_SetSpeed(struct physical *p, int speed) 25736285Sbrian{ 25846686Sbrian if (IntToSpeed(speed) != B0) { 25946686Sbrian p->cfg.speed = speed; 26046686Sbrian return 1; 26146686Sbrian } 26246686Sbrian 26346686Sbrian return 0; 26436285Sbrian} 26536285Sbrian 26646686Sbrianint 26746686Sbrianphysical_Raw(struct physical *p) 26846686Sbrian{ 26946686Sbrian if (p->handler && p->handler->raw) 27046686Sbrian return (*p->handler->raw)(p); 27146686Sbrian 27246686Sbrian return 1; 27346686Sbrian} 27446686Sbrian 27536285Sbrianvoid 27646686Sbrianphysical_Offline(struct physical *p) 27746686Sbrian{ 27846686Sbrian if (p->handler && p->handler->offline) 27946686Sbrian (*p->handler->offline)(p); 28046686Sbrian log_Printf(LogPHASE, "%s: Disconnected!\n", p->link.name); 28146686Sbrian} 28246686Sbrian 28347286Sbrianstatic int 28447286Sbrianphysical_Lock(struct physical *p) 28546686Sbrian{ 28647286Sbrian int res; 28746686Sbrian 28847286Sbrian if (*p->name.full == '/' && p->type != PHYS_DIRECT && 28947286Sbrian (res = ID0uu_lock(p->name.base)) != UU_LOCK_OK) { 29047286Sbrian if (res == UU_LOCK_INUSE) 29147286Sbrian log_Printf(LogPHASE, "%s: %s is in use\n", p->link.name, p->name.full); 29247286Sbrian else 29347286Sbrian log_Printf(LogPHASE, "%s: %s is in use: uu_lock: %s\n", 29447286Sbrian p->link.name, p->name.full, uu_lockerr(res)); 29547286Sbrian return 0; 29646686Sbrian } 29747286Sbrian 29847286Sbrian return 1; 29946686Sbrian} 30046686Sbrian 30147286Sbrianstatic void 30247286Sbrianphysical_Unlock(struct physical *p) 30347286Sbrian{ 30447286Sbrian char fn[MAXPATHLEN]; 30547286Sbrian if (*p->name.full == '/' && p->type != PHYS_DIRECT && 30647286Sbrian ID0uu_unlock(p->name.base) == -1) 30747286Sbrian log_Printf(LogALERT, "%s: Can't uu_unlock %s\n", p->link.name, fn); 30847286Sbrian} 30947286Sbrian 31046686Sbrianvoid 31146686Sbrianphysical_Close(struct physical *p) 31246686Sbrian{ 31347286Sbrian int newsid; 31447286Sbrian char fn[MAXPATHLEN]; 31547286Sbrian 31646686Sbrian if (p->fd < 0) 31746686Sbrian return; 31846686Sbrian 31946686Sbrian log_Printf(LogDEBUG, "%s: Close\n", p->link.name); 32046686Sbrian 32146686Sbrian if (p->handler && p->handler->cooked) 32246686Sbrian (*p->handler->cooked)(p); 32346686Sbrian 32447286Sbrian physical_StopDeviceTimer(p); 32547286Sbrian if (p->Utmp) { 32652429Sbrian if (p->handler && (p->handler->type == TCP_DEVICE || 32752487Sbrian p->handler->type == UDP_DEVICE)) 32852487Sbrian /* Careful - we logged in on line ``ppp'' with IP as our host */ 32952487Sbrian ID0logout(PPPOTCPLINE, 1); 33052487Sbrian else 33152487Sbrian ID0logout(p->name.base, 0); 33247286Sbrian p->Utmp = 0; 33347286Sbrian } 33447286Sbrian newsid = tcgetpgrp(p->fd) == getpgrp(); 33547286Sbrian close(p->fd); 33647286Sbrian p->fd = -1; 33747286Sbrian log_SetTtyCommandMode(p->dl); 33847286Sbrian 33947286Sbrian throughput_stop(&p->link.throughput); 34047286Sbrian throughput_log(&p->link.throughput, LogPHASE, p->link.name); 34147286Sbrian 34247286Sbrian if (p->session_owner != (pid_t)-1) { 34347286Sbrian ID0kill(p->session_owner, SIGHUP); 34447286Sbrian p->session_owner = (pid_t)-1; 34547286Sbrian } 34647286Sbrian 34747286Sbrian if (newsid) 34847286Sbrian bundle_setsid(p->dl->bundle, 0); 34947286Sbrian 35047286Sbrian if (*p->name.full == '/') { 35147286Sbrian snprintf(fn, sizeof fn, "%s%s.if", _PATH_VARRUN, p->name.base); 35247286Sbrian#ifndef RELEASE_CRUNCH 35347286Sbrian if (ID0unlink(fn) == -1) 35447286Sbrian log_Printf(LogALERT, "%s: Can't remove %s: %s\n", 35547286Sbrian p->link.name, fn, strerror(errno)); 35647286Sbrian#else 35747286Sbrian ID0unlink(fn); 35847286Sbrian#endif 35947286Sbrian } 36047286Sbrian physical_Unlock(p); 36147286Sbrian if (p->handler && p->handler->destroy) 36247286Sbrian (*p->handler->destroy)(p); 36347286Sbrian p->handler = NULL; 36447286Sbrian p->name.base = p->name.full; 36547286Sbrian *p->name.full = '\0'; 36646686Sbrian} 36746686Sbrian 36846686Sbrianvoid 36946686Sbrianphysical_Destroy(struct physical *p) 37046686Sbrian{ 37146686Sbrian physical_Close(p); 37249434Sbrian throughput_destroy(&p->link.throughput); 37346686Sbrian free(p); 37446686Sbrian} 37546686Sbrian 37646686Sbrianstatic int 37746686Sbrianphysical_DescriptorWrite(struct descriptor *d, struct bundle *bundle, 37846686Sbrian const fd_set *fdset) 37946686Sbrian{ 38046686Sbrian struct physical *p = descriptor2physical(d); 38146686Sbrian int nw, result = 0; 38246686Sbrian 38346686Sbrian if (p->out == NULL) 38446686Sbrian p->out = link_Dequeue(&p->link); 38546686Sbrian 38646686Sbrian if (p->out) { 38746686Sbrian nw = physical_Write(p, MBUF_CTOP(p->out), p->out->cnt); 38846686Sbrian log_Printf(LogDEBUG, "%s: DescriptorWrite: wrote %d(%d) to %d\n", 38946686Sbrian p->link.name, nw, p->out->cnt, p->fd); 39046686Sbrian if (nw > 0) { 39146686Sbrian p->out->cnt -= nw; 39246686Sbrian p->out->offset += nw; 39346686Sbrian if (p->out->cnt == 0) 39446686Sbrian p->out = mbuf_FreeSeg(p->out); 39546686Sbrian result = 1; 39646686Sbrian } else if (nw < 0) { 39746686Sbrian if (errno != EAGAIN) { 39846686Sbrian log_Printf(LogPHASE, "%s: write (%d): %s\n", p->link.name, 39946686Sbrian p->fd, strerror(errno)); 40046686Sbrian datalink_Down(p->dl, CLOSE_NORMAL); 40146686Sbrian } 40246686Sbrian result = 1; 40346686Sbrian } 40446686Sbrian /* else we shouldn't really have been called ! select() is broken ! */ 40546686Sbrian } 40646686Sbrian 40746686Sbrian return result; 40846686Sbrian} 40946686Sbrian 41046686Sbrianint 41146686Sbrianphysical_ShowStatus(struct cmdargs const *arg) 41246686Sbrian{ 41346686Sbrian struct physical *p = arg->cx->physical; 41453733Sbrian struct cd *cd; 41546686Sbrian const char *dev; 41646686Sbrian int n; 41746686Sbrian 41846686Sbrian prompt_Printf(arg->prompt, "Name: %s\n", p->link.name); 41946686Sbrian prompt_Printf(arg->prompt, " State: "); 42046686Sbrian if (p->fd < 0) 42146686Sbrian prompt_Printf(arg->prompt, "closed\n"); 42246686Sbrian else if (p->handler && p->handler->openinfo) 42346686Sbrian prompt_Printf(arg->prompt, "open (%s)\n", (*p->handler->openinfo)(p)); 42446686Sbrian else 42546686Sbrian prompt_Printf(arg->prompt, "open\n"); 42646686Sbrian 42746686Sbrian prompt_Printf(arg->prompt, " Device: %s", 42846686Sbrian *p->name.full ? p->name.full : 42946686Sbrian p->type == PHYS_DIRECT ? "unknown" : "N/A"); 43046686Sbrian if (p->session_owner != (pid_t)-1) 43146686Sbrian prompt_Printf(arg->prompt, " (session owner: %d)", (int)p->session_owner); 43246686Sbrian 43346686Sbrian prompt_Printf(arg->prompt, "\n Link Type: %s\n", mode2Nam(p->type)); 43446686Sbrian prompt_Printf(arg->prompt, " Connect Count: %d\n", p->connect_count); 43546686Sbrian#ifdef TIOCOUTQ 43646686Sbrian if (p->fd >= 0 && ioctl(p->fd, TIOCOUTQ, &n) >= 0) 43746686Sbrian prompt_Printf(arg->prompt, " Physical outq: %d\n", n); 43846686Sbrian#endif 43946686Sbrian 44046686Sbrian prompt_Printf(arg->prompt, " Queued Packets: %d\n", 44146686Sbrian link_QueueLen(&p->link)); 44246686Sbrian prompt_Printf(arg->prompt, " Phone Number: %s\n", arg->cx->phone.chosen); 44346686Sbrian 44446686Sbrian prompt_Printf(arg->prompt, "\nDefaults:\n"); 44546686Sbrian 44646686Sbrian prompt_Printf(arg->prompt, " Device List: "); 44746686Sbrian dev = p->cfg.devlist; 44846686Sbrian for (n = 0; n < p->cfg.ndev; n++) { 44946686Sbrian if (n) 45046686Sbrian prompt_Printf(arg->prompt, ", "); 45146686Sbrian prompt_Printf(arg->prompt, "\"%s\"", dev); 45246686Sbrian dev += strlen(dev) + 1; 45346686Sbrian } 45446686Sbrian 45546686Sbrian prompt_Printf(arg->prompt, "\n Characteristics: "); 45646686Sbrian if (physical_IsSync(arg->cx->physical)) 45746686Sbrian prompt_Printf(arg->prompt, "sync"); 45846686Sbrian else 45946686Sbrian prompt_Printf(arg->prompt, "%dbps", p->cfg.speed); 46046686Sbrian 46146686Sbrian switch (p->cfg.parity & CSIZE) { 46246686Sbrian case CS7: 46346686Sbrian prompt_Printf(arg->prompt, ", cs7"); 46446686Sbrian break; 46546686Sbrian case CS8: 46646686Sbrian prompt_Printf(arg->prompt, ", cs8"); 46746686Sbrian break; 46846686Sbrian } 46946686Sbrian if (p->cfg.parity & PARENB) { 47046686Sbrian if (p->cfg.parity & PARODD) 47146686Sbrian prompt_Printf(arg->prompt, ", odd parity"); 47246686Sbrian else 47346686Sbrian prompt_Printf(arg->prompt, ", even parity"); 47446686Sbrian } else 47546686Sbrian prompt_Printf(arg->prompt, ", no parity"); 47646686Sbrian 47746686Sbrian prompt_Printf(arg->prompt, ", CTS/RTS %s\n", (p->cfg.rts_cts ? "on" : "off")); 47846686Sbrian 47951699Sbrian prompt_Printf(arg->prompt, " CD check delay: "); 48053733Sbrian cd = p->handler ? &p->handler->cd : &p->cfg.cd; 48153733Sbrian if (cd->necessity == CD_NOTREQUIRED) 48251699Sbrian prompt_Printf(arg->prompt, "no cd"); 48353733Sbrian else if (p->cfg.cd.necessity == CD_DEFAULT) { 48453733Sbrian prompt_Printf(arg->prompt, "device specific"); 48553733Sbrian } else { 48651699Sbrian prompt_Printf(arg->prompt, "%d second%s", p->cfg.cd.delay, 48751699Sbrian p->cfg.cd.delay == 1 ? "" : "s"); 48851699Sbrian if (p->cfg.cd.necessity == CD_REQUIRED) 48951699Sbrian prompt_Printf(arg->prompt, " (required!)"); 49051699Sbrian } 49151699Sbrian prompt_Printf(arg->prompt, "\n\n"); 49246686Sbrian 49346686Sbrian throughput_disp(&p->link.throughput, arg->prompt); 49446686Sbrian 49546686Sbrian return 0; 49646686Sbrian} 49746686Sbrian 49852942Sbrianvoid 49946686Sbrianphysical_DescriptorRead(struct descriptor *d, struct bundle *bundle, 50046686Sbrian const fd_set *fdset) 50146686Sbrian{ 50246686Sbrian struct physical *p = descriptor2physical(d); 50346686Sbrian u_char *rbuff; 50446686Sbrian int n, found; 50546686Sbrian 50646686Sbrian rbuff = p->input.buf + p->input.sz; 50746686Sbrian 50846686Sbrian /* something to read */ 50946686Sbrian n = physical_Read(p, rbuff, sizeof p->input.buf - p->input.sz); 51046686Sbrian log_Printf(LogDEBUG, "%s: DescriptorRead: read %d/%d from %d\n", 51146686Sbrian p->link.name, n, (int)(sizeof p->input.buf - p->input.sz), p->fd); 51246686Sbrian if (n <= 0) { 51346686Sbrian if (n < 0) 51446686Sbrian log_Printf(LogPHASE, "%s: read (%d): %s\n", p->link.name, p->fd, 51546686Sbrian strerror(errno)); 51646686Sbrian else 51746686Sbrian log_Printf(LogPHASE, "%s: read (%d): Got zero bytes\n", 51846686Sbrian p->link.name, p->fd); 51946686Sbrian datalink_Down(p->dl, CLOSE_NORMAL); 52046686Sbrian return; 52146686Sbrian } 52246686Sbrian 52346686Sbrian rbuff -= p->input.sz; 52446686Sbrian n += p->input.sz; 52546686Sbrian 52646686Sbrian if (p->link.lcp.fsm.state <= ST_CLOSED) { 52746686Sbrian if (p->type != PHYS_DEDICATED) { 52846686Sbrian found = hdlc_Detect((u_char const **)&rbuff, n, physical_IsSync(p)); 52946686Sbrian if (rbuff != p->input.buf) 53046686Sbrian log_WritePrompts(p->dl, "%.*s", (int)(rbuff - p->input.buf), 53146686Sbrian p->input.buf); 53246686Sbrian p->input.sz = n - (rbuff - p->input.buf); 53346686Sbrian 53446686Sbrian if (found) { 53546686Sbrian /* LCP packet is detected. Turn ourselves into packet mode */ 53646686Sbrian log_Printf(LogPHASE, "%s: PPP packet detected, coming up\n", 53746686Sbrian p->link.name); 53846686Sbrian log_SetTtyCommandMode(p->dl); 53946686Sbrian datalink_Up(p->dl, 0, 1); 54046686Sbrian link_PullPacket(&p->link, rbuff, p->input.sz, bundle); 54146686Sbrian p->input.sz = 0; 54246686Sbrian } else 54346686Sbrian bcopy(rbuff, p->input.buf, p->input.sz); 54446686Sbrian } else 54546686Sbrian /* In -dedicated mode, we just discard input until LCP is started */ 54646686Sbrian p->input.sz = 0; 54746686Sbrian } else if (n > 0) 54846686Sbrian link_PullPacket(&p->link, rbuff, n, bundle); 54946686Sbrian} 55046686Sbrian 55146686Sbrianstruct physical * 55246686Sbrianiov2physical(struct datalink *dl, struct iovec *iov, int *niov, int maxiov, 55352942Sbrian int fd, int *auxfd, int *nauxfd) 55446686Sbrian{ 55546686Sbrian struct physical *p; 55647061Sbrian int len, h, type; 55746686Sbrian 55846686Sbrian p = (struct physical *)iov[(*niov)++].iov_base; 55946686Sbrian p->link.name = dl->name; 56046686Sbrian memset(p->link.Queue, '\0', sizeof p->link.Queue); 56146686Sbrian 56246686Sbrian p->desc.UpdateSet = physical_UpdateSet; 56346686Sbrian p->desc.IsSet = physical_IsSet; 56446686Sbrian p->desc.Read = physical_DescriptorRead; 56546686Sbrian p->desc.Write = physical_DescriptorWrite; 56646686Sbrian p->type = PHYS_DIRECT; 56746686Sbrian p->dl = dl; 56846686Sbrian len = strlen(_PATH_DEV); 56946686Sbrian p->out = NULL; 57046686Sbrian p->connect_count = 1; 57146686Sbrian 57247682Sbrian physical_SetDevice(p, p->name.full); 57347682Sbrian 57446686Sbrian p->link.lcp.fsm.bundle = dl->bundle; 57546686Sbrian p->link.lcp.fsm.link = &p->link; 57646686Sbrian memset(&p->link.lcp.fsm.FsmTimer, '\0', sizeof p->link.lcp.fsm.FsmTimer); 57746686Sbrian memset(&p->link.lcp.fsm.OpenTimer, '\0', sizeof p->link.lcp.fsm.OpenTimer); 57846686Sbrian memset(&p->link.lcp.fsm.StoppedTimer, '\0', 57946686Sbrian sizeof p->link.lcp.fsm.StoppedTimer); 58046686Sbrian p->link.lcp.fsm.parent = &dl->fsmp; 58146686Sbrian lcp_SetupCallbacks(&p->link.lcp); 58246686Sbrian 58346686Sbrian p->link.ccp.fsm.bundle = dl->bundle; 58446686Sbrian p->link.ccp.fsm.link = &p->link; 58546686Sbrian /* Our in.state & out.state are NULL (no link-level ccp yet) */ 58646686Sbrian memset(&p->link.ccp.fsm.FsmTimer, '\0', sizeof p->link.ccp.fsm.FsmTimer); 58746686Sbrian memset(&p->link.ccp.fsm.OpenTimer, '\0', sizeof p->link.ccp.fsm.OpenTimer); 58846686Sbrian memset(&p->link.ccp.fsm.StoppedTimer, '\0', 58946686Sbrian sizeof p->link.ccp.fsm.StoppedTimer); 59046686Sbrian p->link.ccp.fsm.parent = &dl->fsmp; 59146686Sbrian ccp_SetupCallbacks(&p->link.ccp); 59246686Sbrian 59346686Sbrian p->hdlc.lqm.owner = &p->link.lcp; 59446686Sbrian p->hdlc.ReportTimer.state = TIMER_STOPPED; 59546686Sbrian p->hdlc.lqm.timer.state = TIMER_STOPPED; 59646686Sbrian 59746686Sbrian p->fd = fd; 59849434Sbrian p->link.throughput.SampleOctets = (long long *)iov[(*niov)++].iov_base; 59946686Sbrian 60047769Sbrian type = (long)p->handler; 60147769Sbrian p->handler = NULL; 60247769Sbrian for (h = 0; h < NDEVICES && p->handler == NULL; h++) 60352942Sbrian p->handler = (*devices[h].iov2device)(type, p, iov, niov, maxiov, 60452942Sbrian auxfd, nauxfd); 60547769Sbrian if (p->handler == NULL) { 60652942Sbrian log_Printf(LogPHASE, "%s: Unknown link type\n", p->link.name); 60747769Sbrian free(iov[(*niov)++].iov_base); 60847769Sbrian physical_SetupStack(p, "unknown", PHYSICAL_NOFORCE); 60947769Sbrian } else 61047769Sbrian log_Printf(LogPHASE, "%s: Device %s, link type is %s\n", 61147769Sbrian p->link.name, p->name.full, p->handler->name); 61247769Sbrian 61346686Sbrian if (p->hdlc.lqm.method && p->hdlc.lqm.timer.load) 61446686Sbrian lqr_reStart(&p->link.lcp); 61546686Sbrian hdlc_StartTimer(&p->hdlc); 61646686Sbrian 61749434Sbrian throughput_restart(&p->link.throughput, "physical throughput", 61849434Sbrian Enabled(dl->bundle, OPT_THROUGHPUT)); 61946686Sbrian 62047769Sbrian return p; 62147769Sbrian} 62247061Sbrian 62347769Sbrianint 62447769Sbrianphysical_MaxDeviceSize() 62547769Sbrian{ 62647769Sbrian int biggest, sz, n; 62747061Sbrian 62847769Sbrian biggest = sizeof(struct device); 62947769Sbrian for (sz = n = 0; n < NDEVICES; n++) 63047769Sbrian if (devices[n].DeviceSize) { 63147769Sbrian sz = (*devices[n].DeviceSize)(); 63247769Sbrian if (biggest < sz) 63347769Sbrian biggest = sz; 63447769Sbrian } 63547769Sbrian 63647769Sbrian return biggest; 63746686Sbrian} 63846686Sbrian 63946686Sbrianint 64046686Sbrianphysical2iov(struct physical *p, struct iovec *iov, int *niov, int maxiov, 64153684Sbrian int *auxfd, int *nauxfd) 64246686Sbrian{ 64347769Sbrian struct device *h; 64447769Sbrian int sz; 64547769Sbrian 64647769Sbrian h = NULL; 64746686Sbrian if (p) { 64846686Sbrian hdlc_StopTimer(&p->hdlc); 64946686Sbrian lqr_StopTimer(p); 65046686Sbrian timer_Stop(&p->link.lcp.fsm.FsmTimer); 65146686Sbrian timer_Stop(&p->link.ccp.fsm.FsmTimer); 65246686Sbrian timer_Stop(&p->link.lcp.fsm.OpenTimer); 65346686Sbrian timer_Stop(&p->link.ccp.fsm.OpenTimer); 65446686Sbrian timer_Stop(&p->link.lcp.fsm.StoppedTimer); 65546686Sbrian timer_Stop(&p->link.ccp.fsm.StoppedTimer); 65647061Sbrian if (p->handler) { 65753684Sbrian h = p->handler; 65847061Sbrian p->handler = (struct device *)(long)p->handler->type; 65946686Sbrian } 66047061Sbrian 66147689Sbrian if (Enabled(p->dl->bundle, OPT_KEEPSESSION) || 66247689Sbrian tcgetpgrp(p->fd) == getpgrp()) 66346686Sbrian p->session_owner = getpid(); /* So I'll eventually get HUP'd */ 66447689Sbrian else 66547689Sbrian p->session_owner = (pid_t)-1; 66646686Sbrian timer_Stop(&p->link.throughput.Timer); 66746686Sbrian } 66846686Sbrian 66949434Sbrian if (*niov + 2 >= maxiov) { 67049434Sbrian log_Printf(LogERROR, "physical2iov: No room for physical + throughput" 67149434Sbrian " + device !\n"); 67246686Sbrian if (p) 67346686Sbrian free(p); 67446686Sbrian return -1; 67546686Sbrian } 67646686Sbrian 67753684Sbrian iov[*niov].iov_base = (void *)p; 67846686Sbrian iov[*niov].iov_len = sizeof *p; 67946686Sbrian (*niov)++; 68046686Sbrian 68153684Sbrian iov[*niov].iov_base = p ? (void *)p->link.throughput.SampleOctets : NULL; 68249434Sbrian iov[*niov].iov_len = SAMPLE_PERIOD * sizeof(long long); 68349434Sbrian (*niov)++; 68449434Sbrian 68547769Sbrian sz = physical_MaxDeviceSize(); 68647769Sbrian if (p) { 68753684Sbrian if (h && h->device2iov) 68853684Sbrian (*h->device2iov)(h, iov, niov, maxiov, auxfd, nauxfd); 68947769Sbrian else { 69047769Sbrian iov[*niov].iov_base = malloc(sz); 69153684Sbrian if (h) 69253684Sbrian memcpy(iov[*niov].iov_base, h, sizeof *h); 69347769Sbrian iov[*niov].iov_len = sz; 69447769Sbrian (*niov)++; 69547769Sbrian } 69647769Sbrian } else { 69753684Sbrian iov[*niov].iov_base = NULL; 69847769Sbrian iov[*niov].iov_len = sz; 69947769Sbrian (*niov)++; 70047769Sbrian } 70147769Sbrian 70246686Sbrian return p ? p->fd : 0; 70346686Sbrian} 70446686Sbrian 70553684Sbrianconst char * 70653684Sbrianphysical_LockedDevice(struct physical *p) 70753684Sbrian{ 70853684Sbrian if (p->fd >= 0 && *p->name.full == '/' && p->type != PHYS_DIRECT) 70953684Sbrian return p->name.base; 71053684Sbrian 71153684Sbrian return NULL; 71253684Sbrian} 71353684Sbrian 71446686Sbrianvoid 71546686Sbrianphysical_ChangedPid(struct physical *p, pid_t newpid) 71646686Sbrian{ 71753684Sbrian if (physical_LockedDevice(p)) { 71846686Sbrian int res; 71946686Sbrian 72046686Sbrian if ((res = ID0uu_lock_txfr(p->name.base, newpid)) != UU_LOCK_OK) 72146686Sbrian log_Printf(LogPHASE, "uu_lock_txfr: %s\n", uu_lockerr(res)); 72246686Sbrian } 72346686Sbrian} 72446686Sbrian 72546686Sbrianint 72646686Sbrianphysical_IsSync(struct physical *p) 72746686Sbrian{ 72846686Sbrian return p->cfg.speed == 0; 72946686Sbrian} 73046686Sbrian 73146686Sbrianconst char *physical_GetDevice(struct physical *p) 73246686Sbrian{ 73346686Sbrian return p->name.full; 73446686Sbrian} 73546686Sbrian 73646686Sbrianvoid 73736285Sbrianphysical_SetDeviceList(struct physical *p, int argc, const char *const *argv) 73836285Sbrian{ 73936285Sbrian int f, pos; 74036285Sbrian 74136285Sbrian p->cfg.devlist[sizeof p->cfg.devlist - 1] = '\0'; 74236285Sbrian for (f = 0, pos = 0; f < argc && pos < sizeof p->cfg.devlist - 1; f++) { 74336285Sbrian if (pos) 74446102Sbrian p->cfg.devlist[pos++] = '\0'; 74536285Sbrian strncpy(p->cfg.devlist + pos, argv[f], sizeof p->cfg.devlist - pos - 1); 74636285Sbrian pos += strlen(p->cfg.devlist + pos); 74736285Sbrian } 74846102Sbrian p->cfg.ndev = f; 74936285Sbrian} 75036285Sbrian 75136285Sbrianvoid 75246686Sbrianphysical_SetSync(struct physical *p) 75346686Sbrian{ 75446686Sbrian p->cfg.speed = 0; 75536285Sbrian} 75636285Sbrian 75736285Sbrianint 75846686Sbrianphysical_SetRtsCts(struct physical *p, int enable) 75946686Sbrian{ 76046686Sbrian p->cfg.rts_cts = enable ? 1 : 0; 76136285Sbrian return 1; 76236285Sbrian} 76336285Sbrian 76436285Sbrianssize_t 76546686Sbrianphysical_Read(struct physical *p, void *buf, size_t nbytes) 76646686Sbrian{ 76747061Sbrian ssize_t ret; 76847061Sbrian 76947061Sbrian if (p->handler && p->handler->read) 77047061Sbrian ret = (*p->handler->read)(p, buf, nbytes); 77147061Sbrian else 77247061Sbrian ret = read(p->fd, buf, nbytes); 77347061Sbrian 77447061Sbrian log_DumpBuff(LogPHYSICAL, "read", buf, ret); 77547061Sbrian 77647061Sbrian return ret; 77736285Sbrian} 77836285Sbrian 77936285Sbrianssize_t 78046686Sbrianphysical_Write(struct physical *p, const void *buf, size_t nbytes) 78146686Sbrian{ 78247061Sbrian log_DumpBuff(LogPHYSICAL, "write", buf, nbytes); 78347061Sbrian 78447061Sbrian if (p->handler && p->handler->write) 78547061Sbrian return (*p->handler->write)(p, buf, nbytes); 78647061Sbrian 78747061Sbrian return write(p->fd, buf, nbytes); 78836285Sbrian} 78936285Sbrian 79036285Sbrianint 79146686Sbrianphysical_doUpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, 79246686Sbrian int *n, int force) 79336285Sbrian{ 79436285Sbrian struct physical *p = descriptor2physical(d); 79536285Sbrian int sets; 79636285Sbrian 79736285Sbrian sets = 0; 79836285Sbrian if (p->fd >= 0) { 79936285Sbrian if (r) { 80036285Sbrian FD_SET(p->fd, r); 80136285Sbrian log_Printf(LogTIMER, "%s: fdset(r) %d\n", p->link.name, p->fd); 80236285Sbrian sets++; 80336285Sbrian } 80436285Sbrian if (e) { 80536285Sbrian FD_SET(p->fd, e); 80636285Sbrian log_Printf(LogTIMER, "%s: fdset(e) %d\n", p->link.name, p->fd); 80736285Sbrian sets++; 80836285Sbrian } 80936314Sbrian if (w && (force || link_QueueLen(&p->link) || p->out)) { 81036285Sbrian FD_SET(p->fd, w); 81136285Sbrian log_Printf(LogTIMER, "%s: fdset(w) %d\n", p->link.name, p->fd); 81236285Sbrian sets++; 81336285Sbrian } 81436285Sbrian if (sets && *n < p->fd + 1) 81536285Sbrian *n = p->fd + 1; 81636285Sbrian } 81736285Sbrian 81836285Sbrian return sets; 81936285Sbrian} 82036285Sbrian 82136285Sbrianint 82236285Sbrianphysical_RemoveFromSet(struct physical *p, fd_set *r, fd_set *w, fd_set *e) 82336285Sbrian{ 82452942Sbrian if (p->handler && p->handler->removefromset) 82552942Sbrian return (*p->handler->removefromset)(p, r, w, e); 82652942Sbrian else { 82752942Sbrian int sets; 82836285Sbrian 82952942Sbrian sets = 0; 83052942Sbrian if (p->fd >= 0) { 83152942Sbrian if (r && FD_ISSET(p->fd, r)) { 83252942Sbrian FD_CLR(p->fd, r); 83352942Sbrian log_Printf(LogTIMER, "%s: fdunset(r) %d\n", p->link.name, p->fd); 83452942Sbrian sets++; 83552942Sbrian } 83652942Sbrian if (e && FD_ISSET(p->fd, e)) { 83752942Sbrian FD_CLR(p->fd, e); 83852942Sbrian log_Printf(LogTIMER, "%s: fdunset(e) %d\n", p->link.name, p->fd); 83952942Sbrian sets++; 84052942Sbrian } 84152942Sbrian if (w && FD_ISSET(p->fd, w)) { 84252942Sbrian FD_CLR(p->fd, w); 84352942Sbrian log_Printf(LogTIMER, "%s: fdunset(w) %d\n", p->link.name, p->fd); 84452942Sbrian sets++; 84552942Sbrian } 84636285Sbrian } 84752942Sbrian 84852942Sbrian return sets; 84936285Sbrian } 85036285Sbrian} 85136285Sbrian 85236285Sbrianint 85336285Sbrianphysical_IsSet(struct descriptor *d, const fd_set *fdset) 85436285Sbrian{ 85536285Sbrian struct physical *p = descriptor2physical(d); 85636285Sbrian return p->fd >= 0 && FD_ISSET(p->fd, fdset); 85736285Sbrian} 85836285Sbrian 85936285Sbrianvoid 86046686Sbrianphysical_Login(struct physical *p, const char *name) 86136285Sbrian{ 86246830Sbrian if (p->type == PHYS_DIRECT && *p->name.base && !p->Utmp) { 86346686Sbrian struct utmp ut; 86446686Sbrian const char *connstr; 86552413Sbrian char *colon; 86636285Sbrian 86746686Sbrian memset(&ut, 0, sizeof ut); 86846686Sbrian time(&ut.ut_time); 86946686Sbrian strncpy(ut.ut_name, name, sizeof ut.ut_name); 87052413Sbrian if (p->handler && (p->handler->type == TCP_DEVICE || 87152413Sbrian p->handler->type == UDP_DEVICE)) { 87252429Sbrian strncpy(ut.ut_line, PPPOTCPLINE, sizeof ut.ut_line); 87352413Sbrian strncpy(ut.ut_host, p->name.base, sizeof ut.ut_host); 87452413Sbrian colon = memchr(ut.ut_host, ':', sizeof ut.ut_host); 87552413Sbrian if (colon) 87652413Sbrian *colon = '\0'; 87752413Sbrian } else 87852413Sbrian strncpy(ut.ut_line, p->name.base, sizeof ut.ut_line); 87946686Sbrian if ((connstr = getenv("CONNECT"))) 88046686Sbrian /* mgetty sets this to the connection speed */ 88146686Sbrian strncpy(ut.ut_host, connstr, sizeof ut.ut_host); 88246686Sbrian ID0login(&ut); 88352429Sbrian p->Utmp = ut.ut_time; 88436285Sbrian } 88536285Sbrian} 88636285Sbrian 88736285Sbrianint 88836285Sbrianphysical_SetMode(struct physical *p, int mode) 88936285Sbrian{ 89038174Sbrian if ((p->type & (PHYS_DIRECT|PHYS_DEDICATED) || 89138174Sbrian mode & (PHYS_DIRECT|PHYS_DEDICATED)) && 89238174Sbrian (!(p->type & PHYS_DIRECT) || !(mode & PHYS_BACKGROUND))) { 89353830Sbrian /* Note: The -direct -> -background is for callback ! */ 89436285Sbrian log_Printf(LogWARN, "%s: Cannot change mode %s to %s\n", p->link.name, 89536285Sbrian mode2Nam(p->type), mode2Nam(mode)); 89636285Sbrian return 0; 89736285Sbrian } 89836285Sbrian p->type = mode; 89936285Sbrian return 1; 90036285Sbrian} 90138544Sbrian 90238544Sbrianvoid 90338544Sbrianphysical_DeleteQueue(struct physical *p) 90438544Sbrian{ 90538544Sbrian if (p->out) { 90638544Sbrian mbuf_Free(p->out); 90738544Sbrian p->out = NULL; 90838544Sbrian } 90938544Sbrian link_DeleteQueue(&p->link); 91038544Sbrian} 91146686Sbrian 91246686Sbrianvoid 91346686Sbrianphysical_SetDevice(struct physical *p, const char *name) 91446686Sbrian{ 91546686Sbrian int len = strlen(_PATH_DEV); 91646686Sbrian 91747682Sbrian if (name != p->name.full) { 91847682Sbrian strncpy(p->name.full, name, sizeof p->name.full - 1); 91947682Sbrian p->name.full[sizeof p->name.full - 1] = '\0'; 92047682Sbrian } 92146686Sbrian p->name.base = *p->name.full == '!' ? p->name.full + 1 : 92246686Sbrian strncmp(p->name.full, _PATH_DEV, len) ? 92346686Sbrian p->name.full : p->name.full + len; 92446686Sbrian} 92546686Sbrian 92646686Sbrianstatic void 92746686Sbrianphysical_Found(struct physical *p) 92846686Sbrian{ 92947286Sbrian FILE *lockfile; 93047286Sbrian char fn[MAXPATHLEN]; 93147286Sbrian 93247286Sbrian if (*p->name.full == '/') { 93347286Sbrian snprintf(fn, sizeof fn, "%s%s.if", _PATH_VARRUN, p->name.base); 93447286Sbrian lockfile = ID0fopen(fn, "w"); 93547286Sbrian if (lockfile != NULL) { 93647286Sbrian fprintf(lockfile, "%s%d\n", TUN_NAME, p->dl->bundle->unit); 93747286Sbrian fclose(lockfile); 93847286Sbrian } 93947286Sbrian#ifndef RELEASE_CRUNCH 94047286Sbrian else 94147286Sbrian log_Printf(LogALERT, "%s: Can't create %s: %s\n", 94247286Sbrian p->link.name, fn, strerror(errno)); 94347286Sbrian#endif 94447286Sbrian } 94547286Sbrian 94646686Sbrian throughput_start(&p->link.throughput, "physical throughput", 94746686Sbrian Enabled(p->dl->bundle, OPT_THROUGHPUT)); 94846686Sbrian p->connect_count++; 94946686Sbrian p->input.sz = 0; 95046686Sbrian 95146686Sbrian log_Printf(LogPHASE, "%s: Connected!\n", p->link.name); 95246686Sbrian} 95346686Sbrian 95446686Sbrianint 95546686Sbrianphysical_Open(struct physical *p, struct bundle *bundle) 95646686Sbrian{ 95752942Sbrian int devno, h, wasfd, err; 95846686Sbrian char *dev; 95946686Sbrian 96046686Sbrian if (p->fd >= 0) 96146686Sbrian log_Printf(LogDEBUG, "%s: Open: Modem is already open!\n", p->link.name); 96246686Sbrian /* We're going back into "term" mode */ 96346686Sbrian else if (p->type == PHYS_DIRECT) { 96447061Sbrian physical_SetDevice(p, ""); 96547061Sbrian p->fd = STDIN_FILENO; 96647061Sbrian for (h = 0; h < NDEVICES && p->handler == NULL && p->fd >= 0; h++) 96752942Sbrian p->handler = (*devices[h].create)(p); 96847061Sbrian if (p->fd >= 0) { 96947124Sbrian if (p->handler == NULL) { 97047461Sbrian physical_SetupStack(p, "unknown", PHYSICAL_NOFORCE); 97147124Sbrian log_Printf(LogDEBUG, "%s: stdin is unidentified\n", p->link.name); 97247124Sbrian } 97346686Sbrian physical_Found(p); 97446686Sbrian } 97546686Sbrian } else { 97646686Sbrian dev = p->cfg.devlist; 97746686Sbrian devno = 0; 97846686Sbrian while (devno < p->cfg.ndev && p->fd < 0) { 97946686Sbrian physical_SetDevice(p, dev); 98047286Sbrian if (physical_Lock(p)) { 98147878Sbrian err = 0; 98247878Sbrian 98347878Sbrian if (*p->name.full == '/') { 98447286Sbrian p->fd = ID0open(p->name.full, O_RDWR | O_NONBLOCK); 98547878Sbrian if (p->fd < 0) 98647878Sbrian err = errno; 98747878Sbrian } 98846686Sbrian 98952942Sbrian wasfd = p->fd; 99047286Sbrian for (h = 0; h < NDEVICES && p->handler == NULL; h++) 99152942Sbrian if ((p->handler = (*devices[h].create)(p)) == NULL && wasfd != p->fd) 99247286Sbrian break; 99346686Sbrian 99447286Sbrian if (p->fd < 0) { 99547878Sbrian if (h == NDEVICES) { 99647878Sbrian if (err) 99747878Sbrian log_Printf(LogWARN, "%s: %s: %s\n", p->link.name, p->name.full, 99847878Sbrian strerror(errno)); 99947878Sbrian else 100047878Sbrian log_Printf(LogWARN, "%s: Device (%s) must begin with a '/'," 100152942Sbrian " a '!' or contain at least one ':'\n", p->link.name, 100247878Sbrian p->name.full); 100347878Sbrian } 100447286Sbrian physical_Unlock(p); 100547286Sbrian } else 100647286Sbrian physical_Found(p); 100747286Sbrian } 100846686Sbrian dev += strlen(dev) + 1; 100946686Sbrian devno++; 101046686Sbrian } 101146686Sbrian } 101246686Sbrian 101346686Sbrian return p->fd; 101446686Sbrian} 101546686Sbrian 101646686Sbrianvoid 101747461Sbrianphysical_SetupStack(struct physical *p, const char *who, int how) 101846686Sbrian{ 101946686Sbrian link_EmptyStack(&p->link); 102052942Sbrian if (how == PHYSICAL_FORCE_SYNC || how == PHYSICAL_FORCE_SYNCNOACF || 102147061Sbrian (how == PHYSICAL_NOFORCE && physical_IsSync(p))) 102246686Sbrian link_Stack(&p->link, &synclayer); 102346686Sbrian else { 102446686Sbrian link_Stack(&p->link, &asynclayer); 102546686Sbrian link_Stack(&p->link, &hdlclayer); 102646686Sbrian } 102752942Sbrian if (how != PHYSICAL_FORCE_SYNCNOACF) 102852942Sbrian link_Stack(&p->link, &acflayer); 102946686Sbrian link_Stack(&p->link, &protolayer); 103046686Sbrian link_Stack(&p->link, &lqrlayer); 103146686Sbrian link_Stack(&p->link, &ccplayer); 103246686Sbrian link_Stack(&p->link, &vjlayer); 103350059Sbrian#ifndef NONAT 103450059Sbrian link_Stack(&p->link, &natlayer); 103546686Sbrian#endif 103647061Sbrian if (how == PHYSICAL_FORCE_ASYNC && physical_IsSync(p)) { 103747461Sbrian log_Printf(LogWARN, "Sync device setting ignored for ``%s'' device\n", who); 103847061Sbrian p->cfg.speed = MODEM_SPEED; 103947061Sbrian } else if (how == PHYSICAL_FORCE_SYNC && !physical_IsSync(p)) { 104047061Sbrian log_Printf(LogWARN, "Async device setting ignored for ``%s'' device\n", 104147461Sbrian who); 104247061Sbrian physical_SetSync(p); 104347061Sbrian } 104446686Sbrian} 104547061Sbrian 104647061Sbrianvoid 104747061Sbrianphysical_StopDeviceTimer(struct physical *p) 104847061Sbrian{ 104947061Sbrian if (p->handler && p->handler->stoptimer) 105047061Sbrian (*p->handler->stoptimer)(p); 105147061Sbrian} 105249472Sbrian 105349472Sbrianint 105449472Sbrianphysical_AwaitCarrier(struct physical *p) 105549472Sbrian{ 105649472Sbrian if (p->handler && p->handler->awaitcarrier) 105749472Sbrian return (*p->handler->awaitcarrier)(p); 105849472Sbrian 105949472Sbrian return CARRIER_OK; 106049472Sbrian} 1061