181634Sbrian/*- 281634Sbrian * Copyright (c) 2001 Brian Somers <brian@Awfulhak.org> 381634Sbrian * All rights reserved. 481634Sbrian * 581634Sbrian * Redistribution and use in source and binary forms, with or without 681634Sbrian * modification, are permitted provided that the following conditions 781634Sbrian * are met: 881634Sbrian * 1. Redistributions of source code must retain the above copyright 981634Sbrian * notice, this list of conditions and the following disclaimer. 1081634Sbrian * 2. Redistributions in binary form must reproduce the above copyright 1181634Sbrian * notice, this list of conditions and the following disclaimer in the 1281634Sbrian * documentation and/or other materials provided with the distribution. 1381634Sbrian * 1481634Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1581634Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1681634Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1781634Sbrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1881634Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1981634Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2081634Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2181634Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2281634Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2381634Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2481634Sbrian * SUCH DAMAGE. 2581634Sbrian * 2681634Sbrian * $FreeBSD$ 2781634Sbrian */ 2881634Sbrian 2981634Sbrian#include <sys/param.h> 3081634Sbrian#include <netinet/in_systm.h> 3181634Sbrian#include <netinet/in.h> 3281634Sbrian#include <netinet/ip.h> 3381634Sbrian#include <sys/socket.h> 3481634Sbrian#include <net/route.h> 3581634Sbrian#include <sys/un.h> 3681634Sbrian 3781634Sbrian#include <errno.h> 3881634Sbrian#include <resolv.h> 39102500Sbrian#include <stdarg.h> 4081634Sbrian#include <stdlib.h> 4181634Sbrian#include <string.h> 4281634Sbrian#include <termios.h> 4381634Sbrian 4481634Sbrian#include "layer.h" 4581634Sbrian#include "defs.h" 4681634Sbrian#include "command.h" 4781634Sbrian#include "mbuf.h" 4881634Sbrian#include "log.h" 4981634Sbrian#include "timer.h" 5081634Sbrian#include "fsm.h" 5181634Sbrian#include "iplist.h" 5281634Sbrian#include "throughput.h" 5381634Sbrian#include "slcompress.h" 5481634Sbrian#include "lqr.h" 5581634Sbrian#include "hdlc.h" 5681634Sbrian#include "lcp.h" 5781634Sbrian#include "ncpaddr.h" 5881634Sbrian#include "ipcp.h" 5981634Sbrian#include "filter.h" 6081634Sbrian#include "descriptor.h" 6181634Sbrian#include "async.h" 6281634Sbrian#include "ccp.h" 6381634Sbrian#include "link.h" 6481634Sbrian#include "physical.h" 6581634Sbrian#include "mp.h" 6681634Sbrian#ifndef NORADIUS 6781634Sbrian#include "radius.h" 6881634Sbrian#endif 6981634Sbrian#include "ipv6cp.h" 7081634Sbrian#include "ncp.h" 7181634Sbrian#include "bundle.h" 7281634Sbrian#include "prompt.h" 7381634Sbrian#include "route.h" 7481634Sbrian#include "iface.h" 7581634Sbrian#include "chat.h" 7681634Sbrian#include "auth.h" 7781634Sbrian#include "chap.h" 7881634Sbrian#include "cbcp.h" 7981634Sbrian#include "datalink.h" 8081634Sbrian 8181634Sbrian 8281634Sbrianstatic u_short default_urgent_tcp_ports[] = { 8381634Sbrian 21, /* ftp */ 8481634Sbrian 22, /* ssh */ 8581634Sbrian 23, /* telnet */ 8681634Sbrian 513, /* login */ 8781634Sbrian 514, /* shell */ 8881634Sbrian 543, /* klogin */ 8981634Sbrian 544 /* kshell */ 9081634Sbrian}; 9181634Sbrian 9281634Sbrian#define NDEFTCPPORTS \ 9381634Sbrian (sizeof default_urgent_tcp_ports / sizeof default_urgent_tcp_ports[0]) 9481634Sbrian 9581634Sbrianvoid 9681634Sbrianncp_Init(struct ncp *ncp, struct bundle *bundle) 9781634Sbrian{ 9881634Sbrian ncp->afq = AF_INET; 9981634Sbrian ncp->route = NULL; 10081634Sbrian 10181634Sbrian ncp->cfg.urgent.tcp.port = (u_short *)malloc(NDEFTCPPORTS * sizeof(u_short)); 102136377Sbrian if (ncp->cfg.urgent.tcp.port == NULL) { 103136377Sbrian log_Printf(LogERROR, "ncp_Init: Out of memory allocating urgent ports\n"); 104136377Sbrian ncp->cfg.urgent.tcp.nports = ncp->cfg.urgent.tcp.maxports = 0; 105136377Sbrian } else { 106136377Sbrian ncp->cfg.urgent.tcp.nports = ncp->cfg.urgent.tcp.maxports = NDEFTCPPORTS; 107136377Sbrian memcpy(ncp->cfg.urgent.tcp.port, default_urgent_tcp_ports, 108136377Sbrian NDEFTCPPORTS * sizeof(u_short)); 109136377Sbrian } 11081634Sbrian ncp->cfg.urgent.tos = 1; 11181634Sbrian 112134789Sbrian ncp->cfg.urgent.udp.nports = ncp->cfg.urgent.udp.maxports = 0; 113134789Sbrian ncp->cfg.urgent.udp.port = NULL; 11481634Sbrian 11581634Sbrian mp_Init(&ncp->mp, bundle); 11681634Sbrian 11781634Sbrian /* Send over the first physical link by default */ 11881634Sbrian ipcp_Init(&ncp->ipcp, bundle, &bundle->links->physical->link, 11981634Sbrian &bundle->fsm); 12081634Sbrian#ifndef NOINET6 12181897Sbrian ipv6cp_Init(&ncp->ipv6cp, bundle, &bundle->links->physical->link, 12281897Sbrian &bundle->fsm); 12381634Sbrian#endif 12481634Sbrian} 12581634Sbrian 12681634Sbrianvoid 12781634Sbrianncp_Destroy(struct ncp *ncp) 12881634Sbrian{ 12981634Sbrian ipcp_Destroy(&ncp->ipcp); 13081634Sbrian#ifndef NOINET6 13181897Sbrian ipv6cp_Destroy(&ncp->ipv6cp); 13281634Sbrian#endif 13381634Sbrian 13481634Sbrian if (ncp->cfg.urgent.tcp.maxports) { 13581634Sbrian ncp->cfg.urgent.tcp.nports = ncp->cfg.urgent.tcp.maxports = 0; 13681634Sbrian free(ncp->cfg.urgent.tcp.port); 13781634Sbrian ncp->cfg.urgent.tcp.port = NULL; 13881634Sbrian } 13981634Sbrian if (ncp->cfg.urgent.udp.maxports) { 14081634Sbrian ncp->cfg.urgent.udp.nports = ncp->cfg.urgent.udp.maxports = 0; 14181634Sbrian free(ncp->cfg.urgent.udp.port); 14281634Sbrian ncp->cfg.urgent.udp.port = NULL; 14381634Sbrian } 14481634Sbrian} 14581634Sbrian 14681634Sbrianint 147134875Sbrianncp_fsmStart(struct ncp *ncp, 148134875Sbrian#ifdef NOINET6 149134875Sbrian struct bundle *bundle __unused 150134875Sbrian#else 151134875Sbrian struct bundle *bundle 152134875Sbrian#endif 153134875Sbrian ) 15481634Sbrian{ 15581634Sbrian int res = 0; 15681634Sbrian 15781634Sbrian#ifndef NOINET6 15881634Sbrian if (Enabled(bundle, OPT_IPCP)) { 15981634Sbrian#endif 16081634Sbrian fsm_Up(&ncp->ipcp.fsm); 16181634Sbrian fsm_Open(&ncp->ipcp.fsm); 16281634Sbrian res++; 16381634Sbrian#ifndef NOINET6 16481634Sbrian } 16581634Sbrian 16681897Sbrian if (Enabled(bundle, OPT_IPV6CP)) { 16781634Sbrian fsm_Up(&ncp->ipv6cp.fsm); 16881634Sbrian fsm_Open(&ncp->ipv6cp.fsm); 16981634Sbrian res++; 17081634Sbrian } 17181634Sbrian#endif 17281634Sbrian 17381634Sbrian return res; 17481634Sbrian} 17581634Sbrian 17681634Sbrianvoid 17781634Sbrianncp_IfaceAddrAdded(struct ncp *ncp, const struct iface_addr *addr) 17881634Sbrian{ 17981634Sbrian switch (ncprange_family(&addr->ifa)) { 18081634Sbrian case AF_INET: 18181634Sbrian ipcp_IfaceAddrAdded(&ncp->ipcp, addr); 18281634Sbrian break; 18381634Sbrian#ifndef NOINET6 18481634Sbrian case AF_INET6: 18581634Sbrian ipv6cp_IfaceAddrAdded(&ncp->ipv6cp, addr); 18681634Sbrian break; 18781634Sbrian#endif 18881634Sbrian } 18981634Sbrian} 19081634Sbrian 19181634Sbrianvoid 19281634Sbrianncp_IfaceAddrDeleted(struct ncp *ncp, const struct iface_addr *addr) 19381634Sbrian{ 19481634Sbrian if (ncprange_family(&addr->ifa) == AF_INET) 19581634Sbrian ipcp_IfaceAddrDeleted(&ncp->ipcp, addr); 19681634Sbrian} 19781634Sbrian 19881634Sbrianvoid 19981634Sbrianncp_SetLink(struct ncp *ncp, struct link *l) 20081634Sbrian{ 20181634Sbrian ipcp_SetLink(&ncp->ipcp, l); 20281634Sbrian#ifndef NOINET6 20381897Sbrian ipv6cp_SetLink(&ncp->ipv6cp, l); 20481634Sbrian#endif 20581634Sbrian} 20681634Sbrian 20781634Sbrian/* 20881634Sbrian * Enqueue a packet of the given address family. Nothing will make it 20981634Sbrian * down to the physical link level 'till ncp_FillPhysicalQueues() is used. 21081634Sbrian */ 21181634Sbrianvoid 212134789Sbrianncp_Enqueue(struct ncp *ncp, int af, unsigned pri, char *ptr, int count) 21381634Sbrian{ 21481634Sbrian#ifndef NOINET6 21581634Sbrian struct ipv6cp *ipv6cp = &ncp->ipv6cp; 21681634Sbrian#endif 21781634Sbrian struct ipcp *ipcp = &ncp->ipcp; 21881634Sbrian struct mbuf *bp; 21981634Sbrian 22081634Sbrian /* 22181634Sbrian * We allocate an extra 6 bytes, four at the front and two at the end. 22281634Sbrian * This is an optimisation so that we need to do less work in 22381634Sbrian * m_prepend() in acf_LayerPush() and proto_LayerPush() and 22481634Sbrian * appending in hdlc_LayerPush(). 22581634Sbrian */ 22681634Sbrian 22781634Sbrian switch (af) { 22881634Sbrian case AF_INET: 229134789Sbrian if (pri >= IPCP_QUEUES(ipcp)) { 230134789Sbrian log_Printf(LogERROR, "Can't store in ip queue %u\n", pri); 23181634Sbrian break; 23281634Sbrian } 23381634Sbrian 23481634Sbrian bp = m_get(count + 6, MB_IPOUT); 23581634Sbrian bp->m_offset += 4; 23681634Sbrian bp->m_len -= 6; 23781634Sbrian memcpy(MBUF_CTOP(bp), ptr, count); 23881634Sbrian m_enqueue(ipcp->Queue + pri, bp); 23981634Sbrian break; 24081634Sbrian 24181634Sbrian#ifndef NOINET6 24281634Sbrian case AF_INET6: 243134789Sbrian if (pri >= IPV6CP_QUEUES(ipcp)) { 244134789Sbrian log_Printf(LogERROR, "Can't store in ipv6 queue %u\n", pri); 24581634Sbrian break; 24681634Sbrian } 24781634Sbrian 24881634Sbrian bp = m_get(count + 6, MB_IPOUT); 24981634Sbrian bp->m_offset += 4; 25081634Sbrian bp->m_len -= 6; 25181634Sbrian memcpy(MBUF_CTOP(bp), ptr, count); 25281634Sbrian m_enqueue(ipv6cp->Queue + pri, bp); 25381634Sbrian break; 25481634Sbrian#endif 25581634Sbrian 25681634Sbrian default: 25781634Sbrian log_Printf(LogERROR, "Can't enqueue protocol family %d\n", af); 25881634Sbrian } 25981634Sbrian} 26081634Sbrian 26181634Sbrian/* 26281634Sbrian * How many packets are queued to go out ? 26381634Sbrian */ 26481634Sbriansize_t 26581634Sbrianncp_QueueLen(struct ncp *ncp) 26681634Sbrian{ 26781634Sbrian size_t result; 26881634Sbrian 26981634Sbrian result = ipcp_QueueLen(&ncp->ipcp); 27081634Sbrian#ifndef NOINET6 27181897Sbrian result += ipv6cp_QueueLen(&ncp->ipv6cp); 27281634Sbrian#endif 27381634Sbrian result += mp_QueueLen(&ncp->mp); /* Usually empty */ 27481634Sbrian 27581634Sbrian return result; 27681634Sbrian} 27781634Sbrian 27881634Sbrian/* 27981634Sbrian * Ditch all queued packets. This is usually done after our choked timer 28081634Sbrian * has fired - which happens because we couldn't send any traffic over 28181634Sbrian * any links for some time. 28281634Sbrian */ 28381634Sbrianvoid 28481634Sbrianncp_DeleteQueues(struct ncp *ncp) 28581634Sbrian{ 28681634Sbrian#ifndef NOINET6 28781634Sbrian struct ipv6cp *ipv6cp = &ncp->ipv6cp; 28881634Sbrian#endif 28981634Sbrian struct ipcp *ipcp = &ncp->ipcp; 29081634Sbrian struct mp *mp = &ncp->mp; 29181634Sbrian struct mqueue *q; 29281634Sbrian 29381634Sbrian for (q = ipcp->Queue; q < ipcp->Queue + IPCP_QUEUES(ipcp); q++) 29481634Sbrian while (q->top) 29581634Sbrian m_freem(m_dequeue(q)); 29681634Sbrian 29781634Sbrian#ifndef NOINET6 29881897Sbrian for (q = ipv6cp->Queue; q < ipv6cp->Queue + IPV6CP_QUEUES(ipv6cp); q++) 29981897Sbrian while (q->top) 30081897Sbrian m_freem(m_dequeue(q)); 30181634Sbrian#endif 30281634Sbrian 30381634Sbrian link_DeleteQueue(&mp->link); /* Usually empty anyway */ 30481634Sbrian} 30581634Sbrian 30681634Sbrian/* 30781634Sbrian * Arrange that each of our links has at least one packet. We keep the 30881634Sbrian * number of packets queued at the link level to a minimum so that the 30981634Sbrian * loss of a link in multi-link mode results in the minimum number of 31081634Sbrian * dropped packets. 31181634Sbrian */ 31281634Sbriansize_t 31381634Sbrianncp_FillPhysicalQueues(struct ncp *ncp, struct bundle *bundle) 31481634Sbrian{ 31581634Sbrian size_t total; 31681634Sbrian 31781634Sbrian if (bundle->ncp.mp.active) 31881634Sbrian total = mp_FillPhysicalQueues(bundle); 31981634Sbrian else { 32081634Sbrian struct datalink *dl; 32181634Sbrian size_t add; 32281634Sbrian 32381634Sbrian for (total = 0, dl = bundle->links; dl; dl = dl->next) 32481634Sbrian if (dl->state == DATALINK_OPEN) { 32581634Sbrian add = link_QueueLen(&dl->physical->link); 32681634Sbrian if (add == 0 && dl->physical->out == NULL) 32781634Sbrian add = ncp_PushPacket(ncp, &ncp->afq, &dl->physical->link); 32881634Sbrian total += add; 32981634Sbrian } 33081634Sbrian } 33181634Sbrian 33281634Sbrian return total + ncp_QueueLen(&bundle->ncp); 33381634Sbrian} 33481634Sbrian 33581634Sbrian/* 33681634Sbrian * Push a packet into the given link. ``af'' is used as a persistent record 33781634Sbrian * of what is to be pushed next, coming either from mp->out or ncp->afq. 33881634Sbrian */ 33981634Sbrianint 340134875Sbrianncp_PushPacket(struct ncp *ncp __unused, 341134875Sbrian#ifdef NOINET6 342134875Sbrian int *af __unused, 343134875Sbrian#else 344134875Sbrian int *af, 345134875Sbrian#endif 346134875Sbrian struct link *l) 34781634Sbrian{ 34881634Sbrian struct bundle *bundle = l->lcp.fsm.bundle; 34981634Sbrian int res; 35081634Sbrian 35181634Sbrian#ifndef NOINET6 35281897Sbrian if (*af == AF_INET) { 35381634Sbrian if ((res = ipcp_PushPacket(&bundle->ncp.ipcp, l))) 35481634Sbrian *af = AF_INET6; 35581634Sbrian else 35681634Sbrian res = ipv6cp_PushPacket(&bundle->ncp.ipv6cp, l); 35781634Sbrian } else { 35881634Sbrian if ((res = ipv6cp_PushPacket(&bundle->ncp.ipv6cp, l))) 35981634Sbrian *af = AF_INET; 36081634Sbrian else 36181634Sbrian res = ipcp_PushPacket(&bundle->ncp.ipcp, l); 36281634Sbrian } 36381634Sbrian#else 36481634Sbrian res = ipcp_PushPacket(&bundle->ncp.ipcp, l); 36581634Sbrian#endif 36681634Sbrian 36781634Sbrian return res; 36881634Sbrian} 36981634Sbrian 37081634Sbrianint 37181634Sbrianncp_IsUrgentPort(struct port_range *range, u_short src, u_short dst) 37281634Sbrian{ 373134789Sbrian unsigned f; 37481634Sbrian 37581634Sbrian for (f = 0; f < range->nports; f++) 37681634Sbrian if (range->port[f] == src || range->port[f] == dst) 37781634Sbrian return 1; 37881634Sbrian 37981634Sbrian return 0; 38081634Sbrian} 38181634Sbrian 38281634Sbrianvoid 38381634Sbrianncp_AddUrgentPort(struct port_range *range, u_short port) 38481634Sbrian{ 38581634Sbrian u_short *newport; 386134789Sbrian unsigned p; 38781634Sbrian 38881634Sbrian if (range->nports == range->maxports) { 38981634Sbrian range->maxports += 10; 39081634Sbrian newport = (u_short *)realloc(range->port, 39181634Sbrian range->maxports * sizeof(u_short)); 39281634Sbrian if (newport == NULL) { 39381634Sbrian log_Printf(LogERROR, "ncp_AddUrgentPort: realloc: %s\n", 39481634Sbrian strerror(errno)); 39581634Sbrian range->maxports -= 10; 39681634Sbrian return; 39781634Sbrian } 39881634Sbrian range->port = newport; 39981634Sbrian } 40081634Sbrian 40181634Sbrian for (p = 0; p < range->nports; p++) 40281634Sbrian if (range->port[p] == port) { 40381634Sbrian log_Printf(LogWARN, "%u: Port already set to urgent\n", port); 40481634Sbrian break; 40581634Sbrian } else if (range->port[p] > port) { 40681634Sbrian memmove(range->port + p + 1, range->port + p, 40781634Sbrian (range->nports - p) * sizeof(u_short)); 40881634Sbrian range->port[p] = port; 40981634Sbrian range->nports++; 41081634Sbrian break; 41181634Sbrian } 41281634Sbrian 41381634Sbrian if (p == range->nports) 41481634Sbrian range->port[range->nports++] = port; 41581634Sbrian} 41681634Sbrian 41781634Sbrianvoid 41881634Sbrianncp_RemoveUrgentPort(struct port_range *range, u_short port) 41981634Sbrian{ 420134789Sbrian unsigned p; 42181634Sbrian 42281634Sbrian for (p = 0; p < range->nports; p++) 42381634Sbrian if (range->port[p] == port) { 424134789Sbrian if (p + 1 != range->nports) 42581634Sbrian memmove(range->port + p, range->port + p + 1, 42681634Sbrian (range->nports - p - 1) * sizeof(u_short)); 42781634Sbrian range->nports--; 42881634Sbrian return; 42981634Sbrian } 43081634Sbrian 43181634Sbrian if (p == range->nports) 43281634Sbrian log_Printf(LogWARN, "%u: Port not set to urgent\n", port); 43381634Sbrian} 43481634Sbrian 43581634Sbrianvoid 43681634Sbrianncp_ClearUrgentPorts(struct port_range *range) 43781634Sbrian{ 43881634Sbrian range->nports = 0; 43981634Sbrian} 44081634Sbrian 44181634Sbrianint 44281634Sbrianncp_Show(struct cmdargs const *arg) 44381634Sbrian{ 44481634Sbrian struct ncp *ncp = &arg->bundle->ncp; 445134789Sbrian unsigned p; 44681634Sbrian 44781634Sbrian#ifndef NOINET6 44881897Sbrian prompt_Printf(arg->prompt, "Next queued AF: %s\n", 44981897Sbrian ncp->afq == AF_INET6 ? "inet6" : "inet"); 45081634Sbrian#endif 45181634Sbrian 45281634Sbrian if (ncp->route) { 45381634Sbrian prompt_Printf(arg->prompt, "\n"); 45481634Sbrian route_ShowSticky(arg->prompt, ncp->route, "Sticky routes", 1); 45581634Sbrian } 45681634Sbrian 45781634Sbrian prompt_Printf(arg->prompt, "\nDefaults:\n"); 45881634Sbrian prompt_Printf(arg->prompt, " sendpipe: "); 45981634Sbrian if (ncp->cfg.sendpipe > 0) 46081634Sbrian prompt_Printf(arg->prompt, "%-20ld\n", ncp->cfg.sendpipe); 46181634Sbrian else 46281634Sbrian prompt_Printf(arg->prompt, "unspecified\n"); 46381634Sbrian prompt_Printf(arg->prompt, " recvpipe: "); 46481634Sbrian if (ncp->cfg.recvpipe > 0) 46581634Sbrian prompt_Printf(arg->prompt, "%ld\n", ncp->cfg.recvpipe); 46681634Sbrian else 46781634Sbrian prompt_Printf(arg->prompt, "unspecified\n"); 46881634Sbrian 46981634Sbrian prompt_Printf(arg->prompt, "\n Urgent ports\n"); 47081634Sbrian prompt_Printf(arg->prompt, " TCP: "); 47181634Sbrian if (ncp->cfg.urgent.tcp.nports == 0) 47281634Sbrian prompt_Printf(arg->prompt, "none"); 47381634Sbrian else 47481634Sbrian for (p = 0; p < ncp->cfg.urgent.tcp.nports; p++) { 47581634Sbrian if (p) 47681634Sbrian prompt_Printf(arg->prompt, ", "); 47781634Sbrian prompt_Printf(arg->prompt, "%u", ncp->cfg.urgent.tcp.port[p]); 47881634Sbrian } 47981634Sbrian 48081634Sbrian prompt_Printf(arg->prompt, "\n UDP: "); 48181634Sbrian if (ncp->cfg.urgent.udp.nports == 0) 48281634Sbrian prompt_Printf(arg->prompt, "none"); 48381634Sbrian else 48481634Sbrian for (p = 0; p < ncp->cfg.urgent.udp.nports; p++) { 48581634Sbrian if (p) 48681634Sbrian prompt_Printf(arg->prompt, ", "); 48781634Sbrian prompt_Printf(arg->prompt, "%u", ncp->cfg.urgent.udp.port[p]); 48881634Sbrian } 48981634Sbrian prompt_Printf(arg->prompt, "\n TOS: %s\n\n", 49081634Sbrian ncp->cfg.urgent.tos ? "yes" : "no"); 49181634Sbrian 49281634Sbrian return 0; 49381634Sbrian} 49481634Sbrian 49581634Sbrianint 49681634Sbrianncp_LayersOpen(struct ncp *ncp) 49781634Sbrian{ 49881634Sbrian int n; 49981634Sbrian 50081634Sbrian n = !!(ncp->ipcp.fsm.state == ST_OPENED); 50181634Sbrian#ifndef NOINET6 50281897Sbrian n += !!(ncp->ipv6cp.fsm.state == ST_OPENED); 50381634Sbrian#endif 50481634Sbrian 50581634Sbrian return n; 50681634Sbrian} 50781634Sbrian 50881634Sbrianint 50981634Sbrianncp_LayersUnfinished(struct ncp *ncp) 51081634Sbrian{ 51181634Sbrian int n = 0; 51281634Sbrian 51381634Sbrian if (ncp->ipcp.fsm.state > ST_CLOSED || 51481634Sbrian ncp->ipcp.fsm.state == ST_STARTING) 51581634Sbrian n++; 51681634Sbrian 51781634Sbrian#ifndef NOINET6 51881897Sbrian if (ncp->ipv6cp.fsm.state > ST_CLOSED || 51981897Sbrian ncp->ipv6cp.fsm.state == ST_STARTING) 52081897Sbrian n++; 52181634Sbrian#endif 52281634Sbrian 52381634Sbrian return n; 52481634Sbrian} 52581634Sbrian 52681634Sbrianvoid 52781634Sbrianncp_Close(struct ncp *ncp) 52881634Sbrian{ 52981634Sbrian if (ncp->ipcp.fsm.state > ST_CLOSED || 53081634Sbrian ncp->ipcp.fsm.state == ST_STARTING) 53181634Sbrian fsm_Close(&ncp->ipcp.fsm); 53281634Sbrian 53381634Sbrian#ifndef NOINET6 53481897Sbrian if (ncp->ipv6cp.fsm.state > ST_CLOSED || 53581897Sbrian ncp->ipv6cp.fsm.state == ST_STARTING) 53681897Sbrian fsm_Close(&ncp->ipv6cp.fsm); 53781634Sbrian#endif 53881634Sbrian} 53981634Sbrian 54081634Sbrianvoid 54181634Sbrianncp2initial(struct ncp *ncp) 54281634Sbrian{ 54381634Sbrian fsm2initial(&ncp->ipcp.fsm); 54481634Sbrian#ifndef NOINET6 54581897Sbrian fsm2initial(&ncp->ipv6cp.fsm); 54681634Sbrian#endif 54781634Sbrian} 548