ncp.c revision 102500
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: head/usr.sbin/ppp/ncp.c 102500 2002-08-27 20:11:58Z brian $ 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 9281634Sbrianstatic u_short default_urgent_udp_ports[] = { }; 9381634Sbrian 9481634Sbrian#define NDEFTCPPORTS \ 9581634Sbrian (sizeof default_urgent_tcp_ports / sizeof default_urgent_tcp_ports[0]) 9681634Sbrian#define NDEFUDPPORTS \ 9781634Sbrian (sizeof default_urgent_udp_ports / sizeof default_urgent_udp_ports[0]) 9881634Sbrian 9981634Sbrianvoid 10081634Sbrianncp_Init(struct ncp *ncp, struct bundle *bundle) 10181634Sbrian{ 10281634Sbrian ncp->afq = AF_INET; 10381634Sbrian ncp->route = NULL; 10481634Sbrian 10581634Sbrian ncp->cfg.urgent.tcp.nports = ncp->cfg.urgent.tcp.maxports = NDEFTCPPORTS; 10681634Sbrian ncp->cfg.urgent.tcp.port = (u_short *)malloc(NDEFTCPPORTS * sizeof(u_short)); 10781634Sbrian memcpy(ncp->cfg.urgent.tcp.port, default_urgent_tcp_ports, 10881634Sbrian NDEFTCPPORTS * sizeof(u_short)); 10981634Sbrian ncp->cfg.urgent.tos = 1; 11081634Sbrian 11181634Sbrian ncp->cfg.urgent.udp.nports = ncp->cfg.urgent.udp.maxports = NDEFUDPPORTS; 11281634Sbrian ncp->cfg.urgent.udp.port = (u_short *)malloc(NDEFUDPPORTS * sizeof(u_short)); 11381634Sbrian memcpy(ncp->cfg.urgent.udp.port, default_urgent_udp_ports, 11481634Sbrian NDEFUDPPORTS * sizeof(u_short)); 11581634Sbrian 11681634Sbrian 11781634Sbrian mp_Init(&ncp->mp, bundle); 11881634Sbrian 11981634Sbrian /* Send over the first physical link by default */ 12081634Sbrian ipcp_Init(&ncp->ipcp, bundle, &bundle->links->physical->link, 12181634Sbrian &bundle->fsm); 12281634Sbrian#ifndef NOINET6 12381897Sbrian ipv6cp_Init(&ncp->ipv6cp, bundle, &bundle->links->physical->link, 12481897Sbrian &bundle->fsm); 12581634Sbrian#endif 12681634Sbrian} 12781634Sbrian 12881634Sbrianvoid 12981634Sbrianncp_Destroy(struct ncp *ncp) 13081634Sbrian{ 13181634Sbrian ipcp_Destroy(&ncp->ipcp); 13281634Sbrian#ifndef NOINET6 13381897Sbrian ipv6cp_Destroy(&ncp->ipv6cp); 13481634Sbrian#endif 13581634Sbrian 13681634Sbrian if (ncp->cfg.urgent.tcp.maxports) { 13781634Sbrian ncp->cfg.urgent.tcp.nports = ncp->cfg.urgent.tcp.maxports = 0; 13881634Sbrian free(ncp->cfg.urgent.tcp.port); 13981634Sbrian ncp->cfg.urgent.tcp.port = NULL; 14081634Sbrian } 14181634Sbrian if (ncp->cfg.urgent.udp.maxports) { 14281634Sbrian ncp->cfg.urgent.udp.nports = ncp->cfg.urgent.udp.maxports = 0; 14381634Sbrian free(ncp->cfg.urgent.udp.port); 14481634Sbrian ncp->cfg.urgent.udp.port = NULL; 14581634Sbrian } 14681634Sbrian} 14781634Sbrian 14881634Sbrianint 14981634Sbrianncp_fsmStart(struct ncp *ncp, struct bundle *bundle) 15081634Sbrian{ 15181634Sbrian int res = 0; 15281634Sbrian 15381634Sbrian#ifndef NOINET6 15481634Sbrian if (Enabled(bundle, OPT_IPCP)) { 15581634Sbrian#endif 15681634Sbrian fsm_Up(&ncp->ipcp.fsm); 15781634Sbrian fsm_Open(&ncp->ipcp.fsm); 15881634Sbrian res++; 15981634Sbrian#ifndef NOINET6 16081634Sbrian } 16181634Sbrian 16281897Sbrian if (Enabled(bundle, OPT_IPV6CP)) { 16381634Sbrian fsm_Up(&ncp->ipv6cp.fsm); 16481634Sbrian fsm_Open(&ncp->ipv6cp.fsm); 16581634Sbrian res++; 16681634Sbrian } 16781634Sbrian#endif 16881634Sbrian 16981634Sbrian return res; 17081634Sbrian} 17181634Sbrian 17281634Sbrianvoid 17381634Sbrianncp_IfaceAddrAdded(struct ncp *ncp, const struct iface_addr *addr) 17481634Sbrian{ 17581634Sbrian switch (ncprange_family(&addr->ifa)) { 17681634Sbrian case AF_INET: 17781634Sbrian ipcp_IfaceAddrAdded(&ncp->ipcp, addr); 17881634Sbrian break; 17981634Sbrian#ifndef NOINET6 18081634Sbrian case AF_INET6: 18181634Sbrian ipv6cp_IfaceAddrAdded(&ncp->ipv6cp, addr); 18281634Sbrian break; 18381634Sbrian#endif 18481634Sbrian } 18581634Sbrian} 18681634Sbrian 18781634Sbrianvoid 18881634Sbrianncp_IfaceAddrDeleted(struct ncp *ncp, const struct iface_addr *addr) 18981634Sbrian{ 19081634Sbrian if (ncprange_family(&addr->ifa) == AF_INET) 19181634Sbrian ipcp_IfaceAddrDeleted(&ncp->ipcp, addr); 19281634Sbrian} 19381634Sbrian 19481634Sbrianvoid 19581634Sbrianncp_SetLink(struct ncp *ncp, struct link *l) 19681634Sbrian{ 19781634Sbrian ipcp_SetLink(&ncp->ipcp, l); 19881634Sbrian#ifndef NOINET6 19981897Sbrian ipv6cp_SetLink(&ncp->ipv6cp, l); 20081634Sbrian#endif 20181634Sbrian} 20281634Sbrian 20381634Sbrian/* 20481634Sbrian * Enqueue a packet of the given address family. Nothing will make it 20581634Sbrian * down to the physical link level 'till ncp_FillPhysicalQueues() is used. 20681634Sbrian */ 20781634Sbrianvoid 20881634Sbrianncp_Enqueue(struct ncp *ncp, int af, int pri, char *ptr, int count) 20981634Sbrian{ 21081634Sbrian#ifndef NOINET6 21181634Sbrian struct ipv6cp *ipv6cp = &ncp->ipv6cp; 21281634Sbrian#endif 21381634Sbrian struct ipcp *ipcp = &ncp->ipcp; 21481634Sbrian struct mbuf *bp; 21581634Sbrian 21681634Sbrian /* 21781634Sbrian * We allocate an extra 6 bytes, four at the front and two at the end. 21881634Sbrian * This is an optimisation so that we need to do less work in 21981634Sbrian * m_prepend() in acf_LayerPush() and proto_LayerPush() and 22081634Sbrian * appending in hdlc_LayerPush(). 22181634Sbrian */ 22281634Sbrian 22381634Sbrian switch (af) { 22481634Sbrian case AF_INET: 22581634Sbrian if (pri < 0 || pri >= IPCP_QUEUES(ipcp)) { 22681634Sbrian log_Printf(LogERROR, "Can't store in ip queue %d\n", pri); 22781634Sbrian break; 22881634Sbrian } 22981634Sbrian 23081634Sbrian bp = m_get(count + 6, MB_IPOUT); 23181634Sbrian bp->m_offset += 4; 23281634Sbrian bp->m_len -= 6; 23381634Sbrian memcpy(MBUF_CTOP(bp), ptr, count); 23481634Sbrian m_enqueue(ipcp->Queue + pri, bp); 23581634Sbrian break; 23681634Sbrian 23781634Sbrian#ifndef NOINET6 23881634Sbrian case AF_INET6: 23981634Sbrian if (pri < 0 || pri >= IPV6CP_QUEUES(ipcp)) { 24081634Sbrian log_Printf(LogERROR, "Can't store in ipv6 queue %d\n", pri); 24181634Sbrian break; 24281634Sbrian } 24381634Sbrian 24481634Sbrian bp = m_get(count + 6, MB_IPOUT); 24581634Sbrian bp->m_offset += 4; 24681634Sbrian bp->m_len -= 6; 24781634Sbrian memcpy(MBUF_CTOP(bp), ptr, count); 24881634Sbrian m_enqueue(ipv6cp->Queue + pri, bp); 24981634Sbrian break; 25081634Sbrian#endif 25181634Sbrian 25281634Sbrian default: 25381634Sbrian log_Printf(LogERROR, "Can't enqueue protocol family %d\n", af); 25481634Sbrian } 25581634Sbrian} 25681634Sbrian 25781634Sbrian/* 25881634Sbrian * How many packets are queued to go out ? 25981634Sbrian */ 26081634Sbriansize_t 26181634Sbrianncp_QueueLen(struct ncp *ncp) 26281634Sbrian{ 26381634Sbrian size_t result; 26481634Sbrian 26581634Sbrian result = ipcp_QueueLen(&ncp->ipcp); 26681634Sbrian#ifndef NOINET6 26781897Sbrian result += ipv6cp_QueueLen(&ncp->ipv6cp); 26881634Sbrian#endif 26981634Sbrian result += mp_QueueLen(&ncp->mp); /* Usually empty */ 27081634Sbrian 27181634Sbrian return result; 27281634Sbrian} 27381634Sbrian 27481634Sbrian/* 27581634Sbrian * Ditch all queued packets. This is usually done after our choked timer 27681634Sbrian * has fired - which happens because we couldn't send any traffic over 27781634Sbrian * any links for some time. 27881634Sbrian */ 27981634Sbrianvoid 28081634Sbrianncp_DeleteQueues(struct ncp *ncp) 28181634Sbrian{ 28281634Sbrian#ifndef NOINET6 28381634Sbrian struct ipv6cp *ipv6cp = &ncp->ipv6cp; 28481634Sbrian#endif 28581634Sbrian struct ipcp *ipcp = &ncp->ipcp; 28681634Sbrian struct mp *mp = &ncp->mp; 28781634Sbrian struct mqueue *q; 28881634Sbrian 28981634Sbrian for (q = ipcp->Queue; q < ipcp->Queue + IPCP_QUEUES(ipcp); q++) 29081634Sbrian while (q->top) 29181634Sbrian m_freem(m_dequeue(q)); 29281634Sbrian 29381634Sbrian#ifndef NOINET6 29481897Sbrian for (q = ipv6cp->Queue; q < ipv6cp->Queue + IPV6CP_QUEUES(ipv6cp); q++) 29581897Sbrian while (q->top) 29681897Sbrian m_freem(m_dequeue(q)); 29781634Sbrian#endif 29881634Sbrian 29981634Sbrian link_DeleteQueue(&mp->link); /* Usually empty anyway */ 30081634Sbrian} 30181634Sbrian 30281634Sbrian/* 30381634Sbrian * Arrange that each of our links has at least one packet. We keep the 30481634Sbrian * number of packets queued at the link level to a minimum so that the 30581634Sbrian * loss of a link in multi-link mode results in the minimum number of 30681634Sbrian * dropped packets. 30781634Sbrian */ 30881634Sbriansize_t 30981634Sbrianncp_FillPhysicalQueues(struct ncp *ncp, struct bundle *bundle) 31081634Sbrian{ 31181634Sbrian size_t total; 31281634Sbrian 31381634Sbrian if (bundle->ncp.mp.active) 31481634Sbrian total = mp_FillPhysicalQueues(bundle); 31581634Sbrian else { 31681634Sbrian struct datalink *dl; 31781634Sbrian size_t add; 31881634Sbrian 31981634Sbrian for (total = 0, dl = bundle->links; dl; dl = dl->next) 32081634Sbrian if (dl->state == DATALINK_OPEN) { 32181634Sbrian add = link_QueueLen(&dl->physical->link); 32281634Sbrian if (add == 0 && dl->physical->out == NULL) 32381634Sbrian add = ncp_PushPacket(ncp, &ncp->afq, &dl->physical->link); 32481634Sbrian total += add; 32581634Sbrian } 32681634Sbrian } 32781634Sbrian 32881634Sbrian return total + ncp_QueueLen(&bundle->ncp); 32981634Sbrian} 33081634Sbrian 33181634Sbrian/* 33281634Sbrian * Push a packet into the given link. ``af'' is used as a persistent record 33381634Sbrian * of what is to be pushed next, coming either from mp->out or ncp->afq. 33481634Sbrian */ 33581634Sbrianint 33681634Sbrianncp_PushPacket(struct ncp *ncp, int *af, struct link *l) 33781634Sbrian{ 33881634Sbrian struct bundle *bundle = l->lcp.fsm.bundle; 33981634Sbrian int res; 34081634Sbrian 34181634Sbrian#ifndef NOINET6 34281897Sbrian if (*af == AF_INET) { 34381634Sbrian if ((res = ipcp_PushPacket(&bundle->ncp.ipcp, l))) 34481634Sbrian *af = AF_INET6; 34581634Sbrian else 34681634Sbrian res = ipv6cp_PushPacket(&bundle->ncp.ipv6cp, l); 34781634Sbrian } else { 34881634Sbrian if ((res = ipv6cp_PushPacket(&bundle->ncp.ipv6cp, l))) 34981634Sbrian *af = AF_INET; 35081634Sbrian else 35181634Sbrian res = ipcp_PushPacket(&bundle->ncp.ipcp, l); 35281634Sbrian } 35381634Sbrian#else 35481634Sbrian res = ipcp_PushPacket(&bundle->ncp.ipcp, l); 35581634Sbrian#endif 35681634Sbrian 35781634Sbrian return res; 35881634Sbrian} 35981634Sbrian 36081634Sbrianint 36181634Sbrianncp_IsUrgentPort(struct port_range *range, u_short src, u_short dst) 36281634Sbrian{ 36381634Sbrian int f; 36481634Sbrian 36581634Sbrian for (f = 0; f < range->nports; f++) 36681634Sbrian if (range->port[f] == src || range->port[f] == dst) 36781634Sbrian return 1; 36881634Sbrian 36981634Sbrian return 0; 37081634Sbrian} 37181634Sbrian 37281634Sbrianvoid 37381634Sbrianncp_AddUrgentPort(struct port_range *range, u_short port) 37481634Sbrian{ 37581634Sbrian u_short *newport; 37681634Sbrian int p; 37781634Sbrian 37881634Sbrian if (range->nports == range->maxports) { 37981634Sbrian range->maxports += 10; 38081634Sbrian newport = (u_short *)realloc(range->port, 38181634Sbrian range->maxports * sizeof(u_short)); 38281634Sbrian if (newport == NULL) { 38381634Sbrian log_Printf(LogERROR, "ncp_AddUrgentPort: realloc: %s\n", 38481634Sbrian strerror(errno)); 38581634Sbrian range->maxports -= 10; 38681634Sbrian return; 38781634Sbrian } 38881634Sbrian range->port = newport; 38981634Sbrian } 39081634Sbrian 39181634Sbrian for (p = 0; p < range->nports; p++) 39281634Sbrian if (range->port[p] == port) { 39381634Sbrian log_Printf(LogWARN, "%u: Port already set to urgent\n", port); 39481634Sbrian break; 39581634Sbrian } else if (range->port[p] > port) { 39681634Sbrian memmove(range->port + p + 1, range->port + p, 39781634Sbrian (range->nports - p) * sizeof(u_short)); 39881634Sbrian range->port[p] = port; 39981634Sbrian range->nports++; 40081634Sbrian break; 40181634Sbrian } 40281634Sbrian 40381634Sbrian if (p == range->nports) 40481634Sbrian range->port[range->nports++] = port; 40581634Sbrian} 40681634Sbrian 40781634Sbrianvoid 40881634Sbrianncp_RemoveUrgentPort(struct port_range *range, u_short port) 40981634Sbrian{ 41081634Sbrian int p; 41181634Sbrian 41281634Sbrian for (p = 0; p < range->nports; p++) 41381634Sbrian if (range->port[p] == port) { 41481634Sbrian if (p != range->nports - 1) 41581634Sbrian memmove(range->port + p, range->port + p + 1, 41681634Sbrian (range->nports - p - 1) * sizeof(u_short)); 41781634Sbrian range->nports--; 41881634Sbrian return; 41981634Sbrian } 42081634Sbrian 42181634Sbrian if (p == range->nports) 42281634Sbrian log_Printf(LogWARN, "%u: Port not set to urgent\n", port); 42381634Sbrian} 42481634Sbrian 42581634Sbrianvoid 42681634Sbrianncp_ClearUrgentPorts(struct port_range *range) 42781634Sbrian{ 42881634Sbrian range->nports = 0; 42981634Sbrian} 43081634Sbrian 43181634Sbrianint 43281634Sbrianncp_Show(struct cmdargs const *arg) 43381634Sbrian{ 43481634Sbrian struct ncp *ncp = &arg->bundle->ncp; 43581634Sbrian int p; 43681634Sbrian 43781634Sbrian#ifndef NOINET6 43881897Sbrian prompt_Printf(arg->prompt, "Next queued AF: %s\n", 43981897Sbrian ncp->afq == AF_INET6 ? "inet6" : "inet"); 44081634Sbrian#endif 44181634Sbrian 44281634Sbrian if (ncp->route) { 44381634Sbrian prompt_Printf(arg->prompt, "\n"); 44481634Sbrian route_ShowSticky(arg->prompt, ncp->route, "Sticky routes", 1); 44581634Sbrian } 44681634Sbrian 44781634Sbrian prompt_Printf(arg->prompt, "\nDefaults:\n"); 44881634Sbrian prompt_Printf(arg->prompt, " sendpipe: "); 44981634Sbrian if (ncp->cfg.sendpipe > 0) 45081634Sbrian prompt_Printf(arg->prompt, "%-20ld\n", ncp->cfg.sendpipe); 45181634Sbrian else 45281634Sbrian prompt_Printf(arg->prompt, "unspecified\n"); 45381634Sbrian prompt_Printf(arg->prompt, " recvpipe: "); 45481634Sbrian if (ncp->cfg.recvpipe > 0) 45581634Sbrian prompt_Printf(arg->prompt, "%ld\n", ncp->cfg.recvpipe); 45681634Sbrian else 45781634Sbrian prompt_Printf(arg->prompt, "unspecified\n"); 45881634Sbrian 45981634Sbrian prompt_Printf(arg->prompt, "\n Urgent ports\n"); 46081634Sbrian prompt_Printf(arg->prompt, " TCP: "); 46181634Sbrian if (ncp->cfg.urgent.tcp.nports == 0) 46281634Sbrian prompt_Printf(arg->prompt, "none"); 46381634Sbrian else 46481634Sbrian for (p = 0; p < ncp->cfg.urgent.tcp.nports; p++) { 46581634Sbrian if (p) 46681634Sbrian prompt_Printf(arg->prompt, ", "); 46781634Sbrian prompt_Printf(arg->prompt, "%u", ncp->cfg.urgent.tcp.port[p]); 46881634Sbrian } 46981634Sbrian 47081634Sbrian prompt_Printf(arg->prompt, "\n UDP: "); 47181634Sbrian if (ncp->cfg.urgent.udp.nports == 0) 47281634Sbrian prompt_Printf(arg->prompt, "none"); 47381634Sbrian else 47481634Sbrian for (p = 0; p < ncp->cfg.urgent.udp.nports; p++) { 47581634Sbrian if (p) 47681634Sbrian prompt_Printf(arg->prompt, ", "); 47781634Sbrian prompt_Printf(arg->prompt, "%u", ncp->cfg.urgent.udp.port[p]); 47881634Sbrian } 47981634Sbrian prompt_Printf(arg->prompt, "\n TOS: %s\n\n", 48081634Sbrian ncp->cfg.urgent.tos ? "yes" : "no"); 48181634Sbrian 48281634Sbrian return 0; 48381634Sbrian} 48481634Sbrian 48581634Sbrianint 48681634Sbrianncp_LayersOpen(struct ncp *ncp) 48781634Sbrian{ 48881634Sbrian int n; 48981634Sbrian 49081634Sbrian n = !!(ncp->ipcp.fsm.state == ST_OPENED); 49181634Sbrian#ifndef NOINET6 49281897Sbrian n += !!(ncp->ipv6cp.fsm.state == ST_OPENED); 49381634Sbrian#endif 49481634Sbrian 49581634Sbrian return n; 49681634Sbrian} 49781634Sbrian 49881634Sbrianint 49981634Sbrianncp_LayersUnfinished(struct ncp *ncp) 50081634Sbrian{ 50181634Sbrian int n = 0; 50281634Sbrian 50381634Sbrian if (ncp->ipcp.fsm.state > ST_CLOSED || 50481634Sbrian ncp->ipcp.fsm.state == ST_STARTING) 50581634Sbrian n++; 50681634Sbrian 50781634Sbrian#ifndef NOINET6 50881897Sbrian if (ncp->ipv6cp.fsm.state > ST_CLOSED || 50981897Sbrian ncp->ipv6cp.fsm.state == ST_STARTING) 51081897Sbrian n++; 51181634Sbrian#endif 51281634Sbrian 51381634Sbrian return n; 51481634Sbrian} 51581634Sbrian 51681634Sbrianvoid 51781634Sbrianncp_Close(struct ncp *ncp) 51881634Sbrian{ 51981634Sbrian if (ncp->ipcp.fsm.state > ST_CLOSED || 52081634Sbrian ncp->ipcp.fsm.state == ST_STARTING) 52181634Sbrian fsm_Close(&ncp->ipcp.fsm); 52281634Sbrian 52381634Sbrian#ifndef NOINET6 52481897Sbrian if (ncp->ipv6cp.fsm.state > ST_CLOSED || 52581897Sbrian ncp->ipv6cp.fsm.state == ST_STARTING) 52681897Sbrian fsm_Close(&ncp->ipv6cp.fsm); 52781634Sbrian#endif 52881634Sbrian} 52981634Sbrian 53081634Sbrianvoid 53181634Sbrianncp2initial(struct ncp *ncp) 53281634Sbrian{ 53381634Sbrian fsm2initial(&ncp->ipcp.fsm); 53481634Sbrian#ifndef NOINET6 53581897Sbrian fsm2initial(&ncp->ipv6cp.fsm); 53681634Sbrian#endif 53781634Sbrian} 538