ncp.c revision 81897
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 81897 2001-08-18 19:07:13Z 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 <arpa/inet.h> 3481634Sbrian#include <sys/socket.h> 3581634Sbrian#include <net/if.h> 3681634Sbrian#include <net/route.h> 3781634Sbrian#include <netdb.h> 3881634Sbrian#include <sys/un.h> 3981634Sbrian 4081634Sbrian#include <errno.h> 4181634Sbrian#include <fcntl.h> 4281634Sbrian#include <resolv.h> 4381634Sbrian#include <stdlib.h> 4481634Sbrian#include <string.h> 4581634Sbrian#include <sys/stat.h> 4681634Sbrian#include <termios.h> 4781634Sbrian#include <unistd.h> 4881634Sbrian 4981634Sbrian#include "layer.h" 5081634Sbrian#include "ua.h" 5181634Sbrian#include "defs.h" 5281634Sbrian#include "command.h" 5381634Sbrian#include "mbuf.h" 5481634Sbrian#include "log.h" 5581634Sbrian#include "timer.h" 5681634Sbrian#include "fsm.h" 5781634Sbrian#include "proto.h" 5881634Sbrian#include "iplist.h" 5981634Sbrian#include "throughput.h" 6081634Sbrian#include "slcompress.h" 6181634Sbrian#include "lqr.h" 6281634Sbrian#include "hdlc.h" 6381634Sbrian#include "lcp.h" 6481634Sbrian#include "ncpaddr.h" 6581634Sbrian#include "ip.h" 6681634Sbrian#include "ipcp.h" 6781634Sbrian#include "filter.h" 6881634Sbrian#include "descriptor.h" 6981634Sbrian#include "vjcomp.h" 7081634Sbrian#include "async.h" 7181634Sbrian#include "ccp.h" 7281634Sbrian#include "link.h" 7381634Sbrian#include "physical.h" 7481634Sbrian#include "mp.h" 7581634Sbrian#ifndef NORADIUS 7681634Sbrian#include "radius.h" 7781634Sbrian#endif 7881634Sbrian#include "ipv6cp.h" 7981634Sbrian#include "ncp.h" 8081634Sbrian#include "bundle.h" 8181634Sbrian#include "id.h" 8281634Sbrian#include "arp.h" 8381634Sbrian#include "systems.h" 8481634Sbrian#include "prompt.h" 8581634Sbrian#include "route.h" 8681634Sbrian#include "iface.h" 8781634Sbrian#include "chat.h" 8881634Sbrian#include "auth.h" 8981634Sbrian#include "chap.h" 9081634Sbrian#include "pap.h" 9181634Sbrian#include "cbcp.h" 9281634Sbrian#include "datalink.h" 9381634Sbrian 9481634Sbrian 9581634Sbrianstatic u_short default_urgent_tcp_ports[] = { 9681634Sbrian 21, /* ftp */ 9781634Sbrian 22, /* ssh */ 9881634Sbrian 23, /* telnet */ 9981634Sbrian 513, /* login */ 10081634Sbrian 514, /* shell */ 10181634Sbrian 543, /* klogin */ 10281634Sbrian 544 /* kshell */ 10381634Sbrian}; 10481634Sbrian 10581634Sbrianstatic u_short default_urgent_udp_ports[] = { }; 10681634Sbrian 10781634Sbrian#define NDEFTCPPORTS \ 10881634Sbrian (sizeof default_urgent_tcp_ports / sizeof default_urgent_tcp_ports[0]) 10981634Sbrian#define NDEFUDPPORTS \ 11081634Sbrian (sizeof default_urgent_udp_ports / sizeof default_urgent_udp_ports[0]) 11181634Sbrian 11281634Sbrianvoid 11381634Sbrianncp_Init(struct ncp *ncp, struct bundle *bundle) 11481634Sbrian{ 11581634Sbrian ncp->afq = AF_INET; 11681634Sbrian ncp->route = NULL; 11781634Sbrian 11881634Sbrian ncp->cfg.urgent.tcp.nports = ncp->cfg.urgent.tcp.maxports = NDEFTCPPORTS; 11981634Sbrian ncp->cfg.urgent.tcp.port = (u_short *)malloc(NDEFTCPPORTS * sizeof(u_short)); 12081634Sbrian memcpy(ncp->cfg.urgent.tcp.port, default_urgent_tcp_ports, 12181634Sbrian NDEFTCPPORTS * sizeof(u_short)); 12281634Sbrian ncp->cfg.urgent.tos = 1; 12381634Sbrian 12481634Sbrian ncp->cfg.urgent.udp.nports = ncp->cfg.urgent.udp.maxports = NDEFUDPPORTS; 12581634Sbrian ncp->cfg.urgent.udp.port = (u_short *)malloc(NDEFUDPPORTS * sizeof(u_short)); 12681634Sbrian memcpy(ncp->cfg.urgent.udp.port, default_urgent_udp_ports, 12781634Sbrian NDEFUDPPORTS * sizeof(u_short)); 12881634Sbrian 12981634Sbrian 13081634Sbrian mp_Init(&ncp->mp, bundle); 13181634Sbrian 13281634Sbrian /* Send over the first physical link by default */ 13381634Sbrian ipcp_Init(&ncp->ipcp, bundle, &bundle->links->physical->link, 13481634Sbrian &bundle->fsm); 13581634Sbrian#ifndef NOINET6 13681897Sbrian ipv6cp_Init(&ncp->ipv6cp, bundle, &bundle->links->physical->link, 13781897Sbrian &bundle->fsm); 13881634Sbrian#endif 13981634Sbrian} 14081634Sbrian 14181634Sbrianvoid 14281634Sbrianncp_Destroy(struct ncp *ncp) 14381634Sbrian{ 14481634Sbrian ipcp_Destroy(&ncp->ipcp); 14581634Sbrian#ifndef NOINET6 14681897Sbrian ipv6cp_Destroy(&ncp->ipv6cp); 14781634Sbrian#endif 14881634Sbrian 14981634Sbrian if (ncp->cfg.urgent.tcp.maxports) { 15081634Sbrian ncp->cfg.urgent.tcp.nports = ncp->cfg.urgent.tcp.maxports = 0; 15181634Sbrian free(ncp->cfg.urgent.tcp.port); 15281634Sbrian ncp->cfg.urgent.tcp.port = NULL; 15381634Sbrian } 15481634Sbrian if (ncp->cfg.urgent.udp.maxports) { 15581634Sbrian ncp->cfg.urgent.udp.nports = ncp->cfg.urgent.udp.maxports = 0; 15681634Sbrian free(ncp->cfg.urgent.udp.port); 15781634Sbrian ncp->cfg.urgent.udp.port = NULL; 15881634Sbrian } 15981634Sbrian} 16081634Sbrian 16181634Sbrianint 16281634Sbrianncp_fsmStart(struct ncp *ncp, struct bundle *bundle) 16381634Sbrian{ 16481634Sbrian int res = 0; 16581634Sbrian 16681634Sbrian#ifndef NOINET6 16781634Sbrian if (Enabled(bundle, OPT_IPCP)) { 16881634Sbrian#endif 16981634Sbrian fsm_Up(&ncp->ipcp.fsm); 17081634Sbrian fsm_Open(&ncp->ipcp.fsm); 17181634Sbrian res++; 17281634Sbrian#ifndef NOINET6 17381634Sbrian } 17481634Sbrian 17581897Sbrian if (Enabled(bundle, OPT_IPV6CP)) { 17681634Sbrian fsm_Up(&ncp->ipv6cp.fsm); 17781634Sbrian fsm_Open(&ncp->ipv6cp.fsm); 17881634Sbrian res++; 17981634Sbrian } 18081634Sbrian#endif 18181634Sbrian 18281634Sbrian return res; 18381634Sbrian} 18481634Sbrian 18581634Sbrianvoid 18681634Sbrianncp_IfaceAddrAdded(struct ncp *ncp, const struct iface_addr *addr) 18781634Sbrian{ 18881634Sbrian switch (ncprange_family(&addr->ifa)) { 18981634Sbrian case AF_INET: 19081634Sbrian ipcp_IfaceAddrAdded(&ncp->ipcp, addr); 19181634Sbrian break; 19281634Sbrian#ifndef NOINET6 19381634Sbrian case AF_INET6: 19481634Sbrian ipv6cp_IfaceAddrAdded(&ncp->ipv6cp, addr); 19581634Sbrian break; 19681634Sbrian#endif 19781634Sbrian } 19881634Sbrian} 19981634Sbrian 20081634Sbrianvoid 20181634Sbrianncp_IfaceAddrDeleted(struct ncp *ncp, const struct iface_addr *addr) 20281634Sbrian{ 20381634Sbrian if (ncprange_family(&addr->ifa) == AF_INET) 20481634Sbrian ipcp_IfaceAddrDeleted(&ncp->ipcp, addr); 20581634Sbrian} 20681634Sbrian 20781634Sbrianvoid 20881634Sbrianncp_SetLink(struct ncp *ncp, struct link *l) 20981634Sbrian{ 21081634Sbrian ipcp_SetLink(&ncp->ipcp, l); 21181634Sbrian#ifndef NOINET6 21281897Sbrian ipv6cp_SetLink(&ncp->ipv6cp, l); 21381634Sbrian#endif 21481634Sbrian} 21581634Sbrian 21681634Sbrian/* 21781634Sbrian * Enqueue a packet of the given address family. Nothing will make it 21881634Sbrian * down to the physical link level 'till ncp_FillPhysicalQueues() is used. 21981634Sbrian */ 22081634Sbrianvoid 22181634Sbrianncp_Enqueue(struct ncp *ncp, int af, int pri, char *ptr, int count) 22281634Sbrian{ 22381634Sbrian#ifndef NOINET6 22481634Sbrian struct ipv6cp *ipv6cp = &ncp->ipv6cp; 22581634Sbrian#endif 22681634Sbrian struct ipcp *ipcp = &ncp->ipcp; 22781634Sbrian struct mbuf *bp; 22881634Sbrian 22981634Sbrian /* 23081634Sbrian * We allocate an extra 6 bytes, four at the front and two at the end. 23181634Sbrian * This is an optimisation so that we need to do less work in 23281634Sbrian * m_prepend() in acf_LayerPush() and proto_LayerPush() and 23381634Sbrian * appending in hdlc_LayerPush(). 23481634Sbrian */ 23581634Sbrian 23681634Sbrian switch (af) { 23781634Sbrian case AF_INET: 23881634Sbrian if (pri < 0 || pri >= IPCP_QUEUES(ipcp)) { 23981634Sbrian log_Printf(LogERROR, "Can't store in ip queue %d\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(ipcp->Queue + pri, bp); 24881634Sbrian break; 24981634Sbrian 25081634Sbrian#ifndef NOINET6 25181634Sbrian case AF_INET6: 25281634Sbrian if (pri < 0 || pri >= IPV6CP_QUEUES(ipcp)) { 25381634Sbrian log_Printf(LogERROR, "Can't store in ipv6 queue %d\n", pri); 25481634Sbrian break; 25581634Sbrian } 25681634Sbrian 25781634Sbrian bp = m_get(count + 6, MB_IPOUT); 25881634Sbrian bp->m_offset += 4; 25981634Sbrian bp->m_len -= 6; 26081634Sbrian memcpy(MBUF_CTOP(bp), ptr, count); 26181634Sbrian m_enqueue(ipv6cp->Queue + pri, bp); 26281634Sbrian break; 26381634Sbrian#endif 26481634Sbrian 26581634Sbrian default: 26681634Sbrian log_Printf(LogERROR, "Can't enqueue protocol family %d\n", af); 26781634Sbrian } 26881634Sbrian} 26981634Sbrian 27081634Sbrian/* 27181634Sbrian * How many packets are queued to go out ? 27281634Sbrian */ 27381634Sbriansize_t 27481634Sbrianncp_QueueLen(struct ncp *ncp) 27581634Sbrian{ 27681634Sbrian size_t result; 27781634Sbrian 27881634Sbrian result = ipcp_QueueLen(&ncp->ipcp); 27981634Sbrian#ifndef NOINET6 28081897Sbrian result += ipv6cp_QueueLen(&ncp->ipv6cp); 28181634Sbrian#endif 28281634Sbrian result += mp_QueueLen(&ncp->mp); /* Usually empty */ 28381634Sbrian 28481634Sbrian return result; 28581634Sbrian} 28681634Sbrian 28781634Sbrian/* 28881634Sbrian * Ditch all queued packets. This is usually done after our choked timer 28981634Sbrian * has fired - which happens because we couldn't send any traffic over 29081634Sbrian * any links for some time. 29181634Sbrian */ 29281634Sbrianvoid 29381634Sbrianncp_DeleteQueues(struct ncp *ncp) 29481634Sbrian{ 29581634Sbrian#ifndef NOINET6 29681634Sbrian struct ipv6cp *ipv6cp = &ncp->ipv6cp; 29781634Sbrian#endif 29881634Sbrian struct ipcp *ipcp = &ncp->ipcp; 29981634Sbrian struct mp *mp = &ncp->mp; 30081634Sbrian struct mqueue *q; 30181634Sbrian 30281634Sbrian for (q = ipcp->Queue; q < ipcp->Queue + IPCP_QUEUES(ipcp); q++) 30381634Sbrian while (q->top) 30481634Sbrian m_freem(m_dequeue(q)); 30581634Sbrian 30681634Sbrian#ifndef NOINET6 30781897Sbrian for (q = ipv6cp->Queue; q < ipv6cp->Queue + IPV6CP_QUEUES(ipv6cp); q++) 30881897Sbrian while (q->top) 30981897Sbrian m_freem(m_dequeue(q)); 31081634Sbrian#endif 31181634Sbrian 31281634Sbrian link_DeleteQueue(&mp->link); /* Usually empty anyway */ 31381634Sbrian} 31481634Sbrian 31581634Sbrian/* 31681634Sbrian * Arrange that each of our links has at least one packet. We keep the 31781634Sbrian * number of packets queued at the link level to a minimum so that the 31881634Sbrian * loss of a link in multi-link mode results in the minimum number of 31981634Sbrian * dropped packets. 32081634Sbrian */ 32181634Sbriansize_t 32281634Sbrianncp_FillPhysicalQueues(struct ncp *ncp, struct bundle *bundle) 32381634Sbrian{ 32481634Sbrian size_t total; 32581634Sbrian 32681634Sbrian if (bundle->ncp.mp.active) 32781634Sbrian total = mp_FillPhysicalQueues(bundle); 32881634Sbrian else { 32981634Sbrian struct datalink *dl; 33081634Sbrian size_t add; 33181634Sbrian 33281634Sbrian for (total = 0, dl = bundle->links; dl; dl = dl->next) 33381634Sbrian if (dl->state == DATALINK_OPEN) { 33481634Sbrian add = link_QueueLen(&dl->physical->link); 33581634Sbrian if (add == 0 && dl->physical->out == NULL) 33681634Sbrian add = ncp_PushPacket(ncp, &ncp->afq, &dl->physical->link); 33781634Sbrian total += add; 33881634Sbrian } 33981634Sbrian } 34081634Sbrian 34181634Sbrian return total + ncp_QueueLen(&bundle->ncp); 34281634Sbrian} 34381634Sbrian 34481634Sbrian/* 34581634Sbrian * Push a packet into the given link. ``af'' is used as a persistent record 34681634Sbrian * of what is to be pushed next, coming either from mp->out or ncp->afq. 34781634Sbrian */ 34881634Sbrianint 34981634Sbrianncp_PushPacket(struct ncp *ncp, int *af, struct link *l) 35081634Sbrian{ 35181634Sbrian struct bundle *bundle = l->lcp.fsm.bundle; 35281634Sbrian int res; 35381634Sbrian 35481634Sbrian#ifndef NOINET6 35581897Sbrian if (*af == AF_INET) { 35681634Sbrian if ((res = ipcp_PushPacket(&bundle->ncp.ipcp, l))) 35781634Sbrian *af = AF_INET6; 35881634Sbrian else 35981634Sbrian res = ipv6cp_PushPacket(&bundle->ncp.ipv6cp, l); 36081634Sbrian } else { 36181634Sbrian if ((res = ipv6cp_PushPacket(&bundle->ncp.ipv6cp, l))) 36281634Sbrian *af = AF_INET; 36381634Sbrian else 36481634Sbrian res = ipcp_PushPacket(&bundle->ncp.ipcp, l); 36581634Sbrian } 36681634Sbrian#else 36781634Sbrian res = ipcp_PushPacket(&bundle->ncp.ipcp, l); 36881634Sbrian#endif 36981634Sbrian 37081634Sbrian return res; 37181634Sbrian} 37281634Sbrian 37381634Sbrianint 37481634Sbrianncp_IsUrgentPort(struct port_range *range, u_short src, u_short dst) 37581634Sbrian{ 37681634Sbrian int f; 37781634Sbrian 37881634Sbrian for (f = 0; f < range->nports; f++) 37981634Sbrian if (range->port[f] == src || range->port[f] == dst) 38081634Sbrian return 1; 38181634Sbrian 38281634Sbrian return 0; 38381634Sbrian} 38481634Sbrian 38581634Sbrianvoid 38681634Sbrianncp_AddUrgentPort(struct port_range *range, u_short port) 38781634Sbrian{ 38881634Sbrian u_short *newport; 38981634Sbrian int p; 39081634Sbrian 39181634Sbrian if (range->nports == range->maxports) { 39281634Sbrian range->maxports += 10; 39381634Sbrian newport = (u_short *)realloc(range->port, 39481634Sbrian range->maxports * sizeof(u_short)); 39581634Sbrian if (newport == NULL) { 39681634Sbrian log_Printf(LogERROR, "ncp_AddUrgentPort: realloc: %s\n", 39781634Sbrian strerror(errno)); 39881634Sbrian range->maxports -= 10; 39981634Sbrian return; 40081634Sbrian } 40181634Sbrian range->port = newport; 40281634Sbrian } 40381634Sbrian 40481634Sbrian for (p = 0; p < range->nports; p++) 40581634Sbrian if (range->port[p] == port) { 40681634Sbrian log_Printf(LogWARN, "%u: Port already set to urgent\n", port); 40781634Sbrian break; 40881634Sbrian } else if (range->port[p] > port) { 40981634Sbrian memmove(range->port + p + 1, range->port + p, 41081634Sbrian (range->nports - p) * sizeof(u_short)); 41181634Sbrian range->port[p] = port; 41281634Sbrian range->nports++; 41381634Sbrian break; 41481634Sbrian } 41581634Sbrian 41681634Sbrian if (p == range->nports) 41781634Sbrian range->port[range->nports++] = port; 41881634Sbrian} 41981634Sbrian 42081634Sbrianvoid 42181634Sbrianncp_RemoveUrgentPort(struct port_range *range, u_short port) 42281634Sbrian{ 42381634Sbrian int p; 42481634Sbrian 42581634Sbrian for (p = 0; p < range->nports; p++) 42681634Sbrian if (range->port[p] == port) { 42781634Sbrian if (p != range->nports - 1) 42881634Sbrian memmove(range->port + p, range->port + p + 1, 42981634Sbrian (range->nports - p - 1) * sizeof(u_short)); 43081634Sbrian range->nports--; 43181634Sbrian return; 43281634Sbrian } 43381634Sbrian 43481634Sbrian if (p == range->nports) 43581634Sbrian log_Printf(LogWARN, "%u: Port not set to urgent\n", port); 43681634Sbrian} 43781634Sbrian 43881634Sbrianvoid 43981634Sbrianncp_ClearUrgentPorts(struct port_range *range) 44081634Sbrian{ 44181634Sbrian range->nports = 0; 44281634Sbrian} 44381634Sbrian 44481634Sbrianint 44581634Sbrianncp_Show(struct cmdargs const *arg) 44681634Sbrian{ 44781634Sbrian struct ncp *ncp = &arg->bundle->ncp; 44881634Sbrian int p; 44981634Sbrian 45081634Sbrian#ifndef NOINET6 45181897Sbrian prompt_Printf(arg->prompt, "Next queued AF: %s\n", 45281897Sbrian ncp->afq == AF_INET6 ? "inet6" : "inet"); 45381634Sbrian#endif 45481634Sbrian 45581634Sbrian if (ncp->route) { 45681634Sbrian prompt_Printf(arg->prompt, "\n"); 45781634Sbrian route_ShowSticky(arg->prompt, ncp->route, "Sticky routes", 1); 45881634Sbrian } 45981634Sbrian 46081634Sbrian prompt_Printf(arg->prompt, "\nDefaults:\n"); 46181634Sbrian prompt_Printf(arg->prompt, " sendpipe: "); 46281634Sbrian if (ncp->cfg.sendpipe > 0) 46381634Sbrian prompt_Printf(arg->prompt, "%-20ld\n", ncp->cfg.sendpipe); 46481634Sbrian else 46581634Sbrian prompt_Printf(arg->prompt, "unspecified\n"); 46681634Sbrian prompt_Printf(arg->prompt, " recvpipe: "); 46781634Sbrian if (ncp->cfg.recvpipe > 0) 46881634Sbrian prompt_Printf(arg->prompt, "%ld\n", ncp->cfg.recvpipe); 46981634Sbrian else 47081634Sbrian prompt_Printf(arg->prompt, "unspecified\n"); 47181634Sbrian 47281634Sbrian prompt_Printf(arg->prompt, "\n Urgent ports\n"); 47381634Sbrian prompt_Printf(arg->prompt, " TCP: "); 47481634Sbrian if (ncp->cfg.urgent.tcp.nports == 0) 47581634Sbrian prompt_Printf(arg->prompt, "none"); 47681634Sbrian else 47781634Sbrian for (p = 0; p < ncp->cfg.urgent.tcp.nports; p++) { 47881634Sbrian if (p) 47981634Sbrian prompt_Printf(arg->prompt, ", "); 48081634Sbrian prompt_Printf(arg->prompt, "%u", ncp->cfg.urgent.tcp.port[p]); 48181634Sbrian } 48281634Sbrian 48381634Sbrian prompt_Printf(arg->prompt, "\n UDP: "); 48481634Sbrian if (ncp->cfg.urgent.udp.nports == 0) 48581634Sbrian prompt_Printf(arg->prompt, "none"); 48681634Sbrian else 48781634Sbrian for (p = 0; p < ncp->cfg.urgent.udp.nports; p++) { 48881634Sbrian if (p) 48981634Sbrian prompt_Printf(arg->prompt, ", "); 49081634Sbrian prompt_Printf(arg->prompt, "%u", ncp->cfg.urgent.udp.port[p]); 49181634Sbrian } 49281634Sbrian prompt_Printf(arg->prompt, "\n TOS: %s\n\n", 49381634Sbrian ncp->cfg.urgent.tos ? "yes" : "no"); 49481634Sbrian 49581634Sbrian return 0; 49681634Sbrian} 49781634Sbrian 49881634Sbrianint 49981634Sbrianncp_LayersOpen(struct ncp *ncp) 50081634Sbrian{ 50181634Sbrian int n; 50281634Sbrian 50381634Sbrian n = !!(ncp->ipcp.fsm.state == ST_OPENED); 50481634Sbrian#ifndef NOINET6 50581897Sbrian n += !!(ncp->ipv6cp.fsm.state == ST_OPENED); 50681634Sbrian#endif 50781634Sbrian 50881634Sbrian return n; 50981634Sbrian} 51081634Sbrian 51181634Sbrianint 51281634Sbrianncp_LayersUnfinished(struct ncp *ncp) 51381634Sbrian{ 51481634Sbrian int n = 0; 51581634Sbrian 51681634Sbrian if (ncp->ipcp.fsm.state > ST_CLOSED || 51781634Sbrian ncp->ipcp.fsm.state == ST_STARTING) 51881634Sbrian n++; 51981634Sbrian 52081634Sbrian#ifndef NOINET6 52181897Sbrian if (ncp->ipv6cp.fsm.state > ST_CLOSED || 52281897Sbrian ncp->ipv6cp.fsm.state == ST_STARTING) 52381897Sbrian n++; 52481634Sbrian#endif 52581634Sbrian 52681634Sbrian return n; 52781634Sbrian} 52881634Sbrian 52981634Sbrianvoid 53081634Sbrianncp_Close(struct ncp *ncp) 53181634Sbrian{ 53281634Sbrian if (ncp->ipcp.fsm.state > ST_CLOSED || 53381634Sbrian ncp->ipcp.fsm.state == ST_STARTING) 53481634Sbrian fsm_Close(&ncp->ipcp.fsm); 53581634Sbrian 53681634Sbrian#ifndef NOINET6 53781897Sbrian if (ncp->ipv6cp.fsm.state > ST_CLOSED || 53881897Sbrian ncp->ipv6cp.fsm.state == ST_STARTING) 53981897Sbrian fsm_Close(&ncp->ipv6cp.fsm); 54081634Sbrian#endif 54181634Sbrian} 54281634Sbrian 54381634Sbrianvoid 54481634Sbrianncp2initial(struct ncp *ncp) 54581634Sbrian{ 54681634Sbrian fsm2initial(&ncp->ipcp.fsm); 54781634Sbrian#ifndef NOINET6 54881897Sbrian fsm2initial(&ncp->ipv6cp.fsm); 54981634Sbrian#endif 55081634Sbrian} 551