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