Annotation of embedaddon/mpd/src/l2tp_ctrl.c, revision 1.1

1.1     ! misho       1: 
        !             2: /*
        !             3:  * Copyright (c) 2001-2002 Packet Design, LLC.
        !             4:  * All rights reserved.
        !             5:  * 
        !             6:  * Subject to the following obligations and disclaimer of warranty,
        !             7:  * use and redistribution of this software, in source or object code
        !             8:  * forms, with or without modifications are expressly permitted by
        !             9:  * Packet Design; provided, however, that:
        !            10:  * 
        !            11:  *    (i)  Any and all reproductions of the source or object code
        !            12:  *         must include the copyright notice above and the following
        !            13:  *         disclaimer of warranties; and
        !            14:  *    (ii) No rights are granted, in any manner or form, to use
        !            15:  *         Packet Design trademarks, including the mark "PACKET DESIGN"
        !            16:  *         on advertising, endorsements, or otherwise except as such
        !            17:  *         appears in the above copyright notice or in the software.
        !            18:  * 
        !            19:  * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
        !            20:  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
        !            21:  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
        !            22:  * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
        !            23:  * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
        !            24:  * OR NON-INFRINGEMENT.  PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
        !            25:  * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
        !            26:  * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
        !            27:  * RELIABILITY OR OTHERWISE.  IN NO EVENT SHALL PACKET DESIGN BE
        !            28:  * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
        !            29:  * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
        !            30:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
        !            31:  * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
        !            32:  * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
        !            33:  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            34:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
        !            35:  * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
        !            36:  * THE POSSIBILITY OF SUCH DAMAGE.
        !            37:  *
        !            38:  * Author: Archie Cobbs <archie@freebsd.org>
        !            39:  */
        !            40: 
        !            41: #include "ppp.h"
        !            42: #include <netgraph.h>
        !            43: #include <netgraph/ng_message.h>
        !            44: #include <netgraph/ng_socket.h>
        !            45: #include <netgraph/ng_l2tp.h>
        !            46: #include <netgraph/ng_tee.h>
        !            47: #include <openssl/md5.h>
        !            48: #include "l2tp_avp.h"
        !            49: #include "l2tp_ctrl.h"
        !            50: #include "ngfunc.h"
        !            51: 
        !            52: #ifndef __FreeBSD__
        !            53: #define __printflike(x,y)
        !            54: #endif
        !            55: 
        !            56: #define CTRL_MEM_TYPE          "ppp_l2tp_ctrl"
        !            57: #define SESS_MEM_TYPE          "ppp_l2tp_sess"
        !            58: 
        !            59: /* Retransmit timeout parameters */
        !            60: #define L2TP_REXMIT_MAX                8
        !            61: #define L2TP_REXMIT_MAX_TO     10
        !            62: 
        !            63: #define L2TP_CHALLENGE_LEN     16
        !            64: 
        !            65: #define L2TP_CONNECT_SPEED     10000000                /* XXX hardcoded */
        !            66: #define L2TP_FRAMING_TYPE      L2TP_FRAMING_SYNC       /* XXX hardcoded */
        !            67: 
        !            68: /* Idle timeout for sending 'HELLO' message */
        !            69: #define L2TP_IDLE_TIMEOUT      60
        !            70: 
        !            71: /* Reply timeout for messages */
        !            72: #define L2TP_REPLY_TIMEOUT     60
        !            73: 
        !            74: /* Linger time for dying tunnels and sessions */
        !            75: #define L2TP_CTRL_DEATH_TIMEOUT        11
        !            76: #define L2TP_SESS_DEATH_TIMEOUT        11
        !            77: 
        !            78: #define LOG_ERR                LG_ERR
        !            79: #define LOG_WARNING    LG_PHYS2
        !            80: #define LOG_NOTICE     LG_PHYS2
        !            81: #define LOG_INFO       LG_PHYS3
        !            82: #define LOG_DEBUG      LG_PHYS3
        !            83: 
        !            84: /* Control message types */
        !            85: enum l2tp_msg_type {
        !            86:        SCCRQ           =1,
        !            87:        SCCRP           =2,
        !            88:        SCCCN           =3,
        !            89:        StopCCN         =4,
        !            90:        HELLO           =6,
        !            91:        OCRQ            =7,
        !            92:        OCRP            =8,
        !            93:        OCCN            =9,
        !            94:        ICRQ            =10,
        !            95:        ICRP            =11,
        !            96:        ICCN            =12,
        !            97:        CDN             =14,
        !            98:        WEN             =15,
        !            99:        SLI             =16
        !           100: };
        !           101: 
        !           102: /* Control connection states */
        !           103: enum l2tp_ctrl_state {
        !           104:        CS_IDLE = 0,
        !           105:        CS_WAIT_CTL_REPLY,
        !           106:        CS_WAIT_CTL_CONNECT,
        !           107:        CS_ESTABLISHED,
        !           108:        CS_DYING
        !           109: };
        !           110: 
        !           111: /* Session states */
        !           112: enum l2tp_sess_state {
        !           113:        SS_WAIT_REPLY = 1,
        !           114:        SS_WAIT_CONNECT,
        !           115:        SS_WAIT_ANSWER,
        !           116:        SS_ESTABLISHED,
        !           117:        SS_DYING
        !           118: };
        !           119: 
        !           120: /* Session origination */
        !           121: enum l2tp_sess_orig {
        !           122:        ORIG_LOCAL      =0,
        !           123:        ORIG_REMOTE     =1
        !           124: };
        !           125: 
        !           126: /* Session side */
        !           127: enum l2tp_sess_side {
        !           128:        SIDE_LNS        =0,
        !           129:        SIDE_LAC        =1
        !           130: };
        !           131: 
        !           132: /*
        !           133:  * Control message handler function types.
        !           134:  *
        !           135:  * Messages are either session-specific, or apply to the entire tunnel.
        !           136:  */
        !           137: typedef int    l2tp_ctrl_msg_handler_t(struct ppp_l2tp_ctrl *ctrl,
        !           138:                        const struct ppp_l2tp_avp_list *avps,
        !           139:                        struct ppp_l2tp_avp_ptrs *ptrs);
        !           140: typedef int    l2tp_sess_msg_handler_t(struct ppp_l2tp_sess *sess,
        !           141:                        const struct ppp_l2tp_avp_list *avps,
        !           142:                        struct ppp_l2tp_avp_ptrs *ptrs);
        !           143: 
        !           144: /* Descriptor for one control message */
        !           145: struct l2tp_msg_info {
        !           146:        const char              *name;
        !           147:        enum l2tp_msg_type      type;
        !           148:        l2tp_ctrl_msg_handler_t *ctrl_handler;
        !           149:        l2tp_sess_msg_handler_t *sess_handler;
        !           150:        int                     valid_states[12];
        !           151:        int                     valid_orig[3];
        !           152:        int                     valid_side[3];
        !           153:        int                     req_avps[AVP_MAX + 1];
        !           154: };
        !           155: 
        !           156: /* Control connection */
        !           157: struct ppp_l2tp_ctrl {
        !           158:        enum l2tp_ctrl_state    state;                  /* control state */
        !           159:        const struct ppp_l2tp_ctrl_cb *cb;              /* link callbacks */
        !           160:        struct pevent_ctx       *ctx;                   /* event context */
        !           161:        pthread_mutex_t         *mutex;                 /* mutex */
        !           162:        ng_ID_t                 node_id;                /* l2tp node id */
        !           163:        u_int32_t               peer_id;                /* peer unique id */
        !           164:        char                    path[32];               /* l2tp node path */
        !           165:        int                     csock;                  /* netgraph ctrl sock */
        !           166:        int                     dsock;                  /* netgraph data sock */
        !           167:        u_char                  *secret;                /* shared secret */
        !           168:        u_int                   seclen;                 /* share secret len */
        !           169:        u_char                  chal[L2TP_CHALLENGE_LEN]; /* our L2TP challenge */
        !           170:        struct ng_l2tp_config   config;                 /* netgraph node cfg. */
        !           171:        struct ghash            *sessions;              /* sessions */
        !           172:        struct ppp_l2tp_avp_list *avps;                 /* avps for SCCR[QP] */
        !           173:        struct pevent           *idle_timer;            /* ctrl idle timer */
        !           174:        struct pevent           *reply_timer;           /* reply timer */
        !           175:        struct pevent           *close_timer;           /* close timer */
        !           176:        struct pevent           *death_timer;           /* death timer */
        !           177:        struct pevent           *ctrl_event;            /* ctrl socket event */
        !           178:        struct pevent           *data_event;            /* data socket event */
        !           179:        void                    *link_cookie;           /* opaque link cookie */
        !           180:        u_int16_t               result;                 /* close result code */
        !           181:        u_int16_t               error;                  /* close error code */
        !           182:        u_int32_t               peer_bearer;            /* peer bearer types */
        !           183:        u_int32_t               peer_framing;           /* peer framing types */
        !           184:        u_int                   active_sessions;        /* # of sessns */
        !           185:        char                    *errmsg;                /* close error msg */
        !           186:        u_char                  link_notified;          /* link notified down */
        !           187:        u_char                  peer_notified;          /* peer notified down */
        !           188:        u_char                  hide_avps;              /* enable AVPs hiding */
        !           189:        char                    self_name[MAXHOSTNAMELEN]; /* L2TP local hostname */
        !           190:        char                    peer_name[MAXHOSTNAMELEN]; /* L2TP remote hostname */
        !           191: };
        !           192: 
        !           193: /* Session */
        !           194: struct ppp_l2tp_sess {
        !           195:        struct ppp_l2tp_ctrl    *ctrl;                  /* associated ctrl */
        !           196:        enum l2tp_sess_state    state;                  /* session state */
        !           197:        enum l2tp_sess_orig     orig;                   /* who originated it? */
        !           198:        enum l2tp_sess_side     side;                   /* are we lac or lns? */
        !           199:        u_int32_t               serial;                 /* call serial number */
        !           200:        struct ng_l2tp_sess_config config;              /* netgraph hook cfg. */
        !           201:        struct ppp_l2tp_avp_list *my_avps;              /* avps in [IO]CR[QP] */
        !           202:        struct ppp_l2tp_avp_list *peer_avps;            /* avps in [IO]CCN */
        !           203:        u_int16_t               session_id;             /* session id */
        !           204:        u_int16_t               peer_id;                /* peer session id */
        !           205:        ng_ID_t                 node_id;                /* tee node id */
        !           206:        char                    hook[NG_HOOKSIZ];       /* session hook name */
        !           207:        void                    *link_cookie;           /* opaque link cookie */
        !           208:        u_int16_t               result;                 /* close result code */
        !           209:        u_int16_t               error;                  /* close error code */
        !           210:        char                    *errmsg;                /* close error msg */
        !           211:        struct pevent           *reply_timer;           /* reply timer */
        !           212:        struct pevent           *notify_timer;          /* link notify timer */
        !           213:        struct pevent           *close_timer;           /* close timer */
        !           214:        struct pevent           *death_timer;           /* death timer */
        !           215:        u_char                  link_responded;         /* link notified up */
        !           216:        u_char                  peer_responded;         /* got icrp from lns */
        !           217:        u_char                  dseq_required;          /* data seq. req'd */
        !           218:        u_char                  link_notified;          /* link notified down */
        !           219:        u_char                  peer_notified;          /* peer notified down */
        !           220:        u_char                  include_length;         /* enable Length field in data packets */
        !           221:        u_char                  enable_dseq;            /* enable sequence fields in data packets */
        !           222: };
        !           223: 
        !           224: /***
        !           225: 
        !           226: Notes
        !           227: 
        !           228:     - "link_notified" means the link side has been notified that
        !           229:       the control connection or session has gone down.
        !           230:     - "peer_notified" means the peer has been notified that
        !           231:       the control connection or session has gone down.
        !           232:     - "link_responded" and "peer_responded" are only used for
        !           233:       outgoing calls when we are the LAC; they indicate acceptance
        !           234:       from the link side and the remote peer, respectively. Both
        !           235:       must be true before we send the OCCN.
        !           236:     - "sess->my_avps" are the AVP's included my ICRQ or OCRQ. In case
        !           237:       of ICRQ, these get overwritten by AVP's included in ICCN.
        !           238:     - "sess->peer_avps" are the AVPS included peer's ICCN or OCCN
        !           239: 
        !           240: ***/
        !           241: 
        !           242: /************************************************************************
        !           243:                        INTERNAL FUNCTIONS
        !           244: ************************************************************************/
        !           245: 
        !           246: static int     ppp_l2tp_ctrl_setup_1(struct ppp_l2tp_ctrl *ctrl,
        !           247:                        struct ppp_l2tp_avp_ptrs *ptrs);
        !           248: static int     ppp_l2tp_ctrl_setup_2(struct ppp_l2tp_ctrl *ctrl,
        !           249:                        struct ppp_l2tp_avp_ptrs *ptrs);
        !           250: static void    ppp_l2tp_ctrl_send(struct ppp_l2tp_ctrl *ctrl,
        !           251:                        u_int16_t session_id, enum l2tp_msg_type msgtype,
        !           252:                        const struct ppp_l2tp_avp_list *avps0);
        !           253: static void    ppp_l2tp_ctrl_check_reply(struct ppp_l2tp_ctrl *ctrl);
        !           254: static void    ppp_l2tp_ctrl_close(struct ppp_l2tp_ctrl *ctrl,
        !           255:                        u_int16_t result, u_int16_t error, const char *errmsg);
        !           256: static void    ppp_l2tp_ctrl_death_start(struct ppp_l2tp_ctrl *ctrl);
        !           257: 
        !           258: static struct  ppp_l2tp_sess *ppp_l2tp_sess_create(struct ppp_l2tp_ctrl *ctrl,
        !           259:                        enum l2tp_sess_orig orig, enum l2tp_sess_side side, 
        !           260:                        u_int32_t serial);
        !           261: static void    ppp_l2tp_sess_destroy(struct ppp_l2tp_sess **sessp);
        !           262: static void    ppp_l2tp_sess_close(struct ppp_l2tp_sess *sess,
        !           263:                        u_int16_t result, u_int16_t error, const char *errmsg);
        !           264: static int     ppp_l2tp_sess_setup(struct ppp_l2tp_sess *sess);
        !           265: static int     ppp_l2tp_sess_check_liic(struct ppp_l2tp_sess *sess);
        !           266: static void    ppp_l2tp_sess_check_reply(struct ppp_l2tp_sess *sess);
        !           267: 
        !           268: static l2tp_ctrl_msg_handler_t ppp_l2tp_handle_SCCRQ;
        !           269: static l2tp_ctrl_msg_handler_t ppp_l2tp_handle_SCCRP;
        !           270: static l2tp_ctrl_msg_handler_t ppp_l2tp_handle_SCCCN;
        !           271: static l2tp_ctrl_msg_handler_t ppp_l2tp_handle_StopCCN;
        !           272: static l2tp_ctrl_msg_handler_t ppp_l2tp_handle_HELLO;
        !           273: static l2tp_ctrl_msg_handler_t ppp_l2tp_handle_OCRQ;
        !           274: static l2tp_ctrl_msg_handler_t ppp_l2tp_handle_ICRQ;
        !           275: 
        !           276: static l2tp_sess_msg_handler_t ppp_l2tp_handle_OCRP;
        !           277: static l2tp_sess_msg_handler_t ppp_l2tp_handle_xCCN;
        !           278: static l2tp_sess_msg_handler_t ppp_l2tp_handle_ICRP;
        !           279: static l2tp_sess_msg_handler_t ppp_l2tp_handle_CDN;
        !           280: static l2tp_sess_msg_handler_t ppp_l2tp_handle_WEN;
        !           281: static l2tp_sess_msg_handler_t ppp_l2tp_handle_SLI;
        !           282: 
        !           283: static pevent_handler_t                ppp_l2tp_ctrl_event;
        !           284: static pevent_handler_t                ppp_l2tp_data_event;
        !           285: 
        !           286: static pevent_handler_t                ppp_l2tp_idle_timeout;
        !           287: static pevent_handler_t                ppp_l2tp_unused_timeout;
        !           288: static pevent_handler_t                ppp_l2tp_ctrl_do_close;
        !           289: static pevent_handler_t                ppp_l2tp_ctrl_death_timeout;
        !           290: 
        !           291: static pevent_handler_t                ppp_l2tp_sess_notify;
        !           292: static pevent_handler_t                ppp_l2tp_sess_do_close;
        !           293: static pevent_handler_t                ppp_l2tp_sess_death_timeout;
        !           294: 
        !           295: static void    ppp_l2tp_ctrl_dump(struct ppp_l2tp_ctrl *ctrl,
        !           296:                        struct ppp_l2tp_avp_list *list, const char *fmt, ...)
        !           297:                        __printflike(3, 4);
        !           298: static const   char *ppp_l2tp_ctrl_state_str(enum l2tp_ctrl_state state);
        !           299: static const   char *ppp_l2tp_sess_state_str(enum l2tp_ctrl_state state);
        !           300: static const   char *ppp_l2tp_sess_orig_str(enum l2tp_sess_orig orig);
        !           301: static const   char *ppp_l2tp_sess_side_str(enum l2tp_sess_side side);
        !           302: 
        !           303: static ghash_hash_t    ppp_l2tp_ctrl_hash;
        !           304: static ghash_equal_t   ppp_l2tp_ctrl_equal;
        !           305: 
        !           306: static ghash_hash_t    ppp_l2tp_sess_hash;
        !           307: static ghash_equal_t   ppp_l2tp_sess_equal;
        !           308: 
        !           309: /************************************************************************
        !           310:                        INTERNAL VARIABLES
        !           311: ************************************************************************/
        !           312: 
        !           313: /* Descriptors for each L2TP message type */
        !           314: static const   struct l2tp_msg_info ppp_l2tp_msg_info[] = {
        !           315: 
        !           316:        /* Control connection messages */
        !           317:        { "SCCRQ", SCCRQ,       ppp_l2tp_handle_SCCRQ, NULL,
        !           318:            { CS_IDLE, -1 },
        !           319:            { -1 }, { -1 },
        !           320:            { AVP_PROTOCOL_VERSION, AVP_HOST_NAME,
        !           321:                AVP_FRAMING_CAPABILITIES, AVP_ASSIGNED_TUNNEL_ID, -1 } },
        !           322:        { "SCCRP", SCCRP,       ppp_l2tp_handle_SCCRP, NULL,
        !           323:            { CS_WAIT_CTL_REPLY, -1 },
        !           324:            { -1 }, { -1 },
        !           325:            { AVP_PROTOCOL_VERSION, AVP_HOST_NAME,
        !           326:                AVP_FRAMING_CAPABILITIES, AVP_ASSIGNED_TUNNEL_ID, -1 } },
        !           327:        { "SCCCN", SCCCN,       ppp_l2tp_handle_SCCCN, NULL,
        !           328:            { CS_WAIT_CTL_CONNECT, -1 },
        !           329:            { -1 }, { -1 },
        !           330:            { -1 } },
        !           331:        { "StopCCN", StopCCN,   ppp_l2tp_handle_StopCCN, NULL,
        !           332:            { CS_IDLE, CS_WAIT_CTL_REPLY, CS_WAIT_CTL_CONNECT,
        !           333:                CS_ESTABLISHED, CS_DYING, -1 },
        !           334:            { -1 }, { -1 },
        !           335:            { AVP_ASSIGNED_TUNNEL_ID, AVP_RESULT_CODE, -1 } },
        !           336:        { "HELLO", HELLO,       ppp_l2tp_handle_HELLO, NULL,
        !           337:            { CS_IDLE, CS_WAIT_CTL_REPLY, CS_WAIT_CTL_CONNECT,
        !           338:                CS_ESTABLISHED, CS_DYING, -1 },
        !           339:            { -1 }, { -1 },
        !           340:            { -1 } },
        !           341:        { "ICRQ", ICRQ,         ppp_l2tp_handle_ICRQ, NULL,
        !           342:            { CS_ESTABLISHED, -1 },
        !           343:            { -1 }, { -1 },
        !           344:            { AVP_ASSIGNED_SESSION_ID, AVP_CALL_SERIAL_NUMBER, -1 } },
        !           345:        { "OCRQ", OCRQ,         ppp_l2tp_handle_OCRQ, NULL,
        !           346:            { CS_ESTABLISHED, -1 },
        !           347:            { -1 }, { -1 },
        !           348:            { AVP_ASSIGNED_SESSION_ID, AVP_CALL_SERIAL_NUMBER,
        !           349:                AVP_MINIMUM_BPS, AVP_MAXIMUM_BPS, AVP_BEARER_TYPE,
        !           350:                AVP_FRAMING_TYPE, AVP_CALLED_NUMBER, -1 } },
        !           351: 
        !           352:        /* Session connection messages */
        !           353:        { "ICRP", ICRP,         NULL, ppp_l2tp_handle_ICRP,
        !           354:            { SS_WAIT_REPLY, SS_DYING, -1 },
        !           355:            { ORIG_LOCAL, -1 }, { SIDE_LAC, -1 },
        !           356:            { AVP_ASSIGNED_SESSION_ID, -1 } },
        !           357:        { "OCRP", OCRP,         NULL, ppp_l2tp_handle_OCRP,
        !           358:            { SS_WAIT_REPLY, SS_DYING, -1 },
        !           359:            { ORIG_LOCAL, -1 }, { SIDE_LNS, -1 },
        !           360:            { AVP_ASSIGNED_SESSION_ID, -1 } },
        !           361:        { "ICCN", ICCN,         NULL, ppp_l2tp_handle_xCCN,
        !           362:            { SS_WAIT_CONNECT, SS_DYING, -1 },
        !           363:            { ORIG_REMOTE, -1 }, { SIDE_LNS, -1 },
        !           364:            { AVP_TX_CONNECT_SPEED, AVP_FRAMING_TYPE, -1 } },
        !           365:        { "OCCN", OCCN,         NULL, ppp_l2tp_handle_xCCN,
        !           366:            { SS_WAIT_CONNECT, SS_DYING, -1 },
        !           367:            { ORIG_LOCAL, -1 }, { SIDE_LNS, -1 },
        !           368:            { AVP_TX_CONNECT_SPEED, AVP_FRAMING_TYPE, -1 } },
        !           369:        { "CDN", CDN,           NULL, ppp_l2tp_handle_CDN,
        !           370:            { SS_WAIT_REPLY, SS_WAIT_CONNECT,
        !           371:                SS_WAIT_ANSWER, SS_ESTABLISHED, SS_DYING, -1 },
        !           372:            { ORIG_LOCAL, ORIG_REMOTE, -1 }, { SIDE_LAC, SIDE_LNS, -1 },
        !           373:            { AVP_RESULT_CODE, AVP_ASSIGNED_SESSION_ID, -1 } },
        !           374:        { "WEN", WEN,           NULL, ppp_l2tp_handle_WEN,
        !           375:            { SS_ESTABLISHED, SS_DYING, -1 },
        !           376:            { ORIG_LOCAL, ORIG_REMOTE, -1 }, { SIDE_LNS, -1 },
        !           377:            { AVP_CALL_ERRORS, -1 } },
        !           378:        { "SLI", SLI,           NULL, ppp_l2tp_handle_SLI,
        !           379:            { SS_ESTABLISHED, SS_DYING, -1 },
        !           380:            { ORIG_LOCAL, ORIG_REMOTE, -1 }, { SIDE_LAC, -1 },
        !           381:            { AVP_ACCM, -1 } },
        !           382:        { NULL }
        !           383: };
        !           384: 
        !           385: /* Descriptors for each AVP */
        !           386: 
        !           387: #define AVP_ITEM(x,h,m,min,max)        \
        !           388:        { #x, ppp_l2tp_avp_decode_ ## x, 0, AVP_ ## x, h, m, min, max }
        !           389: 
        !           390: static const   struct ppp_l2tp_avp_info ppp_l2tp_avp_info_list[] = {
        !           391:        AVP_ITEM(MESSAGE_TYPE,          0,  1,  2,  2),
        !           392:        AVP_ITEM(RANDOM_VECTOR,         0,  1,  0,  AVP_MAX_LENGTH),
        !           393:        AVP_ITEM(RESULT_CODE,           0,  1,  2,  AVP_MAX_LENGTH),
        !           394:        AVP_ITEM(PROTOCOL_VERSION,      0,  1,  2,  2),
        !           395:        AVP_ITEM(FRAMING_CAPABILITIES,  1,  1,  4,  4),
        !           396:        AVP_ITEM(BEARER_CAPABILITIES,   1,  1,  4,  4),
        !           397:        AVP_ITEM(TIE_BREAKER,           0,  0,  8,  8),
        !           398:        AVP_ITEM(FIRMWARE_REVISION,     1,  0,  2,  2),
        !           399:        AVP_ITEM(HOST_NAME,             0,  1,  0,  AVP_MAX_LENGTH),
        !           400:        AVP_ITEM(VENDOR_NAME,           1,  0,  0,  AVP_MAX_LENGTH),
        !           401:        AVP_ITEM(ASSIGNED_TUNNEL_ID,    1,  1,  2,  2),
        !           402:        AVP_ITEM(RECEIVE_WINDOW_SIZE,   0,  1,  2,  2),
        !           403:        AVP_ITEM(CHALLENGE,             1,  1,  0,  AVP_MAX_LENGTH),
        !           404:        AVP_ITEM(CHALLENGE_RESPONSE,    1,  1, 16,  16),
        !           405:        AVP_ITEM(CAUSE_CODE,            0,  1,  3,  AVP_MAX_LENGTH),
        !           406:        AVP_ITEM(ASSIGNED_SESSION_ID,   1,  1,  2,  2),
        !           407:        AVP_ITEM(CALL_SERIAL_NUMBER,    1,  1,  4,  4),
        !           408:        AVP_ITEM(MINIMUM_BPS,           1,  1,  4,  4),
        !           409:        AVP_ITEM(MAXIMUM_BPS,           1,  1,  4,  4),
        !           410:        AVP_ITEM(BEARER_TYPE,           1,  1,  4,  4),
        !           411:        AVP_ITEM(FRAMING_TYPE,          1,  1,  4,  4),
        !           412:        AVP_ITEM(CALLED_NUMBER,         1,  1,  0,  AVP_MAX_LENGTH),
        !           413:        AVP_ITEM(CALLING_NUMBER,        1,  1,  0,  AVP_MAX_LENGTH),
        !           414:        AVP_ITEM(SUB_ADDRESS,           1,  1,  0,  AVP_MAX_LENGTH),
        !           415:        AVP_ITEM(TX_CONNECT_SPEED,      1,  1,  4,  4),
        !           416:        AVP_ITEM(RX_CONNECT_SPEED,      1,  0,  4,  4),
        !           417:        AVP_ITEM(PHYSICAL_CHANNEL_ID,   1,  0,  4,  4),
        !           418:        AVP_ITEM(PRIVATE_GROUP_ID,      1,  0,  0,  AVP_MAX_LENGTH),
        !           419:        AVP_ITEM(SEQUENCING_REQUIRED,   0,  1,  0,  0),
        !           420:        AVP_ITEM(INITIAL_RECV_CONFREQ,  1,  0,  0,  AVP_MAX_LENGTH),
        !           421:        AVP_ITEM(LAST_SENT_CONFREQ,     1,  0,  0,  AVP_MAX_LENGTH),
        !           422:        AVP_ITEM(LAST_RECV_CONFREQ,     1,  0,  0,  AVP_MAX_LENGTH),
        !           423:        AVP_ITEM(PROXY_AUTHEN_TYPE,     1,  0,  2,  2),
        !           424:        AVP_ITEM(PROXY_AUTHEN_NAME,     1,  0,  0,  AVP_MAX_LENGTH),
        !           425:        AVP_ITEM(PROXY_AUTHEN_CHALLENGE,1,  0,  0,  AVP_MAX_LENGTH),
        !           426:        AVP_ITEM(PROXY_AUTHEN_ID,       1,  0,  2,  2),
        !           427:        AVP_ITEM(PROXY_AUTHEN_RESPONSE, 1,  0,  0,  AVP_MAX_LENGTH),
        !           428:        AVP_ITEM(CALL_ERRORS,           1,  1, 26,  26),
        !           429:        AVP_ITEM(ACCM,                  1,  1, 10,  10),
        !           430:        { NULL, NULL, 0, 0, 0, 0, 0, 0 }
        !           431: };
        !           432: 
        !           433: /* All control connections */
        !           434: struct ghash   *ppp_l2tp_ctrls;
        !           435: 
        !           436: static uint32_t gNextSerial = 0;
        !           437: 
        !           438: /************************************************************************
        !           439:                        PUBLIC FUNCTIONS
        !           440: ************************************************************************/
        !           441: 
        !           442: /*
        !           443:  * Create a new control connection.
        !           444:  */
        !           445: struct ppp_l2tp_ctrl *
        !           446: ppp_l2tp_ctrl_create(struct pevent_ctx *ctx, pthread_mutex_t *mutex,
        !           447:        const struct ppp_l2tp_ctrl_cb *cb,
        !           448:        u_int32_t peer_id, ng_ID_t *nodep, char *hook,
        !           449:        const struct ppp_l2tp_avp_list *avps, const void *secret, size_t seclen,
        !           450:        u_char hide_avps)
        !           451: {
        !           452:        struct ppp_l2tp_ctrl *ctrl;
        !           453:        struct ngm_mkpeer mkpeer;
        !           454:        u_int16_t value16;
        !           455:        int index, i;
        !           456:        
        !           457:        /* Init Call Serial Number */
        !           458:        if (gNextSerial == 0)
        !           459:            gNextSerial = (random() % 900) * 10000;
        !           460: 
        !           461:        /* Create global control structure hash table */
        !           462:        if (ppp_l2tp_ctrls == NULL
        !           463:            && (ppp_l2tp_ctrls = ghash_create(NULL, 0, 0, CTRL_MEM_TYPE,
        !           464:              ppp_l2tp_ctrl_hash, ppp_l2tp_ctrl_equal, NULL, NULL)) == NULL)
        !           465:                return (NULL);
        !           466: 
        !           467:        /* Create control connection */
        !           468:        ctrl = Malloc(CTRL_MEM_TYPE, sizeof(*ctrl));
        !           469:        ctrl->ctx = ctx;
        !           470:        ctrl->mutex = mutex;
        !           471:        ctrl->cb = cb;
        !           472:        ctrl->peer_id = peer_id;
        !           473:        ctrl->csock = -1;
        !           474:        ctrl->dsock = -1;
        !           475: 
        !           476:        /* Debugging */
        !           477:        Log(LOG_DEBUG, ("L2TP: %s invoked", __FUNCTION__));
        !           478: 
        !           479:        /* Select an unused, non-zero local tunnel ID */
        !           480:        while (ctrl->config.tunnel_id == 0
        !           481:            || ghash_get(ppp_l2tp_ctrls, ctrl) != NULL)
        !           482:                ctrl->config.tunnel_id = random() & 0xffff;
        !           483: 
        !           484:        /* Add control structure to hash table */
        !           485:        if (ghash_put(ppp_l2tp_ctrls, ctrl) == -1)
        !           486:                goto fail;
        !           487: 
        !           488:        /* Copy shared secret, if any */
        !           489:        if (seclen > 0)
        !           490:                ctrl->secret = Mdup(CTRL_MEM_TYPE, secret, seclen);
        !           491:        ctrl->seclen = seclen;
        !           492:        ctrl->hide_avps = hide_avps;
        !           493: 
        !           494:        /* Create sessions hash table */
        !           495:        if ((ctrl->sessions = ghash_create(NULL, 0, 0, CTRL_MEM_TYPE,
        !           496:            ppp_l2tp_sess_hash, ppp_l2tp_sess_equal, NULL, NULL)) == NULL)
        !           497:                goto fail;
        !           498: 
        !           499:        /* Create netgraph node */
        !           500:        if (NgMkSockNode(NULL, &ctrl->csock, &ctrl->dsock) == -1)
        !           501:                goto fail;
        !           502:        memset(&mkpeer, 0, sizeof(mkpeer));
        !           503:        strlcpy(mkpeer.type, NG_L2TP_NODE_TYPE, sizeof(mkpeer.type));
        !           504:        strlcpy(mkpeer.ourhook, NG_L2TP_HOOK_CTRL, sizeof(mkpeer.ourhook));
        !           505:        strlcpy(mkpeer.peerhook, NG_L2TP_HOOK_CTRL, sizeof(mkpeer.peerhook));
        !           506:        if (NgSendMsg(ctrl->csock, ".:", NGM_GENERIC_COOKIE,
        !           507:            NGM_MKPEER, &mkpeer, sizeof(mkpeer)) == -1)
        !           508:                goto fail;
        !           509: 
        !           510:        /* Get l2tp node ID */
        !           511:        if ((ctrl->node_id = NgGetNodeID(ctrl->csock, NG_L2TP_HOOK_CTRL)) == 0) {
        !           512:            Perror("L2TP: Cannot get %s node id", NG_L2TP_NODE_TYPE);
        !           513:            goto fail;
        !           514:        };
        !           515:        snprintf(ctrl->path, sizeof(ctrl->path),
        !           516:            "[%lx]:", (u_long)ctrl->node_id);
        !           517: 
        !           518:        /* Configure netgraph node with initial configuration */
        !           519:        ctrl->config.enabled = 1;
        !           520:        ctrl->config.peer_win = 1;              /* we increase this later */
        !           521:        ctrl->config.rexmit_max = L2TP_REXMIT_MAX;
        !           522:        ctrl->config.rexmit_max_to = L2TP_REXMIT_MAX_TO;
        !           523:        if (NgSendMsg(ctrl->csock, NG_L2TP_HOOK_CTRL, NGM_L2TP_COOKIE,
        !           524:            NGM_L2TP_SET_CONFIG, &ctrl->config, sizeof(ctrl->config)) == -1)
        !           525:                goto fail;
        !           526: 
        !           527:        /* Listen for control messages and control packets */
        !           528:        if (pevent_register(ctrl->ctx, &ctrl->ctrl_event, PEVENT_RECURRING,
        !           529:            ctrl->mutex, ppp_l2tp_ctrl_event, ctrl, PEVENT_READ,
        !           530:            ctrl->csock) == -1)
        !           531:                goto fail;
        !           532:        if (pevent_register(ctrl->ctx, &ctrl->data_event, PEVENT_RECURRING,
        !           533:            ctrl->mutex, ppp_l2tp_data_event, ctrl, PEVENT_READ,
        !           534:            ctrl->dsock) == -1)
        !           535:                goto fail;
        !           536: 
        !           537:        /* Copy initial AVP list */
        !           538:        ctrl->avps = (avps == NULL) ?
        !           539:            ppp_l2tp_avp_list_create() :
        !           540:            ppp_l2tp_avp_list_copy(avps);
        !           541:        if (ctrl->avps == NULL)
        !           542:                goto fail;
        !           543: 
        !           544:        /* Add required AVP's */
        !           545:        if (ppp_l2tp_avp_list_find(ctrl->avps,
        !           546:            0, AVP_PROTOCOL_VERSION)== -1) {
        !           547:                const u_char pv[] = { L2TP_PROTO_VERS, L2TP_PROTO_REV };
        !           548: 
        !           549:                if (ppp_l2tp_avp_list_append(ctrl->avps, 1,
        !           550:                    0, AVP_PROTOCOL_VERSION, pv, sizeof(pv)) == -1)
        !           551:                        goto fail;
        !           552:        }
        !           553:        if ((index = ppp_l2tp_avp_list_find(ctrl->avps,
        !           554:            0, AVP_HOST_NAME)) == -1) {
        !           555:                (void)gethostname(ctrl->self_name, sizeof(ctrl->self_name) - 1);
        !           556:                ctrl->self_name[sizeof(ctrl->self_name) - 1] = '\0';
        !           557:                if (ppp_l2tp_avp_list_append(ctrl->avps, 1,
        !           558:                    0, AVP_HOST_NAME, ctrl->self_name, strlen(ctrl->self_name)) == -1)
        !           559:                        goto fail;
        !           560:        } else {
        !           561:            int len = ctrl->avps->avps[index].vlen;
        !           562:            if (len >= sizeof(ctrl->self_name))
        !           563:                len = sizeof(ctrl->self_name) - 1;
        !           564:            memcpy(ctrl->self_name, ctrl->avps->avps[index].value, len);
        !           565:            ctrl->self_name[len] = 0;
        !           566:        }
        !           567:        if (ppp_l2tp_avp_list_find(ctrl->avps,
        !           568:            0, AVP_FRAMING_CAPABILITIES) == -1) {
        !           569:                const u_int32_t value = htonl(L2TP_FRAMING_SYNC|L2TP_FRAMING_ASYNC);
        !           570: 
        !           571:                if (ppp_l2tp_avp_list_append(ctrl->avps, 1,
        !           572:                    0, AVP_FRAMING_CAPABILITIES, &value, sizeof(value)) == -1)
        !           573:                        goto fail;
        !           574:        }
        !           575:        if ((index = ppp_l2tp_avp_list_find(ctrl->avps,
        !           576:            0, AVP_ASSIGNED_TUNNEL_ID)) != -1)
        !           577:                ppp_l2tp_avp_list_remove(ctrl->avps, index);
        !           578:        value16 = htons(ctrl->config.tunnel_id);
        !           579:        if (ppp_l2tp_avp_list_append(ctrl->avps, 1,
        !           580:            0, AVP_ASSIGNED_TUNNEL_ID, &value16, sizeof(value16)) == -1)
        !           581:                goto fail;
        !           582: 
        !           583:        if ((index = ppp_l2tp_avp_list_find(ctrl->avps,
        !           584:            0, AVP_CHALLENGE)) != -1)
        !           585:                ppp_l2tp_avp_list_remove(ctrl->avps, index);
        !           586: 
        !           587:        if (ctrl->secret != NULL) {
        !           588:            for (i = 0; i < sizeof(ctrl->chal); i++)
        !           589:                    ctrl->chal[i] = random();
        !           590:            if (ppp_l2tp_avp_list_append(ctrl->avps, 1,
        !           591:                0, AVP_CHALLENGE, &ctrl->chal, sizeof(ctrl->chal)) == -1)
        !           592:                    goto fail;
        !           593:        }
        !           594: 
        !           595:        ctrl->state = CS_IDLE;          /* wait for peer's sccrq */
        !           596: 
        !           597:        /* Expect some sort of reply */
        !           598:        ppp_l2tp_ctrl_check_reply(ctrl);
        !           599: 
        !           600:        /* Done */
        !           601:        *nodep = ctrl->node_id;
        !           602:        strlcpy(hook, NG_L2TP_HOOK_LOWER, NG_HOOKSIZ);
        !           603:        return (ctrl);
        !           604: 
        !           605: fail:
        !           606:        /* Clean up after failure */
        !           607:        if (ctrl->csock >= 0)
        !           608:                (void)close(ctrl->csock);       /* l2tp node will go away too */
        !           609:        if (ctrl->dsock >= 0)
        !           610:                (void)close(ctrl->dsock);
        !           611:        pevent_unregister(&ctrl->reply_timer);
        !           612:        pevent_unregister(&ctrl->ctrl_event);
        !           613:        pevent_unregister(&ctrl->data_event);
        !           614:        ppp_l2tp_avp_list_destroy(&ctrl->avps);
        !           615:        ghash_remove(ppp_l2tp_ctrls, ctrl);
        !           616:        ghash_destroy(&ctrl->sessions);
        !           617:        Freee(ctrl->secret);
        !           618:        Freee(ctrl);
        !           619:        if (ppp_l2tp_ctrls != NULL && ghash_size(ppp_l2tp_ctrls) == 0)
        !           620:                ghash_destroy(&ppp_l2tp_ctrls);
        !           621:        return (NULL);
        !           622: }
        !           623: 
        !           624: /*
        !           625:  * Create a new control connection.
        !           626:  */
        !           627: struct ppp_l2tp_ctrl *
        !           628: ppp_l2tp_ctrl_initiate(struct ppp_l2tp_ctrl *ctrl)
        !           629: {
        !           630:        /* Debugging */
        !           631:        Log(LOG_DEBUG, ("L2TP: %s invoked", __FUNCTION__));
        !           632: 
        !           633:        /* Initiate connection, we're the initiator */
        !           634:        ctrl->state = CS_WAIT_CTL_REPLY;
        !           635:        ppp_l2tp_ctrl_send(ctrl, 0, SCCRQ, ctrl->avps);
        !           636: 
        !           637:        /* Expect some sort of reply */
        !           638:        ppp_l2tp_ctrl_check_reply(ctrl);
        !           639: 
        !           640:        /* Done */
        !           641:        return (ctrl);
        !           642: }
        !           643: 
        !           644: /*
        !           645:  * Shutdown a control connection.
        !           646:  */
        !           647: void
        !           648: ppp_l2tp_ctrl_shutdown(struct ppp_l2tp_ctrl *ctrl,
        !           649:         u_int16_t result, u_int16_t error, const char *errmsg)
        !           650: {
        !           651:        /* Debugging */
        !           652:        Log(LOG_DEBUG, ("L2TP: %s invoked, ctrl=%p errmsg=\"%s\"",
        !           653:            __FUNCTION__, ctrl, errmsg));
        !           654: 
        !           655:        /* Close control connection */
        !           656:        ppp_l2tp_ctrl_close(ctrl, result, error, errmsg);
        !           657: }
        !           658: 
        !           659: /*
        !           660:  * Initiate a new session.
        !           661:  */
        !           662: struct ppp_l2tp_sess *
        !           663: ppp_l2tp_initiate(struct ppp_l2tp_ctrl *ctrl, int out,
        !           664:        u_char include_length, u_char enable_dseq,
        !           665:        const struct ppp_l2tp_avp_list *avps)
        !           666: {
        !           667:        struct ppp_l2tp_sess *sess;
        !           668:        u_int32_t value32;
        !           669:        int i;
        !           670: 
        !           671:        /* Debugging */
        !           672:        Log(LOG_DEBUG, ("L2TP: %s invoked, ctrl=%p out=%d", __FUNCTION__, ctrl, out));
        !           673: 
        !           674:        /* Check control connection */
        !           675:        /* XXX add support for sessions waiting for open ctrl conection */
        !           676:        if (ctrl->state != CS_ESTABLISHED) {
        !           677:                errno = ENXIO;
        !           678:                return (NULL);
        !           679:        }
        !           680: 
        !           681:        /* Verify peer supports outgoing calls */
        !           682:        if (out
        !           683:            && (ctrl->peer_bearer
        !           684:              & (L2TP_BEARER_DIGITAL|L2TP_BEARER_ANALOG)) == 0) {
        !           685:                errno = EOPNOTSUPP;
        !           686:                return (NULL);
        !           687:        }
        !           688: 
        !           689:        /* Create new session */
        !           690:        if ((sess = ppp_l2tp_sess_create(ctrl,
        !           691:            ORIG_LOCAL, out ? SIDE_LNS : SIDE_LAC,
        !           692:            gNextSerial++)) == NULL)
        !           693:                return (NULL);
        !           694:        
        !           695:        sess->include_length = include_length;
        !           696:        sess->enable_dseq = enable_dseq;
        !           697: 
        !           698:        /* Copy AVP's supplied by caller */
        !           699:        if (avps) {
        !           700:            for (i = 0; i < avps->length; i++) {
        !           701:                const struct ppp_l2tp_avp *const avp = &avps->avps[i];
        !           702: 
        !           703:                if (ppp_l2tp_avp_list_append(sess->my_avps,
        !           704:                    avp->mandatory, avp->vendor, avp->type,
        !           705:                    avp->value, avp->vlen) == -1)
        !           706:                        goto fail;
        !           707:            }
        !           708:        }
        !           709: 
        !           710:        /* Add other AVP's required by OCRQ */
        !           711:        if (!out)
        !           712:                goto send_msg;
        !           713:        if (ppp_l2tp_avp_list_find(sess->my_avps,
        !           714:            0, AVP_MINIMUM_BPS) == -1) {
        !           715:                value32 = htonl(0);
        !           716:                if (ppp_l2tp_avp_list_append(sess->my_avps, 1,
        !           717:                    0, AVP_MINIMUM_BPS, &value32, sizeof(value32)) == -1)
        !           718:                        goto fail;
        !           719:        }
        !           720:        if (ppp_l2tp_avp_list_find(sess->my_avps,
        !           721:            0, AVP_MAXIMUM_BPS) == -1) {
        !           722:                value32 = htonl(0x7fffffff);
        !           723:                if (ppp_l2tp_avp_list_append(sess->my_avps, 1,
        !           724:                    0, AVP_MAXIMUM_BPS, &value32, sizeof(value32)) == -1)
        !           725:                        goto fail;
        !           726:        }
        !           727:        if (ppp_l2tp_avp_list_find(sess->my_avps,
        !           728:            0, AVP_BEARER_TYPE) == -1) {
        !           729:                value32 = (ctrl->peer_bearer
        !           730:                    & (L2TP_BEARER_DIGITAL|L2TP_BEARER_ANALOG));
        !           731:                value32 = htonl(value32);
        !           732:                if (ppp_l2tp_avp_list_append(sess->my_avps, 1,
        !           733:                    0, AVP_BEARER_TYPE, &value32, sizeof(value32)) == -1)
        !           734:                        goto fail;
        !           735:        }
        !           736:        if (ppp_l2tp_avp_list_find(sess->my_avps,
        !           737:            0, AVP_FRAMING_TYPE) == -1) {
        !           738:                value32 = (ctrl->peer_framing
        !           739:                    & (L2TP_FRAMING_SYNC|L2TP_FRAMING_ASYNC));
        !           740:                value32 = htonl(value32);
        !           741:                if (ppp_l2tp_avp_list_append(sess->my_avps, 1,
        !           742:                    0, AVP_FRAMING_TYPE, &value32, sizeof(value32)) == -1)
        !           743:                        goto fail;
        !           744:        }
        !           745:        if (ppp_l2tp_avp_list_find(sess->my_avps,
        !           746:            0, AVP_CALLED_NUMBER) == -1) {
        !           747:                if (ppp_l2tp_avp_list_append(sess->my_avps, 1,
        !           748:                    0, AVP_CALLED_NUMBER, NULL, 0) == -1)
        !           749:                        goto fail;
        !           750:        }
        !           751: 
        !           752: send_msg:
        !           753:        /* Send request to peer */
        !           754:        ppp_l2tp_ctrl_send(ctrl, 0, out ? OCRQ : ICRQ, sess->my_avps);
        !           755: 
        !           756:        /* Await reply from peer */
        !           757:        ppp_l2tp_sess_check_reply(sess);
        !           758:        return (sess);
        !           759: 
        !           760: fail:
        !           761:        /* Clean up after failure */
        !           762:        ppp_l2tp_sess_destroy(&sess);
        !           763:        return (NULL);
        !           764: }
        !           765: 
        !           766: /*
        !           767:  * Report successful connection of a remotely initiated outgoing call
        !           768:  * or a locally initiated incoming call.
        !           769:  */
        !           770: int
        !           771: ppp_l2tp_connected(struct ppp_l2tp_sess *sess,
        !           772:        const struct ppp_l2tp_avp_list *avps)
        !           773: {
        !           774:        struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
        !           775:        u_int32_t value32;
        !           776:        int i;
        !           777: 
        !           778:        /* Debugging */
        !           779:        Log(LOG_DEBUG, ("L2TP: %s invoked, sess=%p", __FUNCTION__, sess));
        !           780: 
        !           781:        /* Check control connection */
        !           782:        if (ctrl->state != CS_ESTABLISHED) {
        !           783:                Log(LOG_ERR, ("L2TP: inappropriate call to %s", __FUNCTION__));
        !           784:                errno = ENXIO;
        !           785:                return (-1);
        !           786:        }
        !           787: 
        !           788:        /* Check session state */
        !           789:        if (sess->side != SIDE_LAC
        !           790:            || !((sess->orig == ORIG_REMOTE && sess->state == SS_WAIT_ANSWER)
        !           791:              || (sess->orig == ORIG_LOCAL && sess->state == SS_WAIT_REPLY))) {
        !           792:                Log(LOG_ERR, ("L2TP: inappropriate call to %s", __FUNCTION__));
        !           793:                errno = ENOTTY;
        !           794:                return (-1);
        !           795:        }
        !           796: 
        !           797:        /* Copy AVP's supplied by caller */
        !           798:        while (sess->my_avps->length > 0)
        !           799:                ppp_l2tp_avp_list_remove(sess->my_avps, 0);
        !           800:        if (avps != NULL) {
        !           801:                for (i = 0; i < avps->length; i++) {
        !           802:                        struct ppp_l2tp_avp *const avp = &avps->avps[i];
        !           803: 
        !           804:                        if (ppp_l2tp_avp_list_append(sess->my_avps,
        !           805:                            avp->mandatory, avp->vendor, avp->type,
        !           806:                            avp->value, avp->vlen) == -1)
        !           807:                                goto fail;
        !           808:                }
        !           809:        }
        !           810: 
        !           811:        /* Add other AVP's required by ICCN and OCCN */
        !           812:        if (ppp_l2tp_avp_list_find(sess->my_avps,
        !           813:            0, AVP_TX_CONNECT_SPEED) == -1) {
        !           814:                value32 = htonl(L2TP_CONNECT_SPEED);
        !           815:                if (ppp_l2tp_avp_list_append(sess->my_avps, 1,
        !           816:                    0, AVP_TX_CONNECT_SPEED, &value32, sizeof(value32)) == -1)
        !           817:                        goto fail;
        !           818:        }
        !           819:        if (ppp_l2tp_avp_list_find(sess->my_avps,
        !           820:            0, AVP_FRAMING_TYPE) == -1) {
        !           821:                value32 = htonl(L2TP_FRAMING_TYPE);
        !           822:                if (ppp_l2tp_avp_list_append(sess->my_avps, 1,
        !           823:                    0, AVP_FRAMING_TYPE, &value32, sizeof(value32)) == -1)
        !           824:                        goto fail;
        !           825:        }
        !           826: 
        !           827:        /* Handle incoming or outgoing call */
        !           828:        if (sess->orig == ORIG_LOCAL) {
        !           829:                sess->link_responded = 1;
        !           830:                if (ppp_l2tp_sess_check_liic(sess) == -1)
        !           831:                        goto fail;
        !           832:        } else {
        !           833:                if (ppp_l2tp_sess_setup(sess) == -1)
        !           834:                        goto fail;
        !           835:                ppp_l2tp_ctrl_send(ctrl, sess->peer_id, OCCN, sess->my_avps);
        !           836:        }
        !           837: 
        !           838:        /* Done */
        !           839:        return (0);
        !           840: 
        !           841: fail:
        !           842:        /* Clean up after failure */
        !           843:        ppp_l2tp_sess_close(sess, L2TP_RESULT_ERROR,
        !           844:            L2TP_ERROR_GENERIC, strerror(errno));
        !           845:        return (-1);
        !           846: }
        !           847: 
        !           848: /*
        !           849:  * Terminate a session.
        !           850:  */
        !           851: void
        !           852: ppp_l2tp_terminate(struct ppp_l2tp_sess *sess,
        !           853:        u_int16_t result, u_int16_t error, const char *errmsg)
        !           854: {
        !           855:        struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
        !           856: 
        !           857:        /* Debugging */
        !           858:        Log(LOG_DEBUG, ("L2TP: %s invoked, sess=%p errmsg=\"%s\"",
        !           859:            __FUNCTION__, sess, errmsg != NULL ? errmsg : ""));
        !           860: 
        !           861:        /* Check control connection state */
        !           862:        if (ctrl->state == CS_DYING) {
        !           863:                sess->link_notified = 1;
        !           864:                return;
        !           865:        }
        !           866:        if (ctrl->state != CS_ESTABLISHED) {
        !           867:                Log(LOG_ERR, ("L2TP: inappropriate call to %s", __FUNCTION__));
        !           868:                return;
        !           869:        }
        !           870: 
        !           871:        /* Close connection */
        !           872:        sess->link_notified = 1;
        !           873:        ppp_l2tp_sess_close(sess, result, error, errmsg);
        !           874: }
        !           875: 
        !           876: /*
        !           877:  * Send SLI to peer.
        !           878:  */
        !           879: int
        !           880: ppp_l2tp_set_link_info(struct ppp_l2tp_sess *sess,
        !           881:                        u_int32_t xmit, u_int32_t recv)
        !           882: {
        !           883:        struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
        !           884:        struct ppp_l2tp_avp_list *avps;
        !           885:        uint16_t accm[5];
        !           886: 
        !           887:        /* Only LNS should send SLI */
        !           888:        if (sess->side != SIDE_LNS)
        !           889:                return (0);
        !           890: 
        !           891:        avps = ppp_l2tp_avp_list_create();
        !           892: 
        !           893:        accm[0] = 0;
        !           894:        accm[1] = htons(xmit >> 16);
        !           895:        accm[2] = htons(xmit & 0xFFFF);
        !           896:        accm[3] = htons(recv >> 16);
        !           897:        accm[4] = htons(recv & 0xFFFF);
        !           898:        if (ppp_l2tp_avp_list_append(avps, 0,
        !           899:            0, AVP_ACCM, &accm, sizeof(accm)) == -1) {
        !           900:                ppp_l2tp_avp_list_destroy(&avps);
        !           901:                return (-1);
        !           902:        }
        !           903: 
        !           904:        ppp_l2tp_ctrl_send(ctrl, sess->peer_id, SLI, avps);
        !           905:        ppp_l2tp_avp_list_destroy(&avps);
        !           906:        return (0);
        !           907: }
        !           908: 
        !           909: /*
        !           910:  * Get the link side cookie corresponding to a control connection.
        !           911:  */
        !           912: void *
        !           913: ppp_l2tp_ctrl_get_cookie(struct ppp_l2tp_ctrl *ctrl)
        !           914: {
        !           915:        return (ctrl->link_cookie);
        !           916: }
        !           917: 
        !           918: /*
        !           919:  * Set the link side cookie corresponding to a control connection.
        !           920:  */
        !           921: void
        !           922: ppp_l2tp_ctrl_set_cookie(struct ppp_l2tp_ctrl *ctrl, void *cookie)
        !           923: {
        !           924:        ctrl->link_cookie = cookie;
        !           925: }
        !           926: 
        !           927: /*
        !           928:  * Get the link side cookie corresponding to a session.
        !           929:  */
        !           930: void *
        !           931: ppp_l2tp_sess_get_cookie(struct ppp_l2tp_sess *sess)
        !           932: {
        !           933:        return (sess->link_cookie);
        !           934: }
        !           935: 
        !           936: /*
        !           937:  * Set the link side cookie corresponding to a session.
        !           938:  */
        !           939: void
        !           940: ppp_l2tp_sess_set_cookie(struct ppp_l2tp_sess *sess, void *cookie)
        !           941: {
        !           942:        sess->link_cookie = cookie;
        !           943: }
        !           944: 
        !           945: /*
        !           946:  * Get session's Call Serial Number.
        !           947:  */
        !           948: uint32_t
        !           949: ppp_l2tp_sess_get_serial(struct ppp_l2tp_sess *sess)
        !           950: {
        !           951:        return(sess->serial);
        !           952: }
        !           953: 
        !           954: int
        !           955: ppp_l2tp_ctrl_get_self_name(struct ppp_l2tp_ctrl *ctrl,
        !           956:                        void *buf, size_t buf_len) {
        !           957:        strlcpy(buf, ctrl->self_name, buf_len);
        !           958:        return (0);
        !           959: };
        !           960: 
        !           961: int
        !           962: ppp_l2tp_ctrl_get_peer_name(struct ppp_l2tp_ctrl *ctrl,
        !           963:                        void *buf, size_t buf_len) {
        !           964:        strlcpy(buf, ctrl->peer_name, buf_len);
        !           965:        return (0);
        !           966: };
        !           967: 
        !           968: /*
        !           969:  * Get the node path and hook name for the hook that corresponds
        !           970:  * to a control connection's L2TP frames.
        !           971:  */
        !           972: void
        !           973: ppp_l2tp_ctrl_get_hook(struct ppp_l2tp_ctrl *ctrl,
        !           974:        ng_ID_t *nodep, const char **hookp)
        !           975: {
        !           976:        if (nodep != NULL)
        !           977:                *nodep = ctrl->node_id;
        !           978:        if (hookp != NULL)
        !           979:                *hookp = NG_L2TP_HOOK_LOWER;
        !           980: }
        !           981: 
        !           982: /*
        !           983:  * Get the node path and hook name for the hook that corresponds
        !           984:  * to a session's data packets.
        !           985:  */
        !           986: void
        !           987: ppp_l2tp_sess_get_hook(struct ppp_l2tp_sess *sess,
        !           988:        ng_ID_t *nodep, const char **hookp)
        !           989: {
        !           990:        if (nodep != NULL) {
        !           991:            if (sess->node_id)
        !           992:                *nodep = sess->node_id;
        !           993:            else
        !           994:                *nodep = sess->ctrl->node_id;
        !           995:        }
        !           996:        if (hookp != NULL) {
        !           997:            if (sess->node_id)
        !           998:                *hookp = NG_TEE_HOOK_RIGHT;
        !           999:            else
        !          1000:                *hookp = sess->hook;
        !          1001:        }
        !          1002: }
        !          1003: 
        !          1004: /*
        !          1005:  * Informs that hook has been connected and temporal tee can be shutted down.
        !          1006:  */
        !          1007: void
        !          1008: ppp_l2tp_sess_hooked(struct ppp_l2tp_sess *sess) {
        !          1009:        char path[32];
        !          1010: 
        !          1011:        snprintf(path, sizeof(path), "[%lx]:", (u_long)sess->node_id);
        !          1012:        (void)NgSendMsg(sess->ctrl->csock, path,
        !          1013:            NGM_GENERIC_COOKIE, NGM_SHUTDOWN, NULL, 0);
        !          1014:        sess->node_id = 0;
        !          1015: }
        !          1016: 
        !          1017: /************************************************************************
        !          1018:                INTERNAL FUNCTIONS: CONTROL CONNECTION
        !          1019: ************************************************************************/
        !          1020: 
        !          1021: /*
        !          1022:  * Extract peer information from AVP's contained in a SCCRQ or SCCRP.
        !          1023:  * This is the first part of tunnel setup.
        !          1024:  */
        !          1025: static int
        !          1026: ppp_l2tp_ctrl_setup_1(struct ppp_l2tp_ctrl *ctrl,
        !          1027:        struct ppp_l2tp_avp_ptrs *ptrs)
        !          1028: {
        !          1029:        /* Log */
        !          1030:        Log(LOG_INFO, ("L2TP: connected to \"%s\", version=%u.%u",
        !          1031:            ptrs->hostname->hostname, ptrs->protocol->version,
        !          1032:            ptrs->protocol->revision));
        !          1033: 
        !          1034:        /* Get peer's tunnel ID */
        !          1035:        ctrl->config.peer_id = ptrs->tunnelid->id;
        !          1036: 
        !          1037:        /* Get peer's receive window size */
        !          1038:        ctrl->config.peer_win = L2TP_DEFAULT_PEER_WIN;
        !          1039:        if (ptrs->winsize != NULL) {
        !          1040:                if (ptrs->winsize->size == 0)
        !          1041:                        Log(LOG_WARNING, ("L2TP: ignoring zero recv window size AVP"));
        !          1042:                else
        !          1043:                        ctrl->config.peer_win = ptrs->winsize->size;
        !          1044:        }
        !          1045: 
        !          1046:        /* Get peer's bearer and framing types */
        !          1047:        if (ptrs->bearercap != NULL) {
        !          1048:                if (ptrs->bearercap->digital)
        !          1049:                        ctrl->peer_bearer |= L2TP_BEARER_DIGITAL;
        !          1050:                if (ptrs->bearercap->analog)
        !          1051:                        ctrl->peer_bearer |= L2TP_BEARER_ANALOG;
        !          1052:        }
        !          1053:        if (ptrs->framingcap->sync)
        !          1054:                ctrl->peer_framing |= L2TP_FRAMING_SYNC;
        !          1055:        if (ptrs->framingcap->async)
        !          1056:                ctrl->peer_framing |= L2TP_FRAMING_ASYNC;
        !          1057: 
        !          1058:        strlcpy(ctrl->peer_name, ptrs->hostname->hostname, sizeof(ctrl->peer_name));
        !          1059: 
        !          1060:        /* Update netgraph node configuration */
        !          1061:        if (NgSendMsg(ctrl->csock, NG_L2TP_HOOK_CTRL, NGM_L2TP_COOKIE,
        !          1062:            NGM_L2TP_SET_CONFIG, &ctrl->config, sizeof(ctrl->config)) == -1)
        !          1063:                return (-1);
        !          1064: 
        !          1065:        /* See if there is a challenge AVP */
        !          1066:        if (ptrs->challenge != NULL) {
        !          1067:                 MD5_CTX md5ctx;
        !          1068:                u_char hash[MD5_DIGEST_LENGTH];
        !          1069:                uint8_t t;
        !          1070: 
        !          1071:                /* Make sure response was included */
        !          1072:                if (ctrl->secret == NULL) {
        !          1073:                        Log(LOG_WARNING, ("L2TP: tunnel challenge received but"
        !          1074:                            " no shared secret is configured"));
        !          1075:                        ppp_l2tp_ctrl_close(ctrl,
        !          1076:                            L2TP_RESULT_NOT_AUTH, 0, NULL);
        !          1077:                        return (-1);
        !          1078:                }
        !          1079: 
        !          1080:                /* Calculate challenge response */
        !          1081:                t = (ptrs->message->mesgtype == SCCRQ)?SCCRP:SCCCN;
        !          1082:                MD5_Init(&md5ctx);
        !          1083:                MD5_Update(&md5ctx, &t, 1);
        !          1084:                MD5_Update(&md5ctx, ctrl->secret, ctrl->seclen);
        !          1085:                MD5_Update(&md5ctx, &ptrs->challenge->value, ptrs->challenge->length);
        !          1086:                MD5_Final(hash, &md5ctx);
        !          1087: 
        !          1088:                if (ppp_l2tp_avp_list_append(ctrl->avps, 0,
        !          1089:                    0, AVP_CHALLENGE_RESPONSE, hash, sizeof(hash)) == -1)
        !          1090:                return (0);
        !          1091:        }
        !          1092: 
        !          1093:        /* Done */
        !          1094:        return (0);
        !          1095: }
        !          1096: 
        !          1097: /*
        !          1098:  * Extract peer information from AVP's contained in a SCCRP or SCCCN.
        !          1099:  * This is the second part of tunnel setup.
        !          1100:  */
        !          1101: static int
        !          1102: ppp_l2tp_ctrl_setup_2(struct ppp_l2tp_ctrl *ctrl,
        !          1103:        struct ppp_l2tp_avp_ptrs *ptrs)
        !          1104: {
        !          1105:        /* Peer now knows our tunnel ID */
        !          1106:        ctrl->config.match_id = 1;
        !          1107:        if (NgSendMsg(ctrl->csock, NG_L2TP_HOOK_CTRL, NGM_L2TP_COOKIE,
        !          1108:            NGM_L2TP_SET_CONFIG, &ctrl->config, sizeof(ctrl->config)) == -1)
        !          1109:                return (-1);
        !          1110: 
        !          1111:        /* Verify peer's challenge response */
        !          1112:        if (ctrl->secret != NULL) {
        !          1113:                 MD5_CTX md5ctx;
        !          1114:                u_char hash[MD5_DIGEST_LENGTH];
        !          1115:                uint8_t t;
        !          1116: 
        !          1117:                /* Make sure response was included */
        !          1118:                if (ptrs->challengresp == NULL) {
        !          1119:                        Log(LOG_WARNING, ("L2TP: SCCRP lacks challenge response"));
        !          1120:                        ppp_l2tp_ctrl_close(ctrl,
        !          1121:                            L2TP_RESULT_NOT_AUTH, 0, NULL);
        !          1122:                        return (0);
        !          1123:                }
        !          1124: 
        !          1125:                /* Calculate challenge response */
        !          1126:                t = ptrs->message->mesgtype;
        !          1127:                MD5_Init(&md5ctx);
        !          1128:                MD5_Update(&md5ctx, &t, 1);
        !          1129:                MD5_Update(&md5ctx, ctrl->secret, ctrl->seclen);
        !          1130:                MD5_Update(&md5ctx, ctrl->chal, sizeof(ctrl->chal));
        !          1131:                MD5_Final(hash, &md5ctx);
        !          1132:                
        !          1133:                /* Check challenge response */
        !          1134:                if (bcmp(hash, &ptrs->challengresp->value, sizeof(hash))) {
        !          1135:                    Log(LOG_WARNING, ("L2TP: tunnel challenge/response incorrect"));
        !          1136:                    ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_NOT_AUTH, 0, NULL);
        !          1137:                    return (-1);
        !          1138:                }
        !          1139:        }
        !          1140: 
        !          1141:        if (pevent_register(ctrl->ctx, &ctrl->death_timer, 0,
        !          1142:            ctrl->mutex, ppp_l2tp_unused_timeout, ctrl,
        !          1143:            PEVENT_TIME, gL2TPto * 1000) == -1) {
        !          1144:                Perror("L2TP: error starting unused timer");
        !          1145:        }
        !          1146: 
        !          1147:        /* Done */
        !          1148:        return (0);
        !          1149: }
        !          1150: 
        !          1151: /*
        !          1152:  * Create a new session.
        !          1153:  */
        !          1154: static struct ppp_l2tp_sess *
        !          1155: ppp_l2tp_sess_create(struct ppp_l2tp_ctrl *ctrl,
        !          1156:        enum l2tp_sess_orig orig, enum l2tp_sess_side side, u_int32_t serial)
        !          1157: {
        !          1158:        struct ppp_l2tp_sess *sess = NULL;
        !          1159:        u_int16_t value16;
        !          1160:        u_int32_t value32;
        !          1161: 
        !          1162:        /* Create new session object */
        !          1163:        sess = Malloc(SESS_MEM_TYPE, sizeof(*sess));
        !          1164:        sess->ctrl = ctrl;
        !          1165:        sess->orig = orig;
        !          1166:        sess->side = side;
        !          1167:        sess->serial = serial;
        !          1168:        sess->state = (orig == ORIG_LOCAL) ? SS_WAIT_REPLY :
        !          1169:            (side == SIDE_LNS) ? SS_WAIT_CONNECT : SS_WAIT_ANSWER;
        !          1170: 
        !          1171:        /* Get unique session ID */
        !          1172:        while (sess->config.session_id == 0
        !          1173:            || ghash_get(ctrl->sessions, sess) != NULL)
        !          1174:                sess->config.session_id = random() & 0xffff;
        !          1175:        snprintf(sess->hook, sizeof(sess->hook),
        !          1176:            NG_L2TP_HOOK_SESSION_F, sess->config.session_id);
        !          1177: 
        !          1178:        pevent_unregister(&ctrl->death_timer);
        !          1179:        ctrl->active_sessions++;
        !          1180: 
        !          1181:        /* Add to control connection hash table */
        !          1182:        if (ghash_put(ctrl->sessions, sess) == -1) {
        !          1183:                ppp_l2tp_sess_destroy(&sess);
        !          1184:                return (NULL);
        !          1185:        }
        !          1186: 
        !          1187:        /* Create session AVP list to send to peer */
        !          1188:        sess->my_avps = ppp_l2tp_avp_list_create();
        !          1189: 
        !          1190:        /* Add assigned session ID AVP */
        !          1191:        value16 = htons(sess->config.session_id);
        !          1192:        if (ppp_l2tp_avp_list_append(sess->my_avps, 1,
        !          1193:            0, AVP_ASSIGNED_SESSION_ID, &value16, sizeof(value16)) == -1) {
        !          1194:                ppp_l2tp_sess_destroy(&sess);
        !          1195:                return (NULL);
        !          1196:        }
        !          1197: 
        !          1198:        if (orig == ORIG_LOCAL) {
        !          1199:            /* Add call serial number AVP */
        !          1200:            value32 = htonl(sess->serial);
        !          1201:            if (ppp_l2tp_avp_list_append(sess->my_avps, 1,
        !          1202:                0, AVP_CALL_SERIAL_NUMBER, &value32, sizeof(value32)) == -1) {
        !          1203:                    ppp_l2tp_sess_destroy(&sess);
        !          1204:                    return (NULL);
        !          1205:            }
        !          1206:        }
        !          1207: 
        !          1208:        /* Done */
        !          1209:        Log(LOG_DEBUG, ("L2TP: created new session #%u id 0x%04x orig=%s side=%s"
        !          1210:            " state=%s", sess->serial, sess->config.session_id,
        !          1211:            ppp_l2tp_sess_orig_str(sess->orig),
        !          1212:            ppp_l2tp_sess_side_str(sess->side),
        !          1213:            ppp_l2tp_sess_state_str(sess->state)));
        !          1214:        return (sess);
        !          1215: }
        !          1216: 
        !          1217: /*
        !          1218:  * Send a control message.
        !          1219:  */
        !          1220: static void
        !          1221: ppp_l2tp_ctrl_send(struct ppp_l2tp_ctrl *ctrl, u_int16_t session_id,
        !          1222:        enum l2tp_msg_type msgtype, const struct ppp_l2tp_avp_list *avps0)
        !          1223: {
        !          1224:        struct ppp_l2tp_avp_list *avps = NULL;
        !          1225:        struct ppp_l2tp_avp *avp = NULL;
        !          1226:        u_char *data = NULL;
        !          1227:        u_int16_t value;
        !          1228:        int index;
        !          1229:        int len;
        !          1230: 
        !          1231:        /* Copy AVP list */
        !          1232:        avps = (avps0 == NULL) ? ppp_l2tp_avp_list_create()
        !          1233:            : ppp_l2tp_avp_list_copy(avps0);
        !          1234:        if (avps == NULL)
        !          1235:                goto fail;
        !          1236: 
        !          1237:        /* Remove any message type AVP in the way */
        !          1238:        if ((index = ppp_l2tp_avp_list_find(avps, 0, AVP_MESSAGE_TYPE)) != -1)
        !          1239:                ppp_l2tp_avp_list_remove(avps, index);
        !          1240: 
        !          1241:        /* Add message type AVP as first in the list */
        !          1242:        value = htons(msgtype);
        !          1243:        avp = ppp_l2tp_avp_create(1, 0, AVP_MESSAGE_TYPE, &value, sizeof(value));
        !          1244:        if (ppp_l2tp_avp_list_insert(avps, &avp, 0) == -1)
        !          1245:                goto fail;
        !          1246: 
        !          1247:        /* Encoded AVP's into a packet */
        !          1248:        if ((len = ppp_l2tp_avp_pack(ppp_l2tp_avp_info_list,
        !          1249:            avps, (ctrl->hide_avps?ctrl->secret:NULL), ctrl->seclen, NULL)) == -1)
        !          1250:                goto fail;
        !          1251:        data = Malloc(TYPED_MEM_TEMP, 2 + len);
        !          1252:        session_id = htons(session_id);
        !          1253:        memcpy(data, &session_id, 2);
        !          1254:        (void)ppp_l2tp_avp_pack(ppp_l2tp_avp_info_list,
        !          1255:            avps, (ctrl->hide_avps?ctrl->secret:NULL), ctrl->seclen, data + 2);
        !          1256: 
        !          1257:        /* Write packet */
        !          1258:        if (session_id == 0)
        !          1259:                ppp_l2tp_ctrl_dump(ctrl, avps, "L2TP: XMIT ");
        !          1260:        else {
        !          1261:                ppp_l2tp_ctrl_dump(ctrl, avps, "L2TP: XMIT(0x%04x) ",
        !          1262:                    ntohs(session_id));
        !          1263:        }
        !          1264:        if (NgSendData(ctrl->dsock, NG_L2TP_HOOK_CTRL, data, 2 + len) == -1)
        !          1265:                goto fail;
        !          1266: 
        !          1267:        /* Done */
        !          1268:        goto done;
        !          1269: 
        !          1270: fail:
        !          1271:        /* Close up shop */
        !          1272:        Perror("L2TP: error sending ctrl packet");
        !          1273:        ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
        !          1274:            L2TP_ERROR_GENERIC, strerror(errno));
        !          1275: 
        !          1276: done:
        !          1277:        /* Clean up */
        !          1278:        ppp_l2tp_avp_destroy(&avp);
        !          1279:        ppp_l2tp_avp_list_destroy(&avps);
        !          1280:        Freee(data);
        !          1281: }
        !          1282: 
        !          1283: /*
        !          1284:  * Close a control connection gracefully, after the next context switch.
        !          1285:  */
        !          1286: static void
        !          1287: ppp_l2tp_ctrl_close(struct ppp_l2tp_ctrl *ctrl,
        !          1288:        u_int16_t result, u_int16_t error, const char *errmsg)
        !          1289: {
        !          1290:        /* Sanity check */
        !          1291:        if (ctrl->state == CS_DYING)
        !          1292:                return;
        !          1293:        ctrl->state = CS_DYING;
        !          1294: 
        !          1295:        /* Save result code and error string */
        !          1296:        ctrl->result = result;
        !          1297:        ctrl->error = error;
        !          1298:        Freee(ctrl->errmsg);
        !          1299:        ctrl->errmsg = (errmsg == NULL) ? NULL : Mstrdup(CTRL_MEM_TYPE, errmsg);
        !          1300: 
        !          1301:        /* Notify peer if necessary */
        !          1302:        if (!ctrl->peer_notified) {
        !          1303:                struct ppp_l2tp_avp_list *avps = NULL;
        !          1304:                const size_t elen = (ctrl->errmsg == NULL) ?
        !          1305:                    0 : strlen(ctrl->errmsg);
        !          1306:                struct ppp_l2tp_sess *sess;
        !          1307:                struct ghash_walk walk;
        !          1308:                u_char *rbuf = NULL;
        !          1309:                u_int16_t value16;
        !          1310: 
        !          1311:                /* Create AVP list */
        !          1312:                ctrl->peer_notified = 1;
        !          1313:                avps = ppp_l2tp_avp_list_create();
        !          1314: 
        !          1315:                /* Add assigned tunnel ID AVP */
        !          1316:                value16 = htons(ctrl->config.tunnel_id);
        !          1317:                if (ppp_l2tp_avp_list_append(avps, 1, 0,
        !          1318:                    AVP_ASSIGNED_TUNNEL_ID, &value16, sizeof(value16)) == -1) {
        !          1319:                        Perror("L2TP: ppp_l2tp_avp_list_append");
        !          1320:                        goto notify_done;
        !          1321:                }
        !          1322: 
        !          1323:                /* Add result code AVP */
        !          1324:                rbuf = Malloc(TYPED_MEM_TEMP, 4 + elen);
        !          1325:                value16 = htons(ctrl->result);
        !          1326:                memcpy(rbuf, &value16, sizeof(value16));
        !          1327:                value16 = htons(ctrl->error);
        !          1328:                memcpy(rbuf + 2, &value16, sizeof(value16));
        !          1329:                memcpy(rbuf + 4, ctrl->errmsg, elen);
        !          1330:                if (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_RESULT_CODE,
        !          1331:                    rbuf, 4 + elen) == -1) {
        !          1332:                        Perror("L2TP: ppp_l2tp_avp_list_append");
        !          1333:                        goto notify_done;
        !          1334:                }
        !          1335: 
        !          1336:                /* Send StopCCN */
        !          1337:                ppp_l2tp_ctrl_send(ctrl, 0, StopCCN, avps);
        !          1338: 
        !          1339:                /* StopCCN implies closing all sessions */
        !          1340:                ghash_walk_init(ctrl->sessions, &walk);
        !          1341:                while ((sess = ghash_walk_next(ctrl->sessions, &walk)) != NULL)
        !          1342:                        sess->peer_notified = 1;
        !          1343: 
        !          1344: notify_done:
        !          1345:                /* Clean up */
        !          1346:                ppp_l2tp_avp_list_destroy(&avps);
        !          1347:                Freee(rbuf);
        !          1348:        }
        !          1349: 
        !          1350:        /* Stop all timers */
        !          1351:        pevent_unregister(&ctrl->idle_timer);
        !          1352:        pevent_unregister(&ctrl->reply_timer);
        !          1353:        pevent_unregister(&ctrl->close_timer);
        !          1354:        pevent_unregister(&ctrl->death_timer);
        !          1355: 
        !          1356:        /* Start timer to call ppp_l2tp_ctrl_do_close() */
        !          1357:        if (pevent_register(ctrl->ctx, &ctrl->close_timer, 0, ctrl->mutex,
        !          1358:            ppp_l2tp_ctrl_do_close, ctrl, PEVENT_TIME, 0) == -1)
        !          1359:                Perror("L2TP: error starting close timer");
        !          1360: }
        !          1361: 
        !          1362: /*
        !          1363:  * Close a control connection gracefully.
        !          1364:  *
        !          1365:  * We call this in a separate event thread to avoid reentrancy problems.
        !          1366:  */
        !          1367: static void
        !          1368: ppp_l2tp_ctrl_do_close(void *arg)
        !          1369: {
        !          1370:        struct ppp_l2tp_ctrl *ctrl = arg;
        !          1371:        struct ppp_l2tp_sess *sess;
        !          1372:        struct ghash_walk walk;
        !          1373: 
        !          1374:        /* Remove event */
        !          1375:        pevent_unregister(&ctrl->close_timer);
        !          1376: 
        !          1377:        /* Notify link side about all sessions first */
        !          1378:        ghash_walk_init(ctrl->sessions, &walk);
        !          1379:        while ((sess = ghash_walk_next(ctrl->sessions, &walk)) != NULL) {
        !          1380:                if (sess->link_notified)
        !          1381:                        continue;
        !          1382:                sess->link_notified = 1;
        !          1383:                sess->result = L2TP_RESULT_ERROR;
        !          1384:                sess->error = L2TP_ERROR_GENERIC;
        !          1385:                Freee(sess->errmsg);
        !          1386:                sess->errmsg = Mdup(SESS_MEM_TYPE,
        !          1387:                    "control connection closing", strlen("control connection closing") + 1);
        !          1388:                (*ctrl->cb->terminated)(sess,
        !          1389:                    sess->result, sess->error, sess->errmsg);
        !          1390:        }
        !          1391: 
        !          1392:        /* Now notify link side about control connection */
        !          1393:        if (!ctrl->link_notified) {
        !          1394:                ctrl->link_notified = 1;
        !          1395:                (*ctrl->cb->ctrl_terminated)(ctrl, ctrl->result, ctrl->error,
        !          1396:                    (ctrl->errmsg != NULL) ? ctrl->errmsg : "");
        !          1397:        }
        !          1398: 
        !          1399:        /* If no active sessions exist, start dying */
        !          1400:        if (ctrl->active_sessions == 0) {
        !          1401:                ppp_l2tp_ctrl_death_start(ctrl);
        !          1402:                return;
        !          1403:        }
        !          1404: 
        !          1405:        /* Close all active sessions */
        !          1406:        ghash_walk_init(ctrl->sessions, &walk);
        !          1407:        while ((sess = ghash_walk_next(ctrl->sessions, &walk)) != NULL) {
        !          1408:                sess->peer_notified = 1;        /* no need to notify peer */
        !          1409:                ppp_l2tp_sess_close(sess, L2TP_RESULT_ERROR,
        !          1410:                    L2TP_ERROR_GENERIC, "control connection closing");
        !          1411:        }
        !          1412: }
        !          1413: 
        !          1414: /*
        !          1415:  * Notify link side that the control connection has gone away
        !          1416:  * and begin death timer.
        !          1417:  *
        !          1418:  * We rig things so that all the session death notifications happen
        !          1419:  * before the control connection notification, which happens here.
        !          1420:  */
        !          1421: static void
        !          1422: ppp_l2tp_ctrl_death_start(struct ppp_l2tp_ctrl *ctrl)
        !          1423: {
        !          1424:        /* Sanity */
        !          1425:        assert(ctrl->state == CS_DYING);
        !          1426: 
        !          1427:        /* Stop timers */
        !          1428:        pevent_unregister(&ctrl->idle_timer);
        !          1429:        pevent_unregister(&ctrl->reply_timer);
        !          1430:        pevent_unregister(&ctrl->death_timer);
        !          1431:        /* close_timer must not be touched! */
        !          1432: 
        !          1433:        /* Linger for a while before going away */
        !          1434:        if (pevent_register(ctrl->ctx, &ctrl->death_timer, 0,
        !          1435:            ctrl->mutex, ppp_l2tp_ctrl_death_timeout, ctrl,
        !          1436:            PEVENT_TIME, L2TP_CTRL_DEATH_TIMEOUT * 1000) == -1)
        !          1437:                Perror("L2TP: error starting death timer");
        !          1438: }
        !          1439: 
        !          1440: /*
        !          1441:  * Handle idle timeout on control connection.
        !          1442:  */
        !          1443: static void
        !          1444: ppp_l2tp_idle_timeout(void *arg)
        !          1445: {
        !          1446:        struct ppp_l2tp_ctrl *const ctrl = arg;
        !          1447: 
        !          1448:        /* Remove event */
        !          1449:        pevent_unregister(&ctrl->idle_timer);
        !          1450: 
        !          1451:        /* Restart idle timer */
        !          1452:        if (pevent_register(ctrl->ctx, &ctrl->idle_timer, 0,
        !          1453:            ctrl->mutex, ppp_l2tp_idle_timeout, ctrl, PEVENT_TIME,
        !          1454:            L2TP_IDLE_TIMEOUT * 1000) == -1)
        !          1455:                Perror("L2TP: error restarting idle timer");
        !          1456: 
        !          1457:        /* Send a 'hello' packet */
        !          1458:        ppp_l2tp_ctrl_send(ctrl, 0, HELLO, NULL);
        !          1459: }
        !          1460: 
        !          1461: /*
        !          1462:  * Handle unused timeout on control connection.
        !          1463:  */
        !          1464: static void
        !          1465: ppp_l2tp_unused_timeout(void *arg)
        !          1466: {
        !          1467:        struct ppp_l2tp_ctrl *const ctrl = arg;
        !          1468: 
        !          1469:        assert(ctrl->active_sessions == 0);
        !          1470:        assert(ctrl->state != CS_DYING);
        !          1471: 
        !          1472:        ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_CLEARED,
        !          1473:            0, "no more sessions exist in this tunnel");
        !          1474: }
        !          1475: 
        !          1476: /*
        !          1477:  * Remove a control connection that has been dead for a while.
        !          1478:  */
        !          1479: static void
        !          1480: ppp_l2tp_ctrl_death_timeout(void *arg)
        !          1481: {
        !          1482:        struct ppp_l2tp_ctrl *ctrl = arg;
        !          1483: 
        !          1484:        pevent_unregister(&ctrl->death_timer);
        !          1485:        if (*ctrl->cb->ctrl_destroyed != NULL)
        !          1486:            (*ctrl->cb->ctrl_destroyed)(ctrl);
        !          1487:        ppp_l2tp_ctrl_destroy(&ctrl);
        !          1488: }
        !          1489: 
        !          1490: /************************************************************************
        !          1491:                        INTERNAL FUNCTIONS: SESSIONS
        !          1492: ************************************************************************/
        !          1493: 
        !          1494: /*
        !          1495:  * This function handles the situation of a locally initiated incoming
        !          1496:  * call, i.e., we are the LAC. Before sending the ICCN to the LNS, two
        !          1497:  * events must happen: the LNS must reply with a ICRP, and the link
        !          1498:  * side must invoke the ppp_l2tp_connected() function.
        !          1499:  */
        !          1500: static int
        !          1501: ppp_l2tp_sess_check_liic(struct ppp_l2tp_sess *sess)
        !          1502: {
        !          1503:        struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
        !          1504: 
        !          1505:        /* Are we ready to send ICCN yet? */
        !          1506:        if (!sess->link_responded || !sess->peer_responded)
        !          1507:                return (0);
        !          1508: 
        !          1509:        /* Set up session */
        !          1510:        if (ppp_l2tp_sess_setup(sess) == -1)
        !          1511:                return (-1);
        !          1512: 
        !          1513:        /* Now send ICCN to peer */
        !          1514:        ppp_l2tp_ctrl_send(ctrl, sess->peer_id, ICCN, sess->my_avps);
        !          1515: 
        !          1516:        /* Done */
        !          1517:        return (0);
        !          1518: }
        !          1519: 
        !          1520: /*
        !          1521:  * Set up a session that has reached the established state.
        !          1522:  */
        !          1523: static int
        !          1524: ppp_l2tp_sess_setup(struct ppp_l2tp_sess *sess)
        !          1525: {
        !          1526:        struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
        !          1527:        struct ngm_mkpeer mkpeer;
        !          1528:        char path[64];
        !          1529: 
        !          1530:        /* If link side is waiting for confirmation, schedule it */
        !          1531:        if (sess->side == SIDE_LNS || sess->orig == ORIG_LOCAL) {
        !          1532:                pevent_unregister(&sess->notify_timer);
        !          1533:                if (pevent_register(ctrl->ctx, &sess->notify_timer, 0,
        !          1534:                    ctrl->mutex, ppp_l2tp_sess_notify, sess, PEVENT_TIME, 0) == -1) {
        !          1535:                        Perror("L2TP: error starting notify timer");
        !          1536:                        goto fail;
        !          1537:                }
        !          1538:        }
        !          1539: 
        !          1540:        /* Attach a 'tee' node so l2tp node never sees hook disconnect */
        !          1541:        memset(&mkpeer, 0, sizeof(mkpeer));
        !          1542:        strlcpy(mkpeer.type, NG_TEE_NODE_TYPE, sizeof(mkpeer.type));
        !          1543:        strlcpy(mkpeer.ourhook, sess->hook, sizeof(mkpeer.ourhook));
        !          1544:        strlcpy(mkpeer.peerhook, NG_TEE_HOOK_LEFT, sizeof(mkpeer.peerhook));
        !          1545:        if (NgSendMsg(ctrl->csock, NG_L2TP_HOOK_CTRL, NGM_GENERIC_COOKIE,
        !          1546:            NGM_MKPEER, &mkpeer, sizeof(mkpeer)) == -1) {
        !          1547:                Perror("L2TP: mkpeer");
        !          1548:                goto fail;
        !          1549:        }
        !          1550: 
        !          1551:        /* Get ng_tee node ID */
        !          1552:        snprintf(path, sizeof(path), "%s.%s", NG_L2TP_HOOK_CTRL, sess->hook);
        !          1553:        if ((sess->node_id = NgGetNodeID(ctrl->csock, path)) == 0) {
        !          1554:            Perror("L2TP: Cannot get %s node id", NG_TEE_NODE_TYPE);
        !          1555:            goto fail;
        !          1556:        };
        !          1557: 
        !          1558:        /* Configure session hook */
        !          1559:        if (sess->dseq_required) {
        !          1560:            sess->config.control_dseq = sess->dseq_required;
        !          1561:            sess->config.enable_dseq = 1;
        !          1562:        } else {
        !          1563:            sess->config.control_dseq = (sess->side == SIDE_LNS)?1:0;
        !          1564:            sess->config.enable_dseq = sess->enable_dseq;
        !          1565:        }
        !          1566:        sess->config.peer_id = sess->peer_id;
        !          1567:        sess->config.include_length = sess->include_length;
        !          1568:        if (NgSendMsg(ctrl->csock, NG_L2TP_HOOK_CTRL, NGM_L2TP_COOKIE,
        !          1569:            NGM_L2TP_SET_SESS_CONFIG, &sess->config,
        !          1570:            sizeof(sess->config)) == -1) {
        !          1571:                Perror("L2TP: error configuring session hook");
        !          1572:                goto fail;
        !          1573:        }
        !          1574: 
        !          1575:        /* Call is now established */
        !          1576:        sess->state = SS_ESTABLISHED;
        !          1577:        return (0);
        !          1578: 
        !          1579: fail:
        !          1580:        /* Clean up after failure */
        !          1581:        pevent_unregister(&sess->notify_timer);
        !          1582:        return (-1);
        !          1583: }
        !          1584: 
        !          1585: /*
        !          1586:  * Close a session gracefully, after the next context switch.
        !          1587:  */
        !          1588: static void
        !          1589: ppp_l2tp_sess_close(struct ppp_l2tp_sess *sess,
        !          1590:        u_int16_t result, u_int16_t error, const char *errmsg)
        !          1591: {
        !          1592:        struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
        !          1593: 
        !          1594:        /* Sanity check */
        !          1595:        if (sess->state == SS_DYING)
        !          1596:                return;
        !          1597:        sess->state = SS_DYING;
        !          1598: 
        !          1599:        /* Save result code and error string */
        !          1600:        sess->result = result;
        !          1601:        sess->error = error;
        !          1602:        Freee(sess->errmsg);
        !          1603:        sess->errmsg = (errmsg == NULL) ? NULL : Mstrdup(SESS_MEM_TYPE, errmsg);
        !          1604: 
        !          1605:        /* Notify peer if necessary */
        !          1606:        if (!sess->peer_notified) {
        !          1607:                struct ppp_l2tp_avp_list *avps = NULL;
        !          1608:                const size_t elen = (sess->errmsg == NULL) ?
        !          1609:                    0 : strlen(sess->errmsg);
        !          1610:                u_char *rbuf = NULL;
        !          1611:                u_int16_t value16;
        !          1612: 
        !          1613:                /* Create AVP list */
        !          1614:                sess->peer_notified = 1;
        !          1615:                avps = ppp_l2tp_avp_list_create();
        !          1616: 
        !          1617:                /* Add assigned session ID AVP */
        !          1618:                value16 = htons(sess->config.session_id);
        !          1619:                if (ppp_l2tp_avp_list_append(avps, 1, 0,
        !          1620:                    AVP_ASSIGNED_SESSION_ID, &value16, sizeof(value16)) == -1) {
        !          1621:                        Perror("L2TP: ppp_l2tp_avp_list_append");
        !          1622:                        goto notify_done;
        !          1623:                }
        !          1624: 
        !          1625:                /* Add result code AVP */
        !          1626:                rbuf = Malloc(TYPED_MEM_TEMP, 4 + elen);
        !          1627:                value16 = htons(sess->result);
        !          1628:                memcpy(rbuf, &value16, sizeof(value16));
        !          1629:                value16 = htons(sess->error);
        !          1630:                memcpy(rbuf + 2, &value16, sizeof(value16));
        !          1631:                memcpy(rbuf + 4, sess->errmsg, elen);
        !          1632:                if (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_RESULT_CODE,
        !          1633:                    rbuf, 4 + elen) == -1) {
        !          1634:                        Perror("L2TP: ppp_l2tp_avp_list_append");
        !          1635:                        goto notify_done;
        !          1636:                }
        !          1637: 
        !          1638:                /* Send CDN */
        !          1639:                ppp_l2tp_ctrl_send(ctrl, sess->peer_id, CDN, avps);
        !          1640: 
        !          1641: notify_done:
        !          1642:                /* Clean up */
        !          1643:                ppp_l2tp_avp_list_destroy(&avps);
        !          1644:                Freee(rbuf);
        !          1645:        }
        !          1646: 
        !          1647:        /* Stop all session timers */
        !          1648:        pevent_unregister(&sess->notify_timer);
        !          1649:        pevent_unregister(&sess->reply_timer);
        !          1650:        pevent_unregister(&sess->death_timer);
        !          1651:        pevent_unregister(&sess->close_timer);
        !          1652: 
        !          1653:        /* Start timer to call ppp_l2tp_sess_do_close() */
        !          1654:        if (pevent_register(ctrl->ctx, &sess->close_timer, 0,
        !          1655:            ctrl->mutex, ppp_l2tp_sess_do_close, sess, PEVENT_TIME, 0) == -1)
        !          1656:                Perror("L2TP: error starting close timer");
        !          1657: }
        !          1658: 
        !          1659: /*
        !          1660:  * Close a session gracefully.
        !          1661:  *
        !          1662:  * We call this in a separate event thread to avoid reentrancy problems.
        !          1663:  */
        !          1664: static void
        !          1665: ppp_l2tp_sess_do_close(void *arg)
        !          1666: {
        !          1667:        struct ppp_l2tp_sess *const sess = arg;
        !          1668:        struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
        !          1669: 
        !          1670:        /* Remove event */
        !          1671:        pevent_unregister(&sess->close_timer);
        !          1672: 
        !          1673:        ctrl->active_sessions--;
        !          1674: 
        !          1675:        /* Linger for a while before going away */
        !          1676:        if (pevent_register(ctrl->ctx, &sess->death_timer, 0,
        !          1677:            ctrl->mutex, ppp_l2tp_sess_death_timeout, sess, PEVENT_TIME,
        !          1678:            L2TP_SESS_DEATH_TIMEOUT * 1000) == -1)
        !          1679:                Perror("L2TP: error starting death timer");
        !          1680: 
        !          1681:        /* Notify link side about session if necessary */
        !          1682:        if (!sess->link_notified) {
        !          1683:                sess->link_notified = 1;
        !          1684:                (*ctrl->cb->terminated)(sess, sess->result, sess->error,
        !          1685:                    (sess->errmsg != NULL) ? sess->errmsg : "");
        !          1686:        }
        !          1687: 
        !          1688:        /* Close control connection after last session closes */
        !          1689:        if (ctrl->active_sessions == 0) {
        !          1690:                if (ctrl->state == CS_DYING) {
        !          1691:                        ppp_l2tp_ctrl_death_start(ctrl);
        !          1692:                } else if (pevent_register(ctrl->ctx, &ctrl->death_timer, 0,
        !          1693:                    ctrl->mutex, ppp_l2tp_unused_timeout, ctrl,
        !          1694:                    PEVENT_TIME, gL2TPto * 1000) == -1) {
        !          1695:                        Perror("L2TP: error starting unused timer");
        !          1696:                }
        !          1697:        }
        !          1698: }
        !          1699: 
        !          1700: /*
        !          1701:  * Notify link side that a session is connected.
        !          1702:  *
        !          1703:  * We call this in a separate event thread to avoid reentrancy problems.
        !          1704:  */
        !          1705: static void
        !          1706: ppp_l2tp_sess_notify(void *arg)
        !          1707: {
        !          1708:        struct ppp_l2tp_sess *const sess = arg;
        !          1709:        struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
        !          1710: 
        !          1711:        pevent_unregister(&sess->notify_timer);
        !          1712:        (*ctrl->cb->connected)(sess, sess->peer_avps);
        !          1713: }
        !          1714: 
        !          1715: /*
        !          1716:  * Remove a session that has been dead for a while.
        !          1717:  */
        !          1718: static void
        !          1719: ppp_l2tp_sess_death_timeout(void *arg)
        !          1720: {
        !          1721:        struct ppp_l2tp_sess *sess = arg;
        !          1722: 
        !          1723:        pevent_unregister(&sess->death_timer);
        !          1724:        ppp_l2tp_sess_destroy(&sess);
        !          1725: }
        !          1726: 
        !          1727: /************************************************************************
        !          1728:                        NETGRAPH SOCKET READERS
        !          1729: ************************************************************************/
        !          1730: 
        !          1731: /*
        !          1732:  * Read from netgraph data socket. This is where incoming L2TP
        !          1733:  * control connection messages appear.
        !          1734:  */
        !          1735: static void
        !          1736: ppp_l2tp_data_event(void *arg)
        !          1737: {
        !          1738:        struct ppp_l2tp_ctrl *const ctrl = arg;
        !          1739:        const struct l2tp_msg_info *msg_info;
        !          1740:        struct ppp_l2tp_avp_list *avps = NULL;
        !          1741:        struct ppp_l2tp_avp_ptrs *ptrs = NULL;
        !          1742:        struct ppp_l2tp_sess *sess;
        !          1743:        struct ppp_l2tp_sess key;
        !          1744:        static u_char buf[4096];
        !          1745:        u_int16_t msgtype;
        !          1746:        char ebuf[64];
        !          1747:        int len;
        !          1748:        int i;
        !          1749:        int j;
        !          1750: 
        !          1751:        /* Restart idle timer */
        !          1752:        pevent_unregister(&ctrl->idle_timer);
        !          1753:        if (pevent_register(ctrl->ctx, &ctrl->idle_timer, 0,
        !          1754:            ctrl->mutex, ppp_l2tp_idle_timeout, ctrl, PEVENT_TIME,
        !          1755:            L2TP_IDLE_TIMEOUT * 1000) == -1) {
        !          1756:                Perror("L2TP: error restarting idle timer");
        !          1757:                goto fail_errno;
        !          1758:        }
        !          1759: 
        !          1760:        /* Read packet */
        !          1761:        if ((len = read(ctrl->dsock, buf, sizeof(buf))) == -1) {
        !          1762:                Perror("L2TP: error reading ctrl hook");
        !          1763:                goto fail_errno;
        !          1764:        }
        !          1765: 
        !          1766:        /* Extract session ID */
        !          1767:        memcpy(&key.config.session_id, buf, 2);
        !          1768:        key.config.session_id = ntohs(key.config.session_id);
        !          1769: 
        !          1770:        /* Parse out AVP's */
        !          1771:        if ((avps = ppp_l2tp_avp_unpack(ppp_l2tp_avp_info_list,
        !          1772:            buf + 2, len - 2, ctrl->secret, ctrl->seclen)) == NULL) {
        !          1773:                switch (errno) {
        !          1774:                case EILSEQ:
        !          1775:                        Log(LOG_ERR,
        !          1776:                            ("L2TP: rec'd improperly formatted control message"));
        !          1777:                        goto fail_invalid;
        !          1778:                case EAUTH:
        !          1779:                        Log(LOG_ERR,
        !          1780:                            ("L2TP: rec'd hidden AVP, but no shared secret"));
        !          1781:                        ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
        !          1782:                            L2TP_ERROR_GENERIC, "hidden AVP found"
        !          1783:                            " but no shared secret configured");
        !          1784:                        goto done;
        !          1785:                case ENOSYS:
        !          1786:                        Log(LOG_ERR, ("L2TP: rec'd mandatory but unknown AVP"));
        !          1787:                        ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
        !          1788:                            L2TP_ERROR_MANDATORY, NULL);
        !          1789:                        goto done;
        !          1790:                default:
        !          1791:                        Perror("L2TP: error decoding control message");
        !          1792:                        goto fail_errno;
        !          1793:                }
        !          1794:        }
        !          1795: 
        !          1796:        /* Debugging */
        !          1797:        if (key.config.session_id == 0)
        !          1798:                ppp_l2tp_ctrl_dump(ctrl, avps, "L2TP: RECV ");
        !          1799:        else {
        !          1800:                ppp_l2tp_ctrl_dump(ctrl, avps, "L2TP: RECV(0x%04x) ",
        !          1801:                    ntohs(key.config.session_id));
        !          1802:        }
        !          1803: 
        !          1804:        /* Message type AVP must be present and first */
        !          1805:        if (avps->length == 0 || avps->avps[0].type != AVP_MESSAGE_TYPE) {
        !          1806:                Log(LOG_WARNING,
        !          1807:                    ("L2TP: rec'd ctrl message lacking message type AVP"));
        !          1808:                goto fail_invalid;
        !          1809:        }
        !          1810: 
        !          1811:        /* Get message type from message type AVP */
        !          1812:        memcpy(&msgtype, avps->avps[0].value, 2);
        !          1813:        msgtype = ntohs(msgtype);
        !          1814: 
        !          1815:        /* Find descriptor for this message type */
        !          1816:        for (i = 0; ppp_l2tp_msg_info[i].name != NULL
        !          1817:            && msgtype != ppp_l2tp_msg_info[i].type; i++);
        !          1818:        if ((msg_info = &ppp_l2tp_msg_info[i])->name == NULL) {
        !          1819:                if (avps->avps[0].mandatory) {
        !          1820:                        snprintf(ebuf, sizeof(ebuf), "rec'd unsupported"
        !          1821:                            " but mandatory message type %u", msgtype);
        !          1822:                        Log(LOG_WARNING, ("L2TP: %s", ebuf));
        !          1823:                        ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
        !          1824:                            L2TP_ERROR_BAD_VALUE, ebuf);
        !          1825:                        goto done;
        !          1826:                }
        !          1827:                Log(LOG_NOTICE,
        !          1828:                    ("L2TP: rec'd unknown message type %u; ignoring", msgtype));
        !          1829:                goto done;                              /* just ignore it */
        !          1830:        }
        !          1831: 
        !          1832:        /* Check for missing required AVP's */
        !          1833:        for (i = 0; msg_info->req_avps[i] != -1; i++) {
        !          1834:                for (j = 0; j < avps->length
        !          1835:                    && avps->avps[j].type != msg_info->req_avps[i]; j++);
        !          1836:                if (j == avps->length) {
        !          1837:                        snprintf(ebuf, sizeof(ebuf), "rec'd %s control"
        !          1838:                            " message lacking required AVP #%u",
        !          1839:                            msg_info->name, msg_info->req_avps[i]);
        !          1840:                        ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
        !          1841:                            L2TP_ERROR_BAD_VALUE, ebuf);
        !          1842:                        goto done;
        !          1843:                }
        !          1844:        }
        !          1845: 
        !          1846:        /* Convert AVP's to friendly form */
        !          1847:        if ((ptrs = ppp_l2tp_avp_list2ptrs(avps)) == NULL) {
        !          1848:                Perror("L2TP: error decoding AVP list");
        !          1849:                goto fail_errno;
        !          1850:        }
        !          1851: 
        !          1852:        /* If this is a tunnel-level command, do it */
        !          1853:        if (msg_info->ctrl_handler != NULL) {
        !          1854: 
        !          1855:                /* Check for valid control connection state */
        !          1856:                for (i = 0; msg_info->valid_states[i] != -1
        !          1857:                    && msg_info->valid_states[i] != ctrl->state; i++);
        !          1858:                if (msg_info->valid_states[i] == -1) {
        !          1859: 
        !          1860:                        /* Could be in CS_DYING if we just closed the tunnel */
        !          1861:                        if (ctrl->state == CS_DYING) {
        !          1862:                                snprintf(ebuf, sizeof(ebuf),
        !          1863:                                    "ignoring %s in state %s", msg_info->name,
        !          1864:                                    ppp_l2tp_ctrl_state_str(ctrl->state));
        !          1865:                                Log(LOG_INFO, ("L2TP: %s", ebuf));
        !          1866:                                goto done;
        !          1867:                        }
        !          1868: 
        !          1869:                        /* Log a warning message because the peer is broken */
        !          1870:                        snprintf(ebuf, sizeof(ebuf),
        !          1871:                            "rec'd %s in state %s", msg_info->name,
        !          1872:                            ppp_l2tp_ctrl_state_str(ctrl->state));
        !          1873:                        Log(LOG_WARNING, ("L2TP: %s", ebuf));
        !          1874:                        ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_FSM, 0, ebuf);
        !          1875:                        goto done;
        !          1876:                }
        !          1877: 
        !          1878:                /* Cancel reply timer and invoke handler */
        !          1879:                Log((msgtype == HELLO) ? LOG_DEBUG : LOG_INFO,
        !          1880:                    ("L2TP: rec'd %s in state %s", msg_info->name,
        !          1881:                    ppp_l2tp_ctrl_state_str(ctrl->state)));
        !          1882:                pevent_unregister(&ctrl->reply_timer);
        !          1883:                if ((*msg_info->ctrl_handler)(ctrl, avps, ptrs) == -1)
        !          1884:                        goto fail_errno;
        !          1885: 
        !          1886:                /* If we're now expecting a reply, start expecting it */
        !          1887:                ppp_l2tp_ctrl_check_reply(ctrl);
        !          1888:                goto done;
        !          1889:        }
        !          1890: 
        !          1891:        /* Find associated session */
        !          1892:        if (key.config.session_id == 0) {
        !          1893:                struct ghash_walk walk;
        !          1894: 
        !          1895:                /* This should only happen with CDN messages */
        !          1896:                if (msgtype != CDN) {
        !          1897:                        Log(LOG_NOTICE, ("L2TP: rec'd %s with zero session ID",
        !          1898:                            msg_info->name));
        !          1899:                        goto done;
        !          1900:                }
        !          1901: 
        !          1902:                /* Find session with 'reverse lookup' using peer's session ID */
        !          1903:                ghash_walk_init(ctrl->sessions, &walk);
        !          1904:                while ((sess = ghash_walk_next(ctrl->sessions, &walk)) != NULL
        !          1905:                    && sess->peer_id != key.config.session_id);
        !          1906:                if (sess == NULL)
        !          1907:                        goto done;
        !          1908:        } else if ((sess = ghash_get(ctrl->sessions, &key)) == NULL) {
        !          1909:                Log(LOG_NOTICE, ("L2TP: rec'd %s for unknown session 0x%04x",
        !          1910:                    msg_info->name, key.config.session_id));
        !          1911:                goto done;
        !          1912:        }
        !          1913: 
        !          1914:        /* Check for valid session state, origination, and side */
        !          1915:        for (i = 0; msg_info->valid_states[i] != -1
        !          1916:            && msg_info->valid_states[i] != sess->state; i++);
        !          1917:        if (msg_info->valid_states[i] == -1) {
        !          1918:                snprintf(ebuf, sizeof(ebuf), "rec'd %s in state %s",
        !          1919:                    msg_info->name, ppp_l2tp_sess_state_str(sess->state));
        !          1920:                Log(LOG_WARNING, ("L2TP: %s", ebuf));
        !          1921:                ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_FSM, 0, ebuf);
        !          1922:                goto done;
        !          1923:        }
        !          1924:        for (i = 0; msg_info->valid_orig[i] != -1
        !          1925:            && msg_info->valid_orig[i] != sess->orig; i++);
        !          1926:        if (msg_info->valid_orig[i] == -1) {
        !          1927:                snprintf(ebuf, sizeof(ebuf), "rec'd %s in state %s,"
        !          1928:                    " but session originated %sly", msg_info->name,
        !          1929:                    ppp_l2tp_sess_state_str(sess->state),
        !          1930:                    ppp_l2tp_sess_orig_str(sess->orig));
        !          1931:                Log(LOG_WARNING, ("L2TP: %s", ebuf));
        !          1932:                ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_FSM, 0, ebuf);
        !          1933:                goto done;
        !          1934:        }
        !          1935:        for (i = 0; msg_info->valid_side[i] != -1
        !          1936:            && msg_info->valid_side[i] != sess->side; i++);
        !          1937:        if (msg_info->valid_side[i] == -1) {
        !          1938:                snprintf(ebuf, sizeof(ebuf), "rec'd %s in state %s,"
        !          1939:                    " but we are %s for this session", msg_info->name,
        !          1940:                    ppp_l2tp_sess_state_str(sess->state),
        !          1941:                    ppp_l2tp_sess_side_str(sess->side));
        !          1942:                Log(LOG_WARNING, ("L2TP: %s", ebuf));
        !          1943:                ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_FSM, 0, ebuf);
        !          1944:                goto done;
        !          1945:        }
        !          1946: 
        !          1947:        /* Cancel reply timer and invoke handler */
        !          1948:        Log(LOG_INFO, ("L2TP: rec'd %s in state %s",
        !          1949:            msg_info->name, ppp_l2tp_sess_state_str(sess->state)));
        !          1950:        pevent_unregister(&sess->reply_timer);
        !          1951:        if ((*msg_info->sess_handler)(sess, avps, ptrs) == -1)
        !          1952:                goto fail_errno;
        !          1953: 
        !          1954:        /* If we're now expecting a reply, start expecting it */
        !          1955:        ppp_l2tp_sess_check_reply(sess);
        !          1956:        goto done;
        !          1957: 
        !          1958: fail_invalid:
        !          1959:        /* Fail because of a bogus message */
        !          1960:        ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
        !          1961:            L2TP_ERROR_BAD_VALUE, "improperly formatted control message");
        !          1962:        goto done;
        !          1963: 
        !          1964: fail_errno:
        !          1965:        /* Fail because of a system error */
        !          1966:        ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
        !          1967:            L2TP_ERROR_GENERIC, strerror(errno));
        !          1968: 
        !          1969: done:
        !          1970:        /* Clean up */
        !          1971:        ppp_l2tp_avp_list_destroy(&avps);
        !          1972:        ppp_l2tp_avp_ptrs_destroy(&ptrs);
        !          1973: }
        !          1974: 
        !          1975: /*
        !          1976:  * Read from netgraph control socket. This is where incoming
        !          1977:  * netgraph control messages appear.
        !          1978:  */
        !          1979: static void
        !          1980: ppp_l2tp_ctrl_event(void *arg)
        !          1981: {
        !          1982:        struct ppp_l2tp_ctrl *const ctrl = arg;
        !          1983:        union {
        !          1984:            u_char buf[128];
        !          1985:            struct ng_mesg msg;
        !          1986:        } buf;
        !          1987:        struct ng_mesg *const msg = &buf.msg;
        !          1988:        char raddr[NG_PATHSIZ];
        !          1989: 
        !          1990:        /* Read netgraph control message */
        !          1991:        if (NgRecvMsg(ctrl->csock, msg, sizeof(buf), raddr) < 0) {
        !          1992:                Perror("L2TP: error reading control message");
        !          1993:                ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
        !          1994:                    L2TP_ERROR_GENERIC, strerror(errno));
        !          1995:                return;
        !          1996:        }
        !          1997: 
        !          1998:        /* Examine message */
        !          1999:        switch (msg->header.typecookie) {
        !          2000:        case NGM_L2TP_COOKIE:
        !          2001:                switch (msg->header.cmd) {
        !          2002:                case NGM_L2TP_ACK_FAILURE:
        !          2003:                        if (ctrl->state != CS_DYING) {
        !          2004:                                Log(LOG_WARNING,
        !          2005:                                    ("L2TP: acknowledgement timeout"));
        !          2006:                                ppp_l2tp_ctrl_close(ctrl,
        !          2007:                                    L2TP_RESULT_CLEARED, 0, NULL);
        !          2008:                        }
        !          2009:                        break;
        !          2010:                default:
        !          2011:                        break;
        !          2012:                }
        !          2013:                break;
        !          2014:        default:
        !          2015:                break;
        !          2016:        }
        !          2017: }
        !          2018: 
        !          2019: /************************************************************************
        !          2020:                    INCOMING CONTROL MESSAGE HANDLERS
        !          2021: ************************************************************************/
        !          2022: 
        !          2023: static int
        !          2024: ppp_l2tp_handle_SCCRQ(struct ppp_l2tp_ctrl *ctrl,
        !          2025:        const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
        !          2026: {
        !          2027:        struct ppp_l2tp_ctrl *ctrl2;
        !          2028:        const u_char *tiebreaker;
        !          2029:        struct ghash_walk walk;
        !          2030:        int diff;
        !          2031:        int i;
        !          2032: 
        !          2033:        /* See if there is an outstanding SCCRQ to this peer */
        !          2034:        ghash_walk_init(ppp_l2tp_ctrls, &walk);
        !          2035:        while ((ctrl2 = ghash_walk_next(ppp_l2tp_ctrls, &walk)) != NULL) {
        !          2036:                if (ctrl2 != ctrl
        !          2037:                    && ctrl2->peer_id == ctrl->peer_id
        !          2038:                    && ctrl2->state == CS_WAIT_CTL_REPLY)
        !          2039:                        break;
        !          2040:        }
        !          2041:        if (ctrl2 == NULL)
        !          2042:                goto ok;
        !          2043: 
        !          2044:        /* Determine if we used a tie-breaker in our SCCRQ */
        !          2045:        for (tiebreaker = NULL, i = 0; i < ctrl2->avps->length; i++) {
        !          2046:                struct ppp_l2tp_avp *const avp = &ctrl2->avps->avps[i];
        !          2047: 
        !          2048:                if (avp->vendor == 0 && avp->type == AVP_TIE_BREAKER) {
        !          2049:                        tiebreaker = avp->value;
        !          2050:                        break;
        !          2051:                }
        !          2052:        }
        !          2053: 
        !          2054:        /* If neither side used a tie-breaker, allow this connection */
        !          2055:        if (tiebreaker == NULL && ptrs->tiebreaker == NULL)
        !          2056:                goto ok;
        !          2057: 
        !          2058:        /* Compare tie-breaker values to see who wins */
        !          2059:        if (tiebreaker == NULL)                         /* peer wins */
        !          2060:                diff = 1;
        !          2061:        else if (ptrs->tiebreaker == NULL)              /* i win */
        !          2062:                diff = -1;
        !          2063:        else                                            /* compare values */
        !          2064:                diff = memcmp(tiebreaker, &ptrs->tiebreaker->value, 8);
        !          2065:        if (diff == 0) {                                /* we both lose */
        !          2066:                Log(LOG_NOTICE, ("L2TP: SCCRQ tie: we both lose"));
        !          2067:                ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_DUP_CTRL, 0, NULL);
        !          2068:                ppp_l2tp_ctrl_close(ctrl2, L2TP_RESULT_DUP_CTRL, 0, NULL);
        !          2069:                return (0);
        !          2070:        }
        !          2071:        if (diff > 0) {                                 /* i win */
        !          2072:                Log(LOG_NOTICE, ("L2TP: SCCRQ tie: peer loses"));
        !          2073:                ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_DUP_CTRL, 0, NULL);
        !          2074:                return (0);
        !          2075:        }
        !          2076:        Log(LOG_NOTICE, ("L2TP: SCCRQ tie: peer wins"));
        !          2077:        ppp_l2tp_ctrl_close(ctrl2, L2TP_RESULT_DUP_CTRL, 0, NULL);
        !          2078: 
        !          2079: ok:
        !          2080:        /* Do control connection setup */
        !          2081:        if (ppp_l2tp_ctrl_setup_1(ctrl, ptrs) == -1)
        !          2082:                return (-1);
        !          2083: 
        !          2084:        /* Send response and update state */
        !          2085:        ctrl->state = CS_WAIT_CTL_CONNECT;
        !          2086:        ppp_l2tp_ctrl_send(ctrl, 0, SCCRP, ctrl->avps);
        !          2087:        return (0);
        !          2088: }
        !          2089: 
        !          2090: static int
        !          2091: ppp_l2tp_handle_SCCRP(struct ppp_l2tp_ctrl *ctrl,
        !          2092:        const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
        !          2093: {
        !          2094:        /* Do control connection setup */
        !          2095:        if (ppp_l2tp_ctrl_setup_1(ctrl, ptrs) == -1)
        !          2096:                return (-1);
        !          2097:        if (ppp_l2tp_ctrl_setup_2(ctrl, ptrs) == -1)
        !          2098:                return (-1);
        !          2099: 
        !          2100:        /* Send response and update state */
        !          2101:        ctrl->state = CS_ESTABLISHED;
        !          2102:        ppp_l2tp_ctrl_send(ctrl, 0, SCCCN, ctrl->avps);
        !          2103:        if (*ctrl->cb->ctrl_connected != NULL)
        !          2104:            (*ctrl->cb->ctrl_connected)(ctrl);
        !          2105:        return (0);
        !          2106: }
        !          2107: 
        !          2108: static int
        !          2109: ppp_l2tp_handle_SCCCN(struct ppp_l2tp_ctrl *ctrl,
        !          2110:        const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
        !          2111: {
        !          2112:        /* Do control connection setup */
        !          2113:        if (ppp_l2tp_ctrl_setup_2(ctrl, ptrs) == -1)
        !          2114:                return (-1);
        !          2115: 
        !          2116:        /* Update state */
        !          2117:        ctrl->state = CS_ESTABLISHED;
        !          2118:        if (*ctrl->cb->ctrl_connected != NULL)
        !          2119:            (*ctrl->cb->ctrl_connected)(ctrl);
        !          2120:        return (0);
        !          2121: }
        !          2122: 
        !          2123: static int
        !          2124: ppp_l2tp_handle_StopCCN(struct ppp_l2tp_ctrl *ctrl,
        !          2125:        const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
        !          2126: {
        !          2127:        struct ppp_l2tp_sess *sess;
        !          2128:        struct ghash_walk walk;
        !          2129: 
        !          2130:        /* StopCCN implies closing all sessions */
        !          2131:        ctrl->peer_notified = 1;
        !          2132:        ghash_walk_init(ctrl->sessions, &walk);
        !          2133:        while ((sess = ghash_walk_next(ctrl->sessions, &walk)) != NULL)
        !          2134:                sess->peer_notified = 1;
        !          2135: 
        !          2136:        /* Close control connection */
        !          2137:        ppp_l2tp_ctrl_close(ctrl, ptrs->errresultcode->result,
        !          2138:            ptrs->errresultcode->error, ptrs->errresultcode->errmsg);
        !          2139:        return (0);
        !          2140: }
        !          2141: 
        !          2142: static int
        !          2143: ppp_l2tp_handle_HELLO(struct ppp_l2tp_ctrl *ctrl,
        !          2144:        const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
        !          2145: {
        !          2146:        return (0);
        !          2147: }
        !          2148: 
        !          2149: static int
        !          2150: ppp_l2tp_handle_OCRQ(struct ppp_l2tp_ctrl *ctrl,
        !          2151:        const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
        !          2152: {
        !          2153:        struct ppp_l2tp_sess *sess;
        !          2154: 
        !          2155:        /* Create new session */
        !          2156:        if ((sess = ppp_l2tp_sess_create(ctrl, ORIG_REMOTE, SIDE_LAC,
        !          2157:            ptrs->serialnum->serialnum)) == NULL)
        !          2158:                return (-1);
        !          2159:        sess->peer_id = ptrs->sessionid->id;
        !          2160: 
        !          2161:        /* Notify link side */
        !          2162:        (*ctrl->cb->initiated)(ctrl, sess, 1, avps, &sess->include_length, &sess->enable_dseq);
        !          2163: 
        !          2164:        if (sess->state != SS_DYING) {
        !          2165:                /* Send response */
        !          2166:                ppp_l2tp_ctrl_send(ctrl, sess->peer_id, OCRP, sess->my_avps);
        !          2167:        }
        !          2168: 
        !          2169:        /* Clean up */
        !          2170:        return (0);
        !          2171: }
        !          2172: 
        !          2173: static int
        !          2174: ppp_l2tp_handle_ICRQ(struct ppp_l2tp_ctrl *ctrl,
        !          2175:        const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
        !          2176: {
        !          2177:        struct ppp_l2tp_sess *sess;
        !          2178: 
        !          2179:        /* Create new session */
        !          2180:        if ((sess = ppp_l2tp_sess_create(ctrl, ORIG_REMOTE, SIDE_LNS,
        !          2181:            ptrs->serialnum->serialnum)) == NULL)
        !          2182:                return (-1);
        !          2183:        sess->peer_id = ptrs->sessionid->id;
        !          2184: 
        !          2185:        /* Notify link side */
        !          2186:        (*ctrl->cb->initiated)(ctrl, sess, 0, avps, &sess->include_length, &sess->enable_dseq);
        !          2187: 
        !          2188:        if (sess->state != SS_DYING) {
        !          2189:                /* Send response */
        !          2190:                ppp_l2tp_ctrl_send(ctrl, sess->peer_id, ICRP, sess->my_avps);
        !          2191:                ppp_l2tp_sess_check_reply(sess);
        !          2192:        }
        !          2193: 
        !          2194:        /* Clean up */
        !          2195:        return (0);
        !          2196: }
        !          2197: 
        !          2198: static int
        !          2199: ppp_l2tp_handle_OCRP(struct ppp_l2tp_sess *sess,
        !          2200:        const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
        !          2201: {
        !          2202:        if (sess->state == SS_DYING)
        !          2203:                return (0);
        !          2204: 
        !          2205:        sess->peer_id = ptrs->sessionid->id;
        !          2206:        sess->state = SS_WAIT_CONNECT;
        !          2207:        return (0);
        !          2208: }
        !          2209: 
        !          2210: static int
        !          2211: ppp_l2tp_handle_xCCN(struct ppp_l2tp_sess *sess,
        !          2212:        const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
        !          2213: {
        !          2214:        if (sess->state == SS_DYING)
        !          2215:                return (0);
        !          2216: 
        !          2217:        /* Save peer's AVP's for this session */
        !          2218:        ppp_l2tp_avp_list_destroy(&sess->peer_avps);
        !          2219:        if ((sess->peer_avps = ppp_l2tp_avp_list_copy(avps)) == NULL)
        !          2220:                return (-1);
        !          2221: 
        !          2222:        /* Set up session */
        !          2223:        sess->dseq_required = (ptrs->seqrequired != NULL);
        !          2224:        if (ppp_l2tp_sess_setup(sess) == -1)
        !          2225:                return (-1);
        !          2226: 
        !          2227:        /* Done */
        !          2228:        return (0);
        !          2229: }
        !          2230: 
        !          2231: static int
        !          2232: ppp_l2tp_handle_ICRP(struct ppp_l2tp_sess *sess,
        !          2233:        const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
        !          2234: {
        !          2235:        struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
        !          2236:        char buf[64];
        !          2237:        
        !          2238:        if (sess->state == SS_DYING)
        !          2239:                return (0);
        !          2240: 
        !          2241:        /* Save peer ID */
        !          2242:        sess->peer_id = ptrs->sessionid->id;
        !          2243: 
        !          2244:        /* Detect duplicate ICRP's */
        !          2245:        if (sess->peer_responded) {
        !          2246:                snprintf(buf, sizeof(buf), "rec'd duplicate %s in state %s",
        !          2247:                    "ICRP", ppp_l2tp_sess_state_str(sess->state));
        !          2248:                Log(LOG_WARNING, ("L2TP: %s", buf));
        !          2249:                ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_FSM, 0, buf);
        !          2250:                return (0);
        !          2251:        }
        !          2252: 
        !          2253:        /* Check status for locally initiated incoming call */
        !          2254:        sess->peer_responded = 1;
        !          2255:        if (ppp_l2tp_sess_check_liic(sess) == -1)
        !          2256:                return (-1);
        !          2257: 
        !          2258:        /* Done */
        !          2259:        return (0);
        !          2260: }
        !          2261: 
        !          2262: static int
        !          2263: ppp_l2tp_handle_CDN(struct ppp_l2tp_sess *sess,
        !          2264:        const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
        !          2265: {
        !          2266:        sess->peer_notified = 1;
        !          2267:        ppp_l2tp_sess_close(sess, ptrs->errresultcode->result,
        !          2268:            ptrs->errresultcode->error, ptrs->errresultcode->errmsg);
        !          2269:        return (0);
        !          2270: }
        !          2271: 
        !          2272: static int
        !          2273: ppp_l2tp_handle_SLI(struct ppp_l2tp_sess *sess,
        !          2274:        const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
        !          2275: {
        !          2276:        struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
        !          2277: 
        !          2278:        if (sess->state == SS_DYING)
        !          2279:                return (0);
        !          2280: 
        !          2281:        if (ctrl->cb->set_link_info == NULL)
        !          2282:                return (0);
        !          2283:        (*ctrl->cb->set_link_info)(sess, ptrs->accm->xmit, ptrs->accm->recv);
        !          2284:        return (0);
        !          2285: }
        !          2286: 
        !          2287: static int
        !          2288: ppp_l2tp_handle_WEN(struct ppp_l2tp_sess *sess,
        !          2289:        const struct ppp_l2tp_avp_list *avps, struct ppp_l2tp_avp_ptrs *ptrs)
        !          2290: {
        !          2291:        struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
        !          2292: 
        !          2293:        if (sess->state == SS_DYING)
        !          2294:                return (0);
        !          2295: 
        !          2296:        if (ctrl->cb->wan_error_notify == NULL)
        !          2297:                return (0);
        !          2298:        (*ctrl->cb->wan_error_notify)(sess, ptrs->callerror->crc,
        !          2299:            ptrs->callerror->frame, ptrs->callerror->overrun,
        !          2300:            ptrs->callerror->buffer, ptrs->callerror->timeout,
        !          2301:            ptrs->callerror->alignment);
        !          2302:        return (0);
        !          2303: }
        !          2304: 
        !          2305: /************************************************************************
        !          2306:                        REPLY EXPECTORS
        !          2307: ************************************************************************/
        !          2308: 
        !          2309: static pevent_handler_t        ppp_l2tp_ctrl_reply_timeout;
        !          2310: static pevent_handler_t        ppp_l2tp_sess_reply_timeout;
        !          2311: 
        !          2312: static void
        !          2313: ppp_l2tp_ctrl_check_reply(struct ppp_l2tp_ctrl *ctrl)
        !          2314: {
        !          2315:        pevent_unregister(&ctrl->reply_timer);
        !          2316:        switch (ctrl->state) {
        !          2317:        case CS_IDLE:
        !          2318:        case CS_WAIT_CTL_REPLY:
        !          2319:        case CS_WAIT_CTL_CONNECT:
        !          2320:                if (pevent_register(ctrl->ctx, &ctrl->reply_timer, 0,
        !          2321:                    ctrl->mutex, ppp_l2tp_ctrl_reply_timeout, ctrl, PEVENT_TIME,
        !          2322:                    L2TP_REPLY_TIMEOUT * 1000) == -1)
        !          2323:                        Perror("L2TP: error starting reply timer");
        !          2324:                break;
        !          2325:        default:
        !          2326:                break;
        !          2327:        }
        !          2328: }
        !          2329: 
        !          2330: static void
        !          2331: ppp_l2tp_sess_check_reply(struct ppp_l2tp_sess *sess)
        !          2332: {
        !          2333:        struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
        !          2334: 
        !          2335:        pevent_unregister(&sess->reply_timer);
        !          2336:        switch (sess->state) {
        !          2337:        case SS_WAIT_REPLY:
        !          2338:        case SS_WAIT_CONNECT:
        !          2339:                if (pevent_register(ctrl->ctx, &sess->reply_timer, 0,
        !          2340:                    ctrl->mutex, ppp_l2tp_sess_reply_timeout, sess, PEVENT_TIME,
        !          2341:                    L2TP_REPLY_TIMEOUT * 1000) == -1)
        !          2342:                        Perror("L2TP: error starting reply timer");
        !          2343:                break;
        !          2344:        default:
        !          2345:                break;
        !          2346:        }
        !          2347: }
        !          2348: 
        !          2349: static void
        !          2350: ppp_l2tp_ctrl_reply_timeout(void *arg)
        !          2351: {
        !          2352:        struct ppp_l2tp_ctrl *const ctrl = arg;
        !          2353: 
        !          2354:        pevent_unregister(&ctrl->reply_timer);
        !          2355:        Log(LOG_NOTICE, ("L2TP: reply timeout in state %s",
        !          2356:            ppp_l2tp_ctrl_state_str(ctrl->state)));
        !          2357:        ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
        !          2358:            L2TP_ERROR_GENERIC, "expecting reply; none received");
        !          2359: }
        !          2360: 
        !          2361: static void
        !          2362: ppp_l2tp_sess_reply_timeout(void *arg)
        !          2363: {
        !          2364:        struct ppp_l2tp_sess *const sess = arg;
        !          2365:        struct ppp_l2tp_ctrl *const ctrl = sess->ctrl;
        !          2366: 
        !          2367:        pevent_unregister(&sess->reply_timer);
        !          2368:        Log(LOG_NOTICE, ("L2TP: reply timeout in state %s",
        !          2369:            ppp_l2tp_sess_state_str(sess->state)));
        !          2370:        ppp_l2tp_ctrl_close(ctrl, L2TP_RESULT_ERROR,
        !          2371:            L2TP_ERROR_GENERIC, "expecting reply; none received");
        !          2372: }
        !          2373: 
        !          2374: /************************************************************************
        !          2375:                CONTROL AND SESSION OBJECT DESTRUCTORS
        !          2376: ************************************************************************/
        !          2377: 
        !          2378: /*
        !          2379:  * Immediately destroy a control connection and all associated sessions.
        !          2380:  */
        !          2381: void
        !          2382: ppp_l2tp_ctrl_destroy(struct ppp_l2tp_ctrl **ctrlp)
        !          2383: {
        !          2384:        struct ppp_l2tp_ctrl *const ctrl = *ctrlp;
        !          2385: 
        !          2386:        /* Sanity */
        !          2387:        if (ctrl == NULL)
        !          2388:                return;
        !          2389:        *ctrlp = NULL;
        !          2390: 
        !          2391:        /* Destroy all sessions */
        !          2392:        while (ghash_size(ctrl->sessions) > 0) {
        !          2393:                struct ppp_l2tp_sess *sess;
        !          2394:                struct ghash_walk walk;
        !          2395: 
        !          2396:                ghash_walk_init(ctrl->sessions, &walk);
        !          2397:                sess = ghash_walk_next(ctrl->sessions, &walk);
        !          2398:                ppp_l2tp_sess_destroy(&sess);
        !          2399:        }
        !          2400: 
        !          2401:        /* Destroy netgraph node */
        !          2402:        (void)NgSendMsg(ctrl->csock, NG_L2TP_HOOK_CTRL,
        !          2403:            NGM_GENERIC_COOKIE, NGM_SHUTDOWN, NULL, 0);
        !          2404: 
        !          2405:        /* Destroy control connection */
        !          2406:        ghash_remove(ppp_l2tp_ctrls, ctrl);
        !          2407:        if (ghash_size(ppp_l2tp_ctrls) == 0)
        !          2408:                ghash_destroy(&ppp_l2tp_ctrls);
        !          2409:        (void)close(ctrl->csock);
        !          2410:        (void)close(ctrl->dsock);
        !          2411:        pevent_unregister(&ctrl->reply_timer);
        !          2412:        pevent_unregister(&ctrl->close_timer);
        !          2413:        pevent_unregister(&ctrl->death_timer);
        !          2414:        pevent_unregister(&ctrl->idle_timer);
        !          2415:        pevent_unregister(&ctrl->ctrl_event);
        !          2416:        pevent_unregister(&ctrl->data_event);
        !          2417:        ppp_l2tp_avp_list_destroy(&ctrl->avps);
        !          2418:        ghash_destroy(&ctrl->sessions);
        !          2419:        Freee(ctrl->secret);
        !          2420:        Freee(ctrl->errmsg);
        !          2421:        memset(ctrl, 0, sizeof(*ctrl));
        !          2422:        Freee(ctrl);
        !          2423: }
        !          2424: 
        !          2425: /*
        !          2426:  * Immediately destroy a session.
        !          2427:  */
        !          2428: static void
        !          2429: ppp_l2tp_sess_destroy(struct ppp_l2tp_sess **sessp)
        !          2430: {
        !          2431:        struct ppp_l2tp_sess *const sess = *sessp;
        !          2432:        struct ppp_l2tp_ctrl *ctrl;
        !          2433:        char path[32];
        !          2434: 
        !          2435:        /* Sanity */
        !          2436:        if (sess == NULL)
        !          2437:                return;
        !          2438:        *sessp = NULL;
        !          2439: 
        !          2440:        /* Destroy session */
        !          2441:        ctrl = sess->ctrl;
        !          2442:        if (sess->state != SS_DYING || sess->close_timer) {
        !          2443:                ctrl->active_sessions--;
        !          2444:                /* Close control connection after last session closes */
        !          2445:                if (ctrl->active_sessions == 0) {
        !          2446:                        if (ctrl->state == CS_DYING) {
        !          2447:                                ppp_l2tp_ctrl_death_start(ctrl);
        !          2448:                        } else if (pevent_register(ctrl->ctx, &ctrl->death_timer, 0,
        !          2449:                            ctrl->mutex, ppp_l2tp_unused_timeout, ctrl,
        !          2450:                            PEVENT_TIME, gL2TPto * 1000) == -1) {
        !          2451:                                Perror("L2TP: error starting unused timer");
        !          2452:                        }
        !          2453:                }
        !          2454:        }
        !          2455:        ghash_remove(ctrl->sessions, sess);
        !          2456:        snprintf(path, sizeof(path), "[%lx]:", (u_long)sess->node_id);
        !          2457:        (void)NgSendMsg(ctrl->csock, path,
        !          2458:            NGM_GENERIC_COOKIE, NGM_SHUTDOWN, NULL, 0);
        !          2459:        ppp_l2tp_avp_list_destroy(&sess->my_avps);
        !          2460:        ppp_l2tp_avp_list_destroy(&sess->peer_avps);
        !          2461:        pevent_unregister(&sess->notify_timer);
        !          2462:        pevent_unregister(&sess->reply_timer);
        !          2463:        pevent_unregister(&sess->close_timer);
        !          2464:        pevent_unregister(&sess->death_timer);
        !          2465:        Freee(sess->errmsg);
        !          2466:        memset(sess, 0, sizeof(*sess));
        !          2467:        Freee(sess);
        !          2468: }
        !          2469: 
        !          2470: /************************************************************************
        !          2471:                        HASH TABLE FUNCTIONS
        !          2472: ************************************************************************/
        !          2473: 
        !          2474: static int
        !          2475: ppp_l2tp_ctrl_equal(struct ghash *g, const void *item1, const void *item2)
        !          2476: {
        !          2477:        const struct ppp_l2tp_ctrl *const ctrl1 = item1;
        !          2478:        const struct ppp_l2tp_ctrl *const ctrl2 = item2;
        !          2479: 
        !          2480:        return (ctrl1->config.tunnel_id == ctrl2->config.tunnel_id);
        !          2481: }
        !          2482: 
        !          2483: static u_int32_t
        !          2484: ppp_l2tp_ctrl_hash(struct ghash *g, const void *item)
        !          2485: {
        !          2486:        const struct ppp_l2tp_ctrl *const ctrl = item;
        !          2487: 
        !          2488:        return ((u_int32_t)ctrl->config.tunnel_id);
        !          2489: }
        !          2490: 
        !          2491: static int
        !          2492: ppp_l2tp_sess_equal(struct ghash *g, const void *item1, const void *item2)
        !          2493: {
        !          2494:        const struct ppp_l2tp_sess *const sess1 = item1;
        !          2495:        const struct ppp_l2tp_sess *const sess2 = item2;
        !          2496: 
        !          2497:        return (sess1->config.session_id == sess2->config.session_id);
        !          2498: }
        !          2499: 
        !          2500: static u_int32_t
        !          2501: ppp_l2tp_sess_hash(struct ghash *g, const void *item)
        !          2502: {
        !          2503:        const struct ppp_l2tp_sess *const sess = item;
        !          2504: 
        !          2505:        return ((u_int32_t)sess->config.session_id);
        !          2506: }
        !          2507: 
        !          2508: /************************************************************************
        !          2509:                        STRING CONVERTERS
        !          2510: ************************************************************************/
        !          2511: 
        !          2512: /*
        !          2513:  * Dump an AVP list.
        !          2514:  */
        !          2515: static void
        !          2516: ppp_l2tp_ctrl_dump(struct ppp_l2tp_ctrl *ctrl,
        !          2517:        struct ppp_l2tp_avp_list *avps, const char *fmt, ...)
        !          2518: {
        !          2519:        char buf[1024];
        !          2520:        va_list args;
        !          2521:        int i;
        !          2522: 
        !          2523:        va_start(args, fmt);
        !          2524:        vsnprintf(buf, sizeof(buf), fmt, args);
        !          2525:        va_end(args);
        !          2526:        for (i = 0; i < avps->length; i++) {
        !          2527:                struct ppp_l2tp_avp *const avp = &avps->avps[i];
        !          2528:                const struct ppp_l2tp_avp_info *info;
        !          2529:                int j;
        !          2530: 
        !          2531:                strlcat(buf, i > 0 ? " [" : "[", sizeof(buf));
        !          2532:                for (j = 0; (info = &ppp_l2tp_avp_info_list[j])->name != NULL
        !          2533:                    && (info->vendor != avp->vendor
        !          2534:                      || info->type != avp->type); j++);
        !          2535:                if (info->name != NULL) {
        !          2536:                        strlcat(buf, info->name, sizeof(buf));
        !          2537:                        strlcat(buf, " ", sizeof(buf));
        !          2538:                        (*info->decode)(info, avp,
        !          2539:                            buf + strlen(buf), sizeof(buf) - strlen(buf));
        !          2540:                } else {
        !          2541:                        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
        !          2542:                            "%u:%u vlen=%u", avp->vendor, avp->type, avp->vlen);
        !          2543:                }
        !          2544:                strlcat(buf, "]", sizeof(buf));
        !          2545:        }
        !          2546:        Log(LOG_DEBUG, ("%s", buf));
        !          2547: }
        !          2548: 
        !          2549: static const char *
        !          2550: ppp_l2tp_ctrl_state_str(enum l2tp_ctrl_state state)
        !          2551: {
        !          2552:        switch (state) {
        !          2553:        case CS_IDLE:
        !          2554:                return ("idle");
        !          2555:        case CS_WAIT_CTL_REPLY:
        !          2556:                return ("wait-ctl-reply");
        !          2557:        case CS_WAIT_CTL_CONNECT:
        !          2558:                return ("wait-ctl-conn");
        !          2559:        case CS_ESTABLISHED:
        !          2560:                return ("established");
        !          2561:        case CS_DYING:
        !          2562:                return ("dying");
        !          2563:        default:
        !          2564:                return ("UNKNOWN");
        !          2565:        }
        !          2566: }
        !          2567: 
        !          2568: static const char *
        !          2569: ppp_l2tp_sess_state_str(enum l2tp_ctrl_state state)
        !          2570: {
        !          2571:        switch (state) {
        !          2572:        case SS_WAIT_REPLY:
        !          2573:                return ("wait-cs-reply");
        !          2574:        case SS_WAIT_CONNECT:
        !          2575:                return ("wait-connect");
        !          2576:        case SS_WAIT_ANSWER:
        !          2577:                return ("wait-answer");
        !          2578:        case SS_ESTABLISHED:
        !          2579:                return ("established");
        !          2580:        case SS_DYING:
        !          2581:                return ("dying");
        !          2582:        default:
        !          2583:                return ("UNKNOWN");
        !          2584:        }
        !          2585: }
        !          2586: 
        !          2587: static const char *
        !          2588: ppp_l2tp_sess_orig_str(enum l2tp_sess_orig orig)
        !          2589: {
        !          2590:        return (orig == ORIG_LOCAL ? "local" : "remote");
        !          2591: }
        !          2592: 
        !          2593: static const char *
        !          2594: ppp_l2tp_sess_side_str(enum l2tp_sess_side side)
        !          2595: {
        !          2596:        return (side == SIDE_LNS ? "LNS" : "LAC");
        !          2597: }
        !          2598: 
        !          2599: char *
        !          2600: ppp_l2tp_ctrl_stats(struct ppp_l2tp_ctrl *ctrl, char *buf, size_t buf_len)
        !          2601: {
        !          2602:        snprintf(buf, buf_len, "%s",
        !          2603:                ppp_l2tp_ctrl_state_str(ctrl->state));
        !          2604:        return (buf);
        !          2605: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>