LCOV - code coverage report
Current view: top level - net - pipex.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 1318 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 65 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: pipex.c,v 1.106 2017/11/20 10:35:24 mpi Exp $ */
       2             : 
       3             : /*-
       4             :  * Copyright (c) 2009 Internet Initiative Japan Inc.
       5             :  * All rights reserved.
       6             :  *
       7             :  * Redistribution and use in source and binary forms, with or without
       8             :  * modification, are permitted provided that the following conditions
       9             :  * are met:
      10             :  * 1. Redistributions of source code must retain the above copyright
      11             :  *    notice, this list of conditions and the following disclaimer.
      12             :  * 2. Redistributions in binary form must reproduce the above copyright
      13             :  *    notice, this list of conditions and the following disclaimer in the
      14             :  *    documentation and/or other materials provided with the distribution.
      15             :  *
      16             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
      17             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      18             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      19             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
      20             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      21             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      22             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      23             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      24             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      25             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      26             :  * SUCH DAMAGE.
      27             :  */
      28             : 
      29             : #include <sys/param.h>
      30             : #include <sys/systm.h>
      31             : #include <sys/mbuf.h>
      32             : #include <sys/socket.h>
      33             : #include <sys/ioctl.h>
      34             : #include <sys/select.h>
      35             : #include <sys/sysctl.h>
      36             : #include <sys/syslog.h>
      37             : #include <sys/conf.h>
      38             : #include <sys/time.h>
      39             : #include <sys/timeout.h>
      40             : #include <sys/kernel.h>
      41             : #include <sys/pool.h>
      42             : 
      43             : #include <net/if.h>
      44             : #include <net/if_types.h>
      45             : #include <netinet/in.h>
      46             : #include <netinet/if_ether.h>
      47             : #include <net/if_dl.h>
      48             : 
      49             : #include <net/radix.h>
      50             : #include <net/route.h>
      51             : #include <net/netisr.h>
      52             : #include <net/ppp_defs.h>
      53             : #include <net/ppp-comp.h>
      54             : 
      55             : #include "pf.h"
      56             : #if NPF > 0
      57             : #include <net/pfvar.h>
      58             : #endif
      59             : 
      60             : #include "bpfilter.h"
      61             : #if NBPFILTER > 0
      62             : #include <net/bpf.h>
      63             : #endif
      64             : 
      65             : #include <netinet/ip.h>
      66             : #include <netinet/ip_var.h>
      67             : #ifdef INET6
      68             : #include <netinet/ip6.h>
      69             : #include <netinet6/ip6_var.h>
      70             : #endif
      71             : #include <netinet/tcp.h>
      72             : #include <netinet/udp.h>
      73             : #include <netinet/udp_var.h>
      74             : #include <crypto/arc4.h>
      75             : 
      76             : /* drop static for ddb debuggability */
      77             : #define Static
      78             : 
      79             : #include <net/pipex.h>
      80             : #include "pipex_local.h"
      81             : 
      82             : struct pool pipex_session_pool;
      83             : struct pool mppe_key_pool;
      84             : 
      85             : /*
      86             :  * static/global variables
      87             :  */
      88             : int     pipex_enable = 0;
      89             : struct pipex_hash_head
      90             :     pipex_session_list,                         /* master session list */
      91             :     pipex_close_wait_list,                      /* expired session list */
      92             :     pipex_peer_addr_hashtable[PIPEX_HASH_SIZE], /* peer's address hash */
      93             :     pipex_id_hashtable[PIPEX_HASH_SIZE];        /* peer id hash */
      94             : 
      95             : struct radix_node_head  *pipex_rd_head4 = NULL;
      96             : struct radix_node_head  *pipex_rd_head6 = NULL;
      97             : struct timeout pipex_timer_ch;          /* callout timer context */
      98             : int pipex_prune = 1;                    /* walk list every seconds */
      99             : 
     100             : /* pipex traffic queue */
     101             : struct mbuf_queue pipexinq = MBUF_QUEUE_INITIALIZER(IFQ_MAXLEN, IPL_NET);
     102             : struct mbuf_queue pipexoutq = MBUF_QUEUE_INITIALIZER(IFQ_MAXLEN, IPL_NET);
     103             : 
     104             : /* borrow an mbuf pkthdr field */
     105             : #define ph_ppp_proto ether_vtag
     106             : 
     107             : /* from udp_usrreq.c */
     108             : extern int udpcksum;
     109             : 
     110             : #ifdef PIPEX_DEBUG
     111             : int pipex_debug = 0;            /* systcl net.inet.ip.pipex_debug */
     112             : #endif
     113             : 
     114             : /* PPP compression == MPPE is assumed, so don't answer CCP Reset-Request. */
     115             : #define PIPEX_NO_CCP_RESETACK   1
     116             : 
     117             : /************************************************************************
     118             :  * Core functions
     119             :  ************************************************************************/
     120             : void
     121           0 : pipex_init(void)
     122             : {
     123             :         int              i;
     124             :         static int       pipex_init_done = 0;
     125             : 
     126           0 :         if (pipex_init_done++)
     127           0 :                 return;
     128             : 
     129           0 :         rn_init(sizeof(struct sockaddr_in6));
     130             : 
     131           0 :         pool_init(&pipex_session_pool, sizeof(struct pipex_session), 0,
     132             :             IPL_SOFTNET, PR_WAITOK, "ppxss", NULL);
     133           0 :         pool_init(&mppe_key_pool, PIPEX_MPPE_KEYLEN * PIPEX_MPPE_NOLDKEY, 0,
     134             :             IPL_SOFTNET, PR_WAITOK, "mppekey", NULL);
     135             : 
     136           0 :         LIST_INIT(&pipex_session_list);
     137           0 :         LIST_INIT(&pipex_close_wait_list);
     138             : 
     139           0 :         for (i = 0; i < nitems(pipex_id_hashtable); i++)
     140           0 :                 LIST_INIT(&pipex_id_hashtable[i]);
     141           0 :         for (i = 0; i < nitems(pipex_peer_addr_hashtable); i++)
     142           0 :                 LIST_INIT(&pipex_peer_addr_hashtable[i]);
     143           0 : }
     144             : 
     145             : void
     146           0 : pipex_iface_init(struct pipex_iface_context *pipex_iface, struct ifnet *ifp)
     147             : {
     148             :         struct pipex_session *session;
     149             : 
     150           0 :         pipex_iface->pipexmode = 0;
     151           0 :         pipex_iface->ifnet_this = ifp;
     152             : 
     153           0 :         if (pipex_rd_head4 == NULL) {
     154           0 :                 if (!rn_inithead((void **)&pipex_rd_head4,
     155             :                     offsetof(struct sockaddr_in, sin_addr)))
     156           0 :                         panic("rn_inithead() failed on pipex_init()");
     157             :         }
     158           0 :         if (pipex_rd_head6 == NULL) {
     159           0 :                 if (!rn_inithead((void **)&pipex_rd_head6,
     160             :                     offsetof(struct sockaddr_in6, sin6_addr)))
     161           0 :                         panic("rn_inithead() failed on pipex_init()");
     162             :         }
     163             : 
     164             :         /* virtual pipex_session entry for multicast */
     165           0 :         session = pool_get(&pipex_session_pool, PR_WAITOK | PR_ZERO);
     166           0 :         session->is_multicast = 1;
     167           0 :         session->pipex_iface = pipex_iface;
     168           0 :         pipex_iface->multicast_session = session;
     169           0 : }
     170             : 
     171             : Static void
     172           0 : pipex_iface_start(struct pipex_iface_context *pipex_iface)
     173             : {
     174           0 :         pipex_iface->pipexmode = 1;
     175           0 : }
     176             : 
     177             : Static void
     178           0 : pipex_iface_stop(struct pipex_iface_context *pipex_iface)
     179             : {
     180             :         struct pipex_session *session;
     181             :         struct pipex_session *session_next;
     182             : 
     183           0 :         pipex_iface->pipexmode = 0;
     184             :         /*
     185             :          * traversal all pipex sessions.
     186             :          * it will become heavy if the number of pppac devices bocomes large.
     187             :          */
     188           0 :         for (session = LIST_FIRST(&pipex_session_list);
     189             :             session; session = session_next) {
     190           0 :                 session_next = LIST_NEXT(session, session_list);
     191           0 :                 if (session->pipex_iface == pipex_iface)
     192           0 :                         pipex_destroy_session(session);
     193             :         }
     194           0 : }
     195             : 
     196             : void
     197           0 : pipex_iface_fini(struct pipex_iface_context *pipex_iface)
     198             : {
     199           0 :         pool_put(&pipex_session_pool, pipex_iface->multicast_session);
     200           0 :         pipex_iface_stop(pipex_iface);
     201           0 : }
     202             : 
     203             : int
     204           0 : pipex_ioctl(struct pipex_iface_context *pipex_iface, u_long cmd, caddr_t data)
     205             : {
     206             :         int pipexmode, ret = 0;
     207             : 
     208           0 :         NET_LOCK();
     209           0 :         switch (cmd) {
     210             :         case PIPEXSMODE:
     211           0 :                 pipexmode = *(int *)data;
     212           0 :                 if (pipex_iface->pipexmode != pipexmode) {
     213           0 :                         if (pipexmode)
     214           0 :                                 pipex_iface_start(pipex_iface);
     215             :                         else
     216           0 :                                 pipex_iface_stop(pipex_iface);
     217             :                 }
     218             :                 break;
     219             : 
     220             :         case PIPEXGMODE:
     221           0 :                 *(int *)data = pipex_iface->pipexmode;
     222           0 :                 break;
     223             : 
     224             :         case PIPEXASESSION:
     225           0 :                 ret = pipex_add_session((struct pipex_session_req *)data,
     226             :                     pipex_iface);
     227           0 :                 break;
     228             : 
     229             :         case PIPEXDSESSION:
     230           0 :                 ret = pipex_close_session(
     231           0 :                     (struct pipex_session_close_req *)data);
     232           0 :                 break;
     233             : 
     234             :         case PIPEXCSESSION:
     235           0 :                 ret = pipex_config_session(
     236           0 :                     (struct pipex_session_config_req *)data);
     237           0 :                 break;
     238             : 
     239             :         case PIPEXGSTAT:
     240           0 :                 ret = pipex_get_stat((struct pipex_session_stat_req *)data);
     241           0 :                 break;
     242             : 
     243             :         case PIPEXGCLOSED:
     244           0 :                 ret = pipex_get_closed((struct pipex_session_list_req *)data);
     245           0 :                 break;
     246             : 
     247             :         default:
     248             :                 ret = ENOTTY;
     249           0 :                 break;
     250             :         }
     251           0 :         NET_UNLOCK();
     252             : 
     253           0 :         return (ret);
     254             : }
     255             : 
     256             : /************************************************************************
     257             :  * Session management functions
     258             :  ************************************************************************/
     259             : Static int
     260           0 : pipex_add_session(struct pipex_session_req *req,
     261             :     struct pipex_iface_context *iface)
     262             : {
     263             :         struct pipex_session *session;
     264             :         struct pipex_hash_head *chain;
     265             :         struct radix_node *rn;
     266             : #ifdef PIPEX_PPPOE
     267             :         struct ifnet *over_ifp = NULL;
     268             : #endif
     269             : 
     270             :         /* Checks requeted parameters.  */
     271           0 :         if (!iface->pipexmode)
     272           0 :                 return (ENXIO);
     273           0 :         switch (req->pr_protocol) {
     274             : #ifdef PIPEX_PPPOE
     275             :         case PIPEX_PROTO_PPPOE:
     276           0 :                 over_ifp = ifunit(req->pr_proto.pppoe.over_ifname);
     277           0 :                 if (over_ifp == NULL)
     278           0 :                         return (EINVAL);
     279           0 :                 if (req->pr_peer_address.ss_family != AF_UNSPEC)
     280           0 :                         return (EINVAL);
     281             :                 break;
     282             : #endif
     283             : #if defined(PIPEX_L2TP) || defined(PIPEX_PPTP)
     284             : #ifdef PIPEX_PPTP
     285             :         case PIPEX_PROTO_PPTP:
     286             : #endif
     287             : #ifdef PIPEX_L2TP
     288             :         case PIPEX_PROTO_L2TP:
     289             : #endif
     290           0 :                 switch (req->pr_peer_address.ss_family) {
     291             :                 case AF_INET:
     292           0 :                         if (req->pr_peer_address.ss_len !=
     293             :                             sizeof(struct sockaddr_in))
     294           0 :                                 return (EINVAL);
     295             :                         break;
     296             : #ifdef INET6
     297             :                 case AF_INET6:
     298           0 :                         if (req->pr_peer_address.ss_len !=
     299             :                             sizeof(struct sockaddr_in6))
     300           0 :                                 return (EINVAL);
     301             :                         break;
     302             : #endif
     303             :                 default:
     304           0 :                         return (EPROTONOSUPPORT);
     305             :                 }
     306           0 :                 if (req->pr_peer_address.ss_family !=
     307           0 :                     req->pr_local_address.ss_family ||
     308           0 :                     req->pr_peer_address.ss_len !=
     309           0 :                     req->pr_local_address.ss_len)
     310           0 :                         return (EINVAL);
     311             :                 break;
     312             : #endif
     313             :         default:
     314           0 :                 return (EPROTONOSUPPORT);
     315             :         }
     316             : 
     317             :         /* prepare a new session */
     318           0 :         session = pool_get(&pipex_session_pool, PR_WAITOK | PR_ZERO);
     319           0 :         session->state = PIPEX_STATE_OPENED;
     320           0 :         session->protocol = req->pr_protocol;
     321           0 :         session->session_id = req->pr_session_id;
     322           0 :         session->peer_session_id = req->pr_peer_session_id;
     323           0 :         session->peer_mru = req->pr_peer_mru;
     324           0 :         session->timeout_sec = req->pr_timeout_sec;
     325           0 :         session->pipex_iface = iface;
     326           0 :         session->ppp_flags = req->pr_ppp_flags;
     327           0 :         session->ppp_id = req->pr_ppp_id;
     328             : 
     329           0 :         session->ip_forward = 1;
     330             : 
     331           0 :         session->ip_address.sin_family = AF_INET;
     332           0 :         session->ip_address.sin_len = sizeof(struct sockaddr_in);
     333           0 :         session->ip_address.sin_addr = req->pr_ip_address;
     334             : 
     335           0 :         session->ip_netmask.sin_family = AF_INET;
     336           0 :         session->ip_netmask.sin_len = sizeof(struct sockaddr_in);
     337           0 :         session->ip_netmask.sin_addr = req->pr_ip_netmask;
     338             : 
     339           0 :         if (session->ip_netmask.sin_addr.s_addr == 0L)
     340           0 :                 session->ip_netmask.sin_addr.s_addr = 0xffffffffL;
     341           0 :         session->ip_address.sin_addr.s_addr &=
     342           0 :             session->ip_netmask.sin_addr.s_addr;
     343             : 
     344           0 :         if (req->pr_peer_address.ss_len > 0)
     345           0 :                 memcpy(&session->peer, &req->pr_peer_address,
     346             :                     MIN(req->pr_peer_address.ss_len, sizeof(session->peer)));
     347           0 :         if (req->pr_local_address.ss_len > 0)
     348           0 :                 memcpy(&session->local, &req->pr_local_address,
     349             :                     MIN(req->pr_local_address.ss_len, sizeof(session->local)));
     350             : #ifdef PIPEX_PPPOE
     351           0 :         if (req->pr_protocol == PIPEX_PROTO_PPPOE)
     352           0 :                 session->proto.pppoe.over_ifidx = over_ifp->if_index;
     353             : #endif
     354             : #ifdef PIPEX_PPTP
     355           0 :         if (req->pr_protocol == PIPEX_PROTO_PPTP) {
     356           0 :                 struct pipex_pptp_session *sess_pptp = &session->proto.pptp;
     357             : 
     358           0 :                 sess_pptp->snd_gap = 0;
     359           0 :                 sess_pptp->rcv_gap = 0;
     360           0 :                 sess_pptp->snd_una = req->pr_proto.pptp.snd_una;
     361           0 :                 sess_pptp->snd_nxt = req->pr_proto.pptp.snd_nxt;
     362           0 :                 sess_pptp->rcv_nxt = req->pr_proto.pptp.rcv_nxt;
     363           0 :                 sess_pptp->rcv_acked = req->pr_proto.pptp.rcv_acked;
     364             : 
     365           0 :                 sess_pptp->winsz = req->pr_proto.pptp.winsz;
     366           0 :                 sess_pptp->maxwinsz = req->pr_proto.pptp.maxwinsz;
     367           0 :                 sess_pptp->peer_maxwinsz = req->pr_proto.pptp.peer_maxwinsz;
     368             :                 /* last ack number */
     369           0 :                 sess_pptp->ul_snd_una = sess_pptp->snd_una - 1;
     370           0 :         }
     371             : #endif
     372             : #ifdef PIPEX_L2TP
     373           0 :         if (req->pr_protocol == PIPEX_PROTO_L2TP) {
     374           0 :                 struct pipex_l2tp_session *sess_l2tp = &session->proto.l2tp;
     375             : 
     376             :                 /* session keys */
     377           0 :                 sess_l2tp->tunnel_id = req->pr_proto.l2tp.tunnel_id;
     378           0 :                 sess_l2tp->peer_tunnel_id = req->pr_proto.l2tp.peer_tunnel_id;
     379             : 
     380             :                 /* protocol options */
     381           0 :                 sess_l2tp->option_flags = req->pr_proto.l2tp.option_flags;
     382             : 
     383             :                 /* initial state of dynamic context */
     384           0 :                 sess_l2tp->ns_gap = sess_l2tp->nr_gap = 0;
     385           0 :                 sess_l2tp->ns_nxt = req->pr_proto.l2tp.ns_nxt;
     386           0 :                 sess_l2tp->nr_nxt = req->pr_proto.l2tp.nr_nxt;
     387           0 :                 sess_l2tp->ns_una = req->pr_proto.l2tp.ns_una;
     388           0 :                 sess_l2tp->nr_acked = req->pr_proto.l2tp.nr_acked;
     389             :                 /* last ack number */
     390           0 :                 sess_l2tp->ul_ns_una = sess_l2tp->ns_una - 1;
     391           0 :                 sess_l2tp->ipsecflowinfo = req->pr_proto.l2tp.ipsecflowinfo;
     392           0 :         }
     393             : #endif
     394             : #ifdef PIPEX_MPPE
     395           0 :         if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ACCEPTED) != 0) {
     396           0 :                 if (req->pr_mppe_recv.keylenbits <= 0) {
     397           0 :                         pool_put(&pipex_session_pool, session);
     398           0 :                         return (EINVAL);
     399             :                 }
     400           0 :                 pipex_session_init_mppe_recv(session,
     401           0 :                     req->pr_mppe_recv.stateless, req->pr_mppe_recv.keylenbits,
     402           0 :                     req->pr_mppe_recv.master_key);
     403           0 :         }
     404           0 :         if ((req->pr_ppp_flags & PIPEX_PPP_MPPE_ENABLED) != 0) {
     405           0 :                 if (req->pr_mppe_send.keylenbits <= 0) {
     406           0 :                         pool_put(&pipex_session_pool, session);
     407           0 :                         return (EINVAL);
     408             :                 }
     409           0 :                 pipex_session_init_mppe_send(session,
     410           0 :                     req->pr_mppe_send.stateless, req->pr_mppe_send.keylenbits,
     411           0 :                     req->pr_mppe_send.master_key);
     412           0 :         }
     413             : 
     414           0 :         if (pipex_session_is_mppe_required(session)) {
     415           0 :                 if (!pipex_session_is_mppe_enabled(session) ||
     416           0 :                     !pipex_session_is_mppe_accepted(session)) {
     417           0 :                         pool_put(&pipex_session_pool, session);
     418           0 :                         return (EINVAL);
     419             :                 }
     420             :         }
     421             : #endif
     422             : 
     423           0 :         NET_ASSERT_LOCKED();
     424             :         /* commit the session */
     425           0 :         if (!in_nullhost(session->ip_address.sin_addr)) {
     426           0 :                 if (pipex_lookup_by_ip_address(session->ip_address.sin_addr)
     427           0 :                     != NULL) {
     428           0 :                         pool_put(&pipex_session_pool, session);
     429           0 :                         return (EADDRINUSE);
     430             :                 }
     431             : 
     432           0 :                 rn = rn_addroute(&session->ip_address, &session->ip_netmask,
     433           0 :                     pipex_rd_head4, session->ps4_rn, RTP_STATIC);
     434           0 :                 if (rn == NULL) {
     435           0 :                         pool_put(&pipex_session_pool, session);
     436           0 :                         return (ENOMEM);
     437             :                 }
     438             :         }
     439             :         if (0) { /* NOT YET */
     440             :                 rn = rn_addroute(&session->ip6_address, &session->ip6_prefixlen,
     441             :                     pipex_rd_head6, session->ps6_rn, RTP_STATIC);
     442             :                 if (rn == NULL) {
     443             :                         pool_put(&pipex_session_pool, session);
     444             :                         return (ENOMEM);
     445             :                 }
     446             :         }
     447             : 
     448           0 :         chain = PIPEX_ID_HASHTABLE(session->session_id);
     449           0 :         LIST_INSERT_HEAD(chain, session, id_chain);
     450           0 :         LIST_INSERT_HEAD(&pipex_session_list, session, session_list);
     451           0 :         switch (req->pr_protocol) {
     452             :         case PIPEX_PROTO_PPTP:
     453             :         case PIPEX_PROTO_L2TP:
     454           0 :                 chain = PIPEX_PEER_ADDR_HASHTABLE(
     455             :                     pipex_sockaddr_hash_key(&session->peer.sa));
     456           0 :                 LIST_INSERT_HEAD(chain, session, peer_addr_chain);
     457           0 :         }
     458             : 
     459             :         /* if first session is added, start timer */
     460           0 :         if (LIST_NEXT(session, session_list) == NULL)
     461           0 :                 pipex_timer_start();
     462             : 
     463           0 :         pipex_session_log(session, LOG_INFO, "PIPEX is ready.");
     464             : 
     465           0 :         return (0);
     466           0 : }
     467             : 
     468             : int
     469           0 : pipex_notify_close_session(struct pipex_session *session)
     470             : {
     471           0 :         NET_ASSERT_LOCKED();
     472           0 :         session->state = PIPEX_STATE_CLOSE_WAIT;
     473           0 :         session->stat.idle_time = 0;
     474           0 :         LIST_INSERT_HEAD(&pipex_close_wait_list, session, state_list);
     475             : 
     476           0 :         return (0);
     477             : }
     478             : 
     479             : int
     480           0 : pipex_notify_close_session_all(void)
     481             : {
     482             :         struct pipex_session *session;
     483             : 
     484           0 :         NET_ASSERT_LOCKED();
     485           0 :         LIST_FOREACH(session, &pipex_session_list, session_list)
     486           0 :                 if (session->state == PIPEX_STATE_OPENED)
     487           0 :                         pipex_notify_close_session(session);
     488           0 :         return (0);
     489             : }
     490             : 
     491             : Static int
     492           0 : pipex_close_session(struct pipex_session_close_req *req)
     493             : {
     494             :         struct pipex_session *session;
     495             : 
     496           0 :         NET_ASSERT_LOCKED();
     497           0 :         session = pipex_lookup_by_session_id(req->pcr_protocol,
     498           0 :             req->pcr_session_id);
     499           0 :         if (session == NULL)
     500           0 :                 return (EINVAL);
     501             : 
     502             :         /* remove from close_wait list */
     503           0 :         if (session->state == PIPEX_STATE_CLOSE_WAIT)
     504           0 :                 LIST_REMOVE(session, state_list);
     505             : 
     506             :         /* get statistics before destroy the session */
     507           0 :         req->pcr_stat = session->stat;
     508           0 :         session->state = PIPEX_STATE_CLOSED;
     509             : 
     510           0 :         return (0);
     511           0 : }
     512             : 
     513             : Static int
     514           0 : pipex_config_session(struct pipex_session_config_req *req)
     515             : {
     516             :         struct pipex_session *session;
     517             : 
     518           0 :         NET_ASSERT_LOCKED();
     519           0 :         session = pipex_lookup_by_session_id(req->pcr_protocol,
     520           0 :             req->pcr_session_id);
     521           0 :         if (session == NULL)
     522           0 :                 return (EINVAL);
     523           0 :         session->ip_forward = req->pcr_ip_forward;
     524             : 
     525           0 :         return (0);
     526           0 : }
     527             : 
     528             : Static int
     529           0 : pipex_get_stat(struct pipex_session_stat_req *req)
     530             : {
     531             :         struct pipex_session *session;
     532             : 
     533           0 :         NET_ASSERT_LOCKED();
     534           0 :         session = pipex_lookup_by_session_id(req->psr_protocol,
     535           0 :             req->psr_session_id);
     536           0 :         if (session == NULL) {
     537           0 :                 return (EINVAL);
     538             :         }
     539           0 :         req->psr_stat = session->stat;
     540             : 
     541           0 :         return (0);
     542           0 : }
     543             : 
     544             : Static int
     545           0 : pipex_get_closed(struct pipex_session_list_req *req)
     546             : {
     547             :         struct pipex_session *session;
     548             : 
     549           0 :         NET_ASSERT_LOCKED();
     550           0 :         bzero(req, sizeof(*req));
     551           0 :         while (!LIST_EMPTY(&pipex_close_wait_list)) {
     552             :                 session = LIST_FIRST(&pipex_close_wait_list);
     553           0 :                 req->plr_ppp_id[req->plr_ppp_id_count++] = session->ppp_id;
     554           0 :                 LIST_REMOVE(session, state_list);
     555           0 :                 session->state = PIPEX_STATE_CLOSE_WAIT2;
     556           0 :                 if (req->plr_ppp_id_count >= PIPEX_MAX_LISTREQ) {
     557           0 :                         if (!LIST_EMPTY(&pipex_close_wait_list))
     558           0 :                                 req->plr_flags |= PIPEX_LISTREQ_MORE;
     559             :                         break;
     560             :                 }
     561             :         }
     562             : 
     563           0 :         return (0);
     564             : }
     565             : 
     566             : Static int
     567           0 : pipex_destroy_session(struct pipex_session *session)
     568             : {
     569             :         struct radix_node *rn;
     570             : 
     571             :         /* remove from radix tree and hash chain */
     572           0 :         NET_ASSERT_LOCKED();
     573             : 
     574           0 :         if (!in_nullhost(session->ip_address.sin_addr)) {
     575           0 :                 rn = rn_delete(&session->ip_address, &session->ip_netmask,
     576           0 :                     pipex_rd_head4, (struct radix_node *)session);
     577           0 :                 KASSERT(rn != NULL);
     578             :         }
     579             : 
     580           0 :         LIST_REMOVE(session, id_chain);
     581           0 :         LIST_REMOVE(session, session_list);
     582             : #ifdef PIPEX_PPTP
     583           0 :         if (session->protocol == PIPEX_PROTO_PPTP) {
     584           0 :                 LIST_REMOVE(session, peer_addr_chain);
     585           0 :         }
     586             : #endif
     587             : #ifdef PIPEX_L2TP
     588           0 :         if (session->protocol == PIPEX_PROTO_L2TP) {
     589           0 :                 LIST_REMOVE(session, peer_addr_chain);
     590           0 :         }
     591             : #endif
     592             :         /* if final session is destroyed, stop timer */
     593           0 :         if (LIST_EMPTY(&pipex_session_list))
     594           0 :                 pipex_timer_stop();
     595             : 
     596           0 :         if (session->mppe_recv.old_session_keys)
     597           0 :                 pool_put(&mppe_key_pool, session->mppe_recv.old_session_keys);
     598           0 :         pool_put(&pipex_session_pool, session);
     599             : 
     600           0 :         return (0);
     601             : }
     602             : 
     603             : Static struct pipex_session *
     604           0 : pipex_lookup_by_ip_address(struct in_addr addr)
     605             : {
     606             :         struct pipex_session *session;
     607           0 :         struct sockaddr_in pipex_in4, pipex_in4mask;
     608             : 
     609           0 :         bzero(&pipex_in4, sizeof(pipex_in4));
     610           0 :         pipex_in4.sin_addr = addr;
     611           0 :         pipex_in4.sin_family = AF_INET;
     612           0 :         pipex_in4.sin_len = sizeof(pipex_in4);
     613             : 
     614           0 :         bzero(&pipex_in4mask, sizeof(pipex_in4mask));
     615           0 :         pipex_in4mask.sin_addr.s_addr = htonl(0xFFFFFFFFL);
     616           0 :         pipex_in4mask.sin_family = AF_INET;
     617           0 :         pipex_in4mask.sin_len = sizeof(pipex_in4mask);
     618             : 
     619           0 :         session = (struct pipex_session *)rn_lookup(&pipex_in4, &pipex_in4mask,
     620           0 :             pipex_rd_head4);
     621             : 
     622             : #ifdef PIPEX_DEBUG
     623             :         if (session == NULL) {
     624             :                 char buf[INET_ADDRSTRLEN];
     625             : 
     626             :                 PIPEX_DBG((NULL, LOG_DEBUG, "<%s> session not found (addr=%s)",
     627             :                     __func__, inet_ntop(AF_INET, &addr, buf, sizeof(buf))));
     628             :         }
     629             : #endif
     630             : 
     631           0 :         return (session);
     632           0 : }
     633             : 
     634             : Static struct pipex_session *
     635           0 : pipex_lookup_by_session_id(int protocol, int session_id)
     636             : {
     637             :         struct pipex_hash_head *list;
     638             :         struct pipex_session *session;
     639             : 
     640           0 :         NET_ASSERT_LOCKED();
     641           0 :         list = PIPEX_ID_HASHTABLE(session_id);
     642           0 :         LIST_FOREACH(session, list, id_chain) {
     643           0 :                 if (session->protocol == protocol &&
     644           0 :                     session->session_id == session_id)
     645             :                         break;
     646             :         }
     647             : 
     648             : #ifdef PIPEX_DEBUG
     649             :         if (session == NULL)
     650             :                 PIPEX_DBG((NULL, LOG_DEBUG,
     651             :                     "<%s> session not found (session_id=%d)", __func__,
     652             :                     session_id));
     653             : #endif
     654             : 
     655           0 :         return (session);
     656             : }
     657             : 
     658             : /***********************************************************************
     659             :  * Queue and Software Interrupt Handler
     660             :  ***********************************************************************/
     661             : void
     662           0 : pipexintr(void)
     663             : {
     664             :         struct pipex_session *pkt_session;
     665             :         u_int16_t proto;
     666             :         struct mbuf *m;
     667           0 :         struct mbuf_list ml;
     668             : 
     669             :         /* ppp output */
     670           0 :         mq_delist(&pipexoutq, &ml);
     671           0 :         while ((m = ml_dequeue(&ml)) != NULL) {
     672           0 :                 pkt_session = m->m_pkthdr.ph_cookie;
     673           0 :                 if (pkt_session == NULL) {
     674           0 :                         m_freem(m);
     675           0 :                         continue;
     676             :                 }
     677           0 :                 proto = m->m_pkthdr.ph_ppp_proto;
     678             : 
     679           0 :                 m->m_pkthdr.ph_cookie = NULL;
     680           0 :                 m->m_pkthdr.ph_ppp_proto = 0;
     681             : 
     682           0 :                 if (pkt_session->is_multicast != 0) {
     683             :                         struct pipex_session *session;
     684             :                         struct mbuf *m0;
     685             : 
     686           0 :                         LIST_FOREACH(session, &pipex_session_list,
     687             :                             session_list) {
     688           0 :                                 if (session->pipex_iface !=
     689           0 :                                     pkt_session->pipex_iface)
     690             :                                         continue;
     691           0 :                                 if (session->ip_forward == 0 &&
     692           0 :                                     session->ip6_forward == 0)
     693             :                                         continue;
     694           0 :                                 m0 = m_copym(m, 0, M_COPYALL, M_NOWAIT);
     695           0 :                                 if (m0 == NULL) {
     696           0 :                                         session->stat.oerrors++;
     697           0 :                                         continue;
     698             :                                 }
     699           0 :                                 pipex_ppp_output(m0, session, proto);
     700           0 :                         }
     701           0 :                         m_freem(m);
     702           0 :                 } else
     703           0 :                         pipex_ppp_output(m, pkt_session, proto);
     704             :         }
     705             : 
     706             :         /* ppp input */
     707           0 :         mq_delist(&pipexinq, &ml);
     708           0 :         while ((m = ml_dequeue(&ml)) != NULL) {
     709           0 :                 pkt_session = m->m_pkthdr.ph_cookie;
     710           0 :                 if (pkt_session == NULL) {
     711           0 :                         m_freem(m);
     712           0 :                         continue;
     713             :                 }
     714           0 :                 pipex_ppp_input(m, pkt_session, 0);
     715             :         }
     716           0 : }
     717             : 
     718             : Static int
     719           0 : pipex_ppp_enqueue(struct mbuf *m0, struct pipex_session *session,
     720             :     struct mbuf_queue *mq)
     721             : {
     722           0 :         m0->m_pkthdr.ph_cookie = session;
     723             :         /* XXX need to support other protocols */
     724           0 :         m0->m_pkthdr.ph_ppp_proto = PPP_IP;
     725             : 
     726           0 :         if (mq_enqueue(mq, m0) != 0)
     727           0 :                 return (1);
     728             : 
     729           0 :         schednetisr(NETISR_PIPEX);
     730             : 
     731           0 :         return (0);
     732           0 : }
     733             : 
     734             : /***********************************************************************
     735             :  * Timer functions
     736             :  ***********************************************************************/
     737             : Static void
     738           0 : pipex_timer_start(void)
     739             : {
     740           0 :         timeout_set_proc(&pipex_timer_ch, pipex_timer, NULL);
     741           0 :         timeout_add_sec(&pipex_timer_ch, pipex_prune);
     742           0 : }
     743             : 
     744             : Static void
     745           0 : pipex_timer_stop(void)
     746             : {
     747           0 :         timeout_del(&pipex_timer_ch);
     748           0 : }
     749             : 
     750             : Static void
     751           0 : pipex_timer(void *ignored_arg)
     752             : {
     753             :         struct pipex_session *session;
     754             :         struct pipex_session *session_next;
     755             : 
     756           0 :         timeout_add_sec(&pipex_timer_ch, pipex_prune);
     757             : 
     758           0 :         NET_LOCK();
     759             :         /* walk through */
     760           0 :         for (session = LIST_FIRST(&pipex_session_list); session;
     761             :             session = session_next) {
     762           0 :                 session_next = LIST_NEXT(session, session_list);
     763           0 :                 switch (session->state) {
     764             :                 case PIPEX_STATE_OPENED:
     765           0 :                         if (session->timeout_sec == 0)
     766             :                                 continue;
     767             : 
     768           0 :                         session->stat.idle_time++;
     769           0 :                         if (session->stat.idle_time < session->timeout_sec)
     770             :                                 continue;
     771             : 
     772           0 :                         pipex_notify_close_session(session);
     773           0 :                         break;
     774             : 
     775             :                 case PIPEX_STATE_CLOSE_WAIT:
     776             :                 case PIPEX_STATE_CLOSE_WAIT2:
     777             :                         /* Wait PIPEXDSESSION from userland */
     778           0 :                         session->stat.idle_time++;
     779           0 :                         if (session->stat.idle_time < PIPEX_CLOSE_TIMEOUT)
     780             :                                 continue;
     781             : 
     782           0 :                         if (session->state == PIPEX_STATE_CLOSE_WAIT)
     783           0 :                                 LIST_REMOVE(session, state_list);
     784           0 :                         session->state = PIPEX_STATE_CLOSED;
     785             :                         /* FALLTHROUGH */
     786             : 
     787             :                 case PIPEX_STATE_CLOSED:
     788             :                         /*
     789             :                          * mbuf queued in pipexinq or pipexoutq may have a
     790             :                          * refererce to this session.
     791             :                          */
     792           0 :                         if (!mq_empty(&pipexinq) || !mq_empty(&pipexoutq))
     793             :                                 continue;
     794             : 
     795           0 :                         pipex_destroy_session(session);
     796           0 :                         break;
     797             : 
     798             :                 default:
     799             :                         break;
     800             :                 }
     801             :         }
     802             : 
     803           0 :         NET_UNLOCK();
     804           0 : }
     805             : 
     806             : /***********************************************************************
     807             :  * Common network I/O functions.  (tunnel protocol independent)
     808             :  ***********************************************************************/
     809             : struct mbuf *
     810           0 : pipex_output(struct mbuf *m0, int af, int off,
     811             :     struct pipex_iface_context *pipex_iface)
     812             : {
     813             :         struct pipex_session *session;
     814           0 :         struct ip ip;
     815             :         struct mbuf *mret;
     816             : 
     817             :         session = NULL;
     818             :         mret = NULL;
     819           0 :         switch (af) {
     820             :         case AF_INET:
     821           0 :                 if (m0->m_pkthdr.len >= sizeof(struct ip) + off) {
     822           0 :                         m_copydata(m0, off, sizeof(struct ip), (caddr_t)&ip);
     823           0 :                         if (IN_MULTICAST(ip.ip_dst.s_addr))
     824           0 :                                 session = pipex_iface->multicast_session;
     825             :                         else
     826           0 :                                 session = pipex_lookup_by_ip_address(ip.ip_dst);
     827             :                 }
     828           0 :                 if (session != NULL) {
     829           0 :                         if (session == pipex_iface->multicast_session) {
     830             :                                 mret = m0;
     831           0 :                                 m0 = m_copym(m0, 0, M_COPYALL, M_NOWAIT);
     832           0 :                                 if (m0 == NULL) {
     833             :                                         m0 = mret;
     834             :                                         mret = NULL;
     835             :                                         goto drop;
     836             :                                 }
     837             :                         }
     838             : 
     839           0 :                         if (off > 0)
     840           0 :                                 m_adj(m0, off);
     841             : 
     842           0 :                         pipex_ip_output(m0, session);
     843           0 :                         return (mret);
     844             :                 }
     845             :                 break;
     846             :         }
     847             : 
     848           0 :         return (m0);
     849             : 
     850             : drop:
     851           0 :         m_freem(m0);
     852           0 :         if (session != NULL)
     853           0 :                 session->stat.oerrors++;
     854           0 :         return(NULL);
     855           0 : }
     856             : 
     857             : Static void
     858           0 : pipex_ip_output(struct mbuf *m0, struct pipex_session *session)
     859             : {
     860           0 :         int is_idle;
     861             :         struct ifnet *ifp;
     862             : 
     863             :         /* output succeed here as a interface */
     864           0 :         ifp = session->pipex_iface->ifnet_this;
     865           0 :         ifp->if_opackets++;
     866           0 :         ifp->if_obytes+=m0->m_pkthdr.len;
     867             : 
     868           0 :         if (session->is_multicast == 0) {
     869             :                 /*
     870             :                  * Multicast packet is a idle packet and it's not TCP.
     871             :                  */
     872           0 :                 if (session->ip_forward == 0 && session->ip6_forward == 0)
     873             :                         goto drop;
     874             :                 /* reset idle timer */
     875           0 :                 if (session->timeout_sec != 0) {
     876           0 :                         is_idle = 0;
     877           0 :                         m0 = ip_is_idle_packet(m0, &is_idle);
     878           0 :                         if (m0 == NULL)
     879             :                                 goto dropped;
     880           0 :                         if (is_idle == 0)
     881             :                                 /* update expire time */
     882           0 :                                 session->stat.idle_time = 0;
     883             :                 }
     884             : 
     885             :                 /* adjust tcpmss */
     886           0 :                 if ((session->ppp_flags & PIPEX_PPP_ADJUST_TCPMSS) != 0) {
     887           0 :                         m0 = adjust_tcp_mss(m0, session->peer_mru);
     888           0 :                         if (m0 == NULL)
     889             :                                 goto dropped;
     890             :                 }
     891             :         } else
     892           0 :                 m0->m_flags &= ~(M_BCAST|M_MCAST);
     893             : 
     894             :         /* output ip packets to the session tunnel */
     895           0 :         if (pipex_ppp_enqueue(m0, session, &pipexoutq))
     896             :                 goto dropped;
     897             : 
     898           0 :         return;
     899             : drop:
     900           0 :         m_freem(m0);
     901             : dropped:
     902           0 :         session->stat.oerrors++;
     903           0 : }
     904             : 
     905             : Static void
     906           0 : pipex_ppp_output(struct mbuf *m0, struct pipex_session *session, int proto)
     907             : {
     908           0 :         u_char *cp, hdr[16];
     909             : 
     910             : #ifdef PIPEX_MPPE
     911           0 :         if (pipex_session_is_mppe_enabled(session)) {
     912           0 :                 if (proto == PPP_IP) {
     913           0 :                         pipex_mppe_output(m0, session, PPP_IP);
     914           0 :                         return;
     915             :                 }
     916             :         }
     917             : #endif /* PIPEX_MPPE */
     918           0 :         cp = hdr;
     919           0 :         if (session->protocol != PIPEX_PROTO_PPPOE) {
     920             :                 /* PPPoE has not address and control field */
     921           0 :                 PUTCHAR(PPP_ALLSTATIONS, cp);
     922           0 :                 PUTCHAR(PPP_UI, cp);
     923           0 :         }
     924           0 :         PUTSHORT(proto, cp);
     925             : 
     926           0 :         M_PREPEND(m0, cp - hdr, M_NOWAIT);
     927           0 :         if (m0 == NULL)
     928             :                 goto drop;
     929           0 :         memcpy(mtod(m0, u_char *), hdr, cp - hdr);
     930             : 
     931           0 :         switch (session->protocol) {
     932             : #ifdef  PIPEX_PPPOE
     933             :         case PIPEX_PROTO_PPPOE:
     934           0 :                 pipex_pppoe_output(m0, session);
     935           0 :                 break;
     936             : #endif
     937             : #ifdef PIPEX_PPTP
     938             :         case PIPEX_PROTO_PPTP:
     939           0 :                 pipex_pptp_output(m0, session, 1, 1);
     940           0 :                 break;
     941             : #endif
     942             : #ifdef  PIPEX_L2TP
     943             :         case PIPEX_PROTO_L2TP:
     944           0 :                 pipex_l2tp_output(m0, session);
     945           0 :                 break;
     946             : #endif
     947             :         default:
     948             :                 goto drop;
     949             :         }
     950             : 
     951           0 :         return;
     952             : drop:
     953           0 :         m_freem(m0);
     954           0 :         session->stat.oerrors++;
     955           0 : }
     956             : 
     957             : Static void
     958           0 : pipex_ppp_input(struct mbuf *m0, struct pipex_session *session, int decrypted)
     959             : {
     960           0 :         int proto, hlen = 0;
     961             :         struct mbuf *n;
     962             : 
     963           0 :         KASSERT(m0->m_pkthdr.len >= PIPEX_PPPMINLEN);
     964           0 :         proto = pipex_ppp_proto(m0, session, 0, &hlen);
     965             : #ifdef PIPEX_MPPE
     966           0 :         if (proto == PPP_COMP) {
     967           0 :                 if (decrypted)
     968             :                         goto drop;
     969             : 
     970             :                 /* checked this on ppp_common_input() already. */
     971           0 :                 KASSERT(pipex_session_is_mppe_accepted(session));
     972             : 
     973           0 :                 m_adj(m0, hlen);
     974           0 :                 pipex_mppe_input(m0, session);
     975           0 :                 return;
     976             :         }
     977           0 :         if (proto == PPP_CCP) {
     978           0 :                 if (decrypted)
     979             :                         goto drop;
     980             : 
     981             : #if NBPFILTER > 0
     982             :             {
     983           0 :                 struct ifnet *ifp = session->pipex_iface->ifnet_this;
     984           0 :                 if (ifp->if_bpf && ifp->if_type == IFT_PPP)
     985           0 :                         bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_IN);
     986             :             }
     987             : #endif
     988           0 :                 m_adj(m0, hlen);
     989           0 :                 pipex_ccp_input(m0, session);
     990           0 :                 return;
     991             :         }
     992             : #endif
     993           0 :         m_adj(m0, hlen);
     994             :         if (!ALIGNED_POINTER(mtod(m0, caddr_t), uint32_t)) {
     995             :                 n = m_dup_pkt(m0, 0, M_NOWAIT);
     996             :                 if (n == NULL)
     997             :                         goto drop;
     998             :                 m_freem(m0);
     999             :                 m0 = n;
    1000             :         }
    1001             : 
    1002           0 :         switch (proto) {
    1003             :         case PPP_IP:
    1004           0 :                 if (session->ip_forward == 0)
    1005             :                         goto drop;
    1006           0 :                 if (!decrypted && pipex_session_is_mppe_required(session))
    1007             :                         /*
    1008             :                          * if ip packet received when mppe
    1009             :                          * is required, discard it.
    1010             :                          */
    1011             :                         goto drop;
    1012           0 :                 pipex_ip_input(m0, session);
    1013           0 :                 return;
    1014             : #ifdef INET6
    1015             :         case PPP_IPV6:
    1016           0 :                 if (session->ip6_forward == 0)
    1017             :                         goto drop;
    1018           0 :                 if (!decrypted && pipex_session_is_mppe_required(session))
    1019             :                         /*
    1020             :                          * if ip packet received when mppe
    1021             :                          * is required, discard it.
    1022             :                          */
    1023             :                         goto drop;
    1024           0 :                 pipex_ip6_input(m0, session);
    1025           0 :                 return;
    1026             : #endif
    1027             :         default:
    1028           0 :                 if (decrypted)
    1029             :                         goto drop;
    1030             :                 /* protocol must be checked on pipex_common_input() already */
    1031           0 :                 KASSERT(0);
    1032             :                 goto drop;
    1033             :         }
    1034             : 
    1035             :         return;
    1036             : drop:
    1037           0 :         m_freem(m0);
    1038           0 :         session->stat.ierrors++;
    1039           0 : }
    1040             : 
    1041             : Static void
    1042           0 : pipex_ip_input(struct mbuf *m0, struct pipex_session *session)
    1043             : {
    1044             :         struct ifnet *ifp;
    1045             :         struct ip *ip;
    1046             :         int len;
    1047           0 :         int is_idle;
    1048             : 
    1049             :         /* change recvif */
    1050           0 :         ifp = session->pipex_iface->ifnet_this;
    1051           0 :         m0->m_pkthdr.ph_ifidx = ifp->if_index;
    1052             : 
    1053           0 :         if (ISSET(session->ppp_flags, PIPEX_PPP_INGRESS_FILTER)) {
    1054           0 :                 PIPEX_PULLUP(m0, sizeof(struct ip));
    1055           0 :                 if (m0 == NULL)
    1056             :                         goto drop;
    1057             :                 /* ingress filter */
    1058           0 :                 ip = mtod(m0, struct ip *);
    1059           0 :                 if ((ip->ip_src.s_addr & session->ip_netmask.sin_addr.s_addr) !=
    1060           0 :                     session->ip_address.sin_addr.s_addr) {
    1061           0 :                         char src[INET_ADDRSTRLEN];
    1062             : 
    1063           0 :                         pipex_session_log(session, LOG_DEBUG,
    1064             :                             "ip packet discarded by ingress filter (src %s)",
    1065           0 :                             inet_ntop(AF_INET, &ip->ip_src, src, sizeof(src)));
    1066             :                         goto drop;
    1067           0 :                 }
    1068             :         }
    1069             : 
    1070             :         /* idle timer */
    1071           0 :         if (session->timeout_sec != 0) {
    1072           0 :                 is_idle = 0;
    1073           0 :                 m0 = ip_is_idle_packet(m0, &is_idle);
    1074           0 :                 if (m0 == NULL)
    1075             :                         goto drop;
    1076           0 :                 if (is_idle == 0)
    1077             :                         /* update expire time */
    1078           0 :                         session->stat.idle_time = 0;
    1079             :         }
    1080             : 
    1081             :         /* adjust tcpmss */
    1082           0 :         if (session->ppp_flags & PIPEX_PPP_ADJUST_TCPMSS) {
    1083           0 :                 m0 = adjust_tcp_mss(m0, session->peer_mru);
    1084           0 :                 if (m0 == NULL)
    1085             :                         goto drop;
    1086             :         }
    1087             : 
    1088             : #if NPF > 0
    1089           0 :         pf_pkt_addr_changed(m0);
    1090             : #endif
    1091             : 
    1092           0 :         len = m0->m_pkthdr.len;
    1093             : 
    1094             : #if NBPFILTER > 0
    1095           0 :         if (ifp->if_bpf)
    1096           0 :                 bpf_mtap_af(ifp->if_bpf, AF_INET, m0, BPF_DIRECTION_IN);
    1097             : #endif
    1098             : 
    1099           0 :         ifp->if_ipackets++;
    1100           0 :         ifp->if_ibytes += len;
    1101           0 :         session->stat.ipackets++;
    1102           0 :         session->stat.ibytes += len;
    1103           0 :         ipv4_input(ifp, m0);
    1104             : 
    1105           0 :         return;
    1106             : drop:
    1107           0 :         m_freem(m0);
    1108           0 :         session->stat.ierrors++;
    1109           0 : }
    1110             : 
    1111             : #ifdef INET6
    1112             : Static void
    1113           0 : pipex_ip6_input(struct mbuf *m0, struct pipex_session *session)
    1114             : {
    1115             :         struct ifnet *ifp;
    1116             :         int len;
    1117             : 
    1118             :         /* change recvif */
    1119           0 :         ifp = session->pipex_iface->ifnet_this;
    1120           0 :         m0->m_pkthdr.ph_ifidx = ifp->if_index;
    1121             : 
    1122             :         /*
    1123             :          * XXX: what is reasonable ingress filter ???
    1124             :          *      only one address is enough ??
    1125             :          */
    1126             : 
    1127             :         /* XXX: we must define idle packet for IPv6(ICMPv6). */
    1128             : 
    1129             :         /*
    1130             :          * XXX: tcpmss adjustment for IPv6 is required???
    1131             :          *      We may use PMTUD in IPv6....
    1132             :          */
    1133             : 
    1134             : #if NPF > 0
    1135           0 :         pf_pkt_addr_changed(m0);
    1136             : #endif
    1137             : 
    1138           0 :         len = m0->m_pkthdr.len;
    1139             : 
    1140             : #if NBPFILTER > 0
    1141           0 :         if (ifp->if_bpf)
    1142           0 :                 bpf_mtap_af(ifp->if_bpf, AF_INET6, m0, BPF_DIRECTION_IN);
    1143             : #endif
    1144             : 
    1145           0 :         ifp->if_ipackets++;
    1146           0 :         ifp->if_ibytes += len;
    1147           0 :         session->stat.ipackets++;
    1148           0 :         session->stat.ibytes += len;
    1149           0 :         ipv6_input(ifp, m0);
    1150           0 : }
    1151             : #endif
    1152             : 
    1153             : Static struct mbuf *
    1154           0 : pipex_common_input(struct pipex_session *session, struct mbuf *m0, int hlen,
    1155             :     int plen, int useq)
    1156             : {
    1157           0 :         int proto, ppphlen;
    1158           0 :         u_char code;
    1159             : 
    1160           0 :         if ((m0->m_pkthdr.len < hlen + PIPEX_PPPMINLEN) ||
    1161           0 :             (plen < PIPEX_PPPMINLEN))
    1162             :                 goto drop;
    1163             : 
    1164           0 :         proto = pipex_ppp_proto(m0, session, hlen, &ppphlen);
    1165           0 :         switch (proto) {
    1166             : #ifdef PIPEX_MPPE
    1167             :         case PPP_CCP:
    1168           0 :                 code = 0;
    1169           0 :                 KASSERT(m0->m_pkthdr.len >= hlen + ppphlen + 1);
    1170           0 :                 m_copydata(m0, hlen + ppphlen, 1, (caddr_t)&code);
    1171           0 :                 if (code != CCP_RESETREQ && code != CCP_RESETACK)
    1172             :                         goto not_ours;
    1173             :                 break;
    1174             : 
    1175             :         case PPP_COMP:
    1176           0 :                 if (pipex_session_is_mppe_accepted(session))
    1177             :                         break;
    1178             :                 goto not_ours;
    1179             : #endif
    1180             :         case PPP_IP:
    1181             : #ifdef INET6
    1182             :         case PPP_IPV6:
    1183             : #endif
    1184             :                 break;
    1185             :         default:
    1186             :                 goto not_ours;
    1187             :         }
    1188             : 
    1189             :         /* ok,  The packet is for PIPEX */
    1190           0 :         m_adj(m0, hlen);/* cut off the tunnle protocol header */
    1191             : 
    1192             :         /* ensure the mbuf length equals the PPP frame length */
    1193           0 :         if (m0->m_pkthdr.len < plen)
    1194             :                 goto drop;
    1195           0 :         if (m0->m_pkthdr.len > plen) {
    1196           0 :                 if (m0->m_len == m0->m_pkthdr.len) {
    1197           0 :                         m0->m_len = plen;
    1198           0 :                         m0->m_pkthdr.len = plen;
    1199           0 :                 } else
    1200           0 :                         m_adj(m0, plen - m0->m_pkthdr.len);
    1201             :         }
    1202             : 
    1203           0 :         if (!useq) {
    1204           0 :                 pipex_ppp_input(m0, session, 0);
    1205           0 :                 return (NULL);
    1206             :         }
    1207             : 
    1208             :         /* input ppp packets to kernel session */
    1209           0 :         if (pipex_ppp_enqueue(m0, session, &pipexinq) != 0)
    1210             :                 goto dropped;
    1211             :         else
    1212           0 :                 return (NULL);
    1213             : drop:
    1214           0 :         m_freem(m0);
    1215             : dropped:
    1216           0 :         session->stat.ierrors++;
    1217           0 :         return (NULL);
    1218             : 
    1219             : not_ours:
    1220           0 :         return (m0);    /* Not to be handled by PIPEX */
    1221           0 : }
    1222             : 
    1223             : /*
    1224             :  * pipex_ppp_proto
    1225             :  */
    1226             : Static int
    1227           0 : pipex_ppp_proto(struct mbuf *m0, struct pipex_session *session, int off,
    1228             :     int *hlenp)
    1229             : {
    1230             :         int proto;
    1231           0 :         u_char *cp, pktbuf[4];
    1232             : 
    1233           0 :         KASSERT(m0->m_pkthdr.len > sizeof(pktbuf));
    1234           0 :         m_copydata(m0, off, sizeof(pktbuf), pktbuf);
    1235             :         cp = pktbuf;
    1236             : 
    1237           0 :         if (pipex_session_has_acf(session)) {
    1238           0 :                 if (cp[0] == PPP_ALLSTATIONS && cp[1] == PPP_UI)
    1239           0 :                         cp += 2;
    1240             : #ifdef PIPEX_DEBUG
    1241             :                 else if (!pipex_session_is_acfc_accepted(session))
    1242             :                         PIPEX_DBG((session, LOG_DEBUG,
    1243             :                             "no acf but acfc is not accepted by the peer."));
    1244             : #endif
    1245             :         }
    1246           0 :         if ((*cp & 0x01) != 0) {
    1247           0 :                 if (!pipex_session_is_pfc_accepted(session)) {
    1248             :                         PIPEX_DBG((session, LOG_DEBUG, "Received a broken ppp "
    1249             :                             "frame.  No protocol field. %02x-%02x",
    1250             :                             cp[0], cp[1]));
    1251           0 :                         return (-1);
    1252             :                 }
    1253           0 :                 GETCHAR(proto, cp);
    1254           0 :         } else
    1255           0 :                 GETSHORT(proto, cp);
    1256             : 
    1257           0 :         if (hlenp != NULL)
    1258           0 :                 *hlenp = cp - pktbuf;
    1259             : 
    1260           0 :         return (proto);
    1261           0 : }
    1262             : 
    1263             : #ifdef PIPEX_PPPOE
    1264             : /***********************************************************************
    1265             :  * PPPoE
    1266             :  ***********************************************************************/
    1267             : Static u_char   pipex_pppoe_padding[ETHERMIN];
    1268             : /*
    1269             :  * pipex_pppoe_lookup_session
    1270             :  */
    1271             : struct pipex_session *
    1272           0 : pipex_pppoe_lookup_session(struct mbuf *m0)
    1273             : {
    1274             :         struct pipex_session *session;
    1275           0 :         struct pipex_pppoe_header pppoe;
    1276             : 
    1277             :         /* short packet */
    1278           0 :         if (m0->m_pkthdr.len < (sizeof(struct ether_header) + sizeof(pppoe)))
    1279           0 :                 return (NULL);
    1280             : 
    1281           0 :         m_copydata(m0, sizeof(struct ether_header),
    1282             :             sizeof(struct pipex_pppoe_header), (caddr_t)&pppoe);
    1283           0 :         pppoe.session_id = ntohs(pppoe.session_id);
    1284           0 :         session = pipex_lookup_by_session_id(PIPEX_PROTO_PPPOE,
    1285             :             pppoe.session_id);
    1286             : #ifdef PIPEX_DEBUG
    1287             :         if (session == NULL)
    1288             :                 PIPEX_DBG((NULL, LOG_DEBUG, "<%s> session not found (id=%d)",
    1289             :                     __func__, pppoe.session_id));
    1290             : #endif
    1291           0 :         if (session && session->proto.pppoe.over_ifidx != m0->m_pkthdr.ph_ifidx)
    1292           0 :                 session = NULL;
    1293             : 
    1294           0 :         return (session);
    1295           0 : }
    1296             : 
    1297             : struct mbuf *
    1298           0 : pipex_pppoe_input(struct mbuf *m0, struct pipex_session *session)
    1299             : {
    1300             :         int hlen;
    1301           0 :         struct pipex_pppoe_header pppoe;
    1302             : 
    1303             :         /* already checked at pipex_pppoe_lookup_session */
    1304           0 :         KASSERT(m0->m_pkthdr.len >= (sizeof(struct ether_header) +
    1305             :             sizeof(pppoe)));
    1306             : 
    1307           0 :         m_copydata(m0, sizeof(struct ether_header),
    1308             :             sizeof(struct pipex_pppoe_header), (caddr_t)&pppoe);
    1309             : 
    1310             :         hlen = sizeof(struct ether_header) + sizeof(struct pipex_pppoe_header);
    1311           0 :         if ((m0 = pipex_common_input(session, m0, hlen, ntohs(pppoe.length), 0))
    1312           0 :             == NULL)
    1313           0 :                 return (NULL);
    1314           0 :         m_freem(m0);
    1315           0 :         session->stat.ierrors++;
    1316           0 :         return (NULL);
    1317           0 : }
    1318             : 
    1319             : /*
    1320             :  * pipex_ppope_output
    1321             :  */
    1322             : Static void
    1323           0 : pipex_pppoe_output(struct mbuf *m0, struct pipex_session *session)
    1324             : {
    1325             :         struct pipex_pppoe_header *pppoe;
    1326             :         struct ifnet *ifp;
    1327             :         int len, padlen;
    1328             : 
    1329             :         /* save length for pppoe header */
    1330           0 :         len = m0->m_pkthdr.len;
    1331             : 
    1332             :         /* prepend protocol header */
    1333           0 :         M_PREPEND(m0, sizeof(struct pipex_pppoe_header), M_NOWAIT);
    1334           0 :         if (m0 == NULL) {
    1335             :                 PIPEX_DBG((NULL, LOG_ERR,
    1336             :                     "<%s> cannot prepend header.", __func__));
    1337           0 :                 session->stat.oerrors++;
    1338           0 :                 return;
    1339             :         }
    1340           0 :         padlen = ETHERMIN - m0->m_pkthdr.len;
    1341           0 :         if (padlen > 0)
    1342           0 :                 m_copyback(m0, m0->m_pkthdr.len, padlen, pipex_pppoe_padding,
    1343             :                     M_NOWAIT);
    1344             : 
    1345             :         /* setup pppoe header information */
    1346           0 :         pppoe = mtod(m0, struct pipex_pppoe_header *);
    1347           0 :         pppoe->vertype = PIPEX_PPPOE_VERTYPE;
    1348           0 :         pppoe->code = PIPEX_PPPOE_CODE_SESSION;
    1349           0 :         pppoe->session_id = htons(session->session_id);
    1350           0 :         pppoe->length = htons(len);
    1351             : 
    1352           0 :         m0->m_pkthdr.ph_ifidx = session->proto.pppoe.over_ifidx;
    1353           0 :         m0->m_flags &= ~(M_BCAST|M_MCAST);
    1354             : 
    1355           0 :         ifp = if_get(session->proto.pppoe.over_ifidx);
    1356           0 :         if (ifp != NULL) {
    1357           0 :                 ifp->if_output(ifp, m0, &session->peer.sa, NULL);
    1358           0 :                 session->stat.opackets++;
    1359           0 :                 session->stat.obytes += len;
    1360           0 :         } else {
    1361           0 :                 m_freem(m0);
    1362           0 :                 session->stat.oerrors++;
    1363             :         }
    1364           0 :         if_put(ifp);
    1365           0 : }
    1366             : #endif /* PIPEX_PPPOE */
    1367             : 
    1368             : #ifdef PIPEX_PPTP
    1369             : /***********************************************************************
    1370             :  * PPTP
    1371             :  ***********************************************************************/
    1372             : Static void
    1373           0 : pipex_pptp_output(struct mbuf *m0, struct pipex_session *session,
    1374             :     int has_seq, int has_ack)
    1375             : {
    1376             :         int len, reqlen;
    1377             :         struct pipex_gre_header *gre = NULL;
    1378             :         struct ip *ip;
    1379             :         u_char *cp;
    1380             : 
    1381           0 :         reqlen = PIPEX_IPGRE_HDRLEN + (has_seq + has_ack) * 4;
    1382             : 
    1383             :         len = 0;
    1384           0 :         if (m0 != NULL) {
    1385             :                 /* save length for gre header */
    1386           0 :                 len = m0->m_pkthdr.len;
    1387             :                 /* prepend protocol header */
    1388           0 :                 M_PREPEND(m0, reqlen, M_NOWAIT);
    1389           0 :                 if (m0 == NULL)
    1390             :                         goto drop;
    1391             :         } else {
    1392           0 :                 MGETHDR(m0, M_DONTWAIT, MT_DATA);
    1393           0 :                 if (m0 && reqlen > MHLEN) {
    1394           0 :                         MCLGET(m0, M_DONTWAIT);
    1395           0 :                         if ((m0->m_flags & M_EXT) == 0) {
    1396           0 :                                 m_freem(m0);
    1397             :                                 m0 = NULL;
    1398           0 :                         }
    1399             :                 }
    1400           0 :                 if (m0 == NULL)
    1401             :                         goto drop;
    1402           0 :                 m0->m_pkthdr.len = m0->m_len = reqlen;
    1403             :         }
    1404             : 
    1405             :         /* setup ip header information */
    1406           0 :         ip = mtod(m0, struct ip *);
    1407             : 
    1408           0 :         ip->ip_len = htons(m0->m_pkthdr.len);
    1409           0 :         ip->ip_off = 0;
    1410           0 :         ip->ip_ttl = MAXTTL;
    1411           0 :         ip->ip_p = IPPROTO_GRE;
    1412           0 :         ip->ip_tos = 0;
    1413             : 
    1414           0 :         ip->ip_src = session->local.sin4.sin_addr;
    1415           0 :         ip->ip_dst = session->peer.sin4.sin_addr;
    1416             : #if NPF > 0
    1417           0 :         pf_pkt_addr_changed(m0);
    1418             : #endif
    1419             : 
    1420             :         /* setup gre(ver1) header information */
    1421           0 :         gre = PIPEX_SEEK_NEXTHDR(ip, sizeof(struct ip),
    1422             :             struct pipex_gre_header *);
    1423           0 :         gre->type = htons(PIPEX_GRE_PROTO_PPP);
    1424           0 :         gre->call_id = htons(session->peer_session_id);
    1425           0 :         gre->flags = PIPEX_GRE_KFLAG | PIPEX_GRE_VER;        /* do htons later */
    1426           0 :         gre->len = htons(len);
    1427             : 
    1428           0 :         cp = PIPEX_SEEK_NEXTHDR(gre, sizeof(struct pipex_gre_header),u_char *);
    1429           0 :         if (has_seq) {
    1430           0 :                 gre->flags |= PIPEX_GRE_SFLAG;
    1431           0 :                 PUTLONG(session->proto.pptp.snd_nxt, cp);
    1432           0 :                 session->proto.pptp.snd_nxt++;
    1433           0 :                 session->proto.pptp.snd_gap++;
    1434           0 :         }
    1435           0 :         if (has_ack) {
    1436           0 :                 gre->flags |= PIPEX_GRE_AFLAG;
    1437           0 :                 session->proto.pptp.rcv_acked = session->proto.pptp.rcv_nxt - 1;
    1438           0 :                 PUTLONG(session->proto.pptp.rcv_acked, cp);
    1439           0 :         }
    1440           0 :         gre->flags = htons(gre->flags);
    1441             : 
    1442           0 :         m0->m_pkthdr.ph_ifidx = session->pipex_iface->ifnet_this->if_index;
    1443           0 :         if (ip_output(m0, NULL, NULL, 0, NULL, NULL, 0) != 0) {
    1444             :                 PIPEX_DBG((session, LOG_DEBUG, "ip_output failed."));
    1445             :                 goto drop;
    1446             :         }
    1447           0 :         if (len > 0) {       /* network layer only */
    1448             :                 /* countup statistics */
    1449           0 :                 session->stat.opackets++;
    1450           0 :                 session->stat.obytes += len;
    1451           0 :         }
    1452             : 
    1453           0 :         return;
    1454             : drop:
    1455           0 :         session->stat.oerrors++;
    1456           0 : }
    1457             : 
    1458             : struct pipex_session *
    1459           0 : pipex_pptp_lookup_session(struct mbuf *m0)
    1460             : {
    1461             :         struct pipex_session *session;
    1462           0 :         struct pipex_gre_header gre;
    1463           0 :         struct ip ip;
    1464             :         uint16_t flags;
    1465             :         uint16_t id;
    1466             :         int hlen;
    1467             : 
    1468           0 :         if (m0->m_pkthdr.len < PIPEX_IPGRE_HDRLEN) {
    1469             :                 PIPEX_DBG((NULL, LOG_DEBUG,
    1470             :                     "<%s> packet length is too short", __func__));
    1471             :                 goto not_ours;
    1472             :         }
    1473             : 
    1474             :         /* get ip header info */
    1475           0 :         m_copydata(m0, 0, sizeof(struct ip), (caddr_t)&ip);
    1476           0 :         hlen = ip.ip_hl << 2;
    1477             : 
    1478             :         /*
    1479             :          * m0 has already passed ip_input(), so there is
    1480             :          * no necessity for ip packet inspection.
    1481             :          */
    1482             : 
    1483             :         /* get gre flags */
    1484           0 :         m_copydata(m0, hlen, sizeof(gre), (caddr_t)&gre);
    1485           0 :         flags = ntohs(gre.flags);
    1486             : 
    1487             :         /* gre version must be '1' */
    1488           0 :         if ((flags & PIPEX_GRE_VERMASK) != PIPEX_GRE_VER) {
    1489             :                 PIPEX_DBG((NULL, LOG_DEBUG,
    1490             :                     "<%s> gre header wrong version.", __func__));
    1491             :                 goto not_ours;
    1492             :         }
    1493             : 
    1494             :         /* gre keys must be present */
    1495           0 :         if ((flags & PIPEX_GRE_KFLAG) == 0) {
    1496             :                 PIPEX_DBG((NULL, LOG_DEBUG,
    1497             :                     "<%s> gre header has no keys.", __func__));
    1498             :                 goto not_ours;
    1499             :         }
    1500             : 
    1501             :         /* flag check */
    1502           0 :         if ((flags & PIPEX_GRE_UNUSEDFLAGS) != 0) {
    1503             :                 PIPEX_DBG((NULL, LOG_DEBUG,
    1504             :                     "<%s> gre header has unused flags at pptp.", __func__));
    1505             :                 goto not_ours;
    1506             :         }
    1507             : 
    1508             :         /* lookup pipex session table */
    1509           0 :         id = ntohs(gre.call_id);
    1510           0 :         session = pipex_lookup_by_session_id(PIPEX_PROTO_PPTP, id);
    1511             : #ifdef PIPEX_DEBUG
    1512             :         if (session == NULL) {
    1513             :                 PIPEX_DBG((NULL, LOG_DEBUG,
    1514             :                     "<%s> session not found (id=%d)", __func__, id));
    1515             :                 goto not_ours;
    1516             :         }
    1517             : #endif
    1518             : 
    1519           0 :         return (session);
    1520             : 
    1521             : not_ours:
    1522           0 :         return (NULL);
    1523           0 : }
    1524             : 
    1525             : struct mbuf *
    1526           0 : pipex_pptp_input(struct mbuf *m0, struct pipex_session *session)
    1527             : {
    1528             :         int hlen, has_seq, has_ack, nseq;
    1529             :         const char *reason = "";
    1530             :         u_char *cp, *seqp = NULL, *ackp = NULL;
    1531             :         uint32_t flags, seq = 0, ack = 0;
    1532             :         struct ip *ip;
    1533             :         struct pipex_gre_header *gre;
    1534             :         struct pipex_pptp_session *pptp_session;
    1535             :         int rewind = 0;
    1536             : 
    1537           0 :         KASSERT(m0->m_pkthdr.len >= PIPEX_IPGRE_HDRLEN);
    1538           0 :         pptp_session = &session->proto.pptp;
    1539             : 
    1540             :         /* get ip header */
    1541           0 :         ip = mtod(m0, struct ip *);
    1542           0 :         hlen = ip->ip_hl << 2;
    1543             : 
    1544             :         /* seek gre header */
    1545           0 :         gre = PIPEX_SEEK_NEXTHDR(ip, hlen, struct pipex_gre_header *);
    1546           0 :         flags = ntohs(gre->flags);
    1547             : 
    1548             :         /* pullup for seek sequences in header */
    1549           0 :         has_seq = (flags & PIPEX_GRE_SFLAG) ? 1 : 0;
    1550           0 :         has_ack = (flags & PIPEX_GRE_AFLAG) ? 1 : 0;
    1551           0 :         hlen = PIPEX_IPGRE_HDRLEN + 4 * (has_seq + has_ack);
    1552           0 :         if (m0->m_len < hlen) {
    1553           0 :                 m0 = m_pullup(m0, hlen);
    1554           0 :                 if (m0 == NULL) {
    1555             :                         PIPEX_DBG((session, LOG_DEBUG, "pullup failed."));
    1556             :                         goto drop;
    1557             :                 }
    1558             :         }
    1559             : 
    1560             :         /* check sequence */
    1561           0 :         cp = PIPEX_SEEK_NEXTHDR(gre, sizeof(struct pipex_gre_header),u_char *);
    1562           0 :         if (has_seq) {
    1563             :                 seqp = cp;
    1564           0 :                 GETLONG(seq, cp);
    1565           0 :         }
    1566           0 :         if (has_ack) {
    1567             :                 ackp = cp;
    1568           0 :                 GETLONG(ack, cp);
    1569           0 :                 if (ack + 1 == pptp_session->snd_una) {
    1570             :                         /* ack has not changed before */
    1571           0 :                 } else if (SEQ32_LT(ack, pptp_session->snd_una)) {
    1572             :                         /* OoO ack packets should not be dropped. */
    1573             :                         rewind = 1;
    1574           0 :                 } else if (SEQ32_GT(ack, pptp_session->snd_nxt)) {
    1575             :                         reason = "ack for unknown sequence";
    1576           0 :                         goto out_seq;
    1577             :                 } else
    1578           0 :                         pptp_session->snd_una = ack + 1;
    1579             :         }
    1580           0 :         if (!has_seq) {
    1581             :                 /* ack only packet */
    1582             :                 goto not_ours;
    1583             :         }
    1584           0 :         if (SEQ32_LT(seq, pptp_session->rcv_nxt)) {
    1585             :                 rewind = 1;
    1586           0 :                 if (SEQ32_LT(seq,
    1587             :                     pptp_session->rcv_nxt - PIPEX_REWIND_LIMIT)) {
    1588             :                         reason = "out of sequence";
    1589           0 :                         goto out_seq;
    1590             :                 }
    1591           0 :         } else if (SEQ32_GE(seq, pptp_session->rcv_nxt +
    1592             :             pptp_session->maxwinsz)) {
    1593           0 :                 pipex_session_log(session, LOG_DEBUG,
    1594             :                     "received packet caused window overflow. seq=%u(%u-%u)"
    1595             :                     "may lost %d packets.", seq, pptp_session->rcv_nxt,
    1596             :                     pptp_session->rcv_nxt + pptp_session->maxwinsz,
    1597             :                     (int)SEQ32_SUB(seq, pptp_session->rcv_nxt));
    1598           0 :         }
    1599             : 
    1600           0 :         seq++;
    1601           0 :         nseq = SEQ32_SUB(seq, pptp_session->rcv_nxt);
    1602           0 :         if (!rewind) {
    1603           0 :                 pptp_session->rcv_nxt = seq;
    1604           0 :                 if (SEQ32_SUB(seq, pptp_session->rcv_acked) >
    1605           0 :                     roundup(pptp_session->winsz, 2) / 2) /* Send ack only packet. */
    1606           0 :                         pipex_pptp_output(NULL, session, 0, 1);
    1607             :         }
    1608             : 
    1609           0 :         if ((m0 = pipex_common_input(session, m0, hlen, ntohs(gre->len), 1))
    1610           0 :             == NULL) {
    1611             :                 /* ok,  The packet is for PIPEX */
    1612           0 :                 if (!rewind)
    1613           0 :                         session->proto.pptp.rcv_gap += nseq;
    1614           0 :                 return (NULL);
    1615             :         }
    1616             : 
    1617           0 :         if (rewind)
    1618             :                 goto out_seq;
    1619             : 
    1620             : not_ours:
    1621           0 :         seq--;  /* revert original seq value */
    1622             : 
    1623             :         /*
    1624             :          * overwrite sequence numbers to adjust a gap between pipex and
    1625             :          * userland.
    1626             :          */
    1627           0 :         if (seqp != NULL) {
    1628           0 :                 seq -= pptp_session->rcv_gap;
    1629           0 :                 PUTLONG(seq, seqp);
    1630           0 :         }
    1631           0 :         if (ackp != NULL) {
    1632           0 :                 if (pptp_session->snd_nxt == pptp_session->snd_una) {
    1633           0 :                         ack -= session->proto.pptp.snd_gap;
    1634           0 :                         pptp_session->ul_snd_una = ack;
    1635           0 :                 } else {
    1636             :                         /*
    1637             :                          * There are sending packets they are not acked.
    1638             :                          * In this situation, (ack - snd_gap) may points
    1639             :                          * before sending window of userland.  So we don't
    1640             :                          * update the ack number.
    1641             :                          */
    1642           0 :                         ack = pptp_session->ul_snd_una;
    1643             :                 }
    1644           0 :                 PUTLONG(ack, ackp);
    1645           0 :         }
    1646             : 
    1647           0 :         return (m0);
    1648             : out_seq:
    1649           0 :         pipex_session_log(session, LOG_DEBUG,
    1650             :             "Received bad data packet: %s: seq=%u(%u-%u) ack=%u(%u-%u)",
    1651           0 :             reason, seq, pptp_session->rcv_nxt,
    1652           0 :             pptp_session->rcv_nxt + pptp_session->maxwinsz,
    1653           0 :             ack, pptp_session->snd_una,
    1654           0 :             pptp_session->snd_nxt);
    1655             : 
    1656             :         /* FALLTHROUGH */
    1657             : drop:
    1658           0 :         m_freem(m0);
    1659           0 :         session->stat.ierrors++;
    1660             : 
    1661           0 :         return (NULL);
    1662           0 : }
    1663             : 
    1664             : struct pipex_session *
    1665           0 : pipex_pptp_userland_lookup_session_ipv4(struct mbuf *m0, struct in_addr dst)
    1666             : {
    1667           0 :         struct sockaddr_in sin;
    1668             : 
    1669           0 :         memset(&sin, 0, sizeof(sin));
    1670           0 :         sin.sin_len = sizeof(sin);
    1671           0 :         sin.sin_family = AF_INET;
    1672           0 :         sin.sin_addr = dst;
    1673             : 
    1674           0 :         return pipex_pptp_userland_lookup_session(m0, sintosa(&sin));
    1675           0 : }
    1676             : 
    1677             : #ifdef INET6
    1678             : struct pipex_session *
    1679           0 : pipex_pptp_userland_lookup_session_ipv6(struct mbuf *m0, struct in6_addr dst)
    1680             : {
    1681           0 :         struct sockaddr_in6 sin6;
    1682             : 
    1683           0 :         memset(&sin6, 0, sizeof(sin6));
    1684           0 :         sin6.sin6_len = sizeof(sin6);
    1685           0 :         sin6.sin6_family = AF_INET6;
    1686           0 :         in6_recoverscope(&sin6, &dst);
    1687             : 
    1688           0 :         return pipex_pptp_userland_lookup_session(m0, sin6tosa(&sin6));
    1689           0 : }
    1690             : #endif
    1691             : 
    1692             : Static struct pipex_session *
    1693           0 : pipex_pptp_userland_lookup_session(struct mbuf *m0, struct sockaddr *sa)
    1694             : {
    1695           0 :         struct pipex_gre_header gre;
    1696             :         struct pipex_hash_head *list;
    1697             :         struct pipex_session *session;
    1698             :         uint16_t id, flags;
    1699             : 
    1700             :         /* pullup */
    1701           0 :         if (m0->m_pkthdr.len < sizeof(gre)) {
    1702             :                 PIPEX_DBG((NULL, LOG_DEBUG,
    1703             :                     "<%s> packet length is too short", __func__));
    1704           0 :                 return (NULL);
    1705             :         }
    1706             : 
    1707             :         /* get flags */
    1708           0 :         m_copydata(m0, 0, sizeof(struct pipex_gre_header), (caddr_t)&gre);
    1709           0 :         flags = ntohs(gre.flags);
    1710             : 
    1711             :         /* gre version must be '1' */
    1712           0 :         if ((flags & PIPEX_GRE_VERMASK) != PIPEX_GRE_VER) {
    1713             :                 PIPEX_DBG((NULL, LOG_DEBUG,
    1714             :                     "<%s> gre header wrong version.", __func__));
    1715           0 :                 return (NULL);
    1716             :         }
    1717             : 
    1718             :         /* gre keys must be present */
    1719           0 :         if ((flags & PIPEX_GRE_KFLAG) == 0) {
    1720             :                 PIPEX_DBG((NULL, LOG_DEBUG,
    1721             :                     "<%s> gre header has no keys.", __func__));
    1722           0 :                 return (NULL);
    1723             :         }
    1724             : 
    1725             :         /* lookup pipex session table */
    1726           0 :         id = ntohs(gre.call_id);
    1727             : 
    1728           0 :         list = PIPEX_PEER_ADDR_HASHTABLE(pipex_sockaddr_hash_key(sa));
    1729           0 :         LIST_FOREACH(session, list, peer_addr_chain) {
    1730           0 :                 if (pipex_sockaddr_compar_addr(&session->peer.sa, sa) != 0)
    1731             :                         continue;
    1732           0 :                 if (session->peer_session_id == id)
    1733             :                         break;
    1734             :         }
    1735             : #ifdef PIPEX_DEBUG
    1736             :         if (session == NULL) {
    1737             :                 PIPEX_DBG((NULL, LOG_DEBUG,
    1738             :                     "<%s> session not found (,call_id=%d)",
    1739             :                     __func__, (int)gre.call_id));
    1740             :         }
    1741             : #endif
    1742           0 :         return (session);
    1743           0 : }
    1744             : 
    1745             : /*
    1746             :  * pipex_pptp_userland_output
    1747             :  */
    1748             : struct mbuf *
    1749           0 : pipex_pptp_userland_output(struct mbuf *m0, struct pipex_session *session)
    1750             : {
    1751             :         int len;
    1752           0 :         struct pipex_gre_header *gre, gre0;
    1753             :         uint16_t flags;
    1754             :         u_char *cp, *cp0;
    1755             :         uint32_t val32;
    1756             : 
    1757             :         len = sizeof(struct pipex_gre_header);
    1758           0 :         m_copydata(m0, 0, len, (caddr_t)&gre0);
    1759             :         gre = &gre0;
    1760           0 :         flags = ntohs(gre->flags);
    1761           0 :         if ((flags & PIPEX_GRE_SFLAG) != 0)
    1762           0 :                 len += 4;
    1763           0 :         if ((flags & PIPEX_GRE_AFLAG) != 0)
    1764           0 :                 len += 4;
    1765             : 
    1766             :         /* check length */
    1767           0 :         PIPEX_PULLUP(m0, len);
    1768           0 :         if (m0 == NULL) {
    1769             :                 PIPEX_DBG((session, LOG_DEBUG, "gre header is too short."));
    1770           0 :                 return (NULL);
    1771             :         }
    1772             : 
    1773           0 :         gre = mtod(m0, struct pipex_gre_header *);
    1774           0 :         cp = PIPEX_SEEK_NEXTHDR(gre, sizeof(struct pipex_gre_header), u_char *);
    1775             : 
    1776             :         /*
    1777             :          * overwrite sequence numbers to adjust a gap between pipex and
    1778             :          * userland.
    1779             :          */
    1780           0 :         if ((flags & PIPEX_GRE_SFLAG) != 0) {
    1781             :                 cp0 = cp;
    1782           0 :                 GETLONG(val32, cp);
    1783           0 :                 val32 += session->proto.pptp.snd_gap;
    1784           0 :                 PUTLONG(val32, cp0);
    1785           0 :                 session->proto.pptp.snd_nxt++;
    1786           0 :         }
    1787           0 :         if ((flags & PIPEX_GRE_AFLAG) != 0) {
    1788             :                 cp0 = cp;
    1789           0 :                 GETLONG(val32, cp);
    1790           0 :                 val32 += session->proto.pptp.rcv_gap;
    1791           0 :                 PUTLONG(val32, cp0);
    1792           0 :                 if (SEQ32_GT(val32, session->proto.pptp.rcv_acked))
    1793           0 :                         session->proto.pptp.rcv_acked = val32;
    1794             :         }
    1795             : 
    1796           0 :         return (m0);
    1797           0 : }
    1798             : #endif /* PIPEX_PPTP */
    1799             : 
    1800             : #ifdef PIPEX_L2TP
    1801             : /***********************************************************************
    1802             :  * L2TP support
    1803             :  ***********************************************************************/
    1804             : Static void
    1805           0 : pipex_l2tp_output(struct mbuf *m0, struct pipex_session *session)
    1806             : {
    1807             :         int hlen, plen, datalen;
    1808             :         struct pipex_l2tp_header *l2tp = NULL;
    1809             :         struct pipex_l2tp_seq_header *seq = NULL;
    1810             :         struct udphdr *udp;
    1811             :         struct ip *ip;
    1812             : #ifdef INET6
    1813             :         struct ip6_hdr *ip6;
    1814             : #endif
    1815             : 
    1816           0 :         hlen = sizeof(struct pipex_l2tp_header) +
    1817           0 :             ((pipex_session_is_l2tp_data_sequencing_on(session))
    1818           0 :                     ? sizeof(struct pipex_l2tp_seq_header) : 0) +
    1819           0 :             sizeof(struct udphdr) +
    1820             : #ifdef INET6
    1821           0 :             ((session->peer.sin6.sin6_family == AF_INET6)
    1822             :                     ? sizeof(struct ip6_hdr) : sizeof(struct ip));
    1823             : #else
    1824             :             sizeof(struct ip);
    1825             : #endif
    1826             : 
    1827             :         datalen = 0;
    1828           0 :         if (m0 != NULL) {
    1829           0 :                 datalen = m0->m_pkthdr.len;
    1830           0 :                 M_PREPEND(m0, hlen, M_NOWAIT);
    1831           0 :                 if (m0 == NULL)
    1832             :                         goto drop;
    1833             :         } else {
    1834           0 :                 MGETHDR(m0, M_DONTWAIT, MT_DATA);
    1835           0 :                 if (m0 == NULL)
    1836             :                         goto drop;
    1837           0 :                 KASSERT(hlen <= MHLEN);
    1838           0 :                 m0->m_pkthdr.len = m0->m_len = hlen;
    1839             :         }
    1840             : 
    1841             : #ifdef INET6
    1842           0 :         hlen = (session->peer.sin6.sin6_family == AF_INET6)
    1843             :             ? sizeof(struct ip6_hdr) : sizeof(struct ip);
    1844             : #else
    1845             :         hlen = sizeof(struct ip);
    1846             : #endif
    1847           0 :         plen = datalen + sizeof(struct pipex_l2tp_header) +
    1848           0 :             ((pipex_session_is_l2tp_data_sequencing_on(session))
    1849             :                     ? sizeof(struct pipex_l2tp_seq_header) : 0);
    1850             : 
    1851           0 :         l2tp = (struct pipex_l2tp_header *)
    1852           0 :             (mtod(m0, caddr_t) + hlen + sizeof(struct udphdr));
    1853           0 :         l2tp->flagsver = PIPEX_L2TP_VER | PIPEX_L2TP_FLAG_LENGTH;
    1854           0 :         l2tp->length = htons(plen);
    1855           0 :         l2tp->tunnel_id = htons(session->proto.l2tp.peer_tunnel_id);
    1856           0 :         l2tp->session_id = htons(session->peer_session_id);
    1857           0 :         if (pipex_session_is_l2tp_data_sequencing_on(session)) {
    1858           0 :                 seq = (struct pipex_l2tp_seq_header *)(l2tp + 1);
    1859           0 :                 l2tp->flagsver |= PIPEX_L2TP_FLAG_SEQUENCE;
    1860           0 :                 seq->ns = htons(session->proto.l2tp.ns_nxt);
    1861           0 :                 session->proto.l2tp.ns_nxt++;
    1862           0 :                 session->proto.l2tp.ns_gap++;
    1863           0 :                 session->proto.l2tp.nr_acked = session->proto.l2tp.nr_nxt - 1;
    1864           0 :                 seq->nr = htons(session->proto.l2tp.nr_acked);
    1865           0 :         }
    1866           0 :         l2tp->flagsver = htons(l2tp->flagsver);
    1867             : 
    1868           0 :         plen += sizeof(struct udphdr);
    1869           0 :         udp = (struct udphdr *)(mtod(m0, caddr_t) + hlen);
    1870           0 :         udp->uh_sport = session->local.sin6.sin6_port;
    1871           0 :         udp->uh_dport = session->peer.sin6.sin6_port;
    1872           0 :         udp->uh_ulen = htons(plen);
    1873           0 :         udp->uh_sum = 0;
    1874             : 
    1875           0 :         m0->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT;
    1876           0 :         m0->m_pkthdr.ph_ifidx = session->pipex_iface->ifnet_this->if_index;
    1877             : #if NPF > 0
    1878           0 :         pf_pkt_addr_changed(m0);
    1879             : #endif
    1880           0 :         switch (session->peer.sin6.sin6_family) {
    1881             :         case AF_INET:
    1882           0 :                 ip = mtod(m0, struct ip *);
    1883           0 :                 ip->ip_p = IPPROTO_UDP;
    1884           0 :                 ip->ip_src = session->local.sin4.sin_addr;
    1885           0 :                 ip->ip_dst = session->peer.sin4.sin_addr;
    1886           0 :                 ip->ip_len = htons(hlen + plen);
    1887           0 :                 ip->ip_ttl = MAXTTL;
    1888           0 :                 ip->ip_tos = 0;
    1889           0 :                 ip->ip_off = 0;
    1890             : 
    1891           0 :                 if (ip_output(m0, NULL, NULL, 0, NULL, NULL,
    1892           0 :                     session->proto.l2tp.ipsecflowinfo) != 0) {
    1893             :                         PIPEX_DBG((session, LOG_DEBUG, "ip_output failed."));
    1894             :                         goto drop;
    1895             :                 }
    1896             :                 break;
    1897             : #ifdef INET6
    1898             :         case AF_INET6:
    1899           0 :                 ip6 = mtod(m0, struct ip6_hdr *);
    1900             : 
    1901           0 :                 ip6->ip6_flow = 0;
    1902           0 :                 ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
    1903           0 :                 ip6->ip6_vfc |= IPV6_VERSION;
    1904           0 :                 ip6->ip6_nxt = IPPROTO_UDP;
    1905           0 :                 ip6->ip6_src = session->local.sin6.sin6_addr;
    1906           0 :                 (void)in6_embedscope(&ip6->ip6_dst,
    1907             :                     &session->peer.sin6, NULL);
    1908             :                 /* ip6->ip6_plen will be filled in ip6_output. */
    1909             : 
    1910           0 :                 if (ip6_output(m0, NULL, NULL, 0, NULL, NULL) != 0) {
    1911             :                         PIPEX_DBG((session, LOG_DEBUG, "ip6_output failed."));
    1912             :                         goto drop;
    1913             :                 }
    1914             :                 break;
    1915             : #endif
    1916             :         }
    1917           0 :         udpstat_inc(udps_opackets);
    1918             : 
    1919           0 :         if (datalen > 0) {   /* network layer only */
    1920             :                 /* countup statistics */
    1921           0 :                 session->stat.opackets++;
    1922           0 :                 session->stat.obytes += datalen;
    1923           0 :         }
    1924             : 
    1925           0 :         return;
    1926             : drop:
    1927           0 :         session->stat.oerrors++;
    1928           0 : }
    1929             : 
    1930             : struct pipex_session *
    1931           0 : pipex_l2tp_lookup_session(struct mbuf *m0, int off)
    1932             : {
    1933             :         struct pipex_session *session;
    1934             :         uint16_t flags, session_id, ver;
    1935           0 :         u_char *cp, buf[PIPEX_L2TP_MINLEN];
    1936             : 
    1937           0 :         if (m0->m_pkthdr.len < off + PIPEX_L2TP_MINLEN) {
    1938             :                 PIPEX_DBG((NULL, LOG_DEBUG,
    1939             :                     "<%s> packet length is too short", __func__));
    1940             :                 goto not_ours;
    1941             :         }
    1942             : 
    1943             :         /* get first 16bits of L2TP */
    1944           0 :         m_copydata(m0, off, sizeof(buf), buf);
    1945             :         cp = buf;
    1946           0 :         GETSHORT(flags, cp);
    1947           0 :         ver = flags & PIPEX_L2TP_VER_MASK;
    1948             : 
    1949             :         /* l2tp version must be '2' */
    1950           0 :         if (ver != PIPEX_L2TP_VER) {
    1951             :                 PIPEX_DBG((NULL, LOG_DEBUG,
    1952             :                     "<%s> l2tp header wrong version %u.", __func__, ver));
    1953             :                 goto not_ours;
    1954             :         }
    1955           0 :         if ((flags & PIPEX_L2TP_FLAG_TYPE) != 0)
    1956             :                 goto not_ours;
    1957             : 
    1958           0 :         if (flags & PIPEX_L2TP_FLAG_LENGTH)
    1959           0 :                 cp += 2;                        /* skip length field */
    1960           0 :         cp += 2;                                /* skip tunnel-id field */
    1961           0 :         GETSHORT(session_id, cp);               /* get session-id field */
    1962             : 
    1963             :         /* lookup pipex session table */
    1964           0 :         session = pipex_lookup_by_session_id(PIPEX_PROTO_L2TP, session_id);
    1965             : #ifdef PIPEX_DEBUG
    1966             :         if (session == NULL) {
    1967             :                 PIPEX_DBG((NULL, LOG_DEBUG,
    1968             :                     "<%s> session not found (id=%d)", __func__, session_id));
    1969             :                 goto not_ours;
    1970             :         }
    1971             : #endif
    1972             : 
    1973           0 :         return (session);
    1974             : 
    1975             : not_ours:
    1976           0 :         return (NULL);
    1977           0 : }
    1978             : 
    1979             : struct mbuf *
    1980           0 : pipex_l2tp_input(struct mbuf *m0, int off0, struct pipex_session *session,
    1981             :     uint32_t ipsecflowinfo)
    1982             : {
    1983             :         struct pipex_l2tp_session *l2tp_session;
    1984             :         int length, offset, hlen, nseq;
    1985             :         u_char *cp, *nsp, *nrp;
    1986           0 :         uint16_t flags, ns = 0, nr = 0;
    1987             :         int rewind = 0;
    1988             : 
    1989             :         length = offset = ns = nr = 0;
    1990           0 :         l2tp_session = &session->proto.l2tp;
    1991           0 :         l2tp_session->ipsecflowinfo = ipsecflowinfo;
    1992             :         nsp = nrp = NULL;
    1993             : 
    1994           0 :         m_copydata(m0, off0, sizeof(flags), (caddr_t)&flags);
    1995             : 
    1996           0 :         flags = ntohs(flags) & PIPEX_L2TP_FLAG_MASK;
    1997           0 :         KASSERT((flags & PIPEX_L2TP_FLAG_TYPE) == 0);
    1998             : 
    1999             :         hlen = 2;                               /* flags and version fields */
    2000           0 :         if (flags & PIPEX_L2TP_FLAG_LENGTH) /* length */
    2001           0 :                 hlen += 2;
    2002           0 :         hlen += 4;                              /* tunnel-id and session-id */
    2003           0 :         if (flags & PIPEX_L2TP_FLAG_SEQUENCE)       /* ns and nr */
    2004           0 :                 hlen += 4;
    2005           0 :         if (flags & PIPEX_L2TP_FLAG_OFFSET) /* offset */
    2006           0 :                 hlen += 2;
    2007             : 
    2008           0 :         PIPEX_PULLUP(m0, off0 + hlen);
    2009           0 :         if (m0  == NULL)
    2010             :                 goto drop;
    2011             : 
    2012           0 :         cp = mtod(m0, u_char *) + off0;
    2013           0 :         cp += 2;        /* flags and version */
    2014           0 :         if (flags & PIPEX_L2TP_FLAG_LENGTH)
    2015           0 :                 GETSHORT(length, cp);
    2016             :         else
    2017           0 :                 length = m0->m_pkthdr.len - off0;
    2018           0 :         cp += 4;        /* skip tunnel-id and session-id field */
    2019             : 
    2020             :         /* pullup for seek sequences in header */
    2021             :         nseq = 0;
    2022           0 :         if (flags & PIPEX_L2TP_FLAG_SEQUENCE) {
    2023             :                 nsp = cp;
    2024           0 :                 GETSHORT(ns, cp);
    2025             :                 nrp = cp;
    2026           0 :                 GETSHORT(nr, cp);
    2027             : 
    2028           0 :                 nr++;
    2029           0 :                 if (SEQ16_GT(nr, l2tp_session->ns_una) &&
    2030           0 :                     SEQ16_LE(nr, l2tp_session->ns_nxt))
    2031             :                         /* update 'ns_una' only if the ns is in valid range */
    2032           0 :                         l2tp_session->ns_una = nr;
    2033           0 :                 if (SEQ16_LT(ns, l2tp_session->nr_nxt)) {
    2034             :                         rewind = 1;
    2035           0 :                         if (SEQ16_LT(ns,
    2036             :                             l2tp_session->nr_nxt - PIPEX_REWIND_LIMIT))
    2037             :                                 goto out_seq;
    2038             :                 }
    2039             : 
    2040           0 :                 ns++;
    2041           0 :                 nseq = SEQ16_SUB(ns, l2tp_session->nr_nxt);
    2042           0 :                 if (!rewind)
    2043           0 :                         l2tp_session->nr_nxt = ns;
    2044             :         }
    2045           0 :         if (flags & PIPEX_L2TP_FLAG_OFFSET)
    2046           0 :                 GETSHORT(offset, cp);
    2047             : 
    2048           0 :         length -= hlen + offset;
    2049           0 :         hlen += off0 + offset;
    2050           0 :         if ((m0 = pipex_common_input(session, m0, hlen, length, 1)) == NULL) {
    2051             :                 /* ok,  The packet is for PIPEX */
    2052           0 :                 if (!rewind)
    2053           0 :                         session->proto.l2tp.nr_gap += nseq;
    2054           0 :                 return (NULL);
    2055             :         }
    2056             : 
    2057           0 :         if (rewind)
    2058             :                 goto out_seq;
    2059             : 
    2060             :         /*
    2061             :          * overwrite sequence numbers to adjust a gap between pipex and
    2062             :          * userland.
    2063             :          */
    2064           0 :         if (flags & PIPEX_L2TP_FLAG_SEQUENCE) {
    2065           0 :                 --ns; --nr;     /* revert original values */
    2066           0 :                 ns -= l2tp_session->nr_gap;
    2067           0 :                 PUTSHORT(ns, nsp);
    2068             : 
    2069           0 :                 if (l2tp_session->ns_nxt == l2tp_session->ns_una) {
    2070           0 :                         nr -= l2tp_session->ns_gap;
    2071           0 :                         l2tp_session->ul_ns_una = nr;
    2072           0 :                 } else {
    2073             :                         /*
    2074             :                          * There are sending packets they are not acked.
    2075             :                          * In this situation, (ack - snd_gap) may points
    2076             :                          * before sending window of userland.  So we don't
    2077             :                          * update the ack number.
    2078             :                          */
    2079           0 :                         nr = l2tp_session->ul_ns_una;
    2080             :                 }
    2081           0 :                 PUTSHORT(nr, nrp);
    2082           0 :         }
    2083             : 
    2084           0 :         return (m0);
    2085             : out_seq:
    2086           0 :         pipex_session_log(session, LOG_DEBUG,
    2087             :             "Received bad data packet: out of sequence: seq=%u(%u-) "
    2088           0 :             "ack=%u(%u-%u)", ns, l2tp_session->nr_nxt, nr, l2tp_session->ns_una,
    2089           0 :             l2tp_session->ns_nxt);
    2090             : 
    2091             :         /* FALLTHROUGH */
    2092             : drop:
    2093           0 :         m_freem(m0);
    2094           0 :         session->stat.ierrors++;
    2095             : 
    2096           0 :         return (NULL);
    2097           0 : }
    2098             : 
    2099             : struct pipex_session *
    2100           0 : pipex_l2tp_userland_lookup_session_ipv4(struct mbuf *m0, struct in_addr dst)
    2101             : {
    2102           0 :         struct sockaddr_in sin;
    2103             : 
    2104           0 :         memset(&sin, 0, sizeof(sin));
    2105           0 :         sin.sin_len = sizeof(sin);
    2106           0 :         sin.sin_family = AF_INET;
    2107           0 :         sin.sin_addr = dst;
    2108             : 
    2109           0 :         return pipex_l2tp_userland_lookup_session(m0, sintosa(&sin));
    2110           0 : }
    2111             : 
    2112             : #ifdef INET6
    2113             : struct pipex_session *
    2114           0 : pipex_l2tp_userland_lookup_session_ipv6(struct mbuf *m0, struct in6_addr dst)
    2115             : {
    2116           0 :         struct sockaddr_in6 sin6;
    2117             : 
    2118           0 :         memset(&sin6, 0, sizeof(sin6));
    2119           0 :         sin6.sin6_len = sizeof(sin6);
    2120           0 :         sin6.sin6_family = AF_INET6;
    2121           0 :         in6_recoverscope(&sin6, &dst);
    2122             : 
    2123           0 :         return pipex_l2tp_userland_lookup_session(m0, sin6tosa(&sin6));
    2124           0 : }
    2125             : #endif
    2126             : 
    2127             : struct pipex_session *
    2128           0 : pipex_l2tp_userland_lookup_session(struct mbuf *m0, struct sockaddr *sa)
    2129             : {
    2130           0 :         struct pipex_l2tp_header l2tp;
    2131             :         struct pipex_hash_head *list;
    2132             :         struct pipex_session *session;
    2133             :         uint16_t session_id, tunnel_id, flags;
    2134             : 
    2135           0 :         if (sa->sa_family != AF_INET && sa->sa_family != AF_INET6)
    2136           0 :                 return (NULL);
    2137             : 
    2138             :         /* pullup */
    2139           0 :         if (m0->m_pkthdr.len < sizeof(l2tp)) {
    2140             :                 PIPEX_DBG((NULL, LOG_DEBUG,
    2141             :                     "<%s> packet length is too short", __func__));
    2142           0 :                 return (NULL);
    2143             :         }
    2144             : 
    2145             :         /* get flags */
    2146           0 :         m_copydata(m0, 0, sizeof(l2tp), (caddr_t)&l2tp);
    2147           0 :         flags = ntohs(l2tp.flagsver);
    2148             : 
    2149             :         /* l2tp version must be '2' */
    2150           0 :         if ((flags & PIPEX_L2TP_VER_MASK) != PIPEX_L2TP_VER) {
    2151             :                 PIPEX_DBG((NULL, LOG_DEBUG,
    2152             :                     "<%s> l2tp header wrong version.", __func__));
    2153           0 :                 return (NULL);
    2154             :         }
    2155             :         /* We need L2TP data messages only */
    2156           0 :         if ((flags & PIPEX_L2TP_FLAG_TYPE) != 0)
    2157           0 :                 return (NULL);
    2158             :         /* No need to hook packets that don't have the sequence field */
    2159           0 :         if ((flags & PIPEX_L2TP_FLAG_SEQUENCE) == 0)
    2160           0 :                 return (NULL);
    2161             : 
    2162           0 :         session_id = ntohs(l2tp.session_id);
    2163           0 :         tunnel_id = ntohs(l2tp.tunnel_id);
    2164             : 
    2165           0 :         list = PIPEX_PEER_ADDR_HASHTABLE(pipex_sockaddr_hash_key(sa));
    2166           0 :         LIST_FOREACH(session, list, peer_addr_chain) {
    2167           0 :                 if (pipex_sockaddr_compar_addr(&session->peer.sa, sa) != 0)
    2168             :                         continue;
    2169           0 :                 if (session->proto.l2tp.peer_tunnel_id != tunnel_id)
    2170             :                         continue;
    2171           0 :                 if (session->peer_session_id == session_id)
    2172             :                         break;
    2173             :         }
    2174             : #ifdef PIPEX_DEBUG
    2175             :         if (session == NULL) {
    2176             :                 PIPEX_DBG((NULL, LOG_DEBUG, "<%s> session not found "
    2177             :                     "(tunnel_id=%d, session_id=%d)", __func__,
    2178             :                     tunnel_id, session_id));
    2179             :         }
    2180             : #endif
    2181             : 
    2182           0 :         return (session);
    2183           0 : }
    2184             : 
    2185             : struct mbuf *
    2186           0 : pipex_l2tp_userland_output(struct mbuf *m0, struct pipex_session *session)
    2187             : {
    2188             :         struct pipex_l2tp_header *l2tp;
    2189             :         struct pipex_l2tp_seq_header *seq;
    2190             :         uint16_t ns, nr;
    2191             : 
    2192             :         /* check length */
    2193           0 :         PIPEX_PULLUP(m0, sizeof(struct pipex_l2tp_header) +
    2194             :             sizeof(struct pipex_l2tp_seq_header));
    2195           0 :         if (m0 == NULL)
    2196           0 :                 return (NULL);
    2197             : 
    2198           0 :         l2tp = mtod(m0, struct pipex_l2tp_header *);
    2199           0 :         KASSERT(ntohs(l2tp->flagsver) & PIPEX_L2TP_FLAG_SEQUENCE);
    2200             : 
    2201             :         /*
    2202             :          * overwrite sequence numbers to adjust a gap between pipex and
    2203             :          * userland.
    2204             :          */
    2205           0 :                 seq = (struct pipex_l2tp_seq_header *)(l2tp + 1);
    2206           0 :                 ns = ntohs(seq->ns);
    2207           0 :                 nr = ntohs(seq->nr);
    2208             : 
    2209           0 :                 ns += session->proto.l2tp.ns_gap;
    2210           0 :                 seq->ns = htons(ns);
    2211           0 :                 session->proto.l2tp.ns_nxt++;
    2212             : 
    2213           0 :                 nr += session->proto.l2tp.nr_gap;
    2214           0 :                 seq->nr = htons(nr);
    2215           0 :                 if (SEQ16_GT(nr, session->proto.l2tp.nr_acked))
    2216           0 :                         session->proto.l2tp.nr_acked = nr;
    2217             : 
    2218           0 :         return (m0);
    2219           0 : }
    2220             : #endif /* PIPEX_L2TP */
    2221             : 
    2222             : #ifdef PIPEX_MPPE
    2223             : /**********************************************************************
    2224             :  * MPPE
    2225             :  ***********************************************************************/
    2226             : #define PIPEX_COHERENCY_CNT_MASK                0x0fff
    2227             : Static void
    2228           0 : pipex_mppe_init(struct pipex_mppe *mppe, int stateless, int keylenbits,
    2229             :     u_char *master_key, int has_oldkey)
    2230             : {
    2231           0 :         memset(mppe, 0, sizeof(struct pipex_mppe));
    2232           0 :         if (stateless)
    2233           0 :                 mppe->stateless = 1;
    2234           0 :         if (has_oldkey)
    2235           0 :                 mppe->old_session_keys =
    2236           0 :                     pool_get(&mppe_key_pool, PR_WAITOK);
    2237             :         else
    2238           0 :                 mppe->old_session_keys = NULL;
    2239           0 :         memcpy(mppe->master_key, master_key, sizeof(mppe->master_key));
    2240             : 
    2241           0 :         mppe->keylenbits = keylenbits;
    2242           0 :         switch (keylenbits) {
    2243             :         case 40:
    2244             :         case 56:
    2245           0 :                 mppe->keylen = 8;
    2246           0 :                 break;
    2247             :         case 128:
    2248           0 :                 mppe->keylen = 16;
    2249           0 :                 break;
    2250             :         }
    2251             : 
    2252           0 :         GetNewKeyFromSHA(mppe->master_key, mppe->master_key, mppe->keylen,
    2253           0 :             mppe->session_key);
    2254           0 :         pipex_mppe_reduce_key(mppe);
    2255           0 :         pipex_mppe_setkey(mppe);
    2256           0 : }
    2257             : 
    2258             : void
    2259           0 : pipex_session_init_mppe_recv(struct pipex_session *session, int stateless,
    2260             :     int keylenbits, u_char *master_key)
    2261             : {
    2262           0 :         pipex_mppe_init(&session->mppe_recv, stateless, keylenbits,
    2263             :             master_key, stateless);
    2264           0 :         session->ppp_flags |= PIPEX_PPP_MPPE_ACCEPTED;
    2265           0 : }
    2266             : 
    2267             : void
    2268           0 : pipex_session_init_mppe_send(struct pipex_session *session, int stateless,
    2269             :     int keylenbits, u_char *master_key)
    2270             : {
    2271           0 :         pipex_mppe_init(&session->mppe_send, stateless, keylenbits,
    2272             :             master_key, 0);
    2273           0 :         session->ppp_flags |= PIPEX_PPP_MPPE_ENABLED;
    2274           0 : }
    2275             : 
    2276             : #include <crypto/sha1.h>
    2277             : 
    2278             : static u_char SHAPad1[] = {
    2279             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    2280             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    2281             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    2282             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    2283             :         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    2284             : }, SHAPad2[] = {
    2285             :         0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
    2286             :         0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
    2287             :         0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
    2288             :         0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
    2289             :         0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
    2290             : };
    2291             : 
    2292             : Static void
    2293           0 : GetNewKeyFromSHA(u_char *StartKey, u_char *SessionKey, int SessionKeyLength,
    2294             :     u_char *InterimKey)
    2295             : {
    2296           0 :         u_char Digest[20];
    2297           0 :         SHA1_CTX Context;
    2298             : 
    2299           0 :         SHA1Init(&Context);
    2300           0 :         SHA1Update(&Context, StartKey, SessionKeyLength);
    2301           0 :         SHA1Update(&Context, SHAPad1, 40);
    2302           0 :         SHA1Update(&Context, SessionKey, SessionKeyLength);
    2303           0 :         SHA1Update(&Context, SHAPad2, 40);
    2304           0 :         SHA1Final(Digest, &Context);
    2305             : 
    2306           0 :         memcpy(InterimKey, Digest, SessionKeyLength);
    2307           0 : }
    2308             : 
    2309             : Static void
    2310           0 : pipex_mppe_reduce_key(struct pipex_mppe *mppe)
    2311             : {
    2312           0 :         switch (mppe->keylenbits) {
    2313             :         case 40:
    2314           0 :                 mppe->session_key[0] = 0xd1;
    2315           0 :                 mppe->session_key[1] = 0x26;
    2316           0 :                 mppe->session_key[2] = 0x9e;
    2317           0 :                 break;
    2318             :         case 56:
    2319           0 :                 mppe->session_key[0] = 0xd1;
    2320           0 :                 break;
    2321             :         }
    2322           0 : }
    2323             : 
    2324             : Static void
    2325           0 : mppe_key_change(struct pipex_mppe *mppe)
    2326             : {
    2327           0 :         u_char interim[16];
    2328           0 :         struct rc4_ctx keychg;
    2329             : 
    2330           0 :         memset(&keychg, 0, sizeof(keychg));
    2331             : 
    2332           0 :         GetNewKeyFromSHA(mppe->master_key, mppe->session_key, mppe->keylen,
    2333           0 :             interim);
    2334             : 
    2335           0 :         rc4_keysetup(&keychg, interim, mppe->keylen);
    2336           0 :         rc4_crypt(&keychg, interim, mppe->session_key, mppe->keylen);
    2337             : 
    2338           0 :         pipex_mppe_reduce_key(mppe);
    2339             : 
    2340           0 :         if (mppe->old_session_keys) {
    2341           0 :                 int idx = mppe->coher_cnt & PIPEX_MPPE_OLDKEYMASK;
    2342           0 :                 memcpy(mppe->old_session_keys[idx],
    2343             :                     mppe->session_key, PIPEX_MPPE_KEYLEN);
    2344           0 :         }
    2345           0 : }
    2346             : 
    2347             : Static void
    2348           0 : pipex_mppe_input(struct mbuf *m0, struct pipex_session *session)
    2349             : {
    2350             :         int pktloss, encrypt, flushed, m, n, len;
    2351             :         struct pipex_mppe *mppe;
    2352             :         uint16_t coher_cnt;
    2353             :         struct mbuf *m1;
    2354             :         u_char *cp;
    2355             :         int rewind = 0;
    2356             : 
    2357             :         /* pullup */
    2358           0 :         PIPEX_PULLUP(m0, sizeof(coher_cnt));
    2359           0 :         if (m0 == NULL)
    2360             :                 goto drop;
    2361             : 
    2362           0 :         mppe = &session->mppe_recv;
    2363             :         /* get header information */
    2364           0 :         cp = mtod(m0, u_char *);
    2365           0 :         GETSHORT(coher_cnt, cp);
    2366           0 :         flushed = ((coher_cnt & 0x8000) != 0) ? 1 : 0;
    2367           0 :         encrypt = ((coher_cnt & 0x1000) != 0) ? 1 : 0;
    2368           0 :         coher_cnt &= PIPEX_COHERENCY_CNT_MASK;
    2369             :         pktloss = 0;
    2370             : 
    2371             :         PIPEX_MPPE_DBG((session, LOG_DEBUG, "in coher_cnt=%03x %s%s",
    2372             :             mppe->coher_cnt, (flushed) ? "[flushed]" : "",
    2373             :             (encrypt) ? "[encrypt]" : ""));
    2374             : 
    2375           0 :         if (encrypt == 0) {
    2376           0 :                 pipex_session_log(session, LOG_DEBUG,
    2377             :                     "Received unexpected MPPE packet.(no ecrypt)");
    2378           0 :                 goto drop;
    2379             :         }
    2380             : 
    2381             :         /* adjust mbuf */
    2382           0 :         m_adj(m0, sizeof(coher_cnt));
    2383             : 
    2384             :         /*
    2385             :          * L2TP data session may be used without sequencing, PPP frames may
    2386             :          * arrive in disorder.  The 'coherency counter' of MPPE detects such
    2387             :          * situations, but we cannot distinguish between 'disorder' and
    2388             :          * 'packet loss' exactly.
    2389             :          *
    2390             :          * When 'coherency counter' detects lost packets greater than
    2391             :          * (4096 - 256), we treat as 'disorder' otherwise treat as
    2392             :          * 'packet loss'.
    2393             :          */
    2394             :     {
    2395             :         int coher_cnt0;
    2396             : 
    2397           0 :         coher_cnt0 = coher_cnt;
    2398           0 :         if (coher_cnt < mppe->coher_cnt)
    2399           0 :                 coher_cnt0 += 0x1000;
    2400           0 :         if (coher_cnt0 - mppe->coher_cnt > 0x0f00) {
    2401           0 :                 if (!mppe->stateless ||
    2402             :                     coher_cnt0 - mppe->coher_cnt
    2403           0 :                     <= 0x1000 - PIPEX_MPPE_NOLDKEY) {
    2404           0 :                         pipex_session_log(session, LOG_DEBUG,
    2405             :                             "Workaround the out-of-sequence PPP framing problem: "
    2406           0 :                             "%d => %d", mppe->coher_cnt, coher_cnt);
    2407           0 :                         goto drop;
    2408             :                 }
    2409             :                 rewind = 1;
    2410           0 :         }
    2411           0 :     }
    2412             : 
    2413           0 :         if (mppe->stateless != 0) {
    2414           0 :                 if (!rewind) {
    2415           0 :                         mppe_key_change(mppe);
    2416           0 :                         while (mppe->coher_cnt != coher_cnt) {
    2417           0 :                                 mppe->coher_cnt++;
    2418           0 :                                 mppe->coher_cnt &= PIPEX_COHERENCY_CNT_MASK;
    2419           0 :                                 mppe_key_change(mppe);
    2420           0 :                                 pktloss++;
    2421             :                         }
    2422             :                 }
    2423           0 :                 pipex_mppe_setoldkey(mppe, coher_cnt);
    2424           0 :         } else {
    2425           0 :                 if (flushed) {
    2426           0 :                         if (coher_cnt < mppe->coher_cnt) {
    2427           0 :                                 coher_cnt += 0x1000;
    2428           0 :                         }
    2429           0 :                         pktloss += coher_cnt - mppe->coher_cnt;
    2430           0 :                         m = mppe->coher_cnt / 256;
    2431           0 :                         n = coher_cnt / 256;
    2432           0 :                         while (m++ < n)
    2433           0 :                                 mppe_key_change(mppe);
    2434             : 
    2435           0 :                         coher_cnt &= PIPEX_COHERENCY_CNT_MASK;
    2436           0 :                         mppe->coher_cnt = coher_cnt;
    2437           0 :                 } else if (mppe->coher_cnt != coher_cnt) {
    2438             :                         /* Send CCP ResetReq */
    2439             :                         PIPEX_DBG((session, LOG_DEBUG, "CCP SendResetReq"));
    2440           0 :                         pipex_ccp_output(session, CCP_RESETREQ,
    2441           0 :                             session->ccp_id++);
    2442           0 :                         goto drop;
    2443             :                 }
    2444           0 :                 if ((coher_cnt & 0xff) == 0xff) {
    2445           0 :                         mppe_key_change(mppe);
    2446             :                         flushed = 1;
    2447           0 :                 }
    2448           0 :                 if (flushed)
    2449           0 :                         pipex_mppe_setkey(mppe);
    2450             :         }
    2451             : 
    2452           0 :         if (pktloss > 1000) {
    2453           0 :                 pipex_session_log(session, LOG_DEBUG,
    2454             :                     "%d packets loss.", pktloss);
    2455           0 :         }
    2456             : 
    2457             :         /* decrypt ppp payload */
    2458           0 :         for (m1 = m0; m1; m1 = m1->m_next) {
    2459           0 :                 cp = mtod(m1, u_char *);
    2460           0 :                 len = m1->m_len;
    2461           0 :                 pipex_mppe_crypt(mppe, len, cp, cp);
    2462             :         }
    2463             : 
    2464           0 :         if (!rewind) {
    2465             :                 /* update coher_cnt */
    2466           0 :                 mppe->coher_cnt++;
    2467           0 :                 mppe->coher_cnt &= PIPEX_COHERENCY_CNT_MASK;
    2468           0 :         }
    2469           0 :         if (m0->m_pkthdr.len < PIPEX_PPPMINLEN)
    2470             :                 goto drop;
    2471             : 
    2472           0 :         pipex_ppp_input(m0, session, 1);
    2473             : 
    2474           0 :         return;
    2475             : drop:
    2476           0 :         m_freem(m0);
    2477           0 :         session->stat.ierrors++;
    2478           0 : }
    2479             : 
    2480             : Static void
    2481           0 : pipex_mppe_output(struct mbuf *m0, struct pipex_session *session,
    2482             :     uint16_t protocol)
    2483             : {
    2484             :         int encrypt, flushed, len;
    2485             :         struct mppe_header {
    2486             :                 uint16_t coher_cnt;
    2487             :                 uint16_t protocol;
    2488             :         } __packed *hdr;
    2489             :         u_char *cp;
    2490             :         struct pipex_mppe *mppe;
    2491             :         struct mbuf *m;
    2492             : 
    2493           0 :         mppe = &session->mppe_send;
    2494             : 
    2495             :         /*
    2496             :          * create a deep-copy if the mbuf has a shared mbuf cluster.
    2497             :          * this is required to handle cases of tcp retransmition.
    2498             :          */
    2499           0 :         for (m = m0; m != NULL; m = m->m_next) {
    2500           0 :                 if (M_READONLY(m)) {
    2501           0 :                         m = m_dup_pkt(m0, max_linkhdr, M_NOWAIT);
    2502           0 :                         m_freem(m0);
    2503           0 :                         if (m == NULL)
    2504             :                                 goto drop;
    2505             :                         m0 = m;
    2506           0 :                         break;
    2507             :                 }
    2508             :         }
    2509             :         /* prepend mppe header */
    2510           0 :         M_PREPEND(m0, sizeof(struct mppe_header), M_NOWAIT);
    2511           0 :         if (m0 == NULL)
    2512             :                 goto drop;
    2513           0 :         hdr = mtod(m0, struct mppe_header *);
    2514           0 :         hdr->protocol = protocol;
    2515             : 
    2516             :         /* check coherency counter */
    2517             :         flushed = 0;
    2518             :         encrypt = 1;
    2519             : 
    2520           0 :         if (mppe->stateless != 0) {
    2521             :                 flushed = 1;
    2522           0 :                 mppe_key_change(mppe);
    2523           0 :         } else {
    2524           0 :                 if ((mppe->coher_cnt % 0x100) == 0xff) {
    2525             :                         flushed = 1;
    2526           0 :                         mppe_key_change(mppe);
    2527           0 :                 } else if (mppe->resetreq != 0) {
    2528             :                         flushed = 1;
    2529           0 :                         mppe->resetreq = 0;
    2530           0 :                 }
    2531             :         }
    2532             : 
    2533           0 :         if (flushed)
    2534           0 :                 pipex_mppe_setkey(mppe);
    2535             : 
    2536             :         PIPEX_MPPE_DBG((session, LOG_DEBUG, "out coher_cnt=%03x %s%s",
    2537             :             mppe->coher_cnt, (flushed) ? "[flushed]" : "",
    2538             :             (encrypt) ? "[encrypt]" : ""));
    2539             : 
    2540             :         /* setup header information */
    2541           0 :         hdr->coher_cnt = (mppe->coher_cnt++) & PIPEX_COHERENCY_CNT_MASK;
    2542           0 :         hdr->coher_cnt &= PIPEX_COHERENCY_CNT_MASK;
    2543           0 :         if (flushed)
    2544           0 :                 hdr->coher_cnt |= 0x8000;
    2545           0 :         if (encrypt)
    2546           0 :                 hdr->coher_cnt |= 0x1000;
    2547             : 
    2548           0 :         hdr->protocol = htons(hdr->protocol);
    2549           0 :         hdr->coher_cnt = htons(hdr->coher_cnt);
    2550             : 
    2551             :         /* encrypt chain */
    2552           0 :         for (m = m0; m; m = m->m_next) {
    2553           0 :                 cp = mtod(m, u_char *);
    2554           0 :                 len = m->m_len;
    2555           0 :                 if (m == m0 && len > offsetof(struct mppe_header, protocol)) {
    2556           0 :                         len -= offsetof(struct mppe_header, protocol);
    2557           0 :                         cp += offsetof(struct mppe_header, protocol);
    2558           0 :                 }
    2559           0 :                 pipex_mppe_crypt(mppe, len, cp, cp);
    2560             :         }
    2561             : 
    2562           0 :         pipex_ppp_output(m0, session, PPP_COMP);
    2563             : 
    2564           0 :         return;
    2565             : drop:
    2566           0 :         session->stat.oerrors++;
    2567           0 : }
    2568             : 
    2569             : Static void
    2570           0 : pipex_ccp_input(struct mbuf *m0, struct pipex_session *session)
    2571             : {
    2572             :         u_char *cp;
    2573             :         int code, id, len;
    2574             : 
    2575           0 :         if (m0->m_pkthdr.len < PPP_HDRLEN)
    2576             :                 goto drop;
    2577           0 :         if ((m0 = m_pullup(m0, PPP_HDRLEN)) == NULL)
    2578             :                 goto drop;
    2579             : 
    2580           0 :         cp = mtod(m0, u_char *);
    2581           0 :         GETCHAR(code, cp);
    2582           0 :         GETCHAR(id, cp);
    2583           0 :         GETSHORT(len, cp);
    2584             : 
    2585           0 :         switch (code) {
    2586             :         case CCP_RESETREQ:
    2587             :                 PIPEX_DBG((session, LOG_DEBUG, "CCP RecvResetReq"));
    2588           0 :                 session->mppe_send.resetreq = 1;
    2589             : #ifndef PIPEX_NO_CCP_RESETACK
    2590             :                 PIPEX_DBG((session, LOG_DEBUG, "CCP SendResetAck"));
    2591             :                 pipex_ccp_output(session, CCP_RESETACK, id);
    2592             : #endif
    2593             :                 /* ignore error */
    2594           0 :                 break;
    2595             :         case CCP_RESETACK:
    2596             :                 PIPEX_DBG((session, LOG_DEBUG, "CCP RecvResetAck"));
    2597             :                 break;
    2598             :         default:
    2599             :                 PIPEX_DBG((session, LOG_DEBUG, "CCP Recv code=%d", code));
    2600             :                 goto drop;
    2601             :         }
    2602           0 :         m_freem(m0);
    2603             : 
    2604           0 :         return;
    2605             : drop:
    2606           0 :         m_freem(m0);
    2607           0 :         session->stat.ierrors++;
    2608           0 : }
    2609             : 
    2610             : Static int
    2611           0 : pipex_ccp_output(struct pipex_session *session, int code, int id)
    2612             : {
    2613             :         u_char *cp;
    2614             :         struct mbuf *m;
    2615             : 
    2616           0 :         MGETHDR(m, M_DONTWAIT, MT_DATA);
    2617           0 :         if (m == NULL) {
    2618           0 :                 session->stat.oerrors++;
    2619           0 :                 return (1);
    2620             :         }
    2621           0 :         m->m_pkthdr.len = m->m_len = 4;
    2622           0 :         cp = mtod(m, u_char *);
    2623           0 :         PUTCHAR(code, cp);
    2624           0 :         PUTCHAR(id, cp);
    2625           0 :         PUTSHORT(4, cp);
    2626             : 
    2627           0 :         pipex_ppp_output(m, session, PPP_CCP);
    2628             : 
    2629           0 :         return (0);
    2630           0 : }
    2631             : #endif
    2632             : /***********************************************************************
    2633             :  * Miscellaneous fuctions
    2634             :  ***********************************************************************/
    2635             : /* adapted from FreeBSD:src/usr.sbin/ppp/tcpmss.c */
    2636             : /*
    2637             :  * Copyright (c) 2000 Ruslan Ermilov and Brian Somers <brian@Awfulhak.org>
    2638             :  * All rights reserved.
    2639             :  *
    2640             :  * Redistribution and use in source and binary forms, with or without
    2641             :  * modification, are permitted provided that the following conditions
    2642             :  * are met:
    2643             :  * 1. Redistributions of source code must retain the above copyright
    2644             :  *    notice, this list of conditions and the following disclaimer.
    2645             :  * 2. Redistributions in binary form must reproduce the above copyright
    2646             :  *    notice, this list of conditions and the following disclaimer in the
    2647             :  *    documentation and/or other materials provided with the distribution.
    2648             :  *
    2649             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
    2650             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    2651             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    2652             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
    2653             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    2654             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    2655             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    2656             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    2657             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    2658             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    2659             :  * SUCH DAMAGE.
    2660             :  *
    2661             :  * $FreeBSD: src/usr.sbin/ppp/tcpmss.c,v 1.1.4.3 2001/07/19 11:39:54 brian Exp $
    2662             :  */
    2663             : #define TCP_OPTLEN_IN_SEGMENT   12      /* timestamp option and padding */
    2664             : #define MAXMSS(mtu) (mtu - sizeof(struct ip) - sizeof(struct tcphdr) - \
    2665             :     TCP_OPTLEN_IN_SEGMENT)
    2666             : /*
    2667             :  * The following macro is used to update an internet checksum.  "acc" is a
    2668             :  * 32-bit accumulation of all the changes to the checksum (adding in old
    2669             :  * 16-bit words and subtracting out new words), and "cksum" is the checksum
    2670             :  * value to be updated.
    2671             :  */
    2672             : #define ADJUST_CHECKSUM(acc, cksum) {                   \
    2673             :         acc += cksum;                                   \
    2674             :         if (acc < 0) {                                       \
    2675             :                 acc = -acc;                             \
    2676             :                 acc = (acc >> 16) + (acc & 0xffff);   \
    2677             :                 acc += acc >> 16;                 \
    2678             :                 cksum = (u_short) ~acc;                 \
    2679             :         } else {                                        \
    2680             :                 acc = (acc >> 16) + (acc & 0xffff);   \
    2681             :                 acc += acc >> 16;                 \
    2682             :                 cksum = (u_short) acc;                  \
    2683             :         }                                               \
    2684             : }
    2685             : 
    2686             : /*
    2687             :  * Rewrite max-segment-size TCP option to avoid PMTU blackhole issues.
    2688             :  * The mtu parameter should be the MTU bottleneck (as far as we know)
    2689             :  * on the link between the source and the destination.
    2690             :  */
    2691             : Static struct mbuf *
    2692           0 : adjust_tcp_mss(struct mbuf *m0, int mtu)
    2693             : {
    2694             :         int opt, optlen, acc, mss, maxmss, lpktp;
    2695             :         struct ip *pip;
    2696             :         struct tcphdr *th;
    2697             :         u_char *pktp, *mssp;
    2698             :         u_int16_t ip_off;
    2699             : 
    2700             :         lpktp = sizeof(struct ip) + sizeof(struct tcphdr) + PIPEX_TCP_OPTLEN;
    2701           0 :         lpktp = MIN(lpktp, m0->m_pkthdr.len);
    2702             : 
    2703           0 :         PIPEX_PULLUP(m0, lpktp);
    2704           0 :         if (m0 == NULL)
    2705             :                 goto drop;
    2706             : 
    2707           0 :         pktp = mtod(m0, char *);
    2708           0 :         pip = (struct ip *)pktp;
    2709           0 :         ip_off = ntohs(pip->ip_off);
    2710             : 
    2711             :         /* Non TCP or fragmented packet must not have a MSS option */
    2712           0 :         if (pip->ip_p != IPPROTO_TCP ||
    2713           0 :             (ip_off & IP_MF) != 0 || (ip_off & IP_OFFMASK) != 0)
    2714             :                 goto handled;
    2715             : 
    2716           0 :         pktp += pip->ip_hl << 2;
    2717           0 :         lpktp -= pip->ip_hl << 2;
    2718             : 
    2719             :         /* packet is broken */
    2720           0 :         if (sizeof(struct tcphdr) > lpktp)
    2721             :                 goto drop;
    2722           0 :         th = (struct tcphdr *)pktp;
    2723             : 
    2724             :         /*
    2725             :          * As RFC 973, a MSS field must only be sent in the initial
    2726             :          * connection request(it must be with SYN).
    2727             :          */
    2728           0 :         if ((th->th_flags & TH_SYN) == 0)
    2729             :                 goto handled;
    2730             : 
    2731           0 :         lpktp = MIN(th->th_off << 4, lpktp);
    2732             : 
    2733           0 :         pktp += sizeof(struct tcphdr);
    2734           0 :         lpktp -= sizeof(struct tcphdr);
    2735           0 :         while (lpktp >= TCPOLEN_MAXSEG) {
    2736           0 :                 GETCHAR(opt, pktp);
    2737           0 :                 switch (opt) {
    2738             :                 case TCPOPT_MAXSEG:
    2739           0 :                         GETCHAR(optlen, pktp);
    2740             :                         mssp = pktp;            /* mss place holder */
    2741           0 :                         GETSHORT(mss, pktp);
    2742           0 :                         maxmss = MAXMSS(mtu);
    2743           0 :                         if (mss > maxmss) {
    2744             :                                 PIPEX_DBG((NULL, LOG_DEBUG,
    2745             :                                     "change tcp-mss %d => %d", mss, maxmss));
    2746           0 :                                 PUTSHORT(maxmss, mssp);
    2747           0 :                                 acc = htons(mss);
    2748           0 :                                 acc -= htons(maxmss);
    2749           0 :                                 ADJUST_CHECKSUM(acc, th->th_sum);
    2750             :                         }
    2751             :                         goto handled;
    2752             :                         /* NOTREACHED */
    2753             :                 case TCPOPT_EOL:
    2754             :                         goto handled;
    2755             :                         /* NOTREACHED */
    2756             :                 case TCPOPT_NOP:
    2757           0 :                         lpktp--;
    2758           0 :                         break;
    2759             :                 default:
    2760           0 :                         GETCHAR(optlen, pktp);
    2761           0 :                         if (optlen < 2)      /* packet is broken */
    2762             :                                 goto drop;
    2763           0 :                         pktp += optlen - 2;
    2764           0 :                         lpktp -= optlen;
    2765           0 :                         break;
    2766             :                 }
    2767             :         }
    2768             : 
    2769             : handled:
    2770           0 :         return (m0);
    2771             : 
    2772             : drop:
    2773           0 :         m_freem(m0);
    2774           0 :         return (NULL);
    2775           0 : }
    2776             : 
    2777             : /*
    2778             :  *  Check whether a packet should reset idle timer
    2779             :  *  Returns 1 to don't reset timer (i.e. the packet is "idle" packet)
    2780             :  */
    2781             : Static struct mbuf *
    2782           0 : ip_is_idle_packet(struct mbuf *m0, int *ris_idle)
    2783             : {
    2784             :         u_int16_t ip_off;
    2785             :         const struct udphdr *uh;
    2786             :         struct ip *pip;
    2787             :         int len;
    2788             : 
    2789             :         /* pullup ip header */
    2790             :         len = sizeof(struct ip);
    2791           0 :         PIPEX_PULLUP(m0, len);
    2792           0 :         if (m0 == NULL)
    2793             :                 goto error;
    2794           0 :         pip = mtod(m0, struct ip *);
    2795             : 
    2796             :         /*
    2797             :          * the packet which fragmentations was not the idle packet.
    2798             :          */
    2799           0 :         ip_off = ntohs(pip->ip_off);
    2800           0 :         if ((ip_off & IP_MF) || ((ip_off & IP_OFFMASK) != 0))
    2801             :                 goto is_active;
    2802             : 
    2803           0 :         switch (pip->ip_p) {
    2804             :         case IPPROTO_IGMP:
    2805             :                 goto is_active;
    2806             :         case IPPROTO_ICMP:
    2807           0 :                 len = pip->ip_hl * 4 + 8;
    2808           0 :                 PIPEX_PULLUP(m0, len);
    2809           0 :                 if (m0 == NULL)
    2810             :                         goto error;
    2811           0 :                 pip = mtod(m0, struct ip *);
    2812             : 
    2813           0 :                 switch (((unsigned char *) pip)[pip->ip_hl * 4]) {
    2814             :                 case 0: /* Echo Reply */
    2815             :                 case 8: /* Echo Request */
    2816             :                         goto is_active;
    2817             :                 default:
    2818             :                         goto is_idle;
    2819             :                 }
    2820             : 
    2821             :         case IPPROTO_UDP:
    2822             :         case IPPROTO_TCP:
    2823           0 :                 len = pip->ip_hl * 4 + sizeof(struct udphdr);
    2824           0 :                 PIPEX_PULLUP(m0, len);
    2825           0 :                 if (m0 == NULL)
    2826             :                         goto error;
    2827           0 :                 pip = mtod(m0, struct ip *);
    2828           0 :                 uh = (struct udphdr *)(mtod(m0, caddr_t) + pip->ip_hl * 4);
    2829             : 
    2830           0 :                 switch (ntohs(uh->uh_sport)) {
    2831             :                 case 53:        /* DOMAIN */
    2832             :                 case 67:        /* BOOTPS */
    2833             :                 case 68:        /* BOOTPC */
    2834             :                 case 123:       /* NTP */
    2835             :                 case 137:       /* NETBIOS-NS */
    2836             :                 case 520:       /* RIP */
    2837             :                         goto is_idle;
    2838             :                 }
    2839           0 :                 switch (ntohs(uh->uh_dport)) {
    2840             :                 case 53:        /* DOMAIN */
    2841             :                 case 67:        /* BOOTPS */
    2842             :                 case 68:        /* BOOTPC */
    2843             :                 case 123:       /* NTP */
    2844             :                 case 137:       /* NETBIOS-NS */
    2845             :                 case 520:       /* RIP */
    2846             :                         goto is_idle;
    2847             :                 }
    2848             :                 goto is_active;
    2849             :         default:
    2850             :                 goto is_active;
    2851             :         }
    2852             : 
    2853             : is_active:
    2854           0 :         *ris_idle = 0;
    2855           0 :         return (m0);
    2856             : 
    2857             : is_idle:
    2858           0 :         *ris_idle = 1;
    2859           0 :         return (m0);
    2860             : 
    2861             : error:
    2862           0 :         return (NULL);
    2863           0 : }
    2864             : 
    2865             : Static void
    2866           0 : pipex_session_log(struct pipex_session *session, int prio, const char *fmt, ...)
    2867             : {
    2868           0 :         char logbuf[1024];
    2869           0 :         va_list ap;
    2870             : 
    2871           0 :         logpri(prio);
    2872           0 :         if (session != NULL) {
    2873           0 :                 addlog("pipex: ppp=%d iface=%s protocol=%s id=%d ",
    2874           0 :                     session->ppp_id, session->pipex_iface->ifnet_this->if_xname,
    2875           0 :                     (session->protocol == PIPEX_PROTO_PPPOE)? "PPPoE" :
    2876           0 :                     (session->protocol == PIPEX_PROTO_PPTP)? "PPTP" :
    2877           0 :                     (session->protocol == PIPEX_PROTO_L2TP) ? "L2TP" :
    2878           0 :                     "Unknown", session->session_id);
    2879           0 :         } else
    2880           0 :                 addlog("pipex: ");
    2881             : 
    2882           0 :         va_start(ap, fmt);
    2883           0 :         vsnprintf(logbuf, sizeof(logbuf), fmt, ap);
    2884           0 :         va_end(ap);
    2885           0 :         addlog("%s\n", logbuf);
    2886           0 : }
    2887             : 
    2888             : Static uint32_t
    2889           0 : pipex_sockaddr_hash_key(struct sockaddr *sa)
    2890             : {
    2891           0 :         switch (sa->sa_family) {
    2892             :         case AF_INET:
    2893           0 :                 return ntohl(satosin(sa)->sin_addr.s_addr);
    2894             :         case AF_INET6:
    2895           0 :                 return ntohl(satosin6(sa)->sin6_addr.s6_addr32[3]);
    2896             :         }
    2897           0 :         panic("pipex_sockaddr_hash_key: unknown address family");
    2898             :         return (0);
    2899           0 : }
    2900             : 
    2901             : /*
    2902             :  * Compare struct sockaddr_in{,6} with the address only.
    2903             :  * The port number is not covered.
    2904             :  */
    2905             : Static int
    2906           0 : pipex_sockaddr_compar_addr(struct sockaddr *a, struct sockaddr *b)
    2907             : {
    2908             :         int cmp;
    2909             : 
    2910           0 :         cmp = b->sa_family - a->sa_family;
    2911           0 :         if (cmp != 0)
    2912           0 :                 return cmp;
    2913           0 :         switch (a->sa_family) {
    2914             :         case AF_INET:
    2915           0 :                 return (satosin(b)->sin_addr.s_addr -
    2916           0 :                     satosin(a)->sin_addr.s_addr);
    2917             :         case AF_INET6:
    2918           0 :                 cmp = (satosin6(b)->sin6_scope_id - satosin6(a)->sin6_scope_id);
    2919           0 :                 if (cmp != 0)
    2920           0 :                         return cmp;
    2921           0 :                 return (memcmp(&satosin6(a)->sin6_addr,
    2922             :                     &satosin6(b)->sin6_addr,
    2923             :                     sizeof(struct in6_addr)));
    2924             :         }
    2925           0 :         panic("pipex_sockaddr_compar_addr: unknown address family");
    2926             : 
    2927             :         return (-1);
    2928           0 : }
    2929             : 
    2930             : Static inline int
    2931           0 : pipex_mppe_setkey(struct pipex_mppe *mppe)
    2932             : {
    2933           0 :         rc4_keysetup(&mppe->rc4ctx, mppe->session_key, mppe->keylen);
    2934             : 
    2935           0 :         return (0);
    2936             : }
    2937             : 
    2938             : Static inline int
    2939           0 : pipex_mppe_setoldkey(struct pipex_mppe *mppe, uint16_t coher_cnt)
    2940             : {
    2941           0 :         KASSERT(mppe->old_session_keys != NULL);
    2942             : 
    2943           0 :         rc4_keysetup(&mppe->rc4ctx,
    2944           0 :             mppe->old_session_keys[coher_cnt & PIPEX_MPPE_OLDKEYMASK],
    2945           0 :             mppe->keylen);
    2946             : 
    2947           0 :         return (0);
    2948             : }
    2949             : 
    2950             : Static inline void
    2951           0 : pipex_mppe_crypt(struct pipex_mppe *mppe, int len, u_char *indata,
    2952             :     u_char *outdata)
    2953             : {
    2954           0 :         rc4_crypt(&mppe->rc4ctx, indata, outdata, len);
    2955           0 : }
    2956             : 
    2957             : int
    2958           0 : pipex_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
    2959             :     size_t newlen)
    2960             : {
    2961           0 :         switch (name[0]) {
    2962             :         case PIPEXCTL_ENABLE:
    2963           0 :                 if (namelen != 1)
    2964           0 :                         return (ENOTDIR);
    2965           0 :                 return (sysctl_int(oldp, oldlenp, newp, newlen,
    2966             :                     &pipex_enable));
    2967             :         case PIPEXCTL_INQ:
    2968           0 :                 return (sysctl_mq(name + 1, namelen - 1,
    2969             :                     oldp, oldlenp, newp, newlen, &pipexinq));
    2970             :         case PIPEXCTL_OUTQ:
    2971           0 :                 return (sysctl_mq(name + 1, namelen - 1,
    2972             :                     oldp, oldlenp, newp, newlen, &pipexoutq));
    2973             :         default:
    2974           0 :                 return (ENOPROTOOPT);
    2975             :         }
    2976             :         /* NOTREACHED */
    2977           0 : }

Generated by: LCOV version 1.13