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

1.1     ! misho       1: 
        !             2: /*
        !             3:  * l2tp.c
        !             4:  *
        !             5:  * Written by Alexander Motin <mav@FreeBSD.org>
        !             6:  */
        !             7: 
        !             8: #include "ppp.h"
        !             9: #include "phys.h"
        !            10: #include "mbuf.h"
        !            11: #include "ngfunc.h"
        !            12: #include "l2tp.h"
        !            13: #include "l2tp_avp.h"
        !            14: #include "l2tp_ctrl.h"
        !            15: #include "log.h"
        !            16: #include "util.h"
        !            17: 
        !            18: #include <sys/types.h>
        !            19: #ifdef NOLIBPDEL
        !            20: #include "contrib/libpdel/util/ghash.h"
        !            21: #else
        !            22: #include <pdel/util/ghash.h>
        !            23: #endif
        !            24: 
        !            25: #include <netgraph/ng_message.h>
        !            26: #include <netgraph/ng_socket.h>
        !            27: #include <netgraph/ng_ksocket.h>
        !            28: #include <netgraph/ng_l2tp.h>
        !            29: #include <netgraph.h>
        !            30: 
        !            31: /*
        !            32:  * DEFINITIONS
        !            33:  */
        !            34: 
        !            35:   #define L2TP_MTU              1600
        !            36:   #define L2TP_MRU             L2TP_MTU
        !            37:   
        !            38:   #define L2TP_PORT            1701
        !            39: 
        !            40:   #define L2TP_CALL_MIN_BPS    56000
        !            41:   #define L2TP_CALL_MAX_BPS    64000
        !            42: 
        !            43:   struct l2tp_server {
        !            44:     struct u_addr      self_addr;      /* self IP address */
        !            45:     in_port_t          self_port;      /* self port */
        !            46:     int                        refs;
        !            47:     int                        sock;           /* server listen socket */
        !            48:     EventRef           event;          /* listen for data messages */
        !            49:   };
        !            50:   
        !            51:   struct l2tp_tun {
        !            52:     struct u_addr      self_addr;      /* self IP address */
        !            53:     struct u_addr      peer_addr;      /* peer IP address */
        !            54:     char                peer_iface[IFNAMSIZ];  /* Peer iface */
        !            55:     u_char             peer_mac_addr[6];       /* Peer MAC address */
        !            56:     in_port_t          self_port;      /* self port */
        !            57:     in_port_t          peer_port;      /* peer port */
        !            58:     u_char             connected;      /* control connection is connected */
        !            59:     u_char             alive;          /* control connection is not dying */
        !            60:     u_int              active_sessions;/* number of calls in this sunnels */
        !            61:     struct ppp_l2tp_ctrl *ctrl;                /* control connection for this tunnel */
        !            62:   };
        !            63:   
        !            64:   struct l2tpinfo {
        !            65:     struct {
        !            66:        struct u_addr   self_addr;      /* self IP address */
        !            67:        struct u_range  peer_addr;      /* Peer IP addresses allowed */
        !            68:        in_port_t       self_port;      /* self port */
        !            69:        in_port_t       peer_port;      /* Peer port required (or zero) */
        !            70:        struct optinfo  options;
        !            71:        char            callingnum[64]; /* L2TP phone number to use */
        !            72:        char            callednum[64];  /* L2TP phone number to use */
        !            73:        char            hostname[MAXHOSTNAMELEN]; /* L2TP local hostname */
        !            74:        char            secret[64];     /* L2TP tunnel secret */
        !            75:        char            *fqdn_peer_addr;        /* FQDN Peer address */
        !            76:     } conf;
        !            77:     u_char             opened;         /* L2TP opened by phys */
        !            78:     u_char             incoming;       /* Call is incoming vs. outgoing */
        !            79:     u_char             outcall;        /* incall or outcall */
        !            80:     u_char             sync;           /* sync or async call */
        !            81:     struct l2tp_server *server;        /* server associated with link */
        !            82:     struct l2tp_tun    *tun;           /* tunnel associated with link */
        !            83:     struct ppp_l2tp_sess *sess;                /* current session for this link */
        !            84:     char               callingnum[64]; /* current L2TP phone number */
        !            85:     char               callednum[64];  /* current L2TP phone number */
        !            86:   };
        !            87:   typedef struct l2tpinfo      *L2tpInfo;
        !            88: 
        !            89:   /* Set menu options */
        !            90:   enum {
        !            91:     SET_SELFADDR,
        !            92:     SET_PEERADDR,
        !            93:     SET_CALLINGNUM,
        !            94:     SET_CALLEDNUM,
        !            95:     SET_HOSTNAME,
        !            96:     SET_SECRET,
        !            97:     SET_ENABLE,
        !            98:     SET_DISABLE
        !            99:   };
        !           100: 
        !           101:   /* Binary options */
        !           102:   enum {
        !           103:     L2TP_CONF_OUTCALL,         /* when originating, calls are "outgoing" */
        !           104:     L2TP_CONF_HIDDEN,          /* enable AVP hidding */
        !           105:     L2TP_CONF_LENGTH,          /* enable Length field in data packets */
        !           106:     L2TP_CONF_DATASEQ,         /* enable sequence fields in data packets */
        !           107:     L2TP_CONF_RESOLVE_ONCE     /* Only once resolve peer_addr */
        !           108:   };
        !           109: 
        !           110: /*
        !           111:  * INTERNAL FUNCTIONS
        !           112:  */
        !           113: 
        !           114:   static int   L2tpTInit(void);
        !           115:   static void  L2tpTShutdown(void);
        !           116:   static int   L2tpInit(Link l);
        !           117:   static int   L2tpInst(Link l, Link lt);
        !           118:   static void  L2tpOpen(Link l);
        !           119:   static void  L2tpClose(Link l);
        !           120:   static void  L2tpShutdown(Link l);
        !           121:   static void  L2tpStat(Context ctx);
        !           122:   static int   L2tpOriginated(Link l);
        !           123:   static int   L2tpIsSync(Link l);
        !           124:   static int   L2tpSetAccm(Link l, u_int32_t xmit, u_int32_t recv);
        !           125:   static int   L2tpSelfName(Link l, void *buf, size_t buf_len);
        !           126:   static int   L2tpPeerName(Link l, void *buf, size_t buf_len);
        !           127:   static int   L2tpSelfAddr(Link l, void *buf, size_t buf_len);
        !           128:   static int   L2tpPeerAddr(Link l, void *buf, size_t buf_len);
        !           129:   static int   L2tpPeerPort(Link l, void *buf, size_t buf_len);
        !           130:   static int   L2tpPeerMacAddr(Link l, void *buf, size_t buf_len);
        !           131:   static int   L2tpPeerIface(Link l, void *buf, size_t buf_len);
        !           132:   static int   L2tpCallingNum(Link l, void *buf, size_t buf_len);
        !           133:   static int   L2tpCalledNum(Link l, void *buf, size_t buf_len);
        !           134:   static int   L2tpSetCallingNum(Link l, void *buf);
        !           135:   static int   L2tpSetCalledNum(Link l, void *buf);
        !           136: 
        !           137:   static void  L2tpHookUp(Link l);
        !           138:   static void  L2tpUnhook(Link l);
        !           139: 
        !           140:   static void  L2tpNodeUpdate(Link l);
        !           141:   static int   L2tpListen(Link l);
        !           142:   static void  L2tpUnListen(Link l);
        !           143:   static int   L2tpSetCommand(Context ctx, int ac, char *av[], void *arg);
        !           144: 
        !           145:   /* L2TP control callbacks */
        !           146:   static ppp_l2tp_ctrl_connected_t     ppp_l2tp_ctrl_connected_cb;
        !           147:   static ppp_l2tp_ctrl_terminated_t    ppp_l2tp_ctrl_terminated_cb;
        !           148:   static ppp_l2tp_ctrl_destroyed_t     ppp_l2tp_ctrl_destroyed_cb;
        !           149:   static ppp_l2tp_initiated_t          ppp_l2tp_initiated_cb;
        !           150:   static ppp_l2tp_connected_t          ppp_l2tp_connected_cb;
        !           151:   static ppp_l2tp_terminated_t         ppp_l2tp_terminated_cb;
        !           152:   static ppp_l2tp_set_link_info_t      ppp_l2tp_set_link_info_cb;
        !           153: 
        !           154:   static const struct ppp_l2tp_ctrl_cb ppp_l2tp_server_ctrl_cb = {
        !           155:        ppp_l2tp_ctrl_connected_cb,
        !           156:        ppp_l2tp_ctrl_terminated_cb,
        !           157:        ppp_l2tp_ctrl_destroyed_cb,
        !           158:        ppp_l2tp_initiated_cb,
        !           159:        ppp_l2tp_connected_cb,
        !           160:        ppp_l2tp_terminated_cb,
        !           161:        ppp_l2tp_set_link_info_cb,
        !           162:        NULL,
        !           163:   };
        !           164: 
        !           165: /*
        !           166:  * GLOBAL VARIABLES
        !           167:  */
        !           168: 
        !           169:   const struct phystype        gL2tpPhysType = {
        !           170:     .name              = "l2tp",
        !           171:     .descr             = "Layer Two Tunneling Protocol",
        !           172:     .mtu               = L2TP_MTU,
        !           173:     .mru               = L2TP_MRU,
        !           174:     .tmpl              = 1,
        !           175:     .tinit             = L2tpTInit,
        !           176:     .tshutdown         = L2tpTShutdown,
        !           177:     .init              = L2tpInit,
        !           178:     .inst              = L2tpInst,
        !           179:     .open              = L2tpOpen,
        !           180:     .close             = L2tpClose,
        !           181:     .update            = L2tpNodeUpdate,
        !           182:     .shutdown          = L2tpShutdown,
        !           183:     .showstat          = L2tpStat,
        !           184:     .originate         = L2tpOriginated,
        !           185:     .issync            = L2tpIsSync,
        !           186:     .setaccm           = L2tpSetAccm,
        !           187:     .setcallingnum     = L2tpSetCallingNum,
        !           188:     .setcallednum      = L2tpSetCalledNum,
        !           189:     .selfname          = L2tpSelfName,
        !           190:     .peername          = L2tpPeerName,
        !           191:     .selfaddr          = L2tpSelfAddr,
        !           192:     .peeraddr          = L2tpPeerAddr,
        !           193:     .peerport          = L2tpPeerPort,
        !           194:     .peermacaddr       = L2tpPeerMacAddr,
        !           195:     .peeriface         = L2tpPeerIface,
        !           196:     .callingnum                = L2tpCallingNum,
        !           197:     .callednum         = L2tpCalledNum,
        !           198:   };
        !           199: 
        !           200:   const struct cmdtab  L2tpSetCmds[] = {
        !           201:     { "self {ip} [{port}]",            "Set local IP address",
        !           202:        L2tpSetCommand, NULL, 2, (void *) SET_SELFADDR },
        !           203:     { "peer {ip} [{port}]",            "Set remote IP address",
        !           204:        L2tpSetCommand, NULL, 2, (void *) SET_PEERADDR },
        !           205:     { "callingnum {number}",           "Set calling L2TP telephone number",
        !           206:        L2tpSetCommand, NULL, 2, (void *) SET_CALLINGNUM },
        !           207:     { "callednum {number}",            "Set called L2TP telephone number",
        !           208:        L2tpSetCommand, NULL, 2, (void *) SET_CALLEDNUM },
        !           209:     { "hostname {name}",               "Set L2TP local hostname",
        !           210:        L2tpSetCommand, NULL, 2, (void *) SET_HOSTNAME },
        !           211:     { "secret {sec}",                  "Set L2TP tunnel secret",
        !           212:        L2tpSetCommand, NULL, 2, (void *) SET_SECRET },
        !           213:     { "enable [opt ...]",              "Enable option",
        !           214:        L2tpSetCommand, NULL, 2, (void *) SET_ENABLE },
        !           215:     { "disable [opt ...]",             "Disable option",
        !           216:        L2tpSetCommand, NULL, 2, (void *) SET_DISABLE },
        !           217:     { NULL },
        !           218:   };
        !           219: 
        !           220: /*
        !           221:  * INTERNAL VARIABLES
        !           222:  */
        !           223: 
        !           224:   static struct confinfo       gConfList[] = {
        !           225:     { 0,       L2TP_CONF_OUTCALL,      "outcall"       },
        !           226:     { 0,       L2TP_CONF_HIDDEN,       "hidden"        },
        !           227:     { 0,       L2TP_CONF_LENGTH,       "length"        },
        !           228:     { 0,       L2TP_CONF_DATASEQ,      "dataseq"       },
        !           229:     { 0,       L2TP_CONF_RESOLVE_ONCE, "resolve-once"  },
        !           230:     { 0,       0,                      NULL            },
        !           231:   };
        !           232: 
        !           233: int L2tpListenUpdateSheduled = 0;
        !           234: struct pppTimer L2tpListenUpdateTimer;
        !           235: 
        !           236: struct ghash   *gL2tpServers;
        !           237: struct ghash   *gL2tpTuns;
        !           238: int            one = 1;
        !           239: 
        !           240: /*
        !           241:  * L2tpTInit()
        !           242:  */
        !           243: 
        !           244: static int
        !           245: L2tpTInit(void)
        !           246: {
        !           247:     if ((gL2tpServers = ghash_create(NULL, 0, 0, MB_PHYS, NULL, NULL, NULL, NULL))
        !           248:          == NULL)
        !           249:        return(-1);
        !           250:     if ((gL2tpTuns = ghash_create(NULL, 0, 0, MB_PHYS, NULL, NULL, NULL, NULL))
        !           251:          == NULL)
        !           252:        return(-1);
        !           253:     return(0);
        !           254: }
        !           255: 
        !           256: /*
        !           257:  * L2tpTShutdown()
        !           258:  */
        !           259: 
        !           260: static void
        !           261: L2tpTShutdown(void)
        !           262: {
        !           263:     struct ghash_walk walk;
        !           264:     struct l2tp_tun *tun;
        !           265: 
        !           266:     Log(LG_PHYS2, ("L2TP: Total shutdown"));
        !           267:     ghash_walk_init(gL2tpTuns, &walk);
        !           268:     while ((tun = ghash_walk_next(gL2tpTuns, &walk)) != NULL) {
        !           269:         if (tun->ctrl) {
        !           270:            if (tun->alive)
        !           271:                ppp_l2tp_ctrl_shutdown(tun->ctrl,
        !           272:                    L2TP_RESULT_SHUTDOWN, 0, NULL);
        !           273:            ppp_l2tp_ctrl_destroy(&tun->ctrl);
        !           274:        }
        !           275:     }
        !           276:     ghash_destroy(&gL2tpServers);
        !           277:     ghash_destroy(&gL2tpTuns);
        !           278: }
        !           279: 
        !           280: /*
        !           281:  * L2tpInit()
        !           282:  */
        !           283: 
        !           284: static int
        !           285: L2tpInit(Link l)
        !           286: {
        !           287:     L2tpInfo   l2tp;
        !           288: 
        !           289:     /* Initialize this link */
        !           290:     l2tp = (L2tpInfo) (l->info = Malloc(MB_PHYS, sizeof(*l2tp)));
        !           291:   
        !           292:     u_addrclear(&l2tp->conf.self_addr);
        !           293:     l2tp->conf.self_addr.family = AF_INET;
        !           294:     l2tp->conf.self_port = 0;
        !           295:     u_rangeclear(&l2tp->conf.peer_addr);
        !           296:     l2tp->conf.peer_addr.addr.family = AF_INET;
        !           297:     l2tp->conf.peer_addr.width = 0;
        !           298:     l2tp->conf.peer_port = 0;
        !           299:     l2tp->conf.fqdn_peer_addr = NULL;
        !           300: 
        !           301:     Enable(&l2tp->conf.options, L2TP_CONF_DATASEQ);
        !           302:     Enable(&l2tp->conf.options, L2TP_CONF_RESOLVE_ONCE);
        !           303:   
        !           304:     return(0);
        !           305: }
        !           306: 
        !           307: /*
        !           308:  * L2tpInst()
        !           309:  */
        !           310: 
        !           311: static int
        !           312: L2tpInst(Link l, Link lt)
        !           313: {
        !           314:        L2tpInfo pi;
        !           315:        L2tpInfo        const pit = (L2tpInfo) lt->info;
        !           316: 
        !           317:        /* Initialize this link */
        !           318:        pi = (L2tpInfo) (l->info = Mdup(MB_PHYS, lt->info, sizeof(*pit)));
        !           319:        if (pit->conf.fqdn_peer_addr != NULL)
        !           320:            pi->conf.fqdn_peer_addr =
        !           321:                Mstrdup(MB_PHYS, pit->conf.fqdn_peer_addr);
        !           322:        if (pi->server)
        !           323:            pi->server->refs++;
        !           324:        
        !           325:        return(0);
        !           326: }
        !           327: 
        !           328: /*
        !           329:  * L2tpOpen()
        !           330:  */
        !           331: 
        !           332: static void
        !           333: L2tpOpen(Link l)
        !           334: {
        !           335:        L2tpInfo const pi = (L2tpInfo) l->info;
        !           336: 
        !           337:        struct l2tp_tun *tun = NULL;
        !           338:        struct ppp_l2tp_sess *sess;
        !           339:        struct ppp_l2tp_avp_list *avps = NULL;
        !           340:        union {
        !           341:            u_char buf[sizeof(struct ng_ksocket_sockopt) + sizeof(int)];
        !           342:            struct ng_ksocket_sockopt sockopt;
        !           343:        } sockopt_buf;
        !           344:        struct ng_ksocket_sockopt *const sockopt = &sockopt_buf.sockopt;
        !           345:        union {
        !           346:            u_char      buf[sizeof(struct ng_mesg) + sizeof(struct sockaddr_storage)];
        !           347:            struct ng_mesg      reply;
        !           348:        } ugetsas;
        !           349:        struct sockaddr_storage *const getsas = (struct sockaddr_storage *)(void *)ugetsas.reply.data;
        !           350:        struct ngm_mkpeer mkpeer;
        !           351:        struct sockaddr_storage sas;
        !           352:        char hook[NG_HOOKSIZ];
        !           353:        char namebuf[64];
        !           354:        char buf[32], buf2[32];
        !           355:        char hostname[MAXHOSTNAMELEN];
        !           356:        ng_ID_t node_id;
        !           357:        int csock = -1;
        !           358:        int dsock = -1;
        !           359:        struct ghash_walk walk;
        !           360:        u_int32_t       cap;
        !           361:        u_int16_t       win;
        !           362: 
        !           363:        pi->opened=1;
        !           364:        
        !           365:        if (pi->incoming == 1) {
        !           366:                Log(LG_PHYS2, ("[%s] L2tpOpen() on incoming call", l->name));
        !           367:                if (l->state==PHYS_STATE_READY) {
        !           368:                    l->state = PHYS_STATE_UP;
        !           369:                    if (pi->outcall) {
        !           370:                        pi->sync = 1;
        !           371:                        if (l->rep) {
        !           372:                            uint32_t fr;
        !           373:                            avps = ppp_l2tp_avp_list_create();
        !           374:                            if (RepIsSync(l)) {
        !           375:                                fr = htonl(L2TP_FRAMING_SYNC);
        !           376:                            } else {
        !           377:                                fr = htonl(L2TP_FRAMING_ASYNC);
        !           378:                                pi->sync = 0;
        !           379:                            }
        !           380:                            if (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_FRAMING_TYPE,
        !           381:                                &fr, sizeof(fr)) == -1) {
        !           382:                                    Perror("[%s] ppp_l2tp_avp_list_append",
        !           383:                                        l->name);
        !           384:                            }
        !           385:                        } else {
        !           386:                            avps = NULL;
        !           387:                        }
        !           388:                        Log(LG_PHYS, ("[%s] L2TP: Call #%u connected", l->name, 
        !           389:                            ppp_l2tp_sess_get_serial(pi->sess)));
        !           390:                        ppp_l2tp_connected(pi->sess, avps);
        !           391:                        if (avps)
        !           392:                            ppp_l2tp_avp_list_destroy(&avps);
        !           393:                    }
        !           394:                    L2tpHookUp(l);
        !           395:                    PhysUp(l);
        !           396:                }
        !           397:                return;
        !           398:        }
        !           399: 
        !           400:        /* Sanity check. */
        !           401:        if (l->state != PHYS_STATE_DOWN) {
        !           402:                Log(LG_PHYS, ("[%s] L2TP: allready active", l->name));
        !           403:                return;
        !           404:        };
        !           405: 
        !           406:        l->state = PHYS_STATE_CONNECTING;
        !           407:        strlcpy(pi->callingnum, pi->conf.callingnum, sizeof(pi->callingnum));
        !           408:        strlcpy(pi->callednum, pi->conf.callednum, sizeof(pi->callednum));
        !           409: 
        !           410:        if ((!Enabled(&pi->conf.options, L2TP_CONF_RESOLVE_ONCE)) &&
        !           411:            (pi->conf.fqdn_peer_addr != NULL)) {
        !           412:            struct u_range      rng;
        !           413:            if (ParseRange(pi->conf.fqdn_peer_addr, &rng, ALLOW_IPV4|ALLOW_IPV6))
        !           414:                pi->conf.peer_addr = rng;
        !           415:        }
        !           416: 
        !           417:        ghash_walk_init(gL2tpTuns, &walk);
        !           418:        while ((tun = ghash_walk_next(gL2tpTuns, &walk)) != NULL) {
        !           419:            if (tun->ctrl && tun->alive && tun->active_sessions < gL2TPtunlimit &&
        !           420:                (IpAddrInRange(&pi->conf.peer_addr, &tun->peer_addr)) &&
        !           421:                (u_addrempty(&pi->conf.self_addr) || u_addrempty(&tun->self_addr) ||
        !           422:                    u_addrcompare(&pi->conf.self_addr, &tun->self_addr) == 0) &&
        !           423:                (pi->conf.peer_port == 0 || pi->conf.peer_port == tun->peer_port)) {
        !           424:                    pi->tun = tun;
        !           425:                    tun->active_sessions++;
        !           426:                    if (tun->connected) { /* if tun is connected then just initiate */
        !           427:                    
        !           428:                        /* Create number AVPs */
        !           429:                        avps = ppp_l2tp_avp_list_create();
        !           430:                        if (pi->conf.callingnum[0]) {
        !           431:                          if (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_CALLING_NUMBER,
        !           432:                            pi->conf.callingnum, strlen(pi->conf.callingnum)) == -1) {
        !           433:                                Perror("[%s] ppp_l2tp_avp_list_append", l->name);
        !           434:                          }
        !           435:                        }
        !           436:                        if (pi->conf.callednum[0]) {
        !           437:                          if (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_CALLED_NUMBER,
        !           438:                            pi->conf.callednum, strlen(pi->conf.callednum)) == -1) {
        !           439:                                Perror("[%s] ppp_l2tp_avp_list_append", l->name);
        !           440:                          }
        !           441:                        }
        !           442:                        if ((sess = ppp_l2tp_initiate(tun->ctrl, 
        !           443:                                Enabled(&pi->conf.options, L2TP_CONF_OUTCALL)?1:0,
        !           444:                                Enabled(&pi->conf.options, L2TP_CONF_LENGTH)?1:0,
        !           445:                                Enabled(&pi->conf.options, L2TP_CONF_DATASEQ)?1:0,
        !           446:                                avps)) == NULL) {
        !           447:                            Perror("[%s] ppp_l2tp_initiate", l->name);
        !           448:                            ppp_l2tp_avp_list_destroy(&avps);
        !           449:                            pi->sess = NULL;
        !           450:                            pi->tun = NULL;
        !           451:                            tun->active_sessions--;
        !           452:                            l->state = PHYS_STATE_DOWN;
        !           453:                            PhysDown(l, STR_ERROR, NULL);
        !           454:                            return;
        !           455:                        };
        !           456:                        ppp_l2tp_avp_list_destroy(&avps);
        !           457:                        pi->sess = sess;
        !           458:                        pi->outcall = Enabled(&pi->conf.options, L2TP_CONF_OUTCALL);
        !           459:                        Log(LG_PHYS, ("[%s] L2TP: %s call #%u via control connection %p initiated", 
        !           460:                            l->name, (pi->outcall?"Outgoing":"Incoming"), 
        !           461:                            ppp_l2tp_sess_get_serial(sess), tun->ctrl));
        !           462:                        ppp_l2tp_sess_set_cookie(sess, l);
        !           463:                        if (!pi->outcall) {
        !           464:                            pi->sync = 1;
        !           465:                            if (l->rep) {
        !           466:                                uint32_t fr;
        !           467:                                avps = ppp_l2tp_avp_list_create();
        !           468:                                if (RepIsSync(l)) {
        !           469:                                    fr = htonl(L2TP_FRAMING_SYNC);
        !           470:                                } else {
        !           471:                                    fr = htonl(L2TP_FRAMING_ASYNC);
        !           472:                                    pi->sync = 0;
        !           473:                                }
        !           474:                                if (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_FRAMING_TYPE,
        !           475:                                    &fr, sizeof(fr)) == -1) {
        !           476:                                        Perror("[%s] ppp_l2tp_avp_list_append",
        !           477:                                            l->name);
        !           478:                                }
        !           479:                            } else {
        !           480:                                avps = NULL;
        !           481:                            }
        !           482:                            ppp_l2tp_connected(pi->sess, avps);
        !           483:                            if (avps)
        !           484:                                ppp_l2tp_avp_list_destroy(&avps);
        !           485:                        }
        !           486:                    } /* Else wait while it will be connected */
        !           487:                    return;
        !           488:            }
        !           489:        }
        !           490: 
        !           491:        /* There is no tun which we need. Create a new one. */
        !           492:        tun = Malloc(MB_PHYS, sizeof(*tun));
        !           493:        memset(tun, 0, sizeof(*tun));
        !           494:        u_addrcopy(&pi->conf.peer_addr.addr, &tun->peer_addr);
        !           495:        tun->peer_port = pi->conf.peer_port?pi->conf.peer_port:L2TP_PORT;
        !           496:        u_addrcopy(&pi->conf.self_addr, &tun->self_addr);
        !           497:        tun->self_port = pi->conf.self_port;
        !           498:        tun->alive = 1;
        !           499:        tun->connected = 0;
        !           500: 
        !           501:        /* Create vendor name AVP */
        !           502:        avps = ppp_l2tp_avp_list_create();
        !           503: 
        !           504:        if (pi->conf.hostname[0] != 0) {
        !           505:            strlcpy(hostname, pi->conf.hostname, sizeof(hostname));
        !           506:        } else {
        !           507:            (void)gethostname(hostname, sizeof(hostname) - 1);
        !           508:            hostname[sizeof(hostname) - 1] = '\0';
        !           509:        }
        !           510:        cap = htonl(L2TP_BEARER_DIGITAL|L2TP_BEARER_ANALOG);
        !           511:        win = htons(8); /* XXX: this value is empirical. */
        !           512:        if ((ppp_l2tp_avp_list_append(avps, 1, 0, AVP_HOST_NAME,
        !           513:              hostname, strlen(hostname)) == -1) ||
        !           514:            (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_VENDOR_NAME,
        !           515:              MPD_VENDOR, strlen(MPD_VENDOR)) == -1) ||
        !           516:            (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_BEARER_CAPABILITIES,
        !           517:              &cap, sizeof(cap)) == -1) ||
        !           518:            (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_RECEIVE_WINDOW_SIZE,
        !           519:              &win, sizeof(win)) == -1)) {
        !           520:                Perror("L2TP: ppp_l2tp_avp_list_append");
        !           521:                goto fail;
        !           522:        }
        !           523: 
        !           524:        /* Create a new control connection */
        !           525:        if ((tun->ctrl = ppp_l2tp_ctrl_create(gPeventCtx, &gGiantMutex,
        !           526:            &ppp_l2tp_server_ctrl_cb, u_addrtoid(&tun->peer_addr),
        !           527:            &node_id, hook, avps, 
        !           528:            pi->conf.secret, strlen(pi->conf.secret),
        !           529:            Enabled(&pi->conf.options, L2TP_CONF_HIDDEN))) == NULL) {
        !           530:                Perror("[%s] ppp_l2tp_ctrl_create", l->name);
        !           531:                goto fail;
        !           532:        }
        !           533:        ppp_l2tp_ctrl_set_cookie(tun->ctrl, tun);
        !           534: 
        !           535:        Log(LG_PHYS, ("L2TP: Initiating control connection %p %s %u <-> %s %u",
        !           536:            tun->ctrl, u_addrtoa(&tun->self_addr,buf,sizeof(buf)), tun->self_port,
        !           537:            u_addrtoa(&tun->peer_addr,buf2,sizeof(buf2)), tun->peer_port));
        !           538: 
        !           539:        /* Get a temporary netgraph socket node */
        !           540:        if (NgMkSockNode(NULL, &csock, &dsock) == -1) {
        !           541:            Perror("[%s] NgMkSockNode", l->name);
        !           542:            goto fail;
        !           543:        }
        !           544: 
        !           545:        /* Attach a new UDP socket to "lower" hook */
        !           546:        snprintf(namebuf, sizeof(namebuf), "[%lx]:", (u_long)node_id);
        !           547:        memset(&mkpeer, 0, sizeof(mkpeer));
        !           548:        strlcpy(mkpeer.type, NG_KSOCKET_NODE_TYPE, sizeof(mkpeer.type));
        !           549:        strlcpy(mkpeer.ourhook, hook, sizeof(mkpeer.ourhook));
        !           550:        if (tun->peer_addr.family==AF_INET6) {
        !           551:                snprintf(mkpeer.peerhook, sizeof(mkpeer.peerhook), "%d/%d/%d", PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
        !           552:        } else {
        !           553:                snprintf(mkpeer.peerhook, sizeof(mkpeer.peerhook), "inet/dgram/udp");
        !           554:        }
        !           555:        if (NgSendMsg(csock, namebuf, NGM_GENERIC_COOKIE,
        !           556:            NGM_MKPEER, &mkpeer, sizeof(mkpeer)) == -1) {
        !           557:                Perror("[%s] mkpeer", l->name);
        !           558:                goto fail;
        !           559:        }
        !           560: 
        !           561:        /* Point name at ksocket node */
        !           562:        strlcat(namebuf, hook, sizeof(namebuf));
        !           563: 
        !           564:        /* Make UDP port reusable */
        !           565:        memset(&sockopt_buf, 0, sizeof(sockopt_buf));
        !           566:        sockopt->level = SOL_SOCKET;
        !           567:        sockopt->name = SO_REUSEADDR;
        !           568:        memcpy(sockopt->value, &one, sizeof(int));
        !           569:        if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
        !           570:            NGM_KSOCKET_SETOPT, sockopt, sizeof(sockopt_buf)) == -1) {
        !           571:                Perror("[%s] setsockopt", l->name);
        !           572:                goto fail;
        !           573:        }
        !           574:        sockopt->name = SO_REUSEPORT;
        !           575:        if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
        !           576:            NGM_KSOCKET_SETOPT, sockopt, sizeof(sockopt_buf)) == -1) {
        !           577:                Perror("[%s] setsockopt", l->name);
        !           578:                goto fail;
        !           579:        }
        !           580: 
        !           581:        if (!u_addrempty(&tun->self_addr)) {
        !           582:            /* Bind socket to a new port */
        !           583:            u_addrtosockaddr(&tun->self_addr,tun->self_port,&sas);
        !           584:            if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
        !           585:                NGM_KSOCKET_BIND, &sas, sas.ss_len) == -1) {
        !           586:                    Perror("[%s] bind", l->name);
        !           587:                    goto fail;
        !           588:            }
        !           589:        }
        !           590:        /* Connect socket to remote peer's IP and port */
        !           591:        u_addrtosockaddr(&tun->peer_addr,tun->peer_port,&sas);
        !           592:        if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
        !           593:              NGM_KSOCKET_CONNECT, &sas, sas.ss_len) == -1
        !           594:            && errno != EINPROGRESS) {
        !           595:                Perror("[%s] connect", l->name);
        !           596:                goto fail;
        !           597:        }
        !           598: 
        !           599:        if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
        !           600:            NGM_KSOCKET_GETNAME, NULL, 0) == -1) {
        !           601:                Perror("[%s] getname send", l->name);
        !           602:        } else 
        !           603:        if (NgRecvMsg(csock, &ugetsas.reply, sizeof(ugetsas), NULL) == -1) {
        !           604:                Perror("[%s] getname recv", l->name);
        !           605:        } else {
        !           606:            sockaddrtou_addr(getsas,&tun->self_addr,&tun->self_port);
        !           607:        }
        !           608: 
        !           609:        /* Add peer to our hash table */
        !           610:        if (ghash_put(gL2tpTuns, tun) == -1) {
        !           611:                Perror("[%s] ghash_put", l->name);
        !           612:                goto fail;
        !           613:        }
        !           614:        pi->tun = tun;
        !           615:        tun->active_sessions++;
        !           616:        Log(LG_PHYS2, ("L2TP: Control connection %p %s %u <-> %s %u initiated",
        !           617:            tun->ctrl, u_addrtoa(&tun->self_addr,buf,sizeof(buf)), tun->self_port,
        !           618:            u_addrtoa(&tun->peer_addr,buf2,sizeof(buf2)), tun->peer_port));
        !           619:        ppp_l2tp_ctrl_initiate(tun->ctrl);
        !           620: 
        !           621:        /* Clean up and return */
        !           622:        ppp_l2tp_avp_list_destroy(&avps);
        !           623:        (void)close(csock);
        !           624:        (void)close(dsock);
        !           625:        return;
        !           626: 
        !           627: fail:
        !           628:        /* Clean up after failure */
        !           629:        if (csock != -1)
        !           630:                (void)close(csock);
        !           631:        if (dsock != -1)
        !           632:                (void)close(dsock);
        !           633:        if (tun != NULL) {
        !           634:                ppp_l2tp_ctrl_destroy(&tun->ctrl);
        !           635:                Freee(tun);
        !           636:        }
        !           637:        l->state = PHYS_STATE_DOWN;
        !           638:        PhysDown(l, STR_ERROR, NULL);
        !           639: }
        !           640: 
        !           641: /*
        !           642:  * L2tpClose()
        !           643:  */
        !           644: 
        !           645: static void
        !           646: L2tpClose(Link l)
        !           647: {
        !           648:     L2tpInfo      const pi = (L2tpInfo) l->info;
        !           649: 
        !           650:     pi->opened = 0;
        !           651:     pi->incoming = 0;
        !           652:     pi->outcall = 0;
        !           653:     if (l->state == PHYS_STATE_DOWN)
        !           654:        return;
        !           655:     L2tpUnhook(l);
        !           656:     if (pi->sess) {
        !           657:        Log(LG_PHYS, ("[%s] L2TP: Call #%u terminated locally", l->name, 
        !           658:            ppp_l2tp_sess_get_serial(pi->sess)));
        !           659:        ppp_l2tp_terminate(pi->sess, L2TP_RESULT_ADMIN, 0, NULL);
        !           660:        pi->sess = NULL;
        !           661:     }
        !           662:     if (pi->tun)
        !           663:        pi->tun->active_sessions--;
        !           664:     pi->tun = NULL;
        !           665:     pi->callingnum[0]=0;
        !           666:     pi->callednum[0]=0;
        !           667:     l->state = PHYS_STATE_DOWN;
        !           668:     PhysDown(l, STR_MANUALLY, NULL);
        !           669: }
        !           670: 
        !           671: /*
        !           672:  * L2tpShutdown()
        !           673:  */
        !           674: 
        !           675: static void
        !           676: L2tpShutdown(Link l)
        !           677: {
        !           678:     L2tpInfo const pi = (L2tpInfo) l->info;
        !           679: 
        !           680:     if (pi->conf.fqdn_peer_addr)
        !           681:         Freee(pi->conf.fqdn_peer_addr);
        !           682: 
        !           683:     L2tpUnListen(l);
        !           684:     Freee(l->info);
        !           685: }
        !           686: 
        !           687: /*
        !           688:  * L2tpUnhook()
        !           689:  */
        !           690: 
        !           691: static void
        !           692: L2tpUnhook(Link l)
        !           693: {
        !           694:     int                csock = -1;
        !           695:     L2tpInfo   const pi = (L2tpInfo) l->info;
        !           696:     const char *hook;
        !           697:     ng_ID_t    node_id;
        !           698:     char       path[NG_PATHSIZ];
        !           699:        
        !           700:     if (pi->sess) {            /* avoid double close */
        !           701: 
        !           702:        /* Get this link's node and hook */
        !           703:        ppp_l2tp_sess_get_hook(pi->sess, &node_id, &hook);
        !           704:        
        !           705:        if (node_id != 0) {
        !           706: 
        !           707:            /* Get a temporary netgraph socket node */
        !           708:            if (NgMkSockNode(NULL, &csock, NULL) == -1) {
        !           709:                Perror("L2TP: NgMkSockNode");
        !           710:                return;
        !           711:            }
        !           712:        
        !           713:            /* Disconnect session hook. */
        !           714:            snprintf(path, sizeof(path), "[%lx]:", (u_long)node_id);
        !           715:            NgFuncDisconnect(csock, l->name, path, hook);
        !           716:        
        !           717:            close(csock);
        !           718:        }
        !           719:     }
        !           720: }
        !           721: 
        !           722: /*
        !           723:  * L2tpOriginated()
        !           724:  */
        !           725: 
        !           726: static int
        !           727: L2tpOriginated(Link l)
        !           728: {
        !           729:     L2tpInfo   const l2tp = (L2tpInfo) l->info;
        !           730: 
        !           731:     return(l2tp->incoming ? LINK_ORIGINATE_REMOTE : LINK_ORIGINATE_LOCAL);
        !           732: }
        !           733: 
        !           734: /*
        !           735:  * L2tpIsSync()
        !           736:  */
        !           737: 
        !           738: static int
        !           739: L2tpIsSync(Link l)
        !           740: {
        !           741:     L2tpInfo   const l2tp = (L2tpInfo) l->info;
        !           742: 
        !           743:     return (l2tp->sync);
        !           744: }
        !           745: 
        !           746: static int
        !           747: L2tpSetAccm(Link l, u_int32_t xmit, u_int32_t recv)
        !           748: {
        !           749:     L2tpInfo   const l2tp = (L2tpInfo) l->info;
        !           750:     
        !           751:     if (!l2tp->sess)
        !           752:            return (-1);
        !           753: 
        !           754:     return (ppp_l2tp_set_link_info(l2tp->sess, xmit, recv));
        !           755: }
        !           756: 
        !           757: static int
        !           758: L2tpSetCallingNum(Link l, void *buf)
        !           759: {
        !           760:     L2tpInfo   const l2tp = (L2tpInfo) l->info;
        !           761: 
        !           762:     strlcpy(l2tp->conf.callingnum, buf, sizeof(l2tp->conf.callingnum));
        !           763:     return(0);
        !           764: }
        !           765: 
        !           766: static int
        !           767: L2tpSetCalledNum(Link l, void *buf)
        !           768: {
        !           769:     L2tpInfo   const l2tp = (L2tpInfo) l->info;
        !           770: 
        !           771:     strlcpy(l2tp->conf.callednum, buf, sizeof(l2tp->conf.callednum));
        !           772:     return(0);
        !           773: }
        !           774: 
        !           775: static int
        !           776: L2tpSelfName(Link l, void *buf, size_t buf_len)
        !           777: {
        !           778:     L2tpInfo   const l2tp = (L2tpInfo) l->info;
        !           779: 
        !           780:     if (l2tp->tun && l2tp->tun->ctrl)
        !           781:        return (ppp_l2tp_ctrl_get_self_name(l2tp->tun->ctrl, buf, buf_len));
        !           782:     ((char*)buf)[0]=0;
        !           783:     return (0);
        !           784: }
        !           785: 
        !           786: static int
        !           787: L2tpPeerName(Link l, void *buf, size_t buf_len)
        !           788: {
        !           789:     L2tpInfo   const l2tp = (L2tpInfo) l->info;
        !           790: 
        !           791:     if (l2tp->tun && l2tp->tun->ctrl)
        !           792:        return (ppp_l2tp_ctrl_get_peer_name(l2tp->tun->ctrl, buf, buf_len));
        !           793:     ((char*)buf)[0]=0;
        !           794:     return (0);
        !           795: }
        !           796: 
        !           797: static int
        !           798: L2tpSelfAddr(Link l, void *buf, size_t buf_len)
        !           799: {
        !           800:     L2tpInfo   const l2tp = (L2tpInfo) l->info;
        !           801: 
        !           802:     if (l2tp->tun && !u_addrempty(&l2tp->tun->self_addr)) {
        !           803:        if (u_addrtoa(&l2tp->tun->self_addr, buf, buf_len))
        !           804:            return (0);
        !           805:        else {
        !           806:            ((char*)buf)[0]=0;
        !           807:            return (-1);
        !           808:        }
        !           809:     }
        !           810:     ((char*)buf)[0]=0;
        !           811:     return (0);
        !           812: }
        !           813: 
        !           814: static int
        !           815: L2tpPeerAddr(Link l, void *buf, size_t buf_len)
        !           816: {
        !           817:     L2tpInfo   const l2tp = (L2tpInfo) l->info;
        !           818: 
        !           819:     if (l2tp->tun) {
        !           820:        if (u_addrtoa(&l2tp->tun->peer_addr, buf, buf_len))
        !           821:            return(0);
        !           822:        else {
        !           823:            ((char*)buf)[0]=0;
        !           824:            return(-1);
        !           825:        }
        !           826:     }
        !           827:     ((char*)buf)[0]=0;
        !           828:     return(0);
        !           829: }
        !           830: 
        !           831: static int
        !           832: L2tpPeerPort(Link l, void *buf, size_t buf_len)
        !           833: {
        !           834:     L2tpInfo   const l2tp = (L2tpInfo) l->info;
        !           835: 
        !           836:     if (l2tp->tun) {
        !           837:        if (snprintf(buf, buf_len, "%d", l2tp->tun->peer_port))
        !           838:            return(0);
        !           839:        else {
        !           840:            ((char*)buf)[0]=0;
        !           841:            return(-1);
        !           842:        }
        !           843:     }
        !           844:     ((char*)buf)[0]=0;
        !           845:     return(0);
        !           846: }
        !           847: 
        !           848: static int
        !           849: L2tpPeerMacAddr(Link l, void *buf, size_t buf_len)
        !           850: {
        !           851:     L2tpInfo   const l2tp = (L2tpInfo) l->info;
        !           852: 
        !           853:     if (l2tp->tun && l2tp->tun->peer_iface[0]) {
        !           854:        snprintf(buf, buf_len, "%02x:%02x:%02x:%02x:%02x:%02x",
        !           855:            l2tp->tun->peer_mac_addr[0], l2tp->tun->peer_mac_addr[1],
        !           856:            l2tp->tun->peer_mac_addr[2], l2tp->tun->peer_mac_addr[3],
        !           857:            l2tp->tun->peer_mac_addr[4], l2tp->tun->peer_mac_addr[5]);
        !           858:        return (0);
        !           859:     }
        !           860:     ((char*)buf)[0]=0;
        !           861:     return(0);
        !           862: }
        !           863: 
        !           864: static int
        !           865: L2tpPeerIface(Link l, void *buf, size_t buf_len)
        !           866: {
        !           867:     L2tpInfo   const l2tp = (L2tpInfo) l->info;
        !           868: 
        !           869:     if (l2tp->tun && l2tp->tun->peer_iface[0]) {
        !           870:        strlcpy(buf, l2tp->tun->peer_iface, buf_len);
        !           871:        return (0);
        !           872:     }
        !           873:     ((char*)buf)[0]=0;
        !           874:     return(0);
        !           875: }
        !           876: 
        !           877: static int
        !           878: L2tpCallingNum(Link l, void *buf, size_t buf_len)
        !           879: {
        !           880:     L2tpInfo   const l2tp = (L2tpInfo) l->info;
        !           881: 
        !           882:     strlcpy((char*)buf, l2tp->callingnum, buf_len);
        !           883:     return(0);
        !           884: }
        !           885: 
        !           886: static int
        !           887: L2tpCalledNum(Link l, void *buf, size_t buf_len)
        !           888: {
        !           889:     L2tpInfo   const l2tp = (L2tpInfo) l->info;
        !           890: 
        !           891:     strlcpy((char*)buf, l2tp->callednum, buf_len);
        !           892:     return(0);
        !           893: }
        !           894: 
        !           895: /*
        !           896:  * L2tpStat()
        !           897:  */
        !           898: 
        !           899: void
        !           900: L2tpStat(Context ctx)
        !           901: {
        !           902:     L2tpInfo   const l2tp = (L2tpInfo) ctx->lnk->info;
        !           903:     char       buf[32];
        !           904: 
        !           905:     Printf("L2TP configuration:\r\n");
        !           906:     Printf("\tSelf addr    : %s, port %u",
        !           907:        u_addrtoa(&l2tp->conf.self_addr, buf, sizeof(buf)), l2tp->conf.self_port);
        !           908:     Printf("\r\n");
        !           909:     Printf("\tPeer FQDN    : %s\r\n", l2tp->conf.fqdn_peer_addr);
        !           910:     Printf("\tPeer range   : %s",
        !           911:        u_rangetoa(&l2tp->conf.peer_addr, buf, sizeof(buf)));
        !           912:     if (l2tp->conf.peer_port)
        !           913:        Printf(", port %u", l2tp->conf.peer_port);
        !           914:     Printf("\r\n");
        !           915:     Printf("\tHostname     : %s\r\n", l2tp->conf.hostname);
        !           916:     Printf("\tSecret       : %s\r\n", (l2tp->conf.callingnum[0])?"******":"");
        !           917:     Printf("\tCalling number: %s\r\n", l2tp->conf.callingnum);
        !           918:     Printf("\tCalled number: %s\r\n", l2tp->conf.callednum);
        !           919:     Printf("L2TP options:\r\n");
        !           920:     OptStat(ctx, &l2tp->conf.options, gConfList);
        !           921:     Printf("L2TP status:\r\n");
        !           922:     if (ctx->lnk->state != PHYS_STATE_DOWN) {
        !           923:        Printf("\tIncoming     : %s\r\n", (l2tp->incoming?"YES":"NO"));
        !           924:        if (l2tp->tun) {
        !           925:            Printf("\tCurrent self : %s, port %u",
        !           926:                u_addrtoa(&l2tp->tun->self_addr, buf, sizeof(buf)), l2tp->tun->self_port);
        !           927:            L2tpSelfName(ctx->lnk, buf, sizeof(buf));
        !           928:            Printf(" (%s)\r\n", buf);
        !           929:            Printf("\tCurrent peer : %s, port %u",
        !           930:                u_addrtoa(&l2tp->tun->peer_addr, buf, sizeof(buf)), l2tp->tun->peer_port);
        !           931:            L2tpPeerName(ctx->lnk, buf, sizeof(buf));
        !           932:            Printf(" (%s)\r\n", buf);
        !           933:            if (l2tp->tun->peer_iface[0]) {
        !           934:                Printf("\tCurrent peer : %02x:%02x:%02x:%02x:%02x:%02x at %s\r\n",
        !           935:                    l2tp->tun->peer_mac_addr[0], l2tp->tun->peer_mac_addr[1],
        !           936:                    l2tp->tun->peer_mac_addr[2], l2tp->tun->peer_mac_addr[3],
        !           937:                    l2tp->tun->peer_mac_addr[4], l2tp->tun->peer_mac_addr[5],
        !           938:                    l2tp->tun->peer_iface);
        !           939:            }
        !           940: 
        !           941:            Printf("\tFraming      : %s\r\n", (l2tp->sync?"Sync":"Async"));
        !           942:        }
        !           943:        Printf("\tCalling number: %s\r\n", l2tp->callingnum);
        !           944:        Printf("\tCalled number: %s\r\n", l2tp->callednum);
        !           945:     }
        !           946: }
        !           947: 
        !           948: /*
        !           949:  * This is called when a control connection gets opened.
        !           950:  */
        !           951: static void
        !           952: ppp_l2tp_ctrl_connected_cb(struct ppp_l2tp_ctrl *ctrl)
        !           953: {
        !           954:        struct l2tp_tun *tun = ppp_l2tp_ctrl_get_cookie(ctrl);
        !           955:        struct ppp_l2tp_sess *sess;
        !           956:        struct ppp_l2tp_avp_list *avps = NULL;
        !           957:        struct sockaddr_dl  hwa;
        !           958:        char    buf[32], buf2[32];
        !           959:        int     k;
        !           960: 
        !           961:        Log(LG_PHYS, ("L2TP: Control connection %p %s %u <-> %s %u connected",
        !           962:            ctrl, u_addrtoa(&tun->self_addr,buf,sizeof(buf)), tun->self_port,
        !           963:            u_addrtoa(&tun->peer_addr,buf2,sizeof(buf2)), tun->peer_port));
        !           964:        
        !           965:        if (GetPeerEther(&tun->peer_addr, &hwa)) {
        !           966:            if_indextoname(hwa.sdl_index, tun->peer_iface);
        !           967:            memcpy(tun->peer_mac_addr, LLADDR(&hwa), sizeof(tun->peer_mac_addr));
        !           968:        };
        !           969: 
        !           970:        /* Examine all L2TP links. */
        !           971:        for (k = 0; k < gNumLinks; k++) {
        !           972:                Link l;
        !           973:                L2tpInfo pi;
        !           974: 
        !           975:                if (!gLinks[k] || gLinks[k]->type != &gL2tpPhysType)
        !           976:                        continue;
        !           977: 
        !           978:                l = gLinks[k];
        !           979:                pi = (L2tpInfo)l->info;
        !           980: 
        !           981:                if (pi->tun != tun)
        !           982:                        continue;
        !           983: 
        !           984:                tun->connected = 1;
        !           985:                /* Create number AVPs */
        !           986:                avps = ppp_l2tp_avp_list_create();
        !           987:                if (pi->conf.callingnum[0]) {
        !           988:                   if (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_CALLING_NUMBER,
        !           989:                    pi->conf.callingnum, strlen(pi->conf.callingnum)) == -1) {
        !           990:                        Perror("[%s] ppp_l2tp_avp_list_append", l->name);
        !           991:                   }
        !           992:                }
        !           993:                if (pi->conf.callednum[0]) {
        !           994:                   if (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_CALLED_NUMBER,
        !           995:                    pi->conf.callednum, strlen(pi->conf.callednum)) == -1) {
        !           996:                        Perror("[%s] ppp_l2tp_avp_list_append", l->name);
        !           997:                   }
        !           998:                }
        !           999:                if ((sess = ppp_l2tp_initiate(tun->ctrl,
        !          1000:                            Enabled(&pi->conf.options, L2TP_CONF_OUTCALL)?1:0, 
        !          1001:                            Enabled(&pi->conf.options, L2TP_CONF_LENGTH)?1:0,
        !          1002:                            Enabled(&pi->conf.options, L2TP_CONF_DATASEQ)?1:0,
        !          1003:                            avps)) == NULL) {
        !          1004:                        Perror("ppp_l2tp_initiate");
        !          1005:                        pi->sess = NULL;
        !          1006:                        pi->tun = NULL;
        !          1007:                        tun->active_sessions--;
        !          1008:                        l->state = PHYS_STATE_DOWN;
        !          1009:                        PhysDown(l, STR_ERROR, NULL);
        !          1010:                        continue;
        !          1011:                };
        !          1012:                ppp_l2tp_avp_list_destroy(&avps);
        !          1013:                pi->sess = sess;
        !          1014:                pi->outcall = Enabled(&pi->conf.options, L2TP_CONF_OUTCALL);
        !          1015:                Log(LG_PHYS, ("[%s] L2TP: %s call #%u via control connection %p initiated", 
        !          1016:                    l->name, (pi->outcall?"Outgoing":"Incoming"), 
        !          1017:                    ppp_l2tp_sess_get_serial(sess), tun->ctrl));
        !          1018:                ppp_l2tp_sess_set_cookie(sess, l);
        !          1019:                if (!pi->outcall) {
        !          1020:                    pi->sync = 1;
        !          1021:                    if (l->rep) {
        !          1022:                        uint32_t fr;
        !          1023:                        avps = ppp_l2tp_avp_list_create();
        !          1024:                        if (RepIsSync(l)) {
        !          1025:                            fr = htonl(L2TP_FRAMING_SYNC);
        !          1026:                        } else {
        !          1027:                            fr = htonl(L2TP_FRAMING_ASYNC);
        !          1028:                            pi->sync = 0;
        !          1029:                        }
        !          1030:                        if (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_FRAMING_TYPE,
        !          1031:                            &fr, sizeof(fr)) == -1) {
        !          1032:                                Perror("[%s] ppp_l2tp_avp_list_append", l->name);
        !          1033:                        }
        !          1034:                    } else {
        !          1035:                        avps = NULL;
        !          1036:                    }
        !          1037:                    ppp_l2tp_connected(pi->sess, avps);
        !          1038:                    if (avps)
        !          1039:                        ppp_l2tp_avp_list_destroy(&avps);
        !          1040:                }
        !          1041:        };
        !          1042: }
        !          1043: 
        !          1044: /*
        !          1045:  * This is called when a control connection is terminated for any reason
        !          1046:  * other than a call ppp_l2tp_ctrl_destroy().
        !          1047:  */
        !          1048: static void
        !          1049: ppp_l2tp_ctrl_terminated_cb(struct ppp_l2tp_ctrl *ctrl,
        !          1050:        u_int16_t result, u_int16_t error, const char *errmsg)
        !          1051: {
        !          1052:        struct l2tp_tun *tun = ppp_l2tp_ctrl_get_cookie(ctrl);
        !          1053:        int     k;
        !          1054: 
        !          1055:        Log(LG_PHYS, ("L2TP: Control connection %p terminated: %d (%s)", 
        !          1056:            ctrl, error, errmsg));
        !          1057: 
        !          1058:        /* Examine all L2TP links. */
        !          1059:        for (k = 0; k < gNumLinks; k++) {
        !          1060:                Link l;
        !          1061:                L2tpInfo pi;
        !          1062: 
        !          1063:                if (!gLinks[k] || gLinks[k]->type != &gL2tpPhysType)
        !          1064:                        continue;
        !          1065: 
        !          1066:                l = gLinks[k];
        !          1067:                pi = (L2tpInfo)l->info;
        !          1068: 
        !          1069:                if (pi->tun != tun)
        !          1070:                        continue;
        !          1071: 
        !          1072:                l->state = PHYS_STATE_DOWN;
        !          1073:                L2tpUnhook(l);
        !          1074:                pi->sess = NULL;
        !          1075:                pi->tun = NULL;
        !          1076:                tun->active_sessions--;
        !          1077:                pi->callingnum[0]=0;
        !          1078:                pi->callednum[0]=0;
        !          1079:                PhysDown(l, STR_DROPPED, NULL);
        !          1080:        };
        !          1081:        
        !          1082:        tun->alive = 0;
        !          1083: }
        !          1084: 
        !          1085: /*
        !          1086:  * This is called before control connection is destroyed for any reason
        !          1087:  * other than a call ppp_l2tp_ctrl_destroy().
        !          1088:  */
        !          1089: static void
        !          1090: ppp_l2tp_ctrl_destroyed_cb(struct ppp_l2tp_ctrl *ctrl)
        !          1091: {
        !          1092:        struct l2tp_tun *tun = ppp_l2tp_ctrl_get_cookie(ctrl);
        !          1093: 
        !          1094:        Log(LG_PHYS, ("L2TP: Control connection %p destroyed", ctrl));
        !          1095: 
        !          1096:        ghash_remove(gL2tpTuns, tun);
        !          1097:        Freee(tun);
        !          1098: }
        !          1099: 
        !          1100: /*
        !          1101:  * This callback is used to report the peer's initiating a new incoming
        !          1102:  * or outgoing call.
        !          1103:  */
        !          1104: static void
        !          1105: ppp_l2tp_initiated_cb(struct ppp_l2tp_ctrl *ctrl,
        !          1106:        struct ppp_l2tp_sess *sess, int out,
        !          1107:        const struct ppp_l2tp_avp_list *avps,
        !          1108:        u_char *include_length, u_char *enable_dseq)
        !          1109: {
        !          1110:        struct  l2tp_tun *const tun = ppp_l2tp_ctrl_get_cookie(ctrl);
        !          1111:        struct  ppp_l2tp_avp_ptrs *ptrs = NULL;
        !          1112:        Link    l = NULL;
        !          1113:        L2tpInfo pi = NULL;
        !          1114:        int     k;
        !          1115: 
        !          1116:        /* Convert AVP's to friendly form */
        !          1117:        if ((ptrs = ppp_l2tp_avp_list2ptrs(avps)) == NULL) {
        !          1118:                Perror("L2TP: error decoding AVP list");
        !          1119:                ppp_l2tp_terminate(sess, L2TP_RESULT_ERROR,
        !          1120:                    L2TP_ERROR_GENERIC, strerror(errno));
        !          1121:                return;
        !          1122:        }
        !          1123: 
        !          1124:        Log(LG_PHYS, ("L2TP: %s call #%u via connection %p received", 
        !          1125:            (out?"Outgoing":"Incoming"), 
        !          1126:            ppp_l2tp_sess_get_serial(sess), ctrl));
        !          1127: 
        !          1128:        if (gShutdownInProgress) {
        !          1129:                Log(LG_PHYS, ("Shutdown sequence in progress, ignoring request."));
        !          1130:                goto failed;
        !          1131:        }
        !          1132: 
        !          1133:        if (OVERLOAD()) {
        !          1134:                Log(LG_PHYS, ("Daemon overloaded, ignoring request."));
        !          1135:                goto failed;
        !          1136:        }
        !          1137: 
        !          1138:        /* Examine all L2TP links. */
        !          1139:        for (k = 0; k < gNumLinks; k++) {
        !          1140:                Link l2;
        !          1141:                L2tpInfo pi2;
        !          1142: 
        !          1143:                if (!gLinks[k] || gLinks[k]->type != &gL2tpPhysType)
        !          1144:                        continue;
        !          1145: 
        !          1146:                l2 = gLinks[k];
        !          1147:                pi2 = (L2tpInfo)l2->info;
        !          1148: 
        !          1149:                if ((!PhysIsBusy(l2)) &&
        !          1150:                    Enabled(&l2->conf.options, LINK_CONF_INCOMING) &&
        !          1151:                    ((u_addrempty(&pi2->conf.self_addr)) || (u_addrcompare(&pi2->conf.self_addr, &tun->self_addr) == 0)) &&
        !          1152:                    (pi2->conf.self_port == 0 || pi2->conf.self_port == tun->self_port) &&
        !          1153:                    (IpAddrInRange(&pi2->conf.peer_addr, &tun->peer_addr)) &&
        !          1154:                    (pi2->conf.peer_port == 0 || pi2->conf.peer_port == tun->peer_port)) {
        !          1155:                        
        !          1156:                        if (pi == NULL || pi2->conf.peer_addr.width > pi->conf.peer_addr.width) {
        !          1157:                                l = l2;
        !          1158:                                pi = pi2;
        !          1159:                                if (u_rangehost(&pi->conf.peer_addr)) {
        !          1160:                                        break;  /* Nothing could be better */
        !          1161:                                }
        !          1162:                        }
        !          1163:                }
        !          1164:        }
        !          1165:        if (l != NULL && l->tmpl)
        !          1166:                l = LinkInst(l, NULL, 0, 0);
        !          1167: 
        !          1168:        if (l != NULL) {
        !          1169:                pi = (L2tpInfo)l->info;
        !          1170:                Log(LG_PHYS, ("[%s] L2TP: %s call #%u via control connection %p accepted", 
        !          1171:                    l->name, (out?"Outgoing":"Incoming"), 
        !          1172:                    ppp_l2tp_sess_get_serial(sess), ctrl));
        !          1173: 
        !          1174:                if (out)
        !          1175:                    l->state = PHYS_STATE_READY;
        !          1176:                else
        !          1177:                    l->state = PHYS_STATE_CONNECTING;
        !          1178:                pi->incoming = 1;
        !          1179:                pi->outcall = out;
        !          1180:                pi->tun = tun;
        !          1181:                tun->active_sessions++;
        !          1182:                pi->sess = sess;
        !          1183:                if (ptrs->callingnum && ptrs->callingnum->number)
        !          1184:                    strlcpy(pi->callingnum, ptrs->callingnum->number, sizeof(pi->callingnum));
        !          1185:                if (ptrs->callednum && ptrs->callednum->number)
        !          1186:                    strlcpy(pi->callednum, ptrs->callednum->number, sizeof(pi->callednum));
        !          1187:                    
        !          1188:                *include_length = (Enabled(&pi->conf.options, L2TP_CONF_LENGTH)?1:0);
        !          1189:                *enable_dseq = (Enabled(&pi->conf.options, L2TP_CONF_DATASEQ)?1:0);
        !          1190: 
        !          1191:                PhysIncoming(l);
        !          1192: 
        !          1193:                ppp_l2tp_sess_set_cookie(sess, l);
        !          1194:                ppp_l2tp_avp_ptrs_destroy(&ptrs);
        !          1195:                return;
        !          1196:        }
        !          1197:        Log(LG_PHYS, ("L2TP: No free link with requested parameters "
        !          1198:            "was found"));
        !          1199: failed:
        !          1200:        ppp_l2tp_terminate(sess, L2TP_RESULT_AVAIL_TEMP, 0, NULL);
        !          1201:        ppp_l2tp_avp_ptrs_destroy(&ptrs);
        !          1202: }
        !          1203: 
        !          1204: /*
        !          1205:  * This callback is used to report successful connection of a remotely
        !          1206:  * initiated incoming call (see ppp_l2tp_initiated_t) or a locally initiated
        !          1207:  * outgoing call (see ppp_l2tp_initiate()).
        !          1208:  */
        !          1209: static void
        !          1210: ppp_l2tp_connected_cb(struct ppp_l2tp_sess *sess,
        !          1211:        const struct ppp_l2tp_avp_list *avps)
        !          1212: {
        !          1213:        Link l;
        !          1214:        L2tpInfo pi;
        !          1215:        struct ppp_l2tp_avp_ptrs *ptrs = NULL;
        !          1216: 
        !          1217:        l = ppp_l2tp_sess_get_cookie(sess);
        !          1218:        pi = (L2tpInfo)l->info;
        !          1219: 
        !          1220:        Log(LG_PHYS, ("[%s] L2TP: Call #%u connected", l->name, 
        !          1221:            ppp_l2tp_sess_get_serial(sess)));
        !          1222: 
        !          1223:        if ((pi->incoming != pi->outcall) && avps != NULL) {
        !          1224:                /* Convert AVP's to friendly form */
        !          1225:                if ((ptrs = ppp_l2tp_avp_list2ptrs(avps)) == NULL) {
        !          1226:                        Perror("L2TP: error decoding AVP list");
        !          1227:                } else {
        !          1228:                        if (ptrs->framing && ptrs->framing->sync) {
        !          1229:                                pi->sync = 1;
        !          1230:                        } else {
        !          1231:                                pi->sync = 0;
        !          1232:                        }
        !          1233:                        ppp_l2tp_avp_ptrs_destroy(&ptrs);
        !          1234:                }
        !          1235:        }
        !          1236: 
        !          1237:        if (pi->opened) {
        !          1238:            l->state = PHYS_STATE_UP;
        !          1239:            L2tpHookUp(l);
        !          1240:            PhysUp(l);
        !          1241:        } else {
        !          1242:            l->state = PHYS_STATE_READY;
        !          1243:        }
        !          1244: }
        !          1245: 
        !          1246: /*
        !          1247:  * This callback is called when any call, whether successfully connected
        !          1248:  * or not, is terminated for any reason other than explict termination
        !          1249:  * from the link side (via a call to either ppp_l2tp_terminate() or
        !          1250:  * ppp_l2tp_ctrl_destroy()).
        !          1251:  */
        !          1252: static void
        !          1253: ppp_l2tp_terminated_cb(struct ppp_l2tp_sess *sess,
        !          1254:        u_int16_t result, u_int16_t error, const char *errmsg)
        !          1255: {
        !          1256:        char buf[128];
        !          1257:        Link l;
        !          1258:        L2tpInfo pi;
        !          1259: 
        !          1260:        l = ppp_l2tp_sess_get_cookie(sess);
        !          1261:        pi = (L2tpInfo) l->info;
        !          1262: 
        !          1263:        /* Control side is notifying us session is down */
        !          1264:        snprintf(buf, sizeof(buf), "result=%u error=%u errmsg=\"%s\"",
        !          1265:            result, error, (errmsg != NULL) ? errmsg : "");
        !          1266:        Log(LG_PHYS, ("[%s] L2TP: call #%u terminated: %s", l->name, 
        !          1267:            ppp_l2tp_sess_get_serial(sess), buf));
        !          1268: 
        !          1269:        l->state = PHYS_STATE_DOWN;
        !          1270:        L2tpUnhook(l);
        !          1271:        pi->sess = NULL;
        !          1272:        if (pi->tun)
        !          1273:            pi->tun->active_sessions--;
        !          1274:        pi->tun = NULL;
        !          1275:        pi->callingnum[0]=0;
        !          1276:        pi->callednum[0]=0;
        !          1277:        PhysDown(l, STR_DROPPED, NULL);
        !          1278: }
        !          1279: 
        !          1280: /*
        !          1281:  * This callback called on receiving link info from peer.
        !          1282:  */
        !          1283: void
        !          1284: ppp_l2tp_set_link_info_cb(struct ppp_l2tp_sess *sess,
        !          1285:                        u_int32_t xmit, u_int32_t recv)
        !          1286: {
        !          1287:        Link l = ppp_l2tp_sess_get_cookie(sess);
        !          1288: 
        !          1289:        if (l->rep != NULL) {
        !          1290:                RepSetAccm(l, xmit, recv);
        !          1291:        }
        !          1292: }
        !          1293: 
        !          1294: /*
        !          1295:  * Connect L2TP and link hooks.
        !          1296:  */
        !          1297:  
        !          1298: static void
        !          1299: L2tpHookUp(Link l)
        !          1300: {
        !          1301:        int             csock = -1;
        !          1302:        L2tpInfo        pi = (L2tpInfo)l->info;
        !          1303:         const char     *hook;
        !          1304:         ng_ID_t                node_id;
        !          1305:        char            path[NG_PATHSIZ];
        !          1306:        struct ngm_connect      cn;
        !          1307: 
        !          1308:        /* Get a temporary netgraph socket node */
        !          1309:        if (NgMkSockNode(NULL, &csock, NULL) == -1) {
        !          1310:                Perror("L2TP: NgMkSockNode");
        !          1311:                goto fail;
        !          1312:        }
        !          1313: 
        !          1314:        /* Get this link's node and hook */
        !          1315:        ppp_l2tp_sess_get_hook(pi->sess, &node_id, &hook);
        !          1316: 
        !          1317:        /* Initialize cn */
        !          1318:        memset(&cn, 0, sizeof(cn));
        !          1319: 
        !          1320:        /* Connect our ng_ppp(4) node link hook and ng_l2tp(4) node. */
        !          1321:        if (!PhysGetUpperHook(l, cn.path, cn.peerhook)) {
        !          1322:            Log(LG_PHYS, ("[%s] L2TP: can't get upper hook", l->name));
        !          1323:            goto fail;
        !          1324:        }
        !          1325:        snprintf(path, sizeof(path), "[%lx]:", (u_long)node_id);
        !          1326:        strlcpy(cn.ourhook, hook, sizeof(cn.ourhook));
        !          1327:        if (NgSendMsg(csock, path, NGM_GENERIC_COOKIE, NGM_CONNECT, 
        !          1328:            &cn, sizeof(cn)) < 0) {
        !          1329:                Perror("[%s] L2TP: can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
        !          1330:                    l->name, path, cn.ourhook, cn.path, cn.peerhook);
        !          1331:                goto fail;
        !          1332:        }
        !          1333:        ppp_l2tp_sess_hooked(pi->sess);
        !          1334:        close(csock);
        !          1335:        return;
        !          1336: 
        !          1337: fail:
        !          1338:        /* Clean up after failure */
        !          1339:        ppp_l2tp_terminate(pi->sess, L2TP_RESULT_ERROR,
        !          1340:            L2TP_ERROR_GENERIC, strerror(errno));
        !          1341:        pi->sess = NULL;
        !          1342:        if (csock != -1)
        !          1343:                (void)close(csock);
        !          1344: }
        !          1345: 
        !          1346: /*
        !          1347:  * Read an incoming packet that might be a new L2TP connection.
        !          1348:  */
        !          1349:  
        !          1350: static void
        !          1351: L2tpServerEvent(int type, void *arg)
        !          1352: {
        !          1353:        struct l2tp_server *const s = arg;
        !          1354:        L2tpInfo pi = NULL;
        !          1355:        struct ppp_l2tp_avp_list *avps = NULL;
        !          1356:        struct l2tp_tun *tun = NULL;
        !          1357:        union {
        !          1358:            u_char buf[sizeof(struct ng_ksocket_sockopt) + sizeof(int)];
        !          1359:            struct ng_ksocket_sockopt sockopt;
        !          1360:        } sockopt_buf;
        !          1361:        struct ng_ksocket_sockopt *const sockopt = &sockopt_buf.sockopt;
        !          1362:        struct ngm_connect connect;
        !          1363:        struct ngm_rmhook rmhook;
        !          1364:        struct ngm_mkpeer mkpeer;
        !          1365:        struct sockaddr_storage peer_sas;
        !          1366:        struct sockaddr_storage sas;
        !          1367:        const size_t bufsize = 8192;
        !          1368:        u_int16_t *buf = NULL;
        !          1369:        char hook[NG_HOOKSIZ];
        !          1370:        char hostname[MAXHOSTNAMELEN];
        !          1371:        socklen_t sas_len;
        !          1372:        char namebuf[64];
        !          1373:        char buf1[32], buf2[32];
        !          1374:        ng_ID_t node_id;
        !          1375:        int csock = -1;
        !          1376:        int dsock = -1;
        !          1377:        int len;
        !          1378:        u_int32_t       cap;
        !          1379:        u_int16_t       win;
        !          1380:        int     k;
        !          1381: 
        !          1382:        /* Allocate buffer */
        !          1383:        buf = Malloc(MB_PHYS, bufsize);
        !          1384: 
        !          1385:        /* Read packet */
        !          1386:        sas_len = sizeof(peer_sas);
        !          1387:        if ((len = recvfrom(s->sock, buf, bufsize, 0,
        !          1388:            (struct sockaddr *)&peer_sas, &sas_len)) == -1) {
        !          1389:                Perror("L2TP: recvfrom");
        !          1390:                goto fail;
        !          1391:        }
        !          1392: 
        !          1393:        /* Drop it if it's not an initial L2TP packet */
        !          1394:        if (len < 12)
        !          1395:                goto fail;
        !          1396:        if ((ntohs(buf[0]) & 0xcb0f) != 0xc802 || ntohs(buf[1]) < 12
        !          1397:            || buf[2] != 0 || buf[3] != 0 || buf[4] != 0 || buf[5] != 0)
        !          1398:                goto fail;
        !          1399: 
        !          1400:        /* Create a new tun */
        !          1401:        tun = Malloc(MB_PHYS, sizeof(*tun));
        !          1402:        sockaddrtou_addr(&peer_sas,&tun->peer_addr,&tun->peer_port);
        !          1403:        u_addrcopy(&s->self_addr, &tun->self_addr);
        !          1404:        tun->self_port = s->self_port;
        !          1405:        tun->alive = 1;
        !          1406: 
        !          1407:        Log(LG_PHYS, ("Incoming L2TP packet from %s %d", 
        !          1408:                u_addrtoa(&tun->peer_addr, namebuf, sizeof(namebuf)), tun->peer_port));
        !          1409: 
        !          1410:        /* Examine all L2TP links to get best possible fit tunnel parameters. */
        !          1411:        for (k = 0; k < gNumLinks; k++) {
        !          1412:                Link l2;
        !          1413:                L2tpInfo pi2;
        !          1414: 
        !          1415:                if (!gLinks[k] || gLinks[k]->type != &gL2tpPhysType)
        !          1416:                        continue;
        !          1417: 
        !          1418:                l2 = gLinks[k];
        !          1419:                pi2 = (L2tpInfo)l2->info;
        !          1420: 
        !          1421:                /* Simplified comparation as it is not a final one. */
        !          1422:                if ((!PhysIsBusy(l2)) &&
        !          1423:                    (pi2->server == s) &&
        !          1424:                    (IpAddrInRange(&pi2->conf.peer_addr, &tun->peer_addr)) &&
        !          1425:                    (pi2->conf.peer_port == 0 || pi2->conf.peer_port == tun->peer_port)) {
        !          1426:                        
        !          1427:                        if (pi == NULL || pi2->conf.peer_addr.width > pi->conf.peer_addr.width) {
        !          1428:                                pi = pi2;
        !          1429:                                if (u_rangehost(&pi->conf.peer_addr)) {
        !          1430:                                        break;  /* Nothing could be better */
        !          1431:                                }
        !          1432:                        }
        !          1433:                }
        !          1434:        }
        !          1435:        if (pi == NULL) {
        !          1436:                Log(LG_PHYS, ("L2TP: No link with requested parameters "
        !          1437:                    "was found"));
        !          1438:                goto fail;
        !          1439:        }
        !          1440: 
        !          1441:        /* Create vendor name AVP */
        !          1442:        avps = ppp_l2tp_avp_list_create();
        !          1443: 
        !          1444:        if (pi->conf.hostname[0] != 0) {
        !          1445:            strlcpy(hostname, pi->conf.hostname, sizeof(hostname));
        !          1446:        } else {
        !          1447:            (void)gethostname(hostname, sizeof(hostname) - 1);
        !          1448:            hostname[sizeof(hostname) - 1] = '\0';
        !          1449:        }
        !          1450:        cap = htonl(L2TP_BEARER_DIGITAL|L2TP_BEARER_ANALOG);
        !          1451:        win = htons(8); /* XXX: this value is empirical. */
        !          1452:        if ((ppp_l2tp_avp_list_append(avps, 1, 0, AVP_HOST_NAME,
        !          1453:              hostname, strlen(hostname)) == -1) ||
        !          1454:            (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_VENDOR_NAME,
        !          1455:              MPD_VENDOR, strlen(MPD_VENDOR)) == -1) ||
        !          1456:            (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_BEARER_CAPABILITIES,
        !          1457:              &cap, sizeof(cap)) == -1) ||
        !          1458:            (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_RECEIVE_WINDOW_SIZE,
        !          1459:              &win, sizeof(win)) == -1)) {
        !          1460:                Perror("L2TP: ppp_l2tp_avp_list_append");
        !          1461:                goto fail;
        !          1462:        }
        !          1463: 
        !          1464:        /* Create a new control connection */
        !          1465:        if ((tun->ctrl = ppp_l2tp_ctrl_create(gPeventCtx, &gGiantMutex,
        !          1466:            &ppp_l2tp_server_ctrl_cb, u_addrtoid(&tun->peer_addr),
        !          1467:            &node_id, hook, avps, 
        !          1468:            pi->conf.secret, strlen(pi->conf.secret),
        !          1469:            Enabled(&pi->conf.options, L2TP_CONF_HIDDEN))) == NULL) {
        !          1470:                Perror("L2TP: ppp_l2tp_ctrl_create");
        !          1471:                goto fail;
        !          1472:        }
        !          1473:        ppp_l2tp_ctrl_set_cookie(tun->ctrl, tun);
        !          1474: 
        !          1475:        /* Get a temporary netgraph socket node */
        !          1476:        if (NgMkSockNode(NULL, &csock, &dsock) == -1) {
        !          1477:                Perror("L2TP: NgMkSockNode");
        !          1478:                goto fail;
        !          1479:        }
        !          1480: 
        !          1481:        /* Connect to l2tp netgraph node "lower" hook */
        !          1482:        snprintf(namebuf, sizeof(namebuf), "[%lx]:", (u_long)node_id);
        !          1483:        memset(&connect, 0, sizeof(connect));
        !          1484:        strlcpy(connect.path, namebuf, sizeof(connect.path));
        !          1485:        strlcpy(connect.ourhook, hook, sizeof(connect.ourhook));
        !          1486:        strlcpy(connect.peerhook, hook, sizeof(connect.peerhook));
        !          1487:        if (NgSendMsg(csock, ".:", NGM_GENERIC_COOKIE,
        !          1488:            NGM_CONNECT, &connect, sizeof(connect)) == -1) {
        !          1489:                Perror("L2TP: connect");
        !          1490:                goto fail;
        !          1491:        }
        !          1492: 
        !          1493:        /* Write the received packet to the node */
        !          1494:        if (NgSendData(dsock, hook, (u_char *)buf, len) == -1) {
        !          1495:                Perror("L2TP: NgSendData");
        !          1496:                goto fail;
        !          1497:        }
        !          1498: 
        !          1499:        /* Disconnect from netgraph node "lower" hook */
        !          1500:        memset(&rmhook, 0, sizeof(rmhook));
        !          1501:        strlcpy(rmhook.ourhook, hook, sizeof(rmhook.ourhook));
        !          1502:        if (NgSendMsg(csock, ".:", NGM_GENERIC_COOKIE,
        !          1503:            NGM_RMHOOK, &rmhook, sizeof(rmhook)) == -1) {
        !          1504:                Perror("L2TP: rmhook");
        !          1505:                goto fail;
        !          1506:        }
        !          1507: 
        !          1508:        /* Attach a new UDP socket to "lower" hook */
        !          1509:        memset(&mkpeer, 0, sizeof(mkpeer));
        !          1510:        strlcpy(mkpeer.type, NG_KSOCKET_NODE_TYPE, sizeof(mkpeer.type));
        !          1511:        strlcpy(mkpeer.ourhook, hook, sizeof(mkpeer.ourhook));
        !          1512:        if (s->self_addr.family==AF_INET6) {
        !          1513:                snprintf(mkpeer.peerhook, sizeof(mkpeer.peerhook), "%d/%d/%d", PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
        !          1514:        } else {
        !          1515:                snprintf(mkpeer.peerhook, sizeof(mkpeer.peerhook), "inet/dgram/udp");
        !          1516:        }
        !          1517:        if (NgSendMsg(csock, namebuf, NGM_GENERIC_COOKIE,
        !          1518:            NGM_MKPEER, &mkpeer, sizeof(mkpeer)) == -1) {
        !          1519:                Perror("L2TP: mkpeer");
        !          1520:                goto fail;
        !          1521:        }
        !          1522: 
        !          1523:        /* Point name at ksocket node */
        !          1524:        strlcat(namebuf, hook, sizeof(namebuf));
        !          1525: 
        !          1526:        /* Make UDP port reusable */
        !          1527:        memset(&sockopt_buf, 0, sizeof(sockopt_buf));
        !          1528:        sockopt->level = SOL_SOCKET;
        !          1529:        sockopt->name = SO_REUSEADDR;
        !          1530:        memcpy(sockopt->value, &one, sizeof(int));
        !          1531:        if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
        !          1532:            NGM_KSOCKET_SETOPT, sockopt, sizeof(sockopt_buf)) == -1) {
        !          1533:                Perror("L2TP: setsockopt");
        !          1534:                goto fail;
        !          1535:        }
        !          1536:        sockopt->name = SO_REUSEPORT;
        !          1537:        if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
        !          1538:            NGM_KSOCKET_SETOPT, sockopt, sizeof(sockopt_buf)) == -1) {
        !          1539:                Perror("L2TP: setsockopt");
        !          1540:                goto fail;
        !          1541:        }
        !          1542: 
        !          1543:        /* Bind socket to a new port */
        !          1544:        u_addrtosockaddr(&s->self_addr,s->self_port,&sas);
        !          1545:        if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
        !          1546:            NGM_KSOCKET_BIND, &sas, sas.ss_len) == -1) {
        !          1547:                Perror("L2TP: bind");
        !          1548:                goto fail;
        !          1549:        }
        !          1550: 
        !          1551:        /* Connect socket to remote peer's IP and port */
        !          1552:        if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
        !          1553:              NGM_KSOCKET_CONNECT, &peer_sas, peer_sas.ss_len) == -1
        !          1554:            && errno != EINPROGRESS) {
        !          1555:                Perror("L2TP: connect");
        !          1556:                goto fail;
        !          1557:        }
        !          1558: 
        !          1559:        /* Add peer to our hash table */
        !          1560:        if (ghash_put(gL2tpTuns, tun) == -1) {
        !          1561:                Perror("L2TP: ghash_put");
        !          1562:                goto fail;
        !          1563:        }
        !          1564: 
        !          1565:        Log(LG_PHYS2, ("L2TP: Control connection %p %s %u <-> %s %u accepted",
        !          1566:            tun->ctrl, u_addrtoa(&tun->self_addr,buf1,sizeof(buf1)), tun->self_port,
        !          1567:            u_addrtoa(&tun->peer_addr,buf2,sizeof(buf2)), tun->peer_port));
        !          1568: 
        !          1569:        /* Clean up and return */
        !          1570:        ppp_l2tp_avp_list_destroy(&avps);
        !          1571:        (void)close(csock);
        !          1572:        (void)close(dsock);
        !          1573:        Freee(buf);
        !          1574:        return;
        !          1575: 
        !          1576: fail:
        !          1577:        /* Clean up after failure */
        !          1578:        if (csock != -1)
        !          1579:                (void)close(csock);
        !          1580:        if (dsock != -1)
        !          1581:                (void)close(dsock);
        !          1582:        if (tun != NULL) {
        !          1583:                ppp_l2tp_ctrl_destroy(&tun->ctrl);
        !          1584:                Freee(tun);
        !          1585:        }
        !          1586:        ppp_l2tp_avp_list_destroy(&avps);
        !          1587:        Freee(buf);
        !          1588: }
        !          1589: 
        !          1590: 
        !          1591: /*
        !          1592:  * L2tpListen()
        !          1593:  */
        !          1594: 
        !          1595: static int
        !          1596: L2tpListen(Link l)
        !          1597: {
        !          1598:        L2tpInfo        p = (L2tpInfo)l->info;
        !          1599:        struct l2tp_server *s;
        !          1600:        struct sockaddr_storage sa;
        !          1601:        char buf[48];
        !          1602:        struct ghash_walk walk;
        !          1603: 
        !          1604:        if (p->server)
        !          1605:            return(1);
        !          1606: 
        !          1607:        ghash_walk_init(gL2tpServers, &walk);
        !          1608:        while ((s = ghash_walk_next(gL2tpServers, &walk)) != NULL) {
        !          1609:            if ((u_addrcompare(&s->self_addr, &p->conf.self_addr) == 0) && 
        !          1610:                s->self_port == (p->conf.self_port?p->conf.self_port:L2TP_PORT)) {
        !          1611:                    s->refs++;
        !          1612:                    p->server = s;
        !          1613:                    return(1);
        !          1614:            }
        !          1615:        }
        !          1616: 
        !          1617:        s = Malloc(MB_PHYS, sizeof(struct l2tp_server));
        !          1618:        s->refs = 1;
        !          1619:        u_addrcopy(&p->conf.self_addr, &s->self_addr);
        !          1620:        s->self_port = p->conf.self_port?p->conf.self_port:L2TP_PORT;
        !          1621:        
        !          1622:        /* Setup UDP socket that listens for new connections */
        !          1623:        if (s->self_addr.family==AF_INET6) {
        !          1624:                s->sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
        !          1625:        } else {
        !          1626:                s->sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
        !          1627:        }
        !          1628:        if (s->sock == -1) {
        !          1629:                Perror("L2TP: socket");
        !          1630:                goto fail;
        !          1631:        }
        !          1632:        if (setsockopt(s->sock, SOL_SOCKET,
        !          1633:            SO_REUSEADDR, &one, sizeof(one)) == -1) {
        !          1634:                Perror("L2TP: setsockopt");
        !          1635:                goto fail;
        !          1636:        }
        !          1637:        if (setsockopt(s->sock, SOL_SOCKET,
        !          1638:            SO_REUSEPORT, &one, sizeof(one)) == -1) {
        !          1639:                Perror("L2TP: setsockopt");
        !          1640:                goto fail;
        !          1641:        }
        !          1642:        u_addrtosockaddr(&s->self_addr, s->self_port, &sa);
        !          1643:        if (bind(s->sock, (struct sockaddr *)&sa, sa.ss_len) == -1) {
        !          1644:                Perror("L2TP: bind");
        !          1645:                goto fail;
        !          1646:        }
        !          1647: 
        !          1648:        EventRegister(&s->event, EVENT_READ, s->sock,
        !          1649:            EVENT_RECURRING, L2tpServerEvent, s);
        !          1650: 
        !          1651:        Log(LG_PHYS, ("L2TP: waiting for connection on %s %u",
        !          1652:            u_addrtoa(&s->self_addr, buf, sizeof(buf)), s->self_port));
        !          1653:        
        !          1654:        p->server = s;
        !          1655:        ghash_put(gL2tpServers, s);
        !          1656:        return (1);
        !          1657: fail:
        !          1658:        if (s->sock)
        !          1659:            close(s->sock);
        !          1660:        Freee(s);
        !          1661:        return (0);
        !          1662: }
        !          1663: 
        !          1664: /*
        !          1665:  * L2tpUnListen()
        !          1666:  */
        !          1667: 
        !          1668: static void
        !          1669: L2tpUnListen(Link l)
        !          1670: {
        !          1671:        L2tpInfo        p = (L2tpInfo)l->info;
        !          1672:        struct l2tp_server *s = p->server;
        !          1673:        char buf[48];
        !          1674: 
        !          1675:        if (!s)
        !          1676:            return;
        !          1677: 
        !          1678:        s->refs--;
        !          1679:        if (s->refs == 0) {
        !          1680:            Log(LG_PHYS, ("L2TP: stop waiting for connection on %s %u",
        !          1681:                u_addrtoa(&s->self_addr, buf, sizeof(buf)), s->self_port));
        !          1682:        
        !          1683:            ghash_remove(gL2tpServers, s);
        !          1684:            EventUnRegister(&s->event);
        !          1685:            if (s->sock)
        !          1686:                close(s->sock);
        !          1687:            Freee(s);
        !          1688:            p->server = NULL;
        !          1689:        }
        !          1690:        return;
        !          1691: }
        !          1692: 
        !          1693: /*
        !          1694:  * L2tpNodeUpdate()
        !          1695:  */
        !          1696: 
        !          1697: static void
        !          1698: L2tpNodeUpdate(Link l)
        !          1699: {
        !          1700:     L2tpInfo const pi = (L2tpInfo) l->info;
        !          1701:     if (!pi->server) {
        !          1702:        if (Enabled(&l->conf.options, LINK_CONF_INCOMING))
        !          1703:            L2tpListen(l);
        !          1704:     } else {
        !          1705:        if (!Enabled(&l->conf.options, LINK_CONF_INCOMING))
        !          1706:            L2tpUnListen(l);
        !          1707:     }
        !          1708: }
        !          1709: 
        !          1710: /*
        !          1711:  * L2tpSetCommand()
        !          1712:  */
        !          1713: 
        !          1714: static int
        !          1715: L2tpSetCommand(Context ctx, int ac, char *av[], void *arg)
        !          1716: {
        !          1717:     L2tpInfo           const l2tp = (L2tpInfo) ctx->lnk->info;
        !          1718:     char               **fqdn_peer_addr = &l2tp->conf.fqdn_peer_addr;
        !          1719:     struct u_range     rng;
        !          1720:     int                        port;
        !          1721: 
        !          1722:     switch ((intptr_t)arg) {
        !          1723:        case SET_SELFADDR:
        !          1724:        case SET_PEERADDR:
        !          1725:            if ((ac == 1 || ac == 2) && (intptr_t)arg == SET_PEERADDR) {
        !          1726:                if (*fqdn_peer_addr)
        !          1727:                    Freee(*fqdn_peer_addr);
        !          1728:                *fqdn_peer_addr = Mstrdup(MB_PHYS, av[0]);
        !          1729:            }
        !          1730:            if (ac < 1 || ac > 2 || !ParseRange(av[0], &rng, ALLOW_IPV4|ALLOW_IPV6))
        !          1731:                return(-1);
        !          1732:            if (ac > 1) {
        !          1733:                if ((port = atoi(av[1])) < 0 || port > 0xffff)
        !          1734:                    return(-1);
        !          1735:            } else {
        !          1736:                port = 0;
        !          1737:            }
        !          1738:            if ((intptr_t)arg == SET_SELFADDR) {
        !          1739:                l2tp->conf.self_addr = rng.addr;
        !          1740:                l2tp->conf.self_port = port;
        !          1741:                if (l2tp->server) {
        !          1742:                    L2tpUnListen(ctx->lnk);
        !          1743:                    L2tpListen(ctx->lnk);
        !          1744:                }
        !          1745:            } else {
        !          1746:                l2tp->conf.peer_addr = rng;
        !          1747:                l2tp->conf.peer_port = port;
        !          1748:            }
        !          1749:            break;
        !          1750:        case SET_CALLINGNUM:
        !          1751:            if (ac != 1)
        !          1752:                return(-1);
        !          1753:            strlcpy(l2tp->conf.callingnum, av[0], sizeof(l2tp->conf.callingnum));
        !          1754:            break;
        !          1755:        case SET_CALLEDNUM:
        !          1756:            if (ac != 1)
        !          1757:                return(-1);
        !          1758:            strlcpy(l2tp->conf.callednum, av[0], sizeof(l2tp->conf.callednum));
        !          1759:            break;
        !          1760:        case SET_HOSTNAME:
        !          1761:            if (ac != 1)
        !          1762:                return(-1);
        !          1763:            strlcpy(l2tp->conf.hostname, av[0], sizeof(l2tp->conf.hostname));
        !          1764:            break;
        !          1765:        case SET_SECRET:
        !          1766:            if (ac != 1)
        !          1767:                return(-1);
        !          1768:            strlcpy(l2tp->conf.secret, av[0], sizeof(l2tp->conf.secret));
        !          1769:            break;
        !          1770:        case SET_ENABLE:
        !          1771:            EnableCommand(ac, av, &l2tp->conf.options, gConfList);
        !          1772:            break;
        !          1773:        case SET_DISABLE:
        !          1774:            DisableCommand(ac, av, &l2tp->conf.options, gConfList);
        !          1775:            break;
        !          1776:        default:
        !          1777:            assert(0);
        !          1778:     }
        !          1779:     return(0);
        !          1780: }
        !          1781: 
        !          1782: /*
        !          1783:  * L2tpsStat()
        !          1784:  */
        !          1785: 
        !          1786: int
        !          1787: L2tpsStat(Context ctx, int ac, char *av[], void *arg)
        !          1788: {
        !          1789:     struct l2tp_tun    *tun;
        !          1790:     struct ghash_walk  walk;
        !          1791:     char       buf1[64], buf2[64], buf3[64];
        !          1792: 
        !          1793:     Printf("Active L2TP tunnels:\r\n");
        !          1794:     ghash_walk_init(gL2tpTuns, &walk);
        !          1795:     while ((tun = ghash_walk_next(gL2tpTuns, &walk)) != NULL) {
        !          1796: 
        !          1797:        u_addrtoa(&tun->self_addr, buf1, sizeof(buf1));
        !          1798:        u_addrtoa(&tun->peer_addr, buf2, sizeof(buf2));
        !          1799:        ppp_l2tp_ctrl_stats(tun->ctrl, buf3, sizeof(buf3));
        !          1800:        Printf("%p\t %s %d <=> %s %d\t%s %d calls\r\n",
        !          1801:            tun->ctrl, buf1, tun->self_port, buf2, tun->peer_port,
        !          1802:            buf3, tun->active_sessions);
        !          1803:     }
        !          1804: 
        !          1805:     return 0;
        !          1806: }

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