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: releng/10.3/usr.sbin/ppp/physical.c 230349 2012-01-20 01:37:49Z eadler $ 2036285Sbrian * 2136285Sbrian */ 2236285Sbrian 2346686Sbrian#include <sys/param.h> 2446686Sbrian#include <netinet/in.h> 2546686Sbrian#include <netinet/in_systm.h> 2646686Sbrian#include <netinet/ip.h> 2781634Sbrian#include <sys/socket.h> 28202192Sed#include <sys/time.h> 2946686Sbrian#include <sys/un.h> 3046686Sbrian 3146686Sbrian#include <errno.h> 3246686Sbrian#include <fcntl.h> 3346686Sbrian#include <paths.h> 34134789Sbrian#ifdef NOSUID 35134789Sbrian#include <signal.h> 36134789Sbrian#endif 37102500Sbrian#include <stdarg.h> 3836285Sbrian#include <stdio.h> 3936285Sbrian#include <stdlib.h> 4036285Sbrian#include <string.h> 4146686Sbrian#include <sys/uio.h> 42136375Sbrian#include <sysexits.h> 43179568Sed#include <termios.h> 4436285Sbrian#include <time.h> 4536285Sbrian#include <unistd.h> 46202192Sed#include <utmpx.h> 4746686Sbrian#if defined(__OpenBSD__) || defined(__NetBSD__) 4846686Sbrian#include <sys/ioctl.h> 4946686Sbrian#include <util.h> 5046686Sbrian#else 5146686Sbrian#include <libutil.h> 5246686Sbrian#endif 5336285Sbrian 5446686Sbrian#include "layer.h" 5550059Sbrian#ifndef NONAT 5651075Sbrian#include "nat_cmd.h" 5746686Sbrian#endif 5846686Sbrian#include "proto.h" 5946686Sbrian#include "acf.h" 6046686Sbrian#include "vjcomp.h" 6136285Sbrian#include "defs.h" 6246686Sbrian#include "command.h" 6336285Sbrian#include "mbuf.h" 6446686Sbrian#include "log.h" 6546686Sbrian#include "id.h" 6636285Sbrian#include "timer.h" 6746686Sbrian#include "fsm.h" 6836285Sbrian#include "lqr.h" 6936285Sbrian#include "hdlc.h" 7046686Sbrian#include "lcp.h" 7136285Sbrian#include "throughput.h" 7246686Sbrian#include "sync.h" 7336285Sbrian#include "async.h" 7446686Sbrian#include "iplist.h" 7546686Sbrian#include "slcompress.h" 7681634Sbrian#include "ncpaddr.h" 7746686Sbrian#include "ipcp.h" 7846686Sbrian#include "filter.h" 7946686Sbrian#include "descriptor.h" 8036285Sbrian#include "ccp.h" 8136285Sbrian#include "link.h" 8236285Sbrian#include "physical.h" 8346686Sbrian#include "mp.h" 8446686Sbrian#ifndef NORADIUS 8546686Sbrian#include "radius.h" 8646686Sbrian#endif 8781634Sbrian#include "ipv6cp.h" 8881634Sbrian#include "ncp.h" 8946686Sbrian#include "bundle.h" 9046686Sbrian#include "prompt.h" 9146686Sbrian#include "chat.h" 9246686Sbrian#include "auth.h" 93136375Sbrian#include "main.h" 9446686Sbrian#include "chap.h" 9546686Sbrian#include "cbcp.h" 9646686Sbrian#include "datalink.h" 9746686Sbrian#include "tcp.h" 9847061Sbrian#include "udp.h" 9946686Sbrian#include "exec.h" 10046686Sbrian#include "tty.h" 10152942Sbrian#ifndef NONETGRAPH 10252942Sbrian#include "ether.h" 10393418Sbrian#include "netgraph.h" 10452942Sbrian#endif 10565862Sbrian#ifndef NOATM 10665862Sbrian#include "atm.h" 10765862Sbrian#endif 10869303Sbrian#include "tcpmss.h" 10936285Sbrian 11058028Sbrianstatic int physical_DescriptorWrite(struct fdescriptor *, struct bundle *, 11146686Sbrian const fd_set *); 11236285Sbrian 113134789Sbrianstatic unsigned 11447769Sbrianphysical_DeviceSize(void) 11547769Sbrian{ 11647769Sbrian return sizeof(struct device); 11747769Sbrian} 11847769Sbrian 11947061Sbrianstruct { 12047061Sbrian struct device *(*create)(struct physical *); 12152942Sbrian struct device *(*iov2device)(int, struct physical *, struct iovec *, 12252942Sbrian int *, int, int *, int *); 123134789Sbrian unsigned (*DeviceSize)(void); 12447061Sbrian} devices[] = { 12547769Sbrian { tty_Create, tty_iov2device, tty_DeviceSize }, 12652942Sbrian#ifndef NONETGRAPH 12771006Sbrian /* 12871006Sbrian * This must come before ``udp'' so that the probe routine is 12971006Sbrian * able to identify it as a more specific type of SOCK_DGRAM. 13071006Sbrian */ 13152942Sbrian { ether_Create, ether_iov2device, ether_DeviceSize }, 13293418Sbrian#ifdef EXPERIMENTAL_NETGRAPH 13393418Sbrian { ng_Create, ng_iov2device, ng_DeviceSize }, 13452942Sbrian#endif 13593418Sbrian#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 }, 228134789Sbrian { NULL, 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 266134789Sbrianunsigned 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 276134789Sbrianphysical_SetSpeed(struct physical *p, unsigned speed) 27736285Sbrian{ 278134789Sbrian if (UnsignedToSpeed(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]; 335202192Sed struct utmpx ut; 33647286Sbrian 33746686Sbrian if (p->fd < 0) 33846686Sbrian return; 33946686Sbrian 34046686Sbrian log_Printf(LogDEBUG, "%s: Close\n", p->link.name); 34146686Sbrian 34246686Sbrian if (p->handler && p->handler->cooked) 34346686Sbrian (*p->handler->cooked)(p); 34446686Sbrian 34547286Sbrian physical_StopDeviceTimer(p); 34647286Sbrian if (p->Utmp) { 347202192Sed memset(&ut, 0, sizeof ut); 348202192Sed ut.ut_type = DEAD_PROCESS; 349202192Sed gettimeofday(&ut.ut_tv, NULL); 350202192Sed snprintf(ut.ut_id, sizeof ut.ut_id, "%xppp", (int)getpid()); 351202192Sed ID0logout(&ut); 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) { 36397360Sbrian log_Printf(LogPHASE, "%s: HUPing %ld\n", p->link.name, 36497360Sbrian (long)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 399134789Sbrianphysical_DescriptorWrite(struct fdescriptor *d, struct bundle *bundle __unused, 400134789Sbrian const fd_set *fdset __unused) 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) { 422134833Smarcel log_Printf(LogPHASE, "%s: write (fd %d, len %zd): %s\n", p->link.name, 423132423Sbrian p->fd, p->out->m_len, 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; 43999097Sbrian int n, slot; 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"); 44599097Sbrian else { 44699097Sbrian slot = physical_Slot(p); 44799097Sbrian if (p->handler && p->handler->openinfo) { 44899097Sbrian if (slot == -1) 44999097Sbrian prompt_Printf(arg->prompt, "open (%s)\n", (*p->handler->openinfo)(p)); 45099097Sbrian else 45199097Sbrian prompt_Printf(arg->prompt, "open (%s, port %d)\n", 45299097Sbrian (*p->handler->openinfo)(p), slot); 45399097Sbrian } else if (slot == -1) 45499097Sbrian prompt_Printf(arg->prompt, "open\n"); 45599097Sbrian else 45699097Sbrian prompt_Printf(arg->prompt, "open (port %d)\n", slot); 45799097Sbrian } 45846686Sbrian 45946686Sbrian prompt_Printf(arg->prompt, " Device: %s", 46046686Sbrian *p->name.full ? p->name.full : 46146686Sbrian p->type == PHYS_DIRECT ? "unknown" : "N/A"); 46246686Sbrian if (p->session_owner != (pid_t)-1) 46397360Sbrian prompt_Printf(arg->prompt, " (session owner: %ld)", (long)p->session_owner); 46446686Sbrian 46546686Sbrian prompt_Printf(arg->prompt, "\n Link Type: %s\n", mode2Nam(p->type)); 46646686Sbrian prompt_Printf(arg->prompt, " Connect Count: %d\n", p->connect_count); 46746686Sbrian#ifdef TIOCOUTQ 46846686Sbrian if (p->fd >= 0 && ioctl(p->fd, TIOCOUTQ, &n) >= 0) 46946686Sbrian prompt_Printf(arg->prompt, " Physical outq: %d\n", n); 47046686Sbrian#endif 47146686Sbrian 47254912Sbrian prompt_Printf(arg->prompt, " Queued Packets: %lu\n", 47354912Sbrian (u_long)link_QueueLen(&p->link)); 47446686Sbrian prompt_Printf(arg->prompt, " Phone Number: %s\n", arg->cx->phone.chosen); 47546686Sbrian 47646686Sbrian prompt_Printf(arg->prompt, "\nDefaults:\n"); 47746686Sbrian 47846686Sbrian prompt_Printf(arg->prompt, " Device List: "); 47946686Sbrian dev = p->cfg.devlist; 48046686Sbrian for (n = 0; n < p->cfg.ndev; n++) { 48146686Sbrian if (n) 48246686Sbrian prompt_Printf(arg->prompt, ", "); 48346686Sbrian prompt_Printf(arg->prompt, "\"%s\"", dev); 48446686Sbrian dev += strlen(dev) + 1; 48546686Sbrian } 48698243Sbrian 48746686Sbrian prompt_Printf(arg->prompt, "\n Characteristics: "); 48846686Sbrian if (physical_IsSync(arg->cx->physical)) 48946686Sbrian prompt_Printf(arg->prompt, "sync"); 49046686Sbrian else 49146686Sbrian prompt_Printf(arg->prompt, "%dbps", p->cfg.speed); 49246686Sbrian 49346686Sbrian switch (p->cfg.parity & CSIZE) { 49446686Sbrian case CS7: 49546686Sbrian prompt_Printf(arg->prompt, ", cs7"); 49646686Sbrian break; 49746686Sbrian case CS8: 49846686Sbrian prompt_Printf(arg->prompt, ", cs8"); 49946686Sbrian break; 50046686Sbrian } 50146686Sbrian if (p->cfg.parity & PARENB) { 50246686Sbrian if (p->cfg.parity & PARODD) 50346686Sbrian prompt_Printf(arg->prompt, ", odd parity"); 50446686Sbrian else 50546686Sbrian prompt_Printf(arg->prompt, ", even parity"); 50646686Sbrian } else 50746686Sbrian prompt_Printf(arg->prompt, ", no parity"); 50846686Sbrian 50946686Sbrian prompt_Printf(arg->prompt, ", CTS/RTS %s\n", (p->cfg.rts_cts ? "on" : "off")); 51046686Sbrian 51151699Sbrian prompt_Printf(arg->prompt, " CD check delay: "); 51253733Sbrian cd = p->handler ? &p->handler->cd : &p->cfg.cd; 51353733Sbrian if (cd->necessity == CD_NOTREQUIRED) 51451699Sbrian prompt_Printf(arg->prompt, "no cd"); 51553733Sbrian else if (p->cfg.cd.necessity == CD_DEFAULT) { 51653733Sbrian prompt_Printf(arg->prompt, "device specific"); 51753733Sbrian } else { 51851699Sbrian prompt_Printf(arg->prompt, "%d second%s", p->cfg.cd.delay, 51951699Sbrian p->cfg.cd.delay == 1 ? "" : "s"); 52051699Sbrian if (p->cfg.cd.necessity == CD_REQUIRED) 52151699Sbrian prompt_Printf(arg->prompt, " (required!)"); 52251699Sbrian } 52351699Sbrian prompt_Printf(arg->prompt, "\n\n"); 52446686Sbrian 52564652Sbrian throughput_disp(&p->link.stats.total, arg->prompt); 52646686Sbrian 52746686Sbrian return 0; 52846686Sbrian} 52946686Sbrian 53052942Sbrianvoid 53158028Sbrianphysical_DescriptorRead(struct fdescriptor *d, struct bundle *bundle, 532134789Sbrian const fd_set *fdset __unused) 53346686Sbrian{ 53446686Sbrian struct physical *p = descriptor2physical(d); 53546686Sbrian u_char *rbuff; 53646686Sbrian int n, found; 53746686Sbrian 53846686Sbrian rbuff = p->input.buf + p->input.sz; 53946686Sbrian 54046686Sbrian /* something to read */ 54146686Sbrian n = physical_Read(p, rbuff, sizeof p->input.buf - p->input.sz); 54246686Sbrian log_Printf(LogDEBUG, "%s: DescriptorRead: read %d/%d from %d\n", 54346686Sbrian p->link.name, n, (int)(sizeof p->input.buf - p->input.sz), p->fd); 54446686Sbrian if (n <= 0) { 54546686Sbrian if (n < 0) 54646686Sbrian log_Printf(LogPHASE, "%s: read (%d): %s\n", p->link.name, p->fd, 54746686Sbrian strerror(errno)); 54846686Sbrian else 54946686Sbrian log_Printf(LogPHASE, "%s: read (%d): Got zero bytes\n", 55046686Sbrian p->link.name, p->fd); 55146686Sbrian datalink_Down(p->dl, CLOSE_NORMAL); 55246686Sbrian return; 55346686Sbrian } 55446686Sbrian 55546686Sbrian rbuff -= p->input.sz; 55646686Sbrian n += p->input.sz; 55746686Sbrian 55846686Sbrian if (p->link.lcp.fsm.state <= ST_CLOSED) { 55946686Sbrian if (p->type != PHYS_DEDICATED) { 56046686Sbrian found = hdlc_Detect((u_char const **)&rbuff, n, physical_IsSync(p)); 56146686Sbrian if (rbuff != p->input.buf) 56246686Sbrian log_WritePrompts(p->dl, "%.*s", (int)(rbuff - p->input.buf), 56346686Sbrian p->input.buf); 56446686Sbrian p->input.sz = n - (rbuff - p->input.buf); 56546686Sbrian 56646686Sbrian if (found) { 56746686Sbrian /* LCP packet is detected. Turn ourselves into packet mode */ 56846686Sbrian log_Printf(LogPHASE, "%s: PPP packet detected, coming up\n", 56946686Sbrian p->link.name); 57046686Sbrian log_SetTtyCommandMode(p->dl); 57146686Sbrian datalink_Up(p->dl, 0, 1); 57246686Sbrian link_PullPacket(&p->link, rbuff, p->input.sz, bundle); 57346686Sbrian p->input.sz = 0; 57446686Sbrian } else 57546686Sbrian bcopy(rbuff, p->input.buf, p->input.sz); 57646686Sbrian } else 57746686Sbrian /* In -dedicated mode, we just discard input until LCP is started */ 57846686Sbrian p->input.sz = 0; 57946686Sbrian } else if (n > 0) 58046686Sbrian link_PullPacket(&p->link, rbuff, n, bundle); 58146686Sbrian} 58246686Sbrian 58346686Sbrianstruct physical * 58446686Sbrianiov2physical(struct datalink *dl, struct iovec *iov, int *niov, int maxiov, 58552942Sbrian int fd, int *auxfd, int *nauxfd) 58646686Sbrian{ 58746686Sbrian struct physical *p; 588230349Seadler int type; 589134789Sbrian unsigned h; 59046686Sbrian 59146686Sbrian p = (struct physical *)iov[(*niov)++].iov_base; 59246686Sbrian p->link.name = dl->name; 59346686Sbrian memset(p->link.Queue, '\0', sizeof p->link.Queue); 59446686Sbrian 59546686Sbrian p->desc.UpdateSet = physical_UpdateSet; 59646686Sbrian p->desc.IsSet = physical_IsSet; 59746686Sbrian p->desc.Read = physical_DescriptorRead; 59846686Sbrian p->desc.Write = physical_DescriptorWrite; 59946686Sbrian p->type = PHYS_DIRECT; 60046686Sbrian p->dl = dl; 60146686Sbrian p->out = NULL; 60246686Sbrian p->connect_count = 1; 60346686Sbrian 60447682Sbrian physical_SetDevice(p, p->name.full); 60547682Sbrian 60646686Sbrian p->link.lcp.fsm.bundle = dl->bundle; 60746686Sbrian p->link.lcp.fsm.link = &p->link; 60846686Sbrian memset(&p->link.lcp.fsm.FsmTimer, '\0', sizeof p->link.lcp.fsm.FsmTimer); 60946686Sbrian memset(&p->link.lcp.fsm.OpenTimer, '\0', sizeof p->link.lcp.fsm.OpenTimer); 61046686Sbrian memset(&p->link.lcp.fsm.StoppedTimer, '\0', 61146686Sbrian sizeof p->link.lcp.fsm.StoppedTimer); 61246686Sbrian p->link.lcp.fsm.parent = &dl->fsmp; 61346686Sbrian lcp_SetupCallbacks(&p->link.lcp); 61446686Sbrian 61546686Sbrian p->link.ccp.fsm.bundle = dl->bundle; 61646686Sbrian p->link.ccp.fsm.link = &p->link; 61746686Sbrian /* Our in.state & out.state are NULL (no link-level ccp yet) */ 61846686Sbrian memset(&p->link.ccp.fsm.FsmTimer, '\0', sizeof p->link.ccp.fsm.FsmTimer); 61946686Sbrian memset(&p->link.ccp.fsm.OpenTimer, '\0', sizeof p->link.ccp.fsm.OpenTimer); 62046686Sbrian memset(&p->link.ccp.fsm.StoppedTimer, '\0', 62146686Sbrian sizeof p->link.ccp.fsm.StoppedTimer); 62246686Sbrian p->link.ccp.fsm.parent = &dl->fsmp; 62346686Sbrian ccp_SetupCallbacks(&p->link.ccp); 62446686Sbrian 62546686Sbrian p->hdlc.lqm.owner = &p->link.lcp; 62646686Sbrian p->hdlc.ReportTimer.state = TIMER_STOPPED; 62746686Sbrian p->hdlc.lqm.timer.state = TIMER_STOPPED; 62846686Sbrian 62946686Sbrian p->fd = fd; 63064670Sbrian p->link.stats.total.in.SampleOctets = (long long *)iov[(*niov)++].iov_base; 63164670Sbrian p->link.stats.total.out.SampleOctets = (long long *)iov[(*niov)++].iov_base; 63264652Sbrian p->link.stats.parent = dl->bundle->ncp.mp.active ? 63364652Sbrian &dl->bundle->ncp.mp.link.stats.total : NULL; 63464652Sbrian p->link.stats.gather = 1; 63546686Sbrian 63647769Sbrian type = (long)p->handler; 63747769Sbrian p->handler = NULL; 63847769Sbrian for (h = 0; h < NDEVICES && p->handler == NULL; h++) 63952942Sbrian p->handler = (*devices[h].iov2device)(type, p, iov, niov, maxiov, 64052942Sbrian auxfd, nauxfd); 64147769Sbrian if (p->handler == NULL) { 64252942Sbrian log_Printf(LogPHASE, "%s: Unknown link type\n", p->link.name); 64347769Sbrian free(iov[(*niov)++].iov_base); 64447769Sbrian physical_SetupStack(p, "unknown", PHYSICAL_NOFORCE); 64547769Sbrian } else 64647769Sbrian log_Printf(LogPHASE, "%s: Device %s, link type is %s\n", 64747769Sbrian p->link.name, p->name.full, p->handler->name); 64847769Sbrian 64946686Sbrian if (p->hdlc.lqm.method && p->hdlc.lqm.timer.load) 65046686Sbrian lqr_reStart(&p->link.lcp); 65146686Sbrian hdlc_StartTimer(&p->hdlc); 65246686Sbrian 65364652Sbrian throughput_restart(&p->link.stats.total, "physical throughput", 65449434Sbrian Enabled(dl->bundle, OPT_THROUGHPUT)); 65546686Sbrian 65647769Sbrian return p; 65747769Sbrian} 65847061Sbrian 659134789Sbrianunsigned 66047769Sbrianphysical_MaxDeviceSize() 66147769Sbrian{ 662134789Sbrian unsigned biggest, sz, n; 66347061Sbrian 66447769Sbrian biggest = sizeof(struct device); 665134789Sbrian for (n = 0; n < NDEVICES; n++) 66647769Sbrian if (devices[n].DeviceSize) { 66747769Sbrian sz = (*devices[n].DeviceSize)(); 66847769Sbrian if (biggest < sz) 66947769Sbrian biggest = sz; 67047769Sbrian } 67147769Sbrian 67247769Sbrian return biggest; 67346686Sbrian} 67446686Sbrian 67546686Sbrianint 67646686Sbrianphysical2iov(struct physical *p, struct iovec *iov, int *niov, int maxiov, 67753684Sbrian int *auxfd, int *nauxfd) 67846686Sbrian{ 67947769Sbrian struct device *h; 68047769Sbrian int sz; 68147769Sbrian 68247769Sbrian h = NULL; 68346686Sbrian if (p) { 68446686Sbrian hdlc_StopTimer(&p->hdlc); 68546686Sbrian lqr_StopTimer(p); 68646686Sbrian timer_Stop(&p->link.lcp.fsm.FsmTimer); 68746686Sbrian timer_Stop(&p->link.ccp.fsm.FsmTimer); 68846686Sbrian timer_Stop(&p->link.lcp.fsm.OpenTimer); 68946686Sbrian timer_Stop(&p->link.ccp.fsm.OpenTimer); 69046686Sbrian timer_Stop(&p->link.lcp.fsm.StoppedTimer); 69146686Sbrian timer_Stop(&p->link.ccp.fsm.StoppedTimer); 69247061Sbrian if (p->handler) { 69353684Sbrian h = p->handler; 69447061Sbrian p->handler = (struct device *)(long)p->handler->type; 69546686Sbrian } 69647061Sbrian 69747689Sbrian if (Enabled(p->dl->bundle, OPT_KEEPSESSION) || 69847689Sbrian tcgetpgrp(p->fd) == getpgrp()) 69946686Sbrian p->session_owner = getpid(); /* So I'll eventually get HUP'd */ 70047689Sbrian else 70147689Sbrian p->session_owner = (pid_t)-1; 70264652Sbrian timer_Stop(&p->link.stats.total.Timer); 70346686Sbrian } 70446686Sbrian 70549434Sbrian if (*niov + 2 >= maxiov) { 70649434Sbrian log_Printf(LogERROR, "physical2iov: No room for physical + throughput" 70749434Sbrian " + device !\n"); 70846686Sbrian if (p) 70946686Sbrian free(p); 71046686Sbrian return -1; 71146686Sbrian } 71246686Sbrian 71353684Sbrian iov[*niov].iov_base = (void *)p; 71446686Sbrian iov[*niov].iov_len = sizeof *p; 71546686Sbrian (*niov)++; 71646686Sbrian 71764670Sbrian iov[*niov].iov_base = p ? (void *)p->link.stats.total.in.SampleOctets : NULL; 71849434Sbrian iov[*niov].iov_len = SAMPLE_PERIOD * sizeof(long long); 71949434Sbrian (*niov)++; 72064670Sbrian iov[*niov].iov_base = p ? (void *)p->link.stats.total.out.SampleOctets : NULL; 72164670Sbrian iov[*niov].iov_len = SAMPLE_PERIOD * sizeof(long long); 72264670Sbrian (*niov)++; 72349434Sbrian 72447769Sbrian sz = physical_MaxDeviceSize(); 72547769Sbrian if (p) { 72653684Sbrian if (h && h->device2iov) 72753684Sbrian (*h->device2iov)(h, iov, niov, maxiov, auxfd, nauxfd); 72847769Sbrian else { 729136375Sbrian if ((iov[*niov].iov_base = malloc(sz)) == NULL) { 730136375Sbrian log_Printf(LogALERT, "physical2iov: Out of memory (%d bytes)\n", sz); 731136375Sbrian AbortProgram(EX_OSERR); 732136375Sbrian } 73353684Sbrian if (h) 73453684Sbrian memcpy(iov[*niov].iov_base, h, sizeof *h); 73547769Sbrian iov[*niov].iov_len = sz; 73647769Sbrian (*niov)++; 73747769Sbrian } 73847769Sbrian } else { 73953684Sbrian iov[*niov].iov_base = NULL; 74047769Sbrian iov[*niov].iov_len = sz; 74147769Sbrian (*niov)++; 74247769Sbrian } 74347769Sbrian 74446686Sbrian return p ? p->fd : 0; 74546686Sbrian} 74646686Sbrian 74753684Sbrianconst char * 74853684Sbrianphysical_LockedDevice(struct physical *p) 74953684Sbrian{ 75053684Sbrian if (p->fd >= 0 && *p->name.full == '/' && p->type != PHYS_DIRECT) 75153684Sbrian return p->name.base; 75253684Sbrian 75353684Sbrian return NULL; 75453684Sbrian} 75553684Sbrian 75646686Sbrianvoid 75746686Sbrianphysical_ChangedPid(struct physical *p, pid_t newpid) 75846686Sbrian{ 75953684Sbrian if (physical_LockedDevice(p)) { 76046686Sbrian int res; 76146686Sbrian 76246686Sbrian if ((res = ID0uu_lock_txfr(p->name.base, newpid)) != UU_LOCK_OK) 76346686Sbrian log_Printf(LogPHASE, "uu_lock_txfr: %s\n", uu_lockerr(res)); 76446686Sbrian } 76546686Sbrian} 76646686Sbrian 76746686Sbrianint 76846686Sbrianphysical_IsSync(struct physical *p) 76946686Sbrian{ 77046686Sbrian return p->cfg.speed == 0; 77146686Sbrian} 77246686Sbrian 77378410Sbrianu_short 77478410Sbrianphysical_DeviceMTU(struct physical *p) 77578410Sbrian{ 77678410Sbrian return p->handler ? p->handler->mtu : 0; 77778410Sbrian} 77878410Sbrian 77946686Sbrianconst char *physical_GetDevice(struct physical *p) 78046686Sbrian{ 78146686Sbrian return p->name.full; 78246686Sbrian} 78346686Sbrian 78446686Sbrianvoid 78536285Sbrianphysical_SetDeviceList(struct physical *p, int argc, const char *const *argv) 78636285Sbrian{ 787134789Sbrian unsigned pos; 788134789Sbrian int f; 78936285Sbrian 79036285Sbrian p->cfg.devlist[sizeof p->cfg.devlist - 1] = '\0'; 79136285Sbrian for (f = 0, pos = 0; f < argc && pos < sizeof p->cfg.devlist - 1; f++) { 79236285Sbrian if (pos) 79346102Sbrian p->cfg.devlist[pos++] = '\0'; 79436285Sbrian strncpy(p->cfg.devlist + pos, argv[f], sizeof p->cfg.devlist - pos - 1); 79536285Sbrian pos += strlen(p->cfg.devlist + pos); 79636285Sbrian } 79746102Sbrian p->cfg.ndev = f; 79836285Sbrian} 79936285Sbrian 80036285Sbrianvoid 80146686Sbrianphysical_SetSync(struct physical *p) 80246686Sbrian{ 80346686Sbrian p->cfg.speed = 0; 80436285Sbrian} 80536285Sbrian 80636285Sbrianint 80746686Sbrianphysical_SetRtsCts(struct physical *p, int enable) 80846686Sbrian{ 80946686Sbrian p->cfg.rts_cts = enable ? 1 : 0; 81036285Sbrian return 1; 81136285Sbrian} 81236285Sbrian 81336285Sbrianssize_t 81446686Sbrianphysical_Read(struct physical *p, void *buf, size_t nbytes) 81546686Sbrian{ 81647061Sbrian ssize_t ret; 81747061Sbrian 81847061Sbrian if (p->handler && p->handler->read) 81947061Sbrian ret = (*p->handler->read)(p, buf, nbytes); 82047061Sbrian else 82147061Sbrian ret = read(p->fd, buf, nbytes); 82247061Sbrian 82347061Sbrian log_DumpBuff(LogPHYSICAL, "read", buf, ret); 82447061Sbrian 82547061Sbrian return ret; 82636285Sbrian} 82736285Sbrian 82836285Sbrianssize_t 82946686Sbrianphysical_Write(struct physical *p, const void *buf, size_t nbytes) 83046686Sbrian{ 83147061Sbrian log_DumpBuff(LogPHYSICAL, "write", buf, nbytes); 83247061Sbrian 83347061Sbrian if (p->handler && p->handler->write) 83447061Sbrian return (*p->handler->write)(p, buf, nbytes); 83547061Sbrian 83647061Sbrian return write(p->fd, buf, nbytes); 83736285Sbrian} 83836285Sbrian 83936285Sbrianint 84058028Sbrianphysical_doUpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w, fd_set *e, 84146686Sbrian int *n, int force) 84236285Sbrian{ 84336285Sbrian struct physical *p = descriptor2physical(d); 84436285Sbrian int sets; 84536285Sbrian 84636285Sbrian sets = 0; 84736285Sbrian if (p->fd >= 0) { 84836285Sbrian if (r) { 84936285Sbrian FD_SET(p->fd, r); 85036285Sbrian log_Printf(LogTIMER, "%s: fdset(r) %d\n", p->link.name, p->fd); 85136285Sbrian sets++; 85236285Sbrian } 85336285Sbrian if (e) { 85436285Sbrian FD_SET(p->fd, e); 85536285Sbrian log_Printf(LogTIMER, "%s: fdset(e) %d\n", p->link.name, p->fd); 85636285Sbrian sets++; 85736285Sbrian } 85836314Sbrian if (w && (force || link_QueueLen(&p->link) || p->out)) { 85936285Sbrian FD_SET(p->fd, w); 86036285Sbrian log_Printf(LogTIMER, "%s: fdset(w) %d\n", p->link.name, p->fd); 86136285Sbrian sets++; 86236285Sbrian } 86336285Sbrian if (sets && *n < p->fd + 1) 86436285Sbrian *n = p->fd + 1; 86536285Sbrian } 86636285Sbrian 86736285Sbrian return sets; 86836285Sbrian} 86936285Sbrian 87036285Sbrianint 87136285Sbrianphysical_RemoveFromSet(struct physical *p, fd_set *r, fd_set *w, fd_set *e) 87236285Sbrian{ 87352942Sbrian if (p->handler && p->handler->removefromset) 87452942Sbrian return (*p->handler->removefromset)(p, r, w, e); 87552942Sbrian else { 87652942Sbrian int sets; 87736285Sbrian 87852942Sbrian sets = 0; 87952942Sbrian if (p->fd >= 0) { 88052942Sbrian if (r && FD_ISSET(p->fd, r)) { 88152942Sbrian FD_CLR(p->fd, r); 88252942Sbrian log_Printf(LogTIMER, "%s: fdunset(r) %d\n", p->link.name, p->fd); 88352942Sbrian sets++; 88452942Sbrian } 88552942Sbrian if (e && FD_ISSET(p->fd, e)) { 88652942Sbrian FD_CLR(p->fd, e); 88752942Sbrian log_Printf(LogTIMER, "%s: fdunset(e) %d\n", p->link.name, p->fd); 88852942Sbrian sets++; 88952942Sbrian } 89052942Sbrian if (w && FD_ISSET(p->fd, w)) { 89152942Sbrian FD_CLR(p->fd, w); 89252942Sbrian log_Printf(LogTIMER, "%s: fdunset(w) %d\n", p->link.name, p->fd); 89352942Sbrian sets++; 89452942Sbrian } 89536285Sbrian } 89652942Sbrian 89752942Sbrian return sets; 89836285Sbrian } 89936285Sbrian} 90036285Sbrian 90136285Sbrianint 90258028Sbrianphysical_IsSet(struct fdescriptor *d, const fd_set *fdset) 90336285Sbrian{ 90436285Sbrian struct physical *p = descriptor2physical(d); 90536285Sbrian return p->fd >= 0 && FD_ISSET(p->fd, fdset); 90636285Sbrian} 90736285Sbrian 90836285Sbrianvoid 90946686Sbrianphysical_Login(struct physical *p, const char *name) 91036285Sbrian{ 91146830Sbrian if (p->type == PHYS_DIRECT && *p->name.base && !p->Utmp) { 912202192Sed struct utmpx ut; 91346686Sbrian const char *connstr; 91452413Sbrian char *colon; 91536285Sbrian 91646686Sbrian memset(&ut, 0, sizeof ut); 917202192Sed ut.ut_type = USER_PROCESS; 918202192Sed gettimeofday(&ut.ut_tv, NULL); 919202192Sed snprintf(ut.ut_id, sizeof ut.ut_id, "%xppp", (int)getpid()); 920202192Sed strncpy(ut.ut_user, name, sizeof ut.ut_user); 92152413Sbrian if (p->handler && (p->handler->type == TCP_DEVICE || 92252413Sbrian p->handler->type == UDP_DEVICE)) { 92352413Sbrian strncpy(ut.ut_host, p->name.base, sizeof ut.ut_host); 92452413Sbrian colon = memchr(ut.ut_host, ':', sizeof ut.ut_host); 92552413Sbrian if (colon) 92652413Sbrian *colon = '\0'; 92752413Sbrian } else 92852413Sbrian strncpy(ut.ut_line, p->name.base, sizeof ut.ut_line); 92946686Sbrian if ((connstr = getenv("CONNECT"))) 93046686Sbrian /* mgetty sets this to the connection speed */ 93146686Sbrian strncpy(ut.ut_host, connstr, sizeof ut.ut_host); 93246686Sbrian ID0login(&ut); 933202192Sed p->Utmp = 1; 93436285Sbrian } 93536285Sbrian} 93636285Sbrian 93736285Sbrianint 93836285Sbrianphysical_SetMode(struct physical *p, int mode) 93936285Sbrian{ 94038174Sbrian if ((p->type & (PHYS_DIRECT|PHYS_DEDICATED) || 94138174Sbrian mode & (PHYS_DIRECT|PHYS_DEDICATED)) && 94238174Sbrian (!(p->type & PHYS_DIRECT) || !(mode & PHYS_BACKGROUND))) { 94353830Sbrian /* Note: The -direct -> -background is for callback ! */ 94436285Sbrian log_Printf(LogWARN, "%s: Cannot change mode %s to %s\n", p->link.name, 94536285Sbrian mode2Nam(p->type), mode2Nam(mode)); 94636285Sbrian return 0; 94736285Sbrian } 94836285Sbrian p->type = mode; 94936285Sbrian return 1; 95036285Sbrian} 95138544Sbrian 95238544Sbrianvoid 95338544Sbrianphysical_DeleteQueue(struct physical *p) 95438544Sbrian{ 95538544Sbrian if (p->out) { 95654912Sbrian m_freem(p->out); 95738544Sbrian p->out = NULL; 95838544Sbrian } 95938544Sbrian link_DeleteQueue(&p->link); 96038544Sbrian} 96146686Sbrian 96246686Sbrianvoid 96346686Sbrianphysical_SetDevice(struct physical *p, const char *name) 96446686Sbrian{ 96546686Sbrian int len = strlen(_PATH_DEV); 96646686Sbrian 96747682Sbrian if (name != p->name.full) { 96847682Sbrian strncpy(p->name.full, name, sizeof p->name.full - 1); 96947682Sbrian p->name.full[sizeof p->name.full - 1] = '\0'; 97047682Sbrian } 97146686Sbrian p->name.base = *p->name.full == '!' ? p->name.full + 1 : 97246686Sbrian strncmp(p->name.full, _PATH_DEV, len) ? 97346686Sbrian p->name.full : p->name.full + len; 97446686Sbrian} 97546686Sbrian 97646686Sbrianstatic void 97746686Sbrianphysical_Found(struct physical *p) 97846686Sbrian{ 97947286Sbrian FILE *lockfile; 98074001Sbrian char fn[PATH_MAX]; 98147286Sbrian 98247286Sbrian if (*p->name.full == '/') { 98347286Sbrian snprintf(fn, sizeof fn, "%s%s.if", _PATH_VARRUN, p->name.base); 98447286Sbrian lockfile = ID0fopen(fn, "w"); 98547286Sbrian if (lockfile != NULL) { 98647286Sbrian fprintf(lockfile, "%s%d\n", TUN_NAME, p->dl->bundle->unit); 98747286Sbrian fclose(lockfile); 98847286Sbrian } 98947286Sbrian#ifndef RELEASE_CRUNCH 99047286Sbrian else 99147286Sbrian log_Printf(LogALERT, "%s: Can't create %s: %s\n", 99247286Sbrian p->link.name, fn, strerror(errno)); 99347286Sbrian#endif 99447286Sbrian } 99547286Sbrian 99664652Sbrian throughput_start(&p->link.stats.total, "physical throughput", 99746686Sbrian Enabled(p->dl->bundle, OPT_THROUGHPUT)); 99846686Sbrian p->connect_count++; 99946686Sbrian p->input.sz = 0; 100046686Sbrian 100146686Sbrian log_Printf(LogPHASE, "%s: Connected!\n", p->link.name); 100246686Sbrian} 100346686Sbrian 100446686Sbrianint 1005134789Sbrianphysical_Open(struct physical *p) 100646686Sbrian{ 100746686Sbrian char *dev; 1008134789Sbrian int devno, wasfd, err; 1009134789Sbrian unsigned h; 101046686Sbrian 101146686Sbrian if (p->fd >= 0) 101246686Sbrian log_Printf(LogDEBUG, "%s: Open: Modem is already open!\n", p->link.name); 101346686Sbrian /* We're going back into "term" mode */ 101446686Sbrian else if (p->type == PHYS_DIRECT) { 101547061Sbrian physical_SetDevice(p, ""); 101647061Sbrian p->fd = STDIN_FILENO; 101747061Sbrian for (h = 0; h < NDEVICES && p->handler == NULL && p->fd >= 0; h++) 101852942Sbrian p->handler = (*devices[h].create)(p); 1019196514Sbrian close(STDOUT_FILENO); 102047061Sbrian if (p->fd >= 0) { 102147124Sbrian if (p->handler == NULL) { 102247461Sbrian physical_SetupStack(p, "unknown", PHYSICAL_NOFORCE); 102347124Sbrian log_Printf(LogDEBUG, "%s: stdin is unidentified\n", p->link.name); 102447124Sbrian } 102546686Sbrian physical_Found(p); 102646686Sbrian } 102746686Sbrian } else { 102846686Sbrian dev = p->cfg.devlist; 102946686Sbrian devno = 0; 103046686Sbrian while (devno < p->cfg.ndev && p->fd < 0) { 103146686Sbrian physical_SetDevice(p, dev); 103247286Sbrian if (physical_Lock(p)) { 103347878Sbrian err = 0; 103447878Sbrian 103547878Sbrian if (*p->name.full == '/') { 103647286Sbrian p->fd = ID0open(p->name.full, O_RDWR | O_NONBLOCK); 103747878Sbrian if (p->fd < 0) 103847878Sbrian err = errno; 103947878Sbrian } 104046686Sbrian 104152942Sbrian wasfd = p->fd; 104247286Sbrian for (h = 0; h < NDEVICES && p->handler == NULL; h++) 104352942Sbrian if ((p->handler = (*devices[h].create)(p)) == NULL && wasfd != p->fd) 104447286Sbrian break; 104546686Sbrian 104647286Sbrian if (p->fd < 0) { 104747878Sbrian if (h == NDEVICES) { 104847878Sbrian if (err) 104947878Sbrian log_Printf(LogWARN, "%s: %s: %s\n", p->link.name, p->name.full, 105047878Sbrian strerror(errno)); 105147878Sbrian else 105247878Sbrian log_Printf(LogWARN, "%s: Device (%s) must begin with a '/'," 105352942Sbrian " a '!' or contain at least one ':'\n", p->link.name, 105447878Sbrian p->name.full); 105547878Sbrian } 105647286Sbrian physical_Unlock(p); 105747286Sbrian } else 105847286Sbrian physical_Found(p); 105947286Sbrian } 106046686Sbrian dev += strlen(dev) + 1; 106146686Sbrian devno++; 106246686Sbrian } 106346686Sbrian } 106446686Sbrian 106546686Sbrian return p->fd; 106646686Sbrian} 106746686Sbrian 106846686Sbrianvoid 106947461Sbrianphysical_SetupStack(struct physical *p, const char *who, int how) 107046686Sbrian{ 107146686Sbrian link_EmptyStack(&p->link); 107252942Sbrian if (how == PHYSICAL_FORCE_SYNC || how == PHYSICAL_FORCE_SYNCNOACF || 107347061Sbrian (how == PHYSICAL_NOFORCE && physical_IsSync(p))) 107446686Sbrian link_Stack(&p->link, &synclayer); 107546686Sbrian else { 107646686Sbrian link_Stack(&p->link, &asynclayer); 107746686Sbrian link_Stack(&p->link, &hdlclayer); 107846686Sbrian } 107952942Sbrian if (how != PHYSICAL_FORCE_SYNCNOACF) 108052942Sbrian link_Stack(&p->link, &acflayer); 108146686Sbrian link_Stack(&p->link, &protolayer); 108246686Sbrian link_Stack(&p->link, &lqrlayer); 108346686Sbrian link_Stack(&p->link, &ccplayer); 108446686Sbrian link_Stack(&p->link, &vjlayer); 108569303Sbrian link_Stack(&p->link, &tcpmsslayer); 108650059Sbrian#ifndef NONAT 108750059Sbrian link_Stack(&p->link, &natlayer); 108846686Sbrian#endif 108947061Sbrian if (how == PHYSICAL_FORCE_ASYNC && physical_IsSync(p)) { 109047461Sbrian log_Printf(LogWARN, "Sync device setting ignored for ``%s'' device\n", who); 109147061Sbrian p->cfg.speed = MODEM_SPEED; 109247061Sbrian } else if (how == PHYSICAL_FORCE_SYNC && !physical_IsSync(p)) { 109347061Sbrian log_Printf(LogWARN, "Async device setting ignored for ``%s'' device\n", 109447461Sbrian who); 109547061Sbrian physical_SetSync(p); 109647061Sbrian } 109746686Sbrian} 109847061Sbrian 109947061Sbrianvoid 110047061Sbrianphysical_StopDeviceTimer(struct physical *p) 110147061Sbrian{ 110247061Sbrian if (p->handler && p->handler->stoptimer) 110347061Sbrian (*p->handler->stoptimer)(p); 110447061Sbrian} 110549472Sbrian 110649472Sbrianint 110749472Sbrianphysical_AwaitCarrier(struct physical *p) 110849472Sbrian{ 110949472Sbrian if (p->handler && p->handler->awaitcarrier) 111049472Sbrian return (*p->handler->awaitcarrier)(p); 111149472Sbrian 111249472Sbrian return CARRIER_OK; 111349472Sbrian} 111493418Sbrian 111593418Sbrian 111693418Sbrianvoid 111793418Sbrianphysical_SetAsyncParams(struct physical *p, u_int32_t mymap, u_int32_t hismap) 111893418Sbrian{ 111993418Sbrian if (p->handler && p->handler->setasyncparams) 112093418Sbrian return (*p->handler->setasyncparams)(p, mymap, hismap); 112193418Sbrian 112293418Sbrian async_SetLinkParams(&p->async, mymap, hismap); 112393418Sbrian} 112496582Sbrian 112596582Sbrianint 112696582Sbrianphysical_Slot(struct physical *p) 112796582Sbrian{ 112896582Sbrian if (p->handler && p->handler->slot) 112996582Sbrian return (*p->handler->slot)(p); 113096582Sbrian 113196582Sbrian return -1; 113296582Sbrian} 1133132818Sglebius 1134132818Sglebiusint 1135132818Sglebiusphysical_SetPPPoEnonstandard(struct physical *p, int enable) 1136132818Sglebius{ 1137132818Sglebius p->cfg.nonstandard_pppoe = enable ? 1 : 0; 1138132818Sglebius p->cfg.pppoe_configured = 1; 1139132818Sglebius return 1; 1140132818Sglebius} 1141