physical.c revision 50479
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 50479 1999-08-28 01:35:59Z peter $ 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 4946686Sbrian#include "alias_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 9336285Sbrian 9436285Sbrian 9546686Sbrianstatic int physical_DescriptorWrite(struct descriptor *, struct bundle *, 9646686Sbrian const fd_set *); 9746686Sbrianstatic void physical_DescriptorRead(struct descriptor *, struct bundle *, 9846686Sbrian const fd_set *); 9936285Sbrian 10047769Sbrianstatic int 10147769Sbrianphysical_DeviceSize(void) 10247769Sbrian{ 10347769Sbrian return sizeof(struct device); 10447769Sbrian} 10547769Sbrian 10647061Sbrianstruct { 10747061Sbrian struct device *(*create)(struct physical *); 10847061Sbrian struct device *(*iov2device)(int, struct physical *, struct iovec *iov, 10947061Sbrian int *niov, int maxiov); 11047769Sbrian int (*DeviceSize)(void); 11147061Sbrian} devices[] = { 11249472Sbrian#ifndef NOI4B 11349472Sbrian { i4b_Create, i4b_iov2device, i4b_DeviceSize }, 11449472Sbrian#endif 11547769Sbrian { tty_Create, tty_iov2device, tty_DeviceSize }, 11647769Sbrian { tcp_Create, tcp_iov2device, tcp_DeviceSize }, 11747769Sbrian { udp_Create, udp_iov2device, udp_DeviceSize }, 11847769Sbrian { exec_Create, exec_iov2device, exec_DeviceSize } 11946686Sbrian}; 12046686Sbrian 12147061Sbrian#define NDEVICES (sizeof devices / sizeof devices[0]) 12246686Sbrian 12346686Sbrianstatic int 12446686Sbrianphysical_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, 12546686Sbrian int *n) 12646686Sbrian{ 12746686Sbrian return physical_doUpdateSet(d, r, w, e, n, 0); 12846686Sbrian} 12946686Sbrian 13046686Sbrianstruct physical * 13146686Sbrianphysical_Create(struct datalink *dl, int type) 13246686Sbrian{ 13346686Sbrian struct physical *p; 13446686Sbrian 13546686Sbrian p = (struct physical *)malloc(sizeof(struct physical)); 13646686Sbrian if (!p) 13746686Sbrian return NULL; 13846686Sbrian 13946686Sbrian p->link.type = PHYSICAL_LINK; 14046686Sbrian p->link.name = dl->name; 14146686Sbrian p->link.len = sizeof *p; 14246686Sbrian 14349434Sbrian /* The sample period is fixed - see physical2iov() & iov2physical() */ 14449434Sbrian throughput_init(&p->link.throughput, SAMPLE_PERIOD); 14549434Sbrian 14646686Sbrian memset(p->link.Queue, '\0', sizeof p->link.Queue); 14746686Sbrian memset(p->link.proto_in, '\0', sizeof p->link.proto_in); 14846686Sbrian memset(p->link.proto_out, '\0', sizeof p->link.proto_out); 14946686Sbrian link_EmptyStack(&p->link); 15046686Sbrian 15146686Sbrian p->handler = NULL; 15246686Sbrian p->desc.type = PHYSICAL_DESCRIPTOR; 15346686Sbrian p->desc.UpdateSet = physical_UpdateSet; 15446686Sbrian p->desc.IsSet = physical_IsSet; 15546686Sbrian p->desc.Read = physical_DescriptorRead; 15646686Sbrian p->desc.Write = physical_DescriptorWrite; 15746686Sbrian p->type = type; 15846686Sbrian 15946686Sbrian hdlc_Init(&p->hdlc, &p->link.lcp); 16046686Sbrian async_Init(&p->async); 16146686Sbrian 16246686Sbrian p->fd = -1; 16346686Sbrian p->out = NULL; 16446686Sbrian p->connect_count = 0; 16546686Sbrian p->dl = dl; 16646686Sbrian p->input.sz = 0; 16746686Sbrian *p->name.full = '\0'; 16846686Sbrian p->name.base = p->name.full; 16946686Sbrian 17046686Sbrian p->Utmp = 0; 17146686Sbrian p->session_owner = (pid_t)-1; 17246686Sbrian 17346686Sbrian p->cfg.rts_cts = MODEM_CTSRTS; 17446686Sbrian p->cfg.speed = MODEM_SPEED; 17546686Sbrian p->cfg.parity = CS8; 17646686Sbrian memcpy(p->cfg.devlist, MODEM_LIST, sizeof MODEM_LIST); 17746686Sbrian p->cfg.ndev = NMODEMS; 17846686Sbrian p->cfg.cd.required = 0; 17946686Sbrian p->cfg.cd.delay = DEF_CDDELAY; 18046686Sbrian 18146686Sbrian lcp_Init(&p->link.lcp, dl->bundle, &p->link, &dl->fsmp); 18246686Sbrian ccp_Init(&p->link.ccp, dl->bundle, &p->link, &dl->fsmp); 18346686Sbrian 18446686Sbrian return p; 18546686Sbrian} 18646686Sbrian 18746686Sbrianstatic const struct parity { 18846686Sbrian const char *name; 18946686Sbrian const char *name1; 19046686Sbrian int set; 19146686Sbrian} validparity[] = { 19246686Sbrian { "even", "P_EVEN", CS7 | PARENB }, 19346686Sbrian { "odd", "P_ODD", CS7 | PARENB | PARODD }, 19446686Sbrian { "none", "P_ZERO", CS8 }, 19546686Sbrian { NULL, 0 }, 19646686Sbrian}; 19746686Sbrian 19846686Sbrianstatic int 19946686SbrianGetParityValue(const char *str) 20046686Sbrian{ 20146686Sbrian const struct parity *pp; 20246686Sbrian 20346686Sbrian for (pp = validparity; pp->name; pp++) { 20446686Sbrian if (strcasecmp(pp->name, str) == 0 || 20546686Sbrian strcasecmp(pp->name1, str) == 0) { 20646686Sbrian return pp->set; 20746686Sbrian } 20846686Sbrian } 20946686Sbrian return (-1); 21046686Sbrian} 21146686Sbrian 21236285Sbrianint 21346686Sbrianphysical_SetParity(struct physical *p, const char *str) 21446686Sbrian{ 21546686Sbrian struct termios rstio; 21646686Sbrian int val; 21746686Sbrian 21846686Sbrian val = GetParityValue(str); 21946686Sbrian if (val > 0) { 22046686Sbrian p->cfg.parity = val; 22146686Sbrian if (p->fd >= 0) { 22246686Sbrian tcgetattr(p->fd, &rstio); 22346686Sbrian rstio.c_cflag &= ~(CSIZE | PARODD | PARENB); 22446686Sbrian rstio.c_cflag |= val; 22546686Sbrian tcsetattr(p->fd, TCSADRAIN, &rstio); 22646686Sbrian } 22746686Sbrian return 0; 22846686Sbrian } 22946686Sbrian log_Printf(LogWARN, "%s: %s: Invalid parity\n", p->link.name, str); 23046686Sbrian return -1; 23136285Sbrian} 23236285Sbrian 23336285Sbrianint 23446686Sbrianphysical_GetSpeed(struct physical *p) 23546686Sbrian{ 23646686Sbrian if (p->handler && p->handler->speed) 23746686Sbrian return (*p->handler->speed)(p); 23846686Sbrian 23949434Sbrian return 0; 24036285Sbrian} 24136285Sbrian 24246686Sbrianint 24346686Sbrianphysical_SetSpeed(struct physical *p, int speed) 24436285Sbrian{ 24546686Sbrian if (IntToSpeed(speed) != B0) { 24646686Sbrian p->cfg.speed = speed; 24746686Sbrian return 1; 24846686Sbrian } 24946686Sbrian 25046686Sbrian return 0; 25136285Sbrian} 25236285Sbrian 25346686Sbrianint 25446686Sbrianphysical_Raw(struct physical *p) 25546686Sbrian{ 25646686Sbrian if (p->handler && p->handler->raw) 25746686Sbrian return (*p->handler->raw)(p); 25846686Sbrian 25946686Sbrian return 1; 26046686Sbrian} 26146686Sbrian 26236285Sbrianvoid 26346686Sbrianphysical_Offline(struct physical *p) 26446686Sbrian{ 26546686Sbrian if (p->handler && p->handler->offline) 26646686Sbrian (*p->handler->offline)(p); 26746686Sbrian log_Printf(LogPHASE, "%s: Disconnected!\n", p->link.name); 26846686Sbrian} 26946686Sbrian 27047286Sbrianstatic int 27147286Sbrianphysical_Lock(struct physical *p) 27246686Sbrian{ 27347286Sbrian int res; 27446686Sbrian 27547286Sbrian if (*p->name.full == '/' && p->type != PHYS_DIRECT && 27647286Sbrian (res = ID0uu_lock(p->name.base)) != UU_LOCK_OK) { 27747286Sbrian if (res == UU_LOCK_INUSE) 27847286Sbrian log_Printf(LogPHASE, "%s: %s is in use\n", p->link.name, p->name.full); 27947286Sbrian else 28047286Sbrian log_Printf(LogPHASE, "%s: %s is in use: uu_lock: %s\n", 28147286Sbrian p->link.name, p->name.full, uu_lockerr(res)); 28247286Sbrian return 0; 28346686Sbrian } 28447286Sbrian 28547286Sbrian return 1; 28646686Sbrian} 28746686Sbrian 28847286Sbrianstatic void 28947286Sbrianphysical_Unlock(struct physical *p) 29047286Sbrian{ 29147286Sbrian char fn[MAXPATHLEN]; 29247286Sbrian if (*p->name.full == '/' && p->type != PHYS_DIRECT && 29347286Sbrian ID0uu_unlock(p->name.base) == -1) 29447286Sbrian log_Printf(LogALERT, "%s: Can't uu_unlock %s\n", p->link.name, fn); 29547286Sbrian} 29647286Sbrian 29746686Sbrianvoid 29846686Sbrianphysical_Close(struct physical *p) 29946686Sbrian{ 30047286Sbrian int newsid; 30147286Sbrian char fn[MAXPATHLEN]; 30247286Sbrian 30346686Sbrian if (p->fd < 0) 30446686Sbrian return; 30546686Sbrian 30646686Sbrian log_Printf(LogDEBUG, "%s: Close\n", p->link.name); 30746686Sbrian 30846686Sbrian if (p->handler && p->handler->cooked) 30946686Sbrian (*p->handler->cooked)(p); 31046686Sbrian 31147286Sbrian physical_StopDeviceTimer(p); 31247286Sbrian if (p->Utmp) { 31347286Sbrian ID0logout(p->name.base); 31447286Sbrian p->Utmp = 0; 31547286Sbrian } 31647286Sbrian newsid = tcgetpgrp(p->fd) == getpgrp(); 31747286Sbrian close(p->fd); 31847286Sbrian p->fd = -1; 31947286Sbrian log_SetTtyCommandMode(p->dl); 32047286Sbrian 32147286Sbrian throughput_stop(&p->link.throughput); 32247286Sbrian throughput_log(&p->link.throughput, LogPHASE, p->link.name); 32347286Sbrian 32447286Sbrian if (p->session_owner != (pid_t)-1) { 32547286Sbrian ID0kill(p->session_owner, SIGHUP); 32647286Sbrian p->session_owner = (pid_t)-1; 32747286Sbrian } 32847286Sbrian 32947286Sbrian if (newsid) 33047286Sbrian bundle_setsid(p->dl->bundle, 0); 33147286Sbrian 33247286Sbrian if (*p->name.full == '/') { 33347286Sbrian snprintf(fn, sizeof fn, "%s%s.if", _PATH_VARRUN, p->name.base); 33447286Sbrian#ifndef RELEASE_CRUNCH 33547286Sbrian if (ID0unlink(fn) == -1) 33647286Sbrian log_Printf(LogALERT, "%s: Can't remove %s: %s\n", 33747286Sbrian p->link.name, fn, strerror(errno)); 33847286Sbrian#else 33947286Sbrian ID0unlink(fn); 34047286Sbrian#endif 34147286Sbrian } 34247286Sbrian physical_Unlock(p); 34347286Sbrian if (p->handler && p->handler->destroy) 34447286Sbrian (*p->handler->destroy)(p); 34547286Sbrian p->handler = NULL; 34647286Sbrian p->name.base = p->name.full; 34747286Sbrian *p->name.full = '\0'; 34846686Sbrian} 34946686Sbrian 35046686Sbrianvoid 35146686Sbrianphysical_Destroy(struct physical *p) 35246686Sbrian{ 35346686Sbrian physical_Close(p); 35449434Sbrian throughput_destroy(&p->link.throughput); 35546686Sbrian free(p); 35646686Sbrian} 35746686Sbrian 35846686Sbrianstatic int 35946686Sbrianphysical_DescriptorWrite(struct descriptor *d, struct bundle *bundle, 36046686Sbrian const fd_set *fdset) 36146686Sbrian{ 36246686Sbrian struct physical *p = descriptor2physical(d); 36346686Sbrian int nw, result = 0; 36446686Sbrian 36546686Sbrian if (p->out == NULL) 36646686Sbrian p->out = link_Dequeue(&p->link); 36746686Sbrian 36846686Sbrian if (p->out) { 36946686Sbrian nw = physical_Write(p, MBUF_CTOP(p->out), p->out->cnt); 37046686Sbrian log_Printf(LogDEBUG, "%s: DescriptorWrite: wrote %d(%d) to %d\n", 37146686Sbrian p->link.name, nw, p->out->cnt, p->fd); 37246686Sbrian if (nw > 0) { 37346686Sbrian p->out->cnt -= nw; 37446686Sbrian p->out->offset += nw; 37546686Sbrian if (p->out->cnt == 0) 37646686Sbrian p->out = mbuf_FreeSeg(p->out); 37746686Sbrian result = 1; 37846686Sbrian } else if (nw < 0) { 37946686Sbrian if (errno != EAGAIN) { 38046686Sbrian log_Printf(LogPHASE, "%s: write (%d): %s\n", p->link.name, 38146686Sbrian p->fd, strerror(errno)); 38246686Sbrian datalink_Down(p->dl, CLOSE_NORMAL); 38346686Sbrian } 38446686Sbrian result = 1; 38546686Sbrian } 38646686Sbrian /* else we shouldn't really have been called ! select() is broken ! */ 38746686Sbrian } 38846686Sbrian 38946686Sbrian return result; 39046686Sbrian} 39146686Sbrian 39246686Sbrianint 39346686Sbrianphysical_ShowStatus(struct cmdargs const *arg) 39446686Sbrian{ 39546686Sbrian struct physical *p = arg->cx->physical; 39646686Sbrian const char *dev; 39746686Sbrian int n; 39846686Sbrian 39946686Sbrian prompt_Printf(arg->prompt, "Name: %s\n", p->link.name); 40046686Sbrian prompt_Printf(arg->prompt, " State: "); 40146686Sbrian if (p->fd < 0) 40246686Sbrian prompt_Printf(arg->prompt, "closed\n"); 40346686Sbrian else if (p->handler && p->handler->openinfo) 40446686Sbrian prompt_Printf(arg->prompt, "open (%s)\n", (*p->handler->openinfo)(p)); 40546686Sbrian else 40646686Sbrian prompt_Printf(arg->prompt, "open\n"); 40746686Sbrian 40846686Sbrian prompt_Printf(arg->prompt, " Device: %s", 40946686Sbrian *p->name.full ? p->name.full : 41046686Sbrian p->type == PHYS_DIRECT ? "unknown" : "N/A"); 41146686Sbrian if (p->session_owner != (pid_t)-1) 41246686Sbrian prompt_Printf(arg->prompt, " (session owner: %d)", (int)p->session_owner); 41346686Sbrian 41446686Sbrian prompt_Printf(arg->prompt, "\n Link Type: %s\n", mode2Nam(p->type)); 41546686Sbrian prompt_Printf(arg->prompt, " Connect Count: %d\n", p->connect_count); 41646686Sbrian#ifdef TIOCOUTQ 41746686Sbrian if (p->fd >= 0 && ioctl(p->fd, TIOCOUTQ, &n) >= 0) 41846686Sbrian prompt_Printf(arg->prompt, " Physical outq: %d\n", n); 41946686Sbrian#endif 42046686Sbrian 42146686Sbrian prompt_Printf(arg->prompt, " Queued Packets: %d\n", 42246686Sbrian link_QueueLen(&p->link)); 42346686Sbrian prompt_Printf(arg->prompt, " Phone Number: %s\n", arg->cx->phone.chosen); 42446686Sbrian 42546686Sbrian prompt_Printf(arg->prompt, "\nDefaults:\n"); 42646686Sbrian 42746686Sbrian prompt_Printf(arg->prompt, " Device List: "); 42846686Sbrian dev = p->cfg.devlist; 42946686Sbrian for (n = 0; n < p->cfg.ndev; n++) { 43046686Sbrian if (n) 43146686Sbrian prompt_Printf(arg->prompt, ", "); 43246686Sbrian prompt_Printf(arg->prompt, "\"%s\"", dev); 43346686Sbrian dev += strlen(dev) + 1; 43446686Sbrian } 43546686Sbrian 43646686Sbrian prompt_Printf(arg->prompt, "\n Characteristics: "); 43746686Sbrian if (physical_IsSync(arg->cx->physical)) 43846686Sbrian prompt_Printf(arg->prompt, "sync"); 43946686Sbrian else 44046686Sbrian prompt_Printf(arg->prompt, "%dbps", p->cfg.speed); 44146686Sbrian 44246686Sbrian switch (p->cfg.parity & CSIZE) { 44346686Sbrian case CS7: 44446686Sbrian prompt_Printf(arg->prompt, ", cs7"); 44546686Sbrian break; 44646686Sbrian case CS8: 44746686Sbrian prompt_Printf(arg->prompt, ", cs8"); 44846686Sbrian break; 44946686Sbrian } 45046686Sbrian if (p->cfg.parity & PARENB) { 45146686Sbrian if (p->cfg.parity & PARODD) 45246686Sbrian prompt_Printf(arg->prompt, ", odd parity"); 45346686Sbrian else 45446686Sbrian prompt_Printf(arg->prompt, ", even parity"); 45546686Sbrian } else 45646686Sbrian prompt_Printf(arg->prompt, ", no parity"); 45746686Sbrian 45846686Sbrian prompt_Printf(arg->prompt, ", CTS/RTS %s\n", (p->cfg.rts_cts ? "on" : "off")); 45946686Sbrian 46046686Sbrian prompt_Printf(arg->prompt, " CD check delay: %d second%s", 46146686Sbrian p->cfg.cd.delay, p->cfg.cd.delay == 1 ? "" : "s"); 46246686Sbrian if (p->cfg.cd.required) 46346686Sbrian prompt_Printf(arg->prompt, " (required!)\n\n"); 46446686Sbrian else 46546686Sbrian prompt_Printf(arg->prompt, "\n\n"); 46646686Sbrian 46746686Sbrian throughput_disp(&p->link.throughput, arg->prompt); 46846686Sbrian 46946686Sbrian return 0; 47046686Sbrian} 47146686Sbrian 47246686Sbrianstatic void 47346686Sbrianphysical_DescriptorRead(struct descriptor *d, struct bundle *bundle, 47446686Sbrian const fd_set *fdset) 47546686Sbrian{ 47646686Sbrian struct physical *p = descriptor2physical(d); 47746686Sbrian u_char *rbuff; 47846686Sbrian int n, found; 47946686Sbrian 48046686Sbrian rbuff = p->input.buf + p->input.sz; 48146686Sbrian 48246686Sbrian /* something to read */ 48346686Sbrian n = physical_Read(p, rbuff, sizeof p->input.buf - p->input.sz); 48446686Sbrian log_Printf(LogDEBUG, "%s: DescriptorRead: read %d/%d from %d\n", 48546686Sbrian p->link.name, n, (int)(sizeof p->input.buf - p->input.sz), p->fd); 48646686Sbrian if (n <= 0) { 48746686Sbrian if (n < 0) 48846686Sbrian log_Printf(LogPHASE, "%s: read (%d): %s\n", p->link.name, p->fd, 48946686Sbrian strerror(errno)); 49046686Sbrian else 49146686Sbrian log_Printf(LogPHASE, "%s: read (%d): Got zero bytes\n", 49246686Sbrian p->link.name, p->fd); 49346686Sbrian datalink_Down(p->dl, CLOSE_NORMAL); 49446686Sbrian return; 49546686Sbrian } 49646686Sbrian 49746686Sbrian rbuff -= p->input.sz; 49846686Sbrian n += p->input.sz; 49946686Sbrian 50046686Sbrian if (p->link.lcp.fsm.state <= ST_CLOSED) { 50146686Sbrian if (p->type != PHYS_DEDICATED) { 50246686Sbrian found = hdlc_Detect((u_char const **)&rbuff, n, physical_IsSync(p)); 50346686Sbrian if (rbuff != p->input.buf) 50446686Sbrian log_WritePrompts(p->dl, "%.*s", (int)(rbuff - p->input.buf), 50546686Sbrian p->input.buf); 50646686Sbrian p->input.sz = n - (rbuff - p->input.buf); 50746686Sbrian 50846686Sbrian if (found) { 50946686Sbrian /* LCP packet is detected. Turn ourselves into packet mode */ 51046686Sbrian log_Printf(LogPHASE, "%s: PPP packet detected, coming up\n", 51146686Sbrian p->link.name); 51246686Sbrian log_SetTtyCommandMode(p->dl); 51346686Sbrian datalink_Up(p->dl, 0, 1); 51446686Sbrian link_PullPacket(&p->link, rbuff, p->input.sz, bundle); 51546686Sbrian p->input.sz = 0; 51646686Sbrian } else 51746686Sbrian bcopy(rbuff, p->input.buf, p->input.sz); 51846686Sbrian } else 51946686Sbrian /* In -dedicated mode, we just discard input until LCP is started */ 52046686Sbrian p->input.sz = 0; 52146686Sbrian } else if (n > 0) 52246686Sbrian link_PullPacket(&p->link, rbuff, n, bundle); 52346686Sbrian} 52446686Sbrian 52546686Sbrianstruct physical * 52646686Sbrianiov2physical(struct datalink *dl, struct iovec *iov, int *niov, int maxiov, 52746686Sbrian int fd) 52846686Sbrian{ 52946686Sbrian struct physical *p; 53047061Sbrian int len, h, type; 53146686Sbrian 53246686Sbrian p = (struct physical *)iov[(*niov)++].iov_base; 53346686Sbrian p->link.name = dl->name; 53446686Sbrian memset(p->link.Queue, '\0', sizeof p->link.Queue); 53546686Sbrian 53646686Sbrian p->desc.UpdateSet = physical_UpdateSet; 53746686Sbrian p->desc.IsSet = physical_IsSet; 53846686Sbrian p->desc.Read = physical_DescriptorRead; 53946686Sbrian p->desc.Write = physical_DescriptorWrite; 54046686Sbrian p->type = PHYS_DIRECT; 54146686Sbrian p->dl = dl; 54246686Sbrian len = strlen(_PATH_DEV); 54346686Sbrian p->out = NULL; 54446686Sbrian p->connect_count = 1; 54546686Sbrian 54647682Sbrian physical_SetDevice(p, p->name.full); 54747682Sbrian 54846686Sbrian p->link.lcp.fsm.bundle = dl->bundle; 54946686Sbrian p->link.lcp.fsm.link = &p->link; 55046686Sbrian memset(&p->link.lcp.fsm.FsmTimer, '\0', sizeof p->link.lcp.fsm.FsmTimer); 55146686Sbrian memset(&p->link.lcp.fsm.OpenTimer, '\0', sizeof p->link.lcp.fsm.OpenTimer); 55246686Sbrian memset(&p->link.lcp.fsm.StoppedTimer, '\0', 55346686Sbrian sizeof p->link.lcp.fsm.StoppedTimer); 55446686Sbrian p->link.lcp.fsm.parent = &dl->fsmp; 55546686Sbrian lcp_SetupCallbacks(&p->link.lcp); 55646686Sbrian 55746686Sbrian p->link.ccp.fsm.bundle = dl->bundle; 55846686Sbrian p->link.ccp.fsm.link = &p->link; 55946686Sbrian /* Our in.state & out.state are NULL (no link-level ccp yet) */ 56046686Sbrian memset(&p->link.ccp.fsm.FsmTimer, '\0', sizeof p->link.ccp.fsm.FsmTimer); 56146686Sbrian memset(&p->link.ccp.fsm.OpenTimer, '\0', sizeof p->link.ccp.fsm.OpenTimer); 56246686Sbrian memset(&p->link.ccp.fsm.StoppedTimer, '\0', 56346686Sbrian sizeof p->link.ccp.fsm.StoppedTimer); 56446686Sbrian p->link.ccp.fsm.parent = &dl->fsmp; 56546686Sbrian ccp_SetupCallbacks(&p->link.ccp); 56646686Sbrian 56746686Sbrian p->hdlc.lqm.owner = &p->link.lcp; 56846686Sbrian p->hdlc.ReportTimer.state = TIMER_STOPPED; 56946686Sbrian p->hdlc.lqm.timer.state = TIMER_STOPPED; 57046686Sbrian 57146686Sbrian p->fd = fd; 57249434Sbrian p->link.throughput.SampleOctets = (long long *)iov[(*niov)++].iov_base; 57346686Sbrian 57447769Sbrian type = (long)p->handler; 57547769Sbrian p->handler = NULL; 57647769Sbrian for (h = 0; h < NDEVICES && p->handler == NULL; h++) 57747769Sbrian p->handler = (*devices[h].iov2device)(type, p, iov, niov, maxiov); 57847769Sbrian 57947769Sbrian if (p->handler == NULL) { 58047769Sbrian log_Printf(LogPHASE, "%s: Device %s, unknown link type\n", 58147769Sbrian p->link.name, p->name.full); 58247769Sbrian free(iov[(*niov)++].iov_base); 58347769Sbrian physical_SetupStack(p, "unknown", PHYSICAL_NOFORCE); 58447769Sbrian } else 58547769Sbrian log_Printf(LogPHASE, "%s: Device %s, link type is %s\n", 58647769Sbrian p->link.name, p->name.full, p->handler->name); 58747769Sbrian 58846686Sbrian if (p->hdlc.lqm.method && p->hdlc.lqm.timer.load) 58946686Sbrian lqr_reStart(&p->link.lcp); 59046686Sbrian hdlc_StartTimer(&p->hdlc); 59146686Sbrian 59249434Sbrian throughput_restart(&p->link.throughput, "physical throughput", 59349434Sbrian Enabled(dl->bundle, OPT_THROUGHPUT)); 59446686Sbrian 59547769Sbrian return p; 59647769Sbrian} 59747061Sbrian 59847769Sbrianint 59947769Sbrianphysical_MaxDeviceSize() 60047769Sbrian{ 60147769Sbrian int biggest, sz, n; 60247061Sbrian 60347769Sbrian biggest = sizeof(struct device); 60447769Sbrian for (sz = n = 0; n < NDEVICES; n++) 60547769Sbrian if (devices[n].DeviceSize) { 60647769Sbrian sz = (*devices[n].DeviceSize)(); 60747769Sbrian if (biggest < sz) 60847769Sbrian biggest = sz; 60947769Sbrian } 61047769Sbrian 61147769Sbrian return biggest; 61246686Sbrian} 61346686Sbrian 61446686Sbrianint 61546686Sbrianphysical2iov(struct physical *p, struct iovec *iov, int *niov, int maxiov, 61646686Sbrian pid_t newpid) 61746686Sbrian{ 61847769Sbrian struct device *h; 61947769Sbrian int sz; 62047769Sbrian 62147769Sbrian h = NULL; 62246686Sbrian if (p) { 62346686Sbrian hdlc_StopTimer(&p->hdlc); 62446686Sbrian lqr_StopTimer(p); 62546686Sbrian timer_Stop(&p->link.lcp.fsm.FsmTimer); 62646686Sbrian timer_Stop(&p->link.ccp.fsm.FsmTimer); 62746686Sbrian timer_Stop(&p->link.lcp.fsm.OpenTimer); 62846686Sbrian timer_Stop(&p->link.ccp.fsm.OpenTimer); 62946686Sbrian timer_Stop(&p->link.lcp.fsm.StoppedTimer); 63046686Sbrian timer_Stop(&p->link.ccp.fsm.StoppedTimer); 63147061Sbrian if (p->handler) { 63247061Sbrian if (p->handler->device2iov) 63347769Sbrian h = p->handler; 63447061Sbrian p->handler = (struct device *)(long)p->handler->type; 63546686Sbrian } 63647061Sbrian 63747689Sbrian if (Enabled(p->dl->bundle, OPT_KEEPSESSION) || 63847689Sbrian tcgetpgrp(p->fd) == getpgrp()) 63946686Sbrian p->session_owner = getpid(); /* So I'll eventually get HUP'd */ 64047689Sbrian else 64147689Sbrian p->session_owner = (pid_t)-1; 64246686Sbrian timer_Stop(&p->link.throughput.Timer); 64346686Sbrian physical_ChangedPid(p, newpid); 64446686Sbrian } 64546686Sbrian 64649434Sbrian if (*niov + 2 >= maxiov) { 64749434Sbrian log_Printf(LogERROR, "physical2iov: No room for physical + throughput" 64849434Sbrian " + device !\n"); 64946686Sbrian if (p) 65046686Sbrian free(p); 65146686Sbrian return -1; 65246686Sbrian } 65346686Sbrian 65447769Sbrian iov[*niov].iov_base = p ? (void *)p : malloc(sizeof *p); 65546686Sbrian iov[*niov].iov_len = sizeof *p; 65646686Sbrian (*niov)++; 65746686Sbrian 65849434Sbrian iov[*niov].iov_base = p ? (void *)p->link.throughput.SampleOctets : 65949434Sbrian malloc(SAMPLE_PERIOD * sizeof(long long)); 66049434Sbrian iov[*niov].iov_len = SAMPLE_PERIOD * sizeof(long long); 66149434Sbrian (*niov)++; 66249434Sbrian 66347769Sbrian sz = physical_MaxDeviceSize(); 66447769Sbrian if (p) { 66547769Sbrian if (h) 66647769Sbrian (*h->device2iov)(h, iov, niov, maxiov, newpid); 66747769Sbrian else { 66847769Sbrian iov[*niov].iov_base = malloc(sz); 66947769Sbrian if (p->handler) 67047769Sbrian memcpy(iov[*niov].iov_base, p->handler, sizeof *p->handler); 67147769Sbrian iov[*niov].iov_len = sz; 67247769Sbrian (*niov)++; 67347769Sbrian } 67447769Sbrian } else { 67547769Sbrian iov[*niov].iov_base = malloc(sz); 67647769Sbrian iov[*niov].iov_len = sz; 67747769Sbrian (*niov)++; 67847769Sbrian } 67947769Sbrian 68046686Sbrian return p ? p->fd : 0; 68146686Sbrian} 68246686Sbrian 68346686Sbrianvoid 68446686Sbrianphysical_ChangedPid(struct physical *p, pid_t newpid) 68546686Sbrian{ 68647689Sbrian if (p->fd >= 0 && *p->name.full == '/' && p->type != PHYS_DIRECT) { 68746686Sbrian int res; 68846686Sbrian 68946686Sbrian if ((res = ID0uu_lock_txfr(p->name.base, newpid)) != UU_LOCK_OK) 69046686Sbrian log_Printf(LogPHASE, "uu_lock_txfr: %s\n", uu_lockerr(res)); 69146686Sbrian } 69246686Sbrian} 69346686Sbrian 69446686Sbrianint 69546686Sbrianphysical_IsSync(struct physical *p) 69646686Sbrian{ 69746686Sbrian return p->cfg.speed == 0; 69846686Sbrian} 69946686Sbrian 70046686Sbrianconst char *physical_GetDevice(struct physical *p) 70146686Sbrian{ 70246686Sbrian return p->name.full; 70346686Sbrian} 70446686Sbrian 70546686Sbrianvoid 70636285Sbrianphysical_SetDeviceList(struct physical *p, int argc, const char *const *argv) 70736285Sbrian{ 70836285Sbrian int f, pos; 70936285Sbrian 71036285Sbrian p->cfg.devlist[sizeof p->cfg.devlist - 1] = '\0'; 71136285Sbrian for (f = 0, pos = 0; f < argc && pos < sizeof p->cfg.devlist - 1; f++) { 71236285Sbrian if (pos) 71346102Sbrian p->cfg.devlist[pos++] = '\0'; 71436285Sbrian strncpy(p->cfg.devlist + pos, argv[f], sizeof p->cfg.devlist - pos - 1); 71536285Sbrian pos += strlen(p->cfg.devlist + pos); 71636285Sbrian } 71746102Sbrian p->cfg.ndev = f; 71836285Sbrian} 71936285Sbrian 72036285Sbrianvoid 72146686Sbrianphysical_SetSync(struct physical *p) 72246686Sbrian{ 72346686Sbrian p->cfg.speed = 0; 72436285Sbrian} 72536285Sbrian 72636285Sbrianint 72746686Sbrianphysical_SetRtsCts(struct physical *p, int enable) 72846686Sbrian{ 72946686Sbrian p->cfg.rts_cts = enable ? 1 : 0; 73036285Sbrian return 1; 73136285Sbrian} 73236285Sbrian 73336285Sbrianssize_t 73446686Sbrianphysical_Read(struct physical *p, void *buf, size_t nbytes) 73546686Sbrian{ 73647061Sbrian ssize_t ret; 73747061Sbrian 73847061Sbrian if (p->handler && p->handler->read) 73947061Sbrian ret = (*p->handler->read)(p, buf, nbytes); 74047061Sbrian else 74147061Sbrian ret = read(p->fd, buf, nbytes); 74247061Sbrian 74347061Sbrian log_DumpBuff(LogPHYSICAL, "read", buf, ret); 74447061Sbrian 74547061Sbrian return ret; 74636285Sbrian} 74736285Sbrian 74836285Sbrianssize_t 74946686Sbrianphysical_Write(struct physical *p, const void *buf, size_t nbytes) 75046686Sbrian{ 75147061Sbrian log_DumpBuff(LogPHYSICAL, "write", buf, nbytes); 75247061Sbrian 75347061Sbrian if (p->handler && p->handler->write) 75447061Sbrian return (*p->handler->write)(p, buf, nbytes); 75547061Sbrian 75647061Sbrian return write(p->fd, buf, nbytes); 75736285Sbrian} 75836285Sbrian 75936285Sbrianint 76046686Sbrianphysical_doUpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, 76146686Sbrian int *n, int force) 76236285Sbrian{ 76336285Sbrian struct physical *p = descriptor2physical(d); 76436285Sbrian int sets; 76536285Sbrian 76636285Sbrian sets = 0; 76736285Sbrian if (p->fd >= 0) { 76836285Sbrian if (r) { 76936285Sbrian FD_SET(p->fd, r); 77036285Sbrian log_Printf(LogTIMER, "%s: fdset(r) %d\n", p->link.name, p->fd); 77136285Sbrian sets++; 77236285Sbrian } 77336285Sbrian if (e) { 77436285Sbrian FD_SET(p->fd, e); 77536285Sbrian log_Printf(LogTIMER, "%s: fdset(e) %d\n", p->link.name, p->fd); 77636285Sbrian sets++; 77736285Sbrian } 77836314Sbrian if (w && (force || link_QueueLen(&p->link) || p->out)) { 77936285Sbrian FD_SET(p->fd, w); 78036285Sbrian log_Printf(LogTIMER, "%s: fdset(w) %d\n", p->link.name, p->fd); 78136285Sbrian sets++; 78236285Sbrian } 78336285Sbrian if (sets && *n < p->fd + 1) 78436285Sbrian *n = p->fd + 1; 78536285Sbrian } 78636285Sbrian 78736285Sbrian return sets; 78836285Sbrian} 78936285Sbrian 79036285Sbrianint 79136285Sbrianphysical_RemoveFromSet(struct physical *p, fd_set *r, fd_set *w, fd_set *e) 79236285Sbrian{ 79336285Sbrian int sets; 79436285Sbrian 79536285Sbrian sets = 0; 79636285Sbrian if (p->fd >= 0) { 79736285Sbrian if (r && FD_ISSET(p->fd, r)) { 79836285Sbrian FD_CLR(p->fd, r); 79936285Sbrian log_Printf(LogTIMER, "%s: fdunset(r) %d\n", p->link.name, p->fd); 80036285Sbrian sets++; 80136285Sbrian } 80236285Sbrian if (e && FD_ISSET(p->fd, e)) { 80336285Sbrian FD_CLR(p->fd, e); 80436285Sbrian log_Printf(LogTIMER, "%s: fdunset(e) %d\n", p->link.name, p->fd); 80536285Sbrian sets++; 80636285Sbrian } 80736285Sbrian if (w && FD_ISSET(p->fd, w)) { 80836285Sbrian FD_CLR(p->fd, w); 80936285Sbrian log_Printf(LogTIMER, "%s: fdunset(w) %d\n", p->link.name, p->fd); 81036285Sbrian sets++; 81136285Sbrian } 81236285Sbrian } 81336285Sbrian 81436285Sbrian return sets; 81536285Sbrian} 81636285Sbrian 81736285Sbrianint 81836285Sbrianphysical_IsSet(struct descriptor *d, const fd_set *fdset) 81936285Sbrian{ 82036285Sbrian struct physical *p = descriptor2physical(d); 82136285Sbrian return p->fd >= 0 && FD_ISSET(p->fd, fdset); 82236285Sbrian} 82336285Sbrian 82436285Sbrianvoid 82546686Sbrianphysical_Login(struct physical *p, const char *name) 82636285Sbrian{ 82746830Sbrian if (p->type == PHYS_DIRECT && *p->name.base && !p->Utmp) { 82846686Sbrian struct utmp ut; 82946686Sbrian const char *connstr; 83036285Sbrian 83146686Sbrian memset(&ut, 0, sizeof ut); 83246686Sbrian time(&ut.ut_time); 83346686Sbrian strncpy(ut.ut_name, name, sizeof ut.ut_name); 83446686Sbrian strncpy(ut.ut_line, p->name.base, sizeof ut.ut_line); 83546686Sbrian if ((connstr = getenv("CONNECT"))) 83646686Sbrian /* mgetty sets this to the connection speed */ 83746686Sbrian strncpy(ut.ut_host, connstr, sizeof ut.ut_host); 83846686Sbrian ID0login(&ut); 83946686Sbrian p->Utmp = 1; 84036285Sbrian } 84136285Sbrian} 84236285Sbrian 84336285Sbrianint 84436285Sbrianphysical_SetMode(struct physical *p, int mode) 84536285Sbrian{ 84638174Sbrian if ((p->type & (PHYS_DIRECT|PHYS_DEDICATED) || 84738174Sbrian mode & (PHYS_DIRECT|PHYS_DEDICATED)) && 84838174Sbrian (!(p->type & PHYS_DIRECT) || !(mode & PHYS_BACKGROUND))) { 84936285Sbrian log_Printf(LogWARN, "%s: Cannot change mode %s to %s\n", p->link.name, 85036285Sbrian mode2Nam(p->type), mode2Nam(mode)); 85136285Sbrian return 0; 85236285Sbrian } 85336285Sbrian p->type = mode; 85436285Sbrian return 1; 85536285Sbrian} 85638544Sbrian 85738544Sbrianvoid 85838544Sbrianphysical_DeleteQueue(struct physical *p) 85938544Sbrian{ 86038544Sbrian if (p->out) { 86138544Sbrian mbuf_Free(p->out); 86238544Sbrian p->out = NULL; 86338544Sbrian } 86438544Sbrian link_DeleteQueue(&p->link); 86538544Sbrian} 86646686Sbrian 86746686Sbrianvoid 86846686Sbrianphysical_SetDevice(struct physical *p, const char *name) 86946686Sbrian{ 87046686Sbrian int len = strlen(_PATH_DEV); 87146686Sbrian 87247682Sbrian if (name != p->name.full) { 87347682Sbrian strncpy(p->name.full, name, sizeof p->name.full - 1); 87447682Sbrian p->name.full[sizeof p->name.full - 1] = '\0'; 87547682Sbrian } 87646686Sbrian p->name.base = *p->name.full == '!' ? p->name.full + 1 : 87746686Sbrian strncmp(p->name.full, _PATH_DEV, len) ? 87846686Sbrian p->name.full : p->name.full + len; 87946686Sbrian} 88046686Sbrian 88146686Sbrianstatic void 88246686Sbrianphysical_Found(struct physical *p) 88346686Sbrian{ 88447286Sbrian FILE *lockfile; 88547286Sbrian char fn[MAXPATHLEN]; 88647286Sbrian 88747286Sbrian if (*p->name.full == '/') { 88847286Sbrian snprintf(fn, sizeof fn, "%s%s.if", _PATH_VARRUN, p->name.base); 88947286Sbrian lockfile = ID0fopen(fn, "w"); 89047286Sbrian if (lockfile != NULL) { 89147286Sbrian fprintf(lockfile, "%s%d\n", TUN_NAME, p->dl->bundle->unit); 89247286Sbrian fclose(lockfile); 89347286Sbrian } 89447286Sbrian#ifndef RELEASE_CRUNCH 89547286Sbrian else 89647286Sbrian log_Printf(LogALERT, "%s: Can't create %s: %s\n", 89747286Sbrian p->link.name, fn, strerror(errno)); 89847286Sbrian#endif 89947286Sbrian } 90047286Sbrian 90146686Sbrian throughput_start(&p->link.throughput, "physical throughput", 90246686Sbrian Enabled(p->dl->bundle, OPT_THROUGHPUT)); 90346686Sbrian p->connect_count++; 90446686Sbrian p->input.sz = 0; 90546686Sbrian 90646686Sbrian log_Printf(LogPHASE, "%s: Connected!\n", p->link.name); 90746686Sbrian} 90846686Sbrian 90946686Sbrianint 91046686Sbrianphysical_Open(struct physical *p, struct bundle *bundle) 91146686Sbrian{ 91247878Sbrian int devno, h, wasopen, err; 91346686Sbrian char *dev; 91446686Sbrian 91546686Sbrian if (p->fd >= 0) 91646686Sbrian log_Printf(LogDEBUG, "%s: Open: Modem is already open!\n", p->link.name); 91746686Sbrian /* We're going back into "term" mode */ 91846686Sbrian else if (p->type == PHYS_DIRECT) { 91947061Sbrian physical_SetDevice(p, ""); 92047061Sbrian p->fd = STDIN_FILENO; 92147061Sbrian for (h = 0; h < NDEVICES && p->handler == NULL && p->fd >= 0; h++) 92247061Sbrian p->handler = (*devices[h].create)(p); 92347061Sbrian if (p->fd >= 0) { 92447124Sbrian if (p->handler == NULL) { 92547461Sbrian physical_SetupStack(p, "unknown", PHYSICAL_NOFORCE); 92647124Sbrian log_Printf(LogDEBUG, "%s: stdin is unidentified\n", p->link.name); 92747124Sbrian } 92846686Sbrian physical_Found(p); 92946686Sbrian } 93046686Sbrian } else { 93146686Sbrian dev = p->cfg.devlist; 93246686Sbrian devno = 0; 93346686Sbrian while (devno < p->cfg.ndev && p->fd < 0) { 93446686Sbrian physical_SetDevice(p, dev); 93547286Sbrian if (physical_Lock(p)) { 93647878Sbrian err = 0; 93747878Sbrian 93847878Sbrian if (*p->name.full == '/') { 93947286Sbrian p->fd = ID0open(p->name.full, O_RDWR | O_NONBLOCK); 94047878Sbrian if (p->fd < 0) 94147878Sbrian err = errno; 94247878Sbrian } 94346686Sbrian 94447286Sbrian wasopen = p->fd >= 0; 94547286Sbrian for (h = 0; h < NDEVICES && p->handler == NULL; h++) 94647286Sbrian if ((p->handler = (*devices[h].create)(p)) == NULL && 94747286Sbrian wasopen && p->fd == -1) 94847286Sbrian break; 94946686Sbrian 95047286Sbrian if (p->fd < 0) { 95147878Sbrian if (h == NDEVICES) { 95247878Sbrian if (err) 95347878Sbrian log_Printf(LogWARN, "%s: %s: %s\n", p->link.name, p->name.full, 95447878Sbrian strerror(errno)); 95547878Sbrian else 95647878Sbrian log_Printf(LogWARN, "%s: Device (%s) must begin with a '/'," 95747878Sbrian " a '!' or be a host:port pair\n", p->link.name, 95847878Sbrian p->name.full); 95947878Sbrian } 96047286Sbrian physical_Unlock(p); 96147286Sbrian } else 96247286Sbrian physical_Found(p); 96347286Sbrian } 96446686Sbrian dev += strlen(dev) + 1; 96546686Sbrian devno++; 96646686Sbrian } 96746686Sbrian } 96846686Sbrian 96946686Sbrian return p->fd; 97046686Sbrian} 97146686Sbrian 97246686Sbrianvoid 97347461Sbrianphysical_SetupStack(struct physical *p, const char *who, int how) 97446686Sbrian{ 97546686Sbrian link_EmptyStack(&p->link); 97647061Sbrian if (how == PHYSICAL_FORCE_SYNC || 97747061Sbrian (how == PHYSICAL_NOFORCE && physical_IsSync(p))) 97846686Sbrian link_Stack(&p->link, &synclayer); 97946686Sbrian else { 98046686Sbrian link_Stack(&p->link, &asynclayer); 98146686Sbrian link_Stack(&p->link, &hdlclayer); 98246686Sbrian } 98346686Sbrian link_Stack(&p->link, &acflayer); 98446686Sbrian link_Stack(&p->link, &protolayer); 98546686Sbrian link_Stack(&p->link, &lqrlayer); 98646686Sbrian link_Stack(&p->link, &ccplayer); 98746686Sbrian link_Stack(&p->link, &vjlayer); 98850059Sbrian#ifndef NONAT 98950059Sbrian link_Stack(&p->link, &natlayer); 99046686Sbrian#endif 99147061Sbrian if (how == PHYSICAL_FORCE_ASYNC && physical_IsSync(p)) { 99247461Sbrian log_Printf(LogWARN, "Sync device setting ignored for ``%s'' device\n", who); 99347061Sbrian p->cfg.speed = MODEM_SPEED; 99447061Sbrian } else if (how == PHYSICAL_FORCE_SYNC && !physical_IsSync(p)) { 99547061Sbrian log_Printf(LogWARN, "Async device setting ignored for ``%s'' device\n", 99647461Sbrian who); 99747061Sbrian physical_SetSync(p); 99847061Sbrian } 99946686Sbrian} 100047061Sbrian 100147061Sbrianvoid 100247061Sbrianphysical_StopDeviceTimer(struct physical *p) 100347061Sbrian{ 100447061Sbrian if (p->handler && p->handler->stoptimer) 100547061Sbrian (*p->handler->stoptimer)(p); 100647061Sbrian} 100749472Sbrian 100849472Sbrianint 100949472Sbrianphysical_AwaitCarrier(struct physical *p) 101049472Sbrian{ 101149472Sbrian if (p->handler && p->handler->awaitcarrier) 101249472Sbrian return (*p->handler->awaitcarrier)(p); 101349472Sbrian 101449472Sbrian return CARRIER_OK; 101549472Sbrian} 1016