Home | History | Annotate | Download | only in src
      1 /*-
      2  * Copyright (c) 2001 Brian Somers <brian (at) Awfulhak.org>
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     24  * SUCH DAMAGE.
     25  *
     26  * $FreeBSD: src/usr.sbin/ppp/ncp.c,v 1.8.26.1 2010/12/21 17:10:29 kensmith Exp $
     27  */
     28 
     29 #include <sys/param.h>
     30 #include <netinet/in_systm.h>
     31 #include <netinet/in.h>
     32 #include <netinet/ip.h>
     33 #include <sys/socket.h>
     34 #include <net/route.h>
     35 #include <sys/un.h>
     36 
     37 #include <errno.h>
     38 #include <resolv.h>
     39 #include <stdarg.h>
     40 #include <stdlib.h>
     41 #include <string.h>
     42 #include <termios.h>
     43 
     44 #include "layer.h"
     45 #include "defs.h"
     46 #include "command.h"
     47 #include "mbuf.h"
     48 #include "log.h"
     49 #include "timer.h"
     50 #include "fsm.h"
     51 #include "iplist.h"
     52 #include "throughput.h"
     53 #include "slcompress.h"
     54 #include "lqr.h"
     55 #include "hdlc.h"
     56 #include "lcp.h"
     57 #include "ncpaddr.h"
     58 #include "ipcp.h"
     59 #include "filter.h"
     60 #include "descriptor.h"
     61 #include "async.h"
     62 #include "ccp.h"
     63 #include "link.h"
     64 #include "physical.h"
     65 #include "mp.h"
     66 #ifndef NORADIUS
     67 #include "radius.h"
     68 #endif
     69 #include "ipv6cp.h"
     70 #include "ncp.h"
     71 #include "bundle.h"
     72 #include "prompt.h"
     73 #include "route.h"
     74 #include "iface.h"
     75 #include "chat.h"
     76 #include "auth.h"
     77 #include "chap.h"
     78 #include "cbcp.h"
     79 #include "datalink.h"
     80 
     81 
     82 static u_short default_urgent_tcp_ports[] = {
     83   21,	/* ftp */
     84   22,	/* ssh */
     85   23,	/* telnet */
     86   513,	/* login */
     87   514,	/* shell */
     88   543,	/* klogin */
     89   544	/* kshell */
     90 };
     91 
     92 #define NDEFTCPPORTS \
     93   (sizeof default_urgent_tcp_ports / sizeof default_urgent_tcp_ports[0])
     94 
     95 void
     96 ncp_Init(struct ncp *ncp, struct bundle *bundle)
     97 {
     98   ncp->afq = AF_INET;
     99   ncp->route = NULL;
    100 
    101   ncp->cfg.urgent.tcp.port = (u_short *)malloc(NDEFTCPPORTS * sizeof(u_short));
    102   if (ncp->cfg.urgent.tcp.port == NULL) {
    103     log_Printf(LogERROR, "ncp_Init: Out of memory allocating urgent ports\n");
    104     ncp->cfg.urgent.tcp.nports = ncp->cfg.urgent.tcp.maxports = 0;
    105   } else {
    106     ncp->cfg.urgent.tcp.nports = ncp->cfg.urgent.tcp.maxports = NDEFTCPPORTS;
    107     memcpy(ncp->cfg.urgent.tcp.port, default_urgent_tcp_ports,
    108 	   NDEFTCPPORTS * sizeof(u_short));
    109   }
    110   ncp->cfg.urgent.tos = 1;
    111 
    112   ncp->cfg.urgent.udp.nports = ncp->cfg.urgent.udp.maxports = 0;
    113   ncp->cfg.urgent.udp.port = NULL;
    114 
    115   mp_Init(&ncp->mp, bundle);
    116 
    117   /* Send over the first physical link by default */
    118   ipcp_Init(&ncp->ipcp, bundle, &bundle->links->physical->link,
    119             &bundle->fsm);
    120 #ifndef NOINET6
    121   ipv6cp_Init(&ncp->ipv6cp, bundle, &bundle->links->physical->link,
    122               &bundle->fsm);
    123 #endif
    124 }
    125 
    126 void
    127 ncp_Destroy(struct ncp *ncp)
    128 {
    129   ipcp_Destroy(&ncp->ipcp);
    130 #ifndef NOINET6
    131   ipv6cp_Destroy(&ncp->ipv6cp);
    132 #endif
    133 
    134   if (ncp->cfg.urgent.tcp.maxports) {
    135     ncp->cfg.urgent.tcp.nports = ncp->cfg.urgent.tcp.maxports = 0;
    136     free(ncp->cfg.urgent.tcp.port);
    137     ncp->cfg.urgent.tcp.port = NULL;
    138   }
    139   if (ncp->cfg.urgent.udp.maxports) {
    140     ncp->cfg.urgent.udp.nports = ncp->cfg.urgent.udp.maxports = 0;
    141     free(ncp->cfg.urgent.udp.port);
    142     ncp->cfg.urgent.udp.port = NULL;
    143   }
    144 }
    145 
    146 int
    147 ncp_fsmStart(struct ncp *ncp,
    148 #ifdef NOINET6
    149 	     struct bundle *bundle __unused
    150 #else
    151 	     struct bundle *bundle
    152 #endif
    153 	     )
    154 {
    155   int res = 0;
    156 
    157 #ifndef NOINET6
    158   if (Enabled(bundle, OPT_IPCP)) {
    159 #endif
    160     fsm_Up(&ncp->ipcp.fsm);
    161     fsm_Open(&ncp->ipcp.fsm);
    162     res++;
    163 #ifndef NOINET6
    164   }
    165 
    166   if (Enabled(bundle, OPT_IPV6CP)) {
    167     fsm_Up(&ncp->ipv6cp.fsm);
    168     fsm_Open(&ncp->ipv6cp.fsm);
    169     res++;
    170   }
    171 #endif
    172 
    173   return res;
    174 }
    175 
    176 void
    177 ncp_IfaceAddrAdded(struct ncp *ncp, const struct iface_addr *addr)
    178 {
    179   switch (ncprange_family(&addr->ifa)) {
    180   case AF_INET:
    181     ipcp_IfaceAddrAdded(&ncp->ipcp, addr);
    182     break;
    183 #ifndef NOINET6
    184   case AF_INET6:
    185     ipv6cp_IfaceAddrAdded(&ncp->ipv6cp, addr);
    186     break;
    187 #endif
    188   }
    189 }
    190 
    191 void
    192 ncp_IfaceAddrDeleted(struct ncp *ncp, const struct iface_addr *addr)
    193 {
    194   if (ncprange_family(&addr->ifa) == AF_INET)
    195     ipcp_IfaceAddrDeleted(&ncp->ipcp, addr);
    196 }
    197 
    198 void
    199 ncp_SetLink(struct ncp *ncp, struct link *l)
    200 {
    201   ipcp_SetLink(&ncp->ipcp, l);
    202 #ifndef NOINET6
    203   ipv6cp_SetLink(&ncp->ipv6cp, l);
    204 #endif
    205 }
    206 
    207 /*
    208  * Enqueue a packet of the given address family.  Nothing will make it
    209  * down to the physical link level 'till ncp_FillPhysicalQueues() is used.
    210  */
    211 void
    212 ncp_Enqueue(struct ncp *ncp, int af, unsigned pri, char *ptr, int count)
    213 {
    214 #ifndef NOINET6
    215   struct ipv6cp *ipv6cp = &ncp->ipv6cp;
    216 #endif
    217   struct ipcp *ipcp = &ncp->ipcp;
    218   struct mbuf *bp;
    219 
    220   /*
    221    * We allocate an extra 6 bytes, four at the front and two at the end.
    222    * This is an optimisation so that we need to do less work in
    223    * m_prepend() in acf_LayerPush() and proto_LayerPush() and
    224    * appending in hdlc_LayerPush().
    225    */
    226 
    227   switch (af) {
    228   case AF_INET:
    229     if (pri >= IPCP_QUEUES(ipcp)) {
    230       log_Printf(LogERROR, "Can't store in ip queue %u\n", pri);
    231       break;
    232     }
    233 
    234     bp = m_get(count + 6, MB_IPOUT);
    235     bp->m_offset += 4;
    236     bp->m_len -= 6;
    237     memcpy(MBUF_CTOP(bp), ptr, count);
    238     m_enqueue(ipcp->Queue + pri, bp);
    239     break;
    240 
    241 #ifndef NOINET6
    242   case AF_INET6:
    243     if (pri >= IPV6CP_QUEUES(ipcp)) {
    244       log_Printf(LogERROR, "Can't store in ipv6 queue %u\n", pri);
    245       break;
    246     }
    247 
    248     bp = m_get(count + 6, MB_IPOUT);
    249     bp->m_offset += 4;
    250     bp->m_len -= 6;
    251     memcpy(MBUF_CTOP(bp), ptr, count);
    252     m_enqueue(ipv6cp->Queue + pri, bp);
    253     break;
    254 #endif
    255 
    256   default:
    257       log_Printf(LogERROR, "Can't enqueue protocol family %d\n", af);
    258   }
    259 }
    260 
    261 /*
    262  * How many packets are queued to go out ?
    263  */
    264 size_t
    265 ncp_QueueLen(struct ncp *ncp)
    266 {
    267   size_t result;
    268 
    269   result = ipcp_QueueLen(&ncp->ipcp);
    270 #ifndef NOINET6
    271   result += ipv6cp_QueueLen(&ncp->ipv6cp);
    272 #endif
    273   result += mp_QueueLen(&ncp->mp);	/* Usually empty */
    274 
    275   return result;
    276 }
    277 
    278 /*
    279  * Ditch all queued packets.  This is usually done after our choked timer
    280  * has fired - which happens because we couldn't send any traffic over
    281  * any links for some time.
    282  */
    283 void
    284 ncp_DeleteQueues(struct ncp *ncp)
    285 {
    286 #ifndef NOINET6
    287   struct ipv6cp *ipv6cp = &ncp->ipv6cp;
    288 #endif
    289   struct ipcp *ipcp = &ncp->ipcp;
    290   struct mp *mp = &ncp->mp;
    291   struct mqueue *q;
    292 
    293   for (q = ipcp->Queue; q < ipcp->Queue + IPCP_QUEUES(ipcp); q++)
    294     while (q->top)
    295       m_freem(m_dequeue(q));
    296 
    297 #ifndef NOINET6
    298   for (q = ipv6cp->Queue; q < ipv6cp->Queue + IPV6CP_QUEUES(ipv6cp); q++)
    299     while (q->top)
    300       m_freem(m_dequeue(q));
    301 #endif
    302 
    303   link_DeleteQueue(&mp->link);	/* Usually empty anyway */
    304 }
    305 
    306 /*
    307  * Arrange that each of our links has at least one packet.  We keep the
    308  * number of packets queued at the link level to a minimum so that the
    309  * loss of a link in multi-link mode results in the minimum number of
    310  * dropped packets.
    311  */
    312 size_t
    313 ncp_FillPhysicalQueues(struct ncp *ncp, struct bundle *bundle)
    314 {
    315   size_t total;
    316 
    317   if (bundle->ncp.mp.active)
    318     total = mp_FillPhysicalQueues(bundle);
    319   else {
    320     struct datalink *dl;
    321     size_t add;
    322 
    323     for (total = 0, dl = bundle->links; dl; dl = dl->next)
    324       if (dl->state == DATALINK_OPEN) {
    325         add = link_QueueLen(&dl->physical->link);
    326         if (add == 0 && dl->physical->out == NULL)
    327           add = ncp_PushPacket(ncp, &ncp->afq, &dl->physical->link);
    328         total += add;
    329       }
    330   }
    331 
    332   return total + ncp_QueueLen(&bundle->ncp);
    333 }
    334 
    335 /*
    336  * Push a packet into the given link.  ``af'' is used as a persistent record
    337  * of what is to be pushed next, coming either from mp->out or ncp->afq.
    338  */
    339 int
    340 ncp_PushPacket(struct ncp *ncp __unused,
    341 #ifdef NOINET6
    342 	       int *af __unused,
    343 #else
    344 	       int *af,
    345 #endif
    346 	       struct link *l)
    347 {
    348   struct bundle *bundle = l->lcp.fsm.bundle;
    349   int res;
    350 
    351 #ifndef NOINET6
    352   if (*af == AF_INET) {
    353     if ((res = ipcp_PushPacket(&bundle->ncp.ipcp, l)))
    354       *af = AF_INET6;
    355     else
    356       res = ipv6cp_PushPacket(&bundle->ncp.ipv6cp, l);
    357   } else {
    358     if ((res = ipv6cp_PushPacket(&bundle->ncp.ipv6cp, l)))
    359       *af = AF_INET;
    360     else
    361       res = ipcp_PushPacket(&bundle->ncp.ipcp, l);
    362   }
    363 #else
    364   res = ipcp_PushPacket(&bundle->ncp.ipcp, l);
    365 #endif
    366 
    367   return res;
    368 }
    369 
    370 int
    371 ncp_IsUrgentPort(struct port_range *range, u_short src, u_short dst)
    372 {
    373   unsigned f;
    374 
    375   for (f = 0; f < range->nports; f++)
    376     if (range->port[f] == src || range->port[f] == dst)
    377       return 1;
    378 
    379   return 0;
    380 }
    381 
    382 void
    383 ncp_AddUrgentPort(struct port_range *range, u_short port)
    384 {
    385   u_short *newport;
    386   unsigned p;
    387 
    388   if (range->nports == range->maxports) {
    389     range->maxports += 10;
    390     newport = (u_short *)realloc(range->port,
    391                                  range->maxports * sizeof(u_short));
    392     if (newport == NULL) {
    393       log_Printf(LogERROR, "ncp_AddUrgentPort: realloc: %s\n",
    394                  strerror(errno));
    395       range->maxports -= 10;
    396       return;
    397     }
    398     range->port = newport;
    399   }
    400 
    401   for (p = 0; p < range->nports; p++)
    402     if (range->port[p] == port) {
    403       log_Printf(LogWARN, "%u: Port already set to urgent\n", port);
    404       break;
    405     } else if (range->port[p] > port) {
    406       memmove(range->port + p + 1, range->port + p,
    407               (range->nports - p) * sizeof(u_short));
    408       range->port[p] = port;
    409       range->nports++;
    410       break;
    411     }
    412 
    413   if (p == range->nports)
    414     range->port[range->nports++] = port;
    415 }
    416 
    417 void
    418 ncp_RemoveUrgentPort(struct port_range *range, u_short port)
    419 {
    420   unsigned p;
    421 
    422   for (p = 0; p < range->nports; p++)
    423     if (range->port[p] == port) {
    424       if (p + 1 != range->nports)
    425         memmove(range->port + p, range->port + p + 1,
    426                 (range->nports - p - 1) * sizeof(u_short));
    427       range->nports--;
    428       return;
    429     }
    430 
    431   if (p == range->nports)
    432     log_Printf(LogWARN, "%u: Port not set to urgent\n", port);
    433 }
    434 
    435 void
    436 ncp_ClearUrgentPorts(struct port_range *range)
    437 {
    438   range->nports = 0;
    439 }
    440 
    441 int
    442 ncp_Show(struct cmdargs const *arg)
    443 {
    444   struct ncp *ncp = &arg->bundle->ncp;
    445   unsigned p;
    446 
    447 #ifndef NOINET6
    448   prompt_Printf(arg->prompt, "Next queued AF: %s\n",
    449                 ncp->afq == AF_INET6 ? "inet6" : "inet");
    450 #endif
    451 
    452   if (ncp->route) {
    453     prompt_Printf(arg->prompt, "\n");
    454     route_ShowSticky(arg->prompt, ncp->route, "Sticky routes", 1);
    455   }
    456 
    457   prompt_Printf(arg->prompt, "\nDefaults:\n");
    458   prompt_Printf(arg->prompt, "  sendpipe:      ");
    459   if (ncp->cfg.sendpipe > 0)
    460     prompt_Printf(arg->prompt, "%-20ld\n", ncp->cfg.sendpipe);
    461   else
    462     prompt_Printf(arg->prompt, "unspecified\n");
    463   prompt_Printf(arg->prompt, "  recvpipe:      ");
    464   if (ncp->cfg.recvpipe > 0)
    465     prompt_Printf(arg->prompt, "%ld\n", ncp->cfg.recvpipe);
    466   else
    467     prompt_Printf(arg->prompt, "unspecified\n");
    468 
    469   prompt_Printf(arg->prompt, "\n  Urgent ports\n");
    470   prompt_Printf(arg->prompt, "         TCP:    ");
    471   if (ncp->cfg.urgent.tcp.nports == 0)
    472     prompt_Printf(arg->prompt, "none");
    473   else
    474     for (p = 0; p < ncp->cfg.urgent.tcp.nports; p++) {
    475       if (p)
    476         prompt_Printf(arg->prompt, ", ");
    477       prompt_Printf(arg->prompt, "%u", ncp->cfg.urgent.tcp.port[p]);
    478     }
    479 
    480   prompt_Printf(arg->prompt, "\n         UDP:    ");
    481   if (ncp->cfg.urgent.udp.nports == 0)
    482     prompt_Printf(arg->prompt, "none");
    483   else
    484     for (p = 0; p < ncp->cfg.urgent.udp.nports; p++) {
    485       if (p)
    486         prompt_Printf(arg->prompt, ", ");
    487       prompt_Printf(arg->prompt, "%u", ncp->cfg.urgent.udp.port[p]);
    488     }
    489   prompt_Printf(arg->prompt, "\n         TOS:    %s\n\n",
    490                 ncp->cfg.urgent.tos ? "yes" : "no");
    491 
    492   return 0;
    493 }
    494 
    495 int
    496 ncp_LayersOpen(struct ncp *ncp)
    497 {
    498   int n;
    499 
    500   n = !!(ncp->ipcp.fsm.state == ST_OPENED);
    501 #ifndef NOINET6
    502   n += !!(ncp->ipv6cp.fsm.state == ST_OPENED);
    503 #endif
    504 
    505   return n;
    506 }
    507 
    508 int
    509 ncp_LayersUnfinished(struct ncp *ncp)
    510 {
    511   int n = 0;
    512 
    513   if (ncp->ipcp.fsm.state > ST_CLOSED ||
    514       ncp->ipcp.fsm.state == ST_STARTING)
    515     n++;
    516 
    517 #ifndef NOINET6
    518   if (ncp->ipv6cp.fsm.state > ST_CLOSED ||
    519       ncp->ipv6cp.fsm.state == ST_STARTING)
    520     n++;
    521 #endif
    522 
    523   return n;
    524 }
    525 
    526 void
    527 ncp_Close(struct ncp *ncp)
    528 {
    529   if (ncp->ipcp.fsm.state > ST_CLOSED ||
    530       ncp->ipcp.fsm.state == ST_STARTING)
    531     fsm_Close(&ncp->ipcp.fsm);
    532 
    533 #ifndef NOINET6
    534   if (ncp->ipv6cp.fsm.state > ST_CLOSED ||
    535       ncp->ipv6cp.fsm.state == ST_STARTING)
    536     fsm_Close(&ncp->ipv6cp.fsm);
    537 #endif
    538 }
    539 
    540 void
    541 ncp2initial(struct ncp *ncp)
    542 {
    543   fsm2initial(&ncp->ipcp.fsm);
    544 #ifndef NOINET6
    545   fsm2initial(&ncp->ipv6cp.fsm);
    546 #endif
    547 }
    548