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

1.1     ! misho       1: 
        !             2: /*
        !             3:  * pptp.c
        !             4:  *
        !             5:  * Written by Archie Cobbs <archie@freebsd.org>
        !             6:  * Copyright (c) 1998-1999 Whistle Communications, Inc. All rights reserved.
        !             7:  * See ``COPYRIGHT.whistle''
        !             8:  */
        !             9: 
        !            10: #include "ppp.h"
        !            11: #include "phys.h"
        !            12: #include "mbuf.h"
        !            13: #include "ngfunc.h"
        !            14: #include "pptp.h"
        !            15: #include "pptp_ctrl.h"
        !            16: #include "log.h"
        !            17: #include "util.h"
        !            18: 
        !            19: #include <netgraph/ng_message.h>
        !            20: #include <netgraph/ng_socket.h>
        !            21: #include <netgraph/ng_ksocket.h>
        !            22: #include <netgraph/ng_pptpgre.h>
        !            23: #include <netgraph.h>
        !            24: 
        !            25: /*
        !            26:  * DEFINITIONS
        !            27:  */
        !            28: 
        !            29:   #define PPTP_MRU             PPTP_MTU
        !            30: 
        !            31:   #define PPTP_CALL_MIN_BPS    56000
        !            32:   #define PPTP_CALL_MAX_BPS    64000
        !            33: 
        !            34:   struct pptptun {
        !            35:     struct u_addr      self_addr;      /* Current self IP address */
        !            36:     struct u_addr      peer_addr;      /* Current peer IP address */
        !            37:     ng_ID_t            node_id;
        !            38:     int                        refs;
        !            39:   };
        !            40:   typedef struct pptptun       *PptpTun;
        !            41: 
        !            42:   struct pptpinfo {
        !            43:     struct {
        !            44:        struct u_addr   self_addr;      /* self IP address */
        !            45:        struct u_range  peer_addr;      /* Peer IP addresses allowed */
        !            46:        in_port_t       self_port;      /* self port */
        !            47:        in_port_t       peer_port;      /* Peer port required (or zero) */
        !            48:        struct optinfo  options;
        !            49:        char            callingnum[64]; /* PPTP phone number to use */
        !            50:        char            callednum[64];  /* PPTP phone number to use */
        !            51:        char            *fqdn_peer_addr;        /* FQDN Peer address */
        !            52:     } conf;
        !            53:     void               *listener;      /* Listener pointer */
        !            54:     struct u_addr      self_addr;      /* Current self IP address */
        !            55:     struct u_addr      peer_addr;      /* Current peer IP address */
        !            56:     char                peer_iface[IFNAMSIZ];  /* Peer iface */
        !            57:     u_char             peer_mac_addr[6];       /* Peer MAC address */
        !            58:     in_port_t          peer_port;      /* Current peer port */
        !            59:     u_char             originate;      /* Call originated locally */
        !            60:     u_char             outcall;        /* Call is outgoing vs. incoming */
        !            61:     u_char             sync;           /* Call is sync vs. async */
        !            62:     u_int16_t          cid;            /* call id */
        !            63:     PptpTun            tun;
        !            64:     struct pptpctrlinfo        cinfo;
        !            65:     char               callingnum[64]; /* PPTP phone number to use */
        !            66:     char               callednum[64];  /* PPTP phone number to use */
        !            67:   };
        !            68:   typedef struct pptpinfo      *PptpInfo;
        !            69: 
        !            70:   /* Set menu options */
        !            71:   enum {
        !            72:     SET_SELFADDR,
        !            73:     SET_PEERADDR,
        !            74:     SET_CALLINGNUM,
        !            75:     SET_CALLEDNUM,
        !            76:     SET_ENABLE,
        !            77:     SET_DISABLE
        !            78:   };
        !            79: 
        !            80:   /* Binary options */
        !            81:   enum {
        !            82:     PPTP_CONF_OUTCALL,         /* when originating, calls are "outgoing" */
        !            83:     PPTP_CONF_DELAYED_ACK,     /* enable delayed receive ack algorithm */
        !            84:     PPTP_CONF_ALWAYS_ACK,      /* include ack with all outgoing data packets */
        !            85:     PPTP_CONF_RESOLVE_ONCE,    /* Only once resolve peer_addr */
        !            86: #if NGM_PPTPGRE_COOKIE >= 1082548365
        !            87:     PPTP_CONF_WINDOWING                /* control (stupid) windowing algorithm */
        !            88: #endif
        !            89:   };
        !            90: 
        !            91: /*
        !            92:  * INTERNAL FUNCTIONS
        !            93:  */
        !            94: 
        !            95:   static int   PptpTInit(void);
        !            96:   static void  PptpTShutdown(void);
        !            97:   static int   PptpInit(Link l);
        !            98:   static int   PptpInst(Link l, Link lt);
        !            99:   static void  PptpOpen(Link l);
        !           100:   static void  PptpClose(Link l);
        !           101:   static void  PptpShutdown(Link l);
        !           102:   static void  PptpStat(Context ctx);
        !           103:   static int   PptpOriginated(Link l);
        !           104:   static int   PptpIsSync(Link l);
        !           105:   static int   PptpSetAccm(Link l, u_int32_t xmit, u_int32_t recv);
        !           106:   static int   PptpSetCallingNum(Link l, void *buf);
        !           107:   static int   PptpSetCalledNum(Link l, void *buf);
        !           108:   static int   PptpSelfName(Link l, void *buf, size_t buf_len);
        !           109:   static int   PptpPeerName(Link l, void *buf, size_t buf_len);
        !           110:   static int   PptpSelfAddr(Link l, void *buf, size_t buf_len);
        !           111:   static int   PptpPeerAddr(Link l, void *buf, size_t buf_len);
        !           112:   static int   PptpPeerPort(Link l, void *buf, size_t buf_len);
        !           113:   static int   PptpPeerMacAddr(Link l, void *buf, size_t buf_len);
        !           114:   static int   PptpPeerIface(Link l, void *buf, size_t buf_len);
        !           115:   static int   PptpCallingNum(Link l, void *buf, size_t buf_len);
        !           116:   static int   PptpCalledNum(Link l, void *buf, size_t buf_len);
        !           117: 
        !           118:   static int   PptpOriginate(Link l);
        !           119:   static void  PptpDoClose(Link l);
        !           120:   static void  PptpUnhook(Link l);
        !           121:   static void  PptpResult(void *cookie, const char *errmsg, int frameType);
        !           122:   static void  PptpSetLinkInfo(void *cookie, u_int32_t sa, u_int32_t ra);
        !           123:   static void  PptpCancel(void *cookie);
        !           124:   static int   PptpHookUp(Link l);
        !           125:   static void  PptpListenUpdate(Link l);
        !           126: 
        !           127:   static struct pptplinkinfo   PptpIncoming(struct pptpctrlinfo *cinfo,
        !           128:                                  struct u_addr *self, struct u_addr *peer, in_port_t port, int bearType,
        !           129:                                  const char *callingNum,
        !           130:                                  const char *calledNum,
        !           131:                                  const char *subAddress);
        !           132: 
        !           133:   static struct pptplinkinfo   PptpOutgoing(struct pptpctrlinfo *cinfo,
        !           134:                                  struct u_addr *self, struct u_addr *peer, in_port_t port, int bearType,
        !           135:                                  int frameType, int minBps, int maxBps,
        !           136:                                  const char *calledNum,
        !           137:                                  const char *subAddress);
        !           138: 
        !           139:   static struct pptplinkinfo   PptpPeerCall(struct pptpctrlinfo *cinfo,
        !           140:                                  struct u_addr *self, struct u_addr *peer, in_port_t port, int incoming,
        !           141:                                  const char *callingNum,
        !           142:                                  const char *calledNum,
        !           143:                                  const char *subAddress);
        !           144: 
        !           145:   static int   PptpSetCommand(Context ctx, int ac, char *av[], void *arg);
        !           146:   static int   PptpTunEQ(struct ghash *g, const void *item1, const void *item2);
        !           147:   static u_int32_t     PptpTunHash(struct ghash *g, const void *item);
        !           148: 
        !           149: 
        !           150: /*
        !           151:  * GLOBAL VARIABLES
        !           152:  */
        !           153: 
        !           154:   const struct phystype        gPptpPhysType = {
        !           155:     .name              = "pptp",
        !           156:     .descr             = "Point-to-Point Tunneling Protocol",
        !           157:     .mtu               = PPTP_MTU,
        !           158:     .mru               = PPTP_MRU,
        !           159:     .tmpl              = 1,
        !           160:     .tinit             = PptpTInit,
        !           161:     .tshutdown         = PptpTShutdown,
        !           162:     .init              = PptpInit,
        !           163:     .inst              = PptpInst,
        !           164:     .open              = PptpOpen,
        !           165:     .close             = PptpClose,
        !           166:     .update            = PptpListenUpdate,
        !           167:     .shutdown          = PptpShutdown,
        !           168:     .showstat          = PptpStat,
        !           169:     .originate         = PptpOriginated,
        !           170:     .issync            = PptpIsSync,
        !           171:     .setaccm            = PptpSetAccm,
        !           172:     .setcallingnum     = PptpSetCallingNum,
        !           173:     .setcallednum      = PptpSetCalledNum,
        !           174:     .selfname          = PptpSelfName,
        !           175:     .peername          = PptpPeerName,
        !           176:     .selfaddr          = PptpSelfAddr,
        !           177:     .peeraddr          = PptpPeerAddr,
        !           178:     .peerport          = PptpPeerPort,
        !           179:     .peermacaddr       = PptpPeerMacAddr,
        !           180:     .peeriface         = PptpPeerIface,
        !           181:     .callingnum                = PptpCallingNum,
        !           182:     .callednum         = PptpCalledNum,
        !           183:   };
        !           184: 
        !           185:   const struct cmdtab  PptpSetCmds[] = {
        !           186:     { "self {ip} [{port}]",            "Set local IP address",
        !           187:        PptpSetCommand, NULL, 2, (void *) SET_SELFADDR },
        !           188:     { "peer {ip} [{port}]",            "Set remote IP address",
        !           189:        PptpSetCommand, NULL, 2, (void *) SET_PEERADDR },
        !           190:     { "callingnum {number}",           "Set calling PPTP telephone number",
        !           191:        PptpSetCommand, NULL, 2, (void *) SET_CALLINGNUM },
        !           192:     { "callednum {number}",            "Set called PPTP telephone number",
        !           193:        PptpSetCommand, NULL, 2, (void *) SET_CALLEDNUM },
        !           194:     { "enable [opt ...]",              "Enable option",
        !           195:        PptpSetCommand, NULL, 2, (void *) SET_ENABLE },
        !           196:     { "disable [opt ...]",             "Disable option",
        !           197:        PptpSetCommand, NULL, 2, (void *) SET_DISABLE },
        !           198:     { NULL },
        !           199:   };
        !           200: 
        !           201: /*
        !           202:  * INTERNAL VARIABLES
        !           203:  */
        !           204: 
        !           205:   static struct confinfo       gConfList[] = {
        !           206:     { 0,       PPTP_CONF_OUTCALL,      "outcall"       },
        !           207:     { 0,       PPTP_CONF_DELAYED_ACK,  "delayed-ack"   },
        !           208:     { 0,       PPTP_CONF_ALWAYS_ACK,   "always-ack"    },
        !           209:     { 0,       PPTP_CONF_RESOLVE_ONCE, "resolve-once"  },
        !           210: #if NGM_PPTPGRE_COOKIE >= 1082548365
        !           211:     { 0,       PPTP_CONF_WINDOWING,    "windowing"     },
        !           212: #endif
        !           213:     { 0,       0,                      NULL            },
        !           214:   };
        !           215: 
        !           216: struct ghash    *gPptpTuns;
        !           217: 
        !           218: /*
        !           219:  * PptpTInit()
        !           220:  */
        !           221: 
        !           222: static int
        !           223: PptpTInit(void)
        !           224: {
        !           225:     if ((gPptpTuns = ghash_create(NULL, 0, 0, MB_PHYS, PptpTunHash, PptpTunEQ, NULL, NULL))
        !           226:          == NULL)
        !           227:        return(-1);
        !           228:     return (PptpCtrlInit(PptpIncoming, PptpOutgoing));
        !           229: }
        !           230: 
        !           231: /*
        !           232:  * PptpTShutdown()
        !           233:  */
        !           234: 
        !           235: static void
        !           236: PptpTShutdown(void)
        !           237: {
        !           238:     Log(LG_PHYS2, ("PPTP: Total shutdown"));
        !           239:     ghash_destroy(&gPptpTuns);
        !           240: }
        !           241: 
        !           242: /*
        !           243:  * PptpInit()
        !           244:  */
        !           245: 
        !           246: static int
        !           247: PptpInit(Link l)
        !           248: {
        !           249:     PptpInfo   pptp;
        !           250: 
        !           251:     /* Initialize this link */
        !           252:     pptp = (PptpInfo) (l->info = Malloc(MB_PHYS, sizeof(*pptp)));
        !           253: 
        !           254:     pptp->conf.self_addr.family = AF_INET;
        !           255:     pptp->conf.fqdn_peer_addr = NULL;
        !           256:     Enable(&pptp->conf.options, PPTP_CONF_OUTCALL);
        !           257:     Enable(&pptp->conf.options, PPTP_CONF_DELAYED_ACK);
        !           258:     Enable(&pptp->conf.options, PPTP_CONF_RESOLVE_ONCE);
        !           259: 
        !           260:     return(0);
        !           261: }
        !           262: 
        !           263: /*
        !           264:  * PptpInst()
        !           265:  */
        !           266: 
        !           267: static int
        !           268: PptpInst(Link l, Link lt)
        !           269: {
        !           270:     PptpInfo   pptp;
        !           271:     PptpInfo   const pptpt = (PptpInfo) lt->info;
        !           272: 
        !           273:     /* Initialize this link */
        !           274:     pptp = (PptpInfo) (l->info = Mdup(MB_PHYS, lt->info, sizeof(*pptp)));
        !           275:     if (pptpt->conf.fqdn_peer_addr != NULL)
        !           276:         pptp->conf.fqdn_peer_addr =
        !           277:             Mstrdup(MB_PHYS, pptpt->conf.fqdn_peer_addr);
        !           278:     pptp->listener = NULL;
        !           279: 
        !           280:     return(0);
        !           281: }
        !           282: 
        !           283: /*
        !           284:  * PptpOpen()
        !           285:  */
        !           286: 
        !           287: static void
        !           288: PptpOpen(Link l)
        !           289: {
        !           290:     PptpInfo           const pptp = (PptpInfo) l->info;
        !           291:     struct sockaddr_dl  hwa;
        !           292: 
        !           293:     /* Check state */
        !           294:     switch (l->state) {
        !           295:        case PHYS_STATE_DOWN:
        !           296:            if (PptpOriginate(l) < 0) {
        !           297:                Log(LG_PHYS, ("[%s] PPTP call failed", l->name));
        !           298:                PhysDown(l, STR_ERROR, NULL);
        !           299:                return;
        !           300:            }
        !           301:            l->state = PHYS_STATE_CONNECTING;
        !           302:            break;
        !           303: 
        !           304:        case PHYS_STATE_CONNECTING:
        !           305:            if (pptp->originate)        /* our call to peer is already in progress */
        !           306:                break;
        !           307:            if (pptp->outcall) {
        !           308: 
        !           309:                /* Hook up nodes */
        !           310:                Log(LG_PHYS, ("[%s] PPTP: attaching to peer's outgoing call", l->name));
        !           311:                if (PptpHookUp(l) < 0) {
        !           312:                    PptpDoClose(l);
        !           313:                    /* We should not set state=DOWN as PptpResult() will be called once more */
        !           314:                    break;
        !           315:                }
        !           316: 
        !           317:                if (GetPeerEther(&pptp->peer_addr, &hwa)) {
        !           318:                    if_indextoname(hwa.sdl_index, pptp->peer_iface);
        !           319:                    memcpy(pptp->peer_mac_addr, LLADDR(&hwa), sizeof(pptp->peer_mac_addr));
        !           320:                };
        !           321: 
        !           322:                (*pptp->cinfo.answer)(pptp->cinfo.cookie,
        !           323:                    PPTP_OCR_RESL_OK, 0, 0, 64000 /*XXX*/ );
        !           324: 
        !           325:                /* Report UP if there was no error. */
        !           326:                if (l->state == PHYS_STATE_CONNECTING) {
        !           327:                    l->state = PHYS_STATE_UP;
        !           328:                    PhysUp(l);
        !           329:                }
        !           330:                return;
        !           331:            }
        !           332:            return;     /* wait for peer's incoming pptp call to complete */
        !           333: 
        !           334:        case PHYS_STATE_UP:
        !           335:            PhysUp(l);
        !           336:            return;
        !           337: 
        !           338:        default:
        !           339:            assert(0);
        !           340:     }
        !           341: }
        !           342: 
        !           343: /*
        !           344:  * PptpOriginate()
        !           345:  *
        !           346:  * Initiate an "incoming" or an "outgoing" call to the remote site
        !           347:  */
        !           348: 
        !           349: static int
        !           350: PptpOriginate(Link l)
        !           351: {
        !           352:     PptpInfo           const pptp = (PptpInfo) l->info;
        !           353:     struct pptplinkinfo        linfo;
        !           354:     const u_short      port = pptp->conf.peer_port ?
        !           355:                            pptp->conf.peer_port : PPTP_PORT;
        !           356: 
        !           357:     pptp->originate = TRUE;
        !           358:     pptp->outcall = Enabled(&pptp->conf.options, PPTP_CONF_OUTCALL);
        !           359:     memset(&linfo, 0, sizeof(linfo));
        !           360:     linfo.cookie = l;
        !           361:     linfo.result = PptpResult;
        !           362:     linfo.setLinkInfo = PptpSetLinkInfo;
        !           363:     linfo.cancel = PptpCancel;
        !           364:     strlcpy(pptp->callingnum, pptp->conf.callingnum, sizeof(pptp->callingnum));
        !           365:     strlcpy(pptp->callednum, pptp->conf.callednum, sizeof(pptp->callednum));
        !           366:     if ((!Enabled(&pptp->conf.options, PPTP_CONF_RESOLVE_ONCE)) &&
        !           367:        (pptp->conf.fqdn_peer_addr != NULL)) {
        !           368:        struct u_range  rng;
        !           369:        if (ParseRange(pptp->conf.fqdn_peer_addr, &rng, ALLOW_IPV4|ALLOW_IPV6))
        !           370:            pptp->conf.peer_addr = rng;
        !           371:     }
        !           372:     if (!pptp->outcall) {
        !           373:        int frameType = PPTP_FRAMECAP_SYNC;
        !           374:        if (l->rep && !RepIsSync(l))
        !           375:            frameType = PPTP_FRAMECAP_ASYNC;
        !           376:        PptpCtrlInCall(&pptp->cinfo, &linfo, 
        !           377:            &pptp->conf.self_addr, &pptp->conf.peer_addr.addr, port,
        !           378:            PPTP_BEARCAP_ANY, frameType,
        !           379:            PPTP_CALL_MIN_BPS, PPTP_CALL_MAX_BPS, 
        !           380:            pptp->callingnum, pptp->callednum, "");
        !           381:     } else {
        !           382:        PptpCtrlOutCall(&pptp->cinfo, &linfo, 
        !           383:            &pptp->conf.self_addr, &pptp->conf.peer_addr.addr, port,
        !           384:            PPTP_BEARCAP_ANY, PPTP_FRAMECAP_ANY,
        !           385:            PPTP_CALL_MIN_BPS, PPTP_CALL_MAX_BPS,
        !           386:            pptp->callednum, "");
        !           387:     }
        !           388:     if (pptp->cinfo.cookie == NULL)
        !           389:        return(-1);
        !           390:     pptp->self_addr = pptp->conf.self_addr;
        !           391:     pptp->peer_addr = pptp->conf.peer_addr.addr;
        !           392:     pptp->peer_port = port;
        !           393:     return(0);
        !           394: }
        !           395: 
        !           396: /*
        !           397:  * PptpClose()
        !           398:  */
        !           399: 
        !           400: static void
        !           401: PptpClose(Link l)
        !           402: {
        !           403:     PptpDoClose(l);
        !           404: }
        !           405: 
        !           406: /*
        !           407:  * PptpShutdown()
        !           408:  */
        !           409: 
        !           410: static void
        !           411: PptpShutdown(Link l)
        !           412: {
        !           413:     PptpInfo      const pptp = (PptpInfo) l->info;
        !           414: 
        !           415: 
        !           416:     if (pptp->conf.fqdn_peer_addr)
        !           417:         Freee(pptp->conf.fqdn_peer_addr);
        !           418:     if (pptp->listener) {
        !           419:        PptpCtrlUnListen(pptp->listener);
        !           420:        pptp->listener = NULL;
        !           421:     }
        !           422:     PptpUnhook(l);
        !           423:     Freee(l->info);
        !           424: }
        !           425: 
        !           426: /*
        !           427:  * PptpDoClose()
        !           428:  */
        !           429: 
        !           430: static void
        !           431: PptpDoClose(Link l)
        !           432: {
        !           433:     PptpInfo      const pptp = (PptpInfo) l->info;
        !           434: 
        !           435:     if (l->state != PHYS_STATE_DOWN)           /* avoid double close */
        !           436:        (*pptp->cinfo.close)(pptp->cinfo.cookie, PPTP_CDN_RESL_ADMIN, 0, 0);
        !           437: }
        !           438: 
        !           439: /*
        !           440:  * PptpUnhook()
        !           441:  */
        !           442: 
        !           443: static void
        !           444: PptpUnhook(Link l)
        !           445: {
        !           446:        PptpInfo const  pptp = (PptpInfo) l->info;
        !           447:        char            path[NG_PATHSIZ];
        !           448:        int             csock = -1;
        !           449: 
        !           450:        if (pptp->tun == NULL)
        !           451:                return;
        !           452: 
        !           453:        /* Get a temporary netgraph socket node */
        !           454:        if (NgMkSockNode(NULL, &csock, NULL) == -1) {
        !           455:                Perror("PPTP: NgMkSockNode");
        !           456:                return;
        !           457:        }
        !           458:        
        !           459:        pptp->tun->refs--;
        !           460:        snprintf(path, sizeof(path), "[%lx]:", (u_long)pptp->tun->node_id);
        !           461:        if (pptp->tun->refs == 0) {
        !           462:            /* Disconnect session hook. */
        !           463:            NgFuncShutdownNode(csock, l->name, path);
        !           464:            ghash_remove(gPptpTuns, pptp->tun);
        !           465:            Freee(pptp->tun);
        !           466: #ifdef NG_PPTPGRE_HOOK_SESSION_F
        !           467:        } else {
        !           468:            char        hook[NG_HOOKSIZ];
        !           469:            snprintf(hook, sizeof(hook), NG_PPTPGRE_HOOK_SESSION_F, pptp->cid);
        !           470:            NgFuncDisconnect(csock, l->name, path, hook);
        !           471: #endif
        !           472:        }
        !           473:        
        !           474:        close(csock);
        !           475:        
        !           476:        pptp->tun = NULL;
        !           477: }
        !           478: 
        !           479: /*
        !           480:  * PptpOriginated()
        !           481:  */
        !           482: 
        !           483: static int
        !           484: PptpOriginated(Link l)
        !           485: {
        !           486:     PptpInfo   const pptp = (PptpInfo) l->info;
        !           487: 
        !           488:     return(pptp->originate ? LINK_ORIGINATE_LOCAL : LINK_ORIGINATE_REMOTE);
        !           489: }
        !           490: 
        !           491: /*
        !           492:  * PptpIsSync()
        !           493:  */
        !           494: 
        !           495: static int
        !           496: PptpIsSync(Link l)
        !           497: {
        !           498:     PptpInfo   const pptp = (PptpInfo) l->info;
        !           499: 
        !           500:     return (pptp->sync);
        !           501: }
        !           502: 
        !           503: static int
        !           504: PptpSetAccm(Link l, u_int32_t xmit, u_int32_t recv)
        !           505: {
        !           506:     PptpInfo   const pptp = (PptpInfo) l->info;
        !           507:     
        !           508:     if (!pptp->cinfo.close || !pptp->cinfo.cookie)
        !           509:            return (-1);
        !           510: 
        !           511:     (*pptp->cinfo.setLinkInfo)(pptp->cinfo.cookie, xmit, recv);
        !           512:     return (0);
        !           513: }
        !           514: 
        !           515: static int
        !           516: PptpSetCallingNum(Link l, void *buf)
        !           517: {
        !           518:     PptpInfo   const pptp = (PptpInfo) l->info;
        !           519: 
        !           520:     strlcpy(pptp->conf.callingnum, buf, sizeof(pptp->conf.callingnum));
        !           521:     return(0);
        !           522: }
        !           523: 
        !           524: static int
        !           525: PptpSetCalledNum(Link l, void *buf)
        !           526: {
        !           527:     PptpInfo   const pptp = (PptpInfo) l->info;
        !           528: 
        !           529:     strlcpy(pptp->conf.callednum, buf, sizeof(pptp->conf.callednum));
        !           530:     return(0);
        !           531: }
        !           532: 
        !           533: static int
        !           534: PptpSelfName(Link l, void *buf, size_t buf_len)
        !           535: {
        !           536:     PptpInfo   const pptp = (PptpInfo) l->info;
        !           537: 
        !           538:     if (pptp->cinfo.cookie)
        !           539:        return(PptpCtrlGetSelfName(&pptp->cinfo, buf, buf_len));
        !           540:     ((char*)buf)[0]=0;
        !           541:     return (0);
        !           542: }
        !           543: 
        !           544: static int
        !           545: PptpPeerName(Link l, void *buf, size_t buf_len)
        !           546: {
        !           547:     PptpInfo   const pptp = (PptpInfo) l->info;
        !           548: 
        !           549:     if (pptp->cinfo.cookie)
        !           550:        return(PptpCtrlGetPeerName(&pptp->cinfo, buf, buf_len));
        !           551:     ((char*)buf)[0]=0;
        !           552:     return (0);
        !           553: }
        !           554: 
        !           555: static int
        !           556: PptpSelfAddr(Link l, void *buf, size_t buf_len)
        !           557: {
        !           558:     PptpInfo   const pptp = (PptpInfo) l->info;
        !           559: 
        !           560:     if (u_addrtoa(&pptp->self_addr, buf, buf_len))
        !           561:        return(0);
        !           562:     else
        !           563:        return(-1);
        !           564: }
        !           565: 
        !           566: static int
        !           567: PptpPeerAddr(Link l, void *buf, size_t buf_len)
        !           568: {
        !           569:     PptpInfo   const pptp = (PptpInfo) l->info;
        !           570: 
        !           571:     if (u_addrtoa(&pptp->peer_addr, buf, buf_len))
        !           572:        return(0);
        !           573:     else
        !           574:        return(-1);
        !           575: }
        !           576: 
        !           577: static int
        !           578: PptpPeerPort(Link l, void *buf, size_t buf_len)
        !           579: {
        !           580:     PptpInfo   const pptp = (PptpInfo) l->info;
        !           581: 
        !           582:     if (snprintf(buf, buf_len, "%d", pptp->peer_port))
        !           583:        return(0);
        !           584:     else
        !           585:        return(-1);
        !           586: }
        !           587: 
        !           588: static int
        !           589: PptpPeerMacAddr(Link l, void *buf, size_t buf_len)
        !           590: {
        !           591:     PptpInfo   const pptp = (PptpInfo) l->info;
        !           592: 
        !           593:     if (pptp->peer_iface[0]) {
        !           594:        snprintf(buf, buf_len, "%02x:%02x:%02x:%02x:%02x:%02x",
        !           595:            pptp->peer_mac_addr[0], pptp->peer_mac_addr[1],
        !           596:            pptp->peer_mac_addr[2], pptp->peer_mac_addr[3],
        !           597:            pptp->peer_mac_addr[4], pptp->peer_mac_addr[5]);
        !           598:        return (0);
        !           599:     }
        !           600:     ((char*)buf)[0]=0;
        !           601:     return(0);
        !           602: }
        !           603: 
        !           604: static int
        !           605: PptpPeerIface(Link l, void *buf, size_t buf_len)
        !           606: {
        !           607:     PptpInfo   const pptp = (PptpInfo) l->info;
        !           608: 
        !           609:     if (pptp->peer_iface[0]) {
        !           610:        strlcpy(buf, pptp->peer_iface, buf_len);
        !           611:        return (0);
        !           612:     }
        !           613:     ((char*)buf)[0]=0;
        !           614:     return(0);
        !           615: }
        !           616: 
        !           617: static int
        !           618: PptpCallingNum(Link l, void *buf, size_t buf_len)
        !           619: {
        !           620:     PptpInfo   const pptp = (PptpInfo) l->info;
        !           621: 
        !           622:     strlcpy((char*)buf, pptp->callingnum, buf_len);
        !           623:     return(0);
        !           624: }
        !           625: 
        !           626: static int
        !           627: PptpCalledNum(Link l, void *buf, size_t buf_len)
        !           628: {
        !           629:     PptpInfo   const pptp = (PptpInfo) l->info;
        !           630: 
        !           631:     strlcpy((char*)buf, pptp->callednum, buf_len);
        !           632:     return(0);
        !           633: }
        !           634: 
        !           635: /*
        !           636:  * PptpStat()
        !           637:  */
        !           638: 
        !           639: void
        !           640: PptpStat(Context ctx)
        !           641: {
        !           642:     PptpInfo   const pptp = (PptpInfo) ctx->lnk->info;
        !           643:     char       buf[32];
        !           644: 
        !           645:     Printf("PPTP configuration:\r\n");
        !           646:     Printf("\tSelf addr    : %s",
        !           647:        u_addrtoa(&pptp->conf.self_addr, buf, sizeof(buf)));
        !           648:     if (pptp->conf.self_port)
        !           649:        Printf(", port %u", pptp->conf.self_port);
        !           650:     Printf("\r\n");
        !           651:     Printf("\tPeer FQDN    : %s\r\n", pptp->conf.fqdn_peer_addr);
        !           652:     Printf("\tPeer range   : %s",
        !           653:        u_rangetoa(&pptp->conf.peer_addr, buf, sizeof(buf)));
        !           654:     if (pptp->conf.peer_port)
        !           655:        Printf(", port %u", pptp->conf.peer_port);
        !           656:     Printf("\r\n");
        !           657:     Printf("\tCalling number: %s\r\n", pptp->conf.callingnum);
        !           658:     Printf("\tCalled number: %s\r\n", pptp->conf.callednum);
        !           659:     Printf("PPTP options:\r\n");
        !           660:     OptStat(ctx, &pptp->conf.options, gConfList);
        !           661:     Printf("PPTP status:\r\n");
        !           662:     if (ctx->lnk->state != PHYS_STATE_DOWN) {
        !           663:        Printf("\tIncoming     : %s\r\n", (pptp->originate?"NO":"YES"));
        !           664:        Printf("\tCurrent self : %s",
        !           665:            u_addrtoa(&pptp->self_addr, buf, sizeof(buf)));
        !           666:        PptpSelfName(ctx->lnk, buf, sizeof(buf));
        !           667:        Printf(" (%s)\r\n", buf);
        !           668:        Printf("\tCurrent peer : %s, port %u",
        !           669:            u_addrtoa(&pptp->peer_addr, buf, sizeof(buf)), pptp->peer_port);
        !           670:        PptpPeerName(ctx->lnk, buf, sizeof(buf));
        !           671:        Printf(" (%s)\r\n", buf);
        !           672:        if (pptp->peer_iface[0]) {
        !           673:            Printf("\tCurrent peer : %02x:%02x:%02x:%02x:%02x:%02x at %s\r\n",
        !           674:                pptp->peer_mac_addr[0], pptp->peer_mac_addr[1],
        !           675:                pptp->peer_mac_addr[2], pptp->peer_mac_addr[3],
        !           676:                pptp->peer_mac_addr[4], pptp->peer_mac_addr[5],
        !           677:                pptp->peer_iface);
        !           678:        }
        !           679:        Printf("\tFraming      : %s\r\n", (pptp->sync?"Sync":"Async"));
        !           680:        Printf("\tCalling number: %s\r\n", pptp->callingnum);
        !           681:        Printf("\tCalled number: %s\r\n", pptp->callednum);
        !           682:     }
        !           683: }
        !           684: 
        !           685: /*
        !           686:  * PptpResult()
        !           687:  *
        !           688:  * The control code calls this function to report a PPTP link
        !           689:  * being connected, disconnected, or failing to connect.
        !           690:  */
        !           691: 
        !           692: static void
        !           693: PptpResult(void *cookie, const char *errmsg, int frameType)
        !           694: {
        !           695:     PptpInfo   pptp;
        !           696:     Link       l;
        !           697:     struct sockaddr_dl  hwa;
        !           698: 
        !           699:     /* It this fake call? */
        !           700:     if (!cookie)
        !           701:        return;
        !           702: 
        !           703:     l = (Link)cookie;
        !           704:     pptp = (PptpInfo) l->info;
        !           705: 
        !           706:     switch (l->state) {
        !           707:        case PHYS_STATE_CONNECTING:
        !           708:            if (!errmsg) {
        !           709: 
        !           710:                /* Hook up nodes */
        !           711:                Log(LG_PHYS, ("[%s] PPTP call successful", l->name));
        !           712:                if (PptpHookUp(l) < 0) {
        !           713:                    PptpDoClose(l);
        !           714:                    /* We should not set state=DOWN as PptpResult() will be called once more */
        !           715:                    break;
        !           716:                }
        !           717: 
        !           718:                if (pptp->originate && !pptp->outcall)
        !           719:                    (*pptp->cinfo.connected)(pptp->cinfo.cookie, 64000 /*XXX*/ );
        !           720: 
        !           721:                /* Report UP if there was no error. */
        !           722:                if (l->state == PHYS_STATE_CONNECTING) {
        !           723:                    if (GetPeerEther(&pptp->peer_addr, &hwa)) {
        !           724:                        if_indextoname(hwa.sdl_index, pptp->peer_iface);
        !           725:                        memcpy(pptp->peer_mac_addr, LLADDR(&hwa), sizeof(pptp->peer_mac_addr));
        !           726:                    };
        !           727: 
        !           728:                    /* OK */
        !           729:                    l->state = PHYS_STATE_UP;
        !           730:                    pptp->sync = (frameType&PPTP_FRAMECAP_ASYNC)?0:1;
        !           731:                    PhysUp(l);
        !           732:                }
        !           733:            } else {
        !           734:                Log(LG_PHYS, ("[%s] PPTP call failed", l->name));
        !           735:                PptpUnhook(l);          /* For the (*connected)() error. */
        !           736:                l->state = PHYS_STATE_DOWN;
        !           737:                u_addrclear(&pptp->self_addr);
        !           738:                u_addrclear(&pptp->peer_addr);
        !           739:                pptp->peer_port = 0;
        !           740:                pptp->callingnum[0]=0;
        !           741:                pptp->callednum[0]=0;
        !           742:                pptp->peer_iface[0] = 0;
        !           743:                PhysDown(l, STR_CON_FAILED, errmsg);
        !           744:            }
        !           745:            break;
        !           746:        case PHYS_STATE_UP:
        !           747:            assert(errmsg);
        !           748:            Log(LG_PHYS, ("[%s] PPTP call terminated", l->name));
        !           749:            PptpUnhook(l);
        !           750:            l->state = PHYS_STATE_DOWN;
        !           751:             u_addrclear(&pptp->self_addr);
        !           752:            u_addrclear(&pptp->peer_addr);
        !           753:            pptp->peer_port = 0;
        !           754:            pptp->callingnum[0]=0;
        !           755:            pptp->callednum[0]=0;
        !           756:            pptp->peer_iface[0] = 0;
        !           757:            PhysDown(l, STR_DROPPED, NULL);
        !           758:            break;
        !           759:        case PHYS_STATE_DOWN:
        !           760:            return;
        !           761:        default:
        !           762:            assert(0);
        !           763:     }
        !           764: }
        !           765: 
        !           766: /*
        !           767:  * PptpSetLinkInfo()
        !           768:  *
        !           769:  * Received LinkInfo from peer;
        !           770:  */
        !           771: 
        !           772: void
        !           773: PptpSetLinkInfo(void *cookie, u_int32_t sa, u_int32_t ra)
        !           774: {
        !           775:     Link       l;
        !           776: 
        !           777:     /* It this fake call? */
        !           778:     if (!cookie)
        !           779:            return;
        !           780: 
        !           781:     l = (Link)cookie;
        !           782: 
        !           783:     if (l->rep != NULL)
        !           784:            RepSetAccm(l, sa, ra);
        !           785: }
        !           786: 
        !           787: static int
        !           788: PptpTunEQ(struct ghash *g, const void *item1, const void *item2)
        !           789: {
        !           790:     const struct pptptun *tun1 = item1;
        !           791:     const struct pptptun *tun2 = item2;
        !           792:     if (u_addrcompare(&tun1->self_addr, &tun2->self_addr) == 0 &&
        !           793:        u_addrcompare(&tun1->peer_addr, &tun2->peer_addr) == 0)
        !           794:            return (1);
        !           795:     return (0);
        !           796: }
        !           797: 
        !           798: static u_int32_t
        !           799: PptpTunHash(struct ghash *g, const void *item)
        !           800: {
        !           801:     const struct pptptun *tun = item;
        !           802:     return (u_addrtoid(&tun->self_addr) + u_addrtoid(&tun->peer_addr));
        !           803: }
        !           804: 
        !           805: /*
        !           806:  * PptpHookUp()
        !           807:  *
        !           808:  * Connect the PPTP/GRE node to the PPP node
        !           809:  */
        !           810: 
        !           811: static int
        !           812: PptpHookUp(Link l)
        !           813: {
        !           814:     const PptpInfo             pi = (PptpInfo)l->info;
        !           815:     char                       ksockpath[NG_PATHSIZ];
        !           816:     char                       pptppath[NG_PATHSIZ];
        !           817:     struct ngm_mkpeer          mkp;
        !           818:     struct ng_pptpgre_conf     gc;
        !           819:     struct sockaddr_storage    self_addr, peer_addr;
        !           820:     struct u_addr              u_self_addr, u_peer_addr;
        !           821:     union {
        !           822:        u_char buf[sizeof(struct ng_ksocket_sockopt) + sizeof(int)];
        !           823:        struct ng_ksocket_sockopt ksso;
        !           824:     } u;
        !           825:     struct ng_ksocket_sockopt *const ksso = &u.ksso;
        !           826:     int                csock = -1;
        !           827:     char        path[NG_PATHSIZ];
        !           828:     char       hook[NG_HOOKSIZ];
        !           829:     PptpTun    tun = NULL;
        !           830: 
        !           831:     /* Get session info */
        !           832:     memset(&gc, 0, sizeof(gc));
        !           833:     PptpCtrlGetSessionInfo(&pi->cinfo, &u_self_addr,
        !           834:        &u_peer_addr, &gc.cid, &gc.peerCid, &gc.recvWin, &gc.peerPpd);
        !           835:     pi->cid = gc.cid;
        !           836:     
        !           837:     u_addrtosockaddr(&u_self_addr, 0, &self_addr);
        !           838:     u_addrtosockaddr(&u_peer_addr, 0, &peer_addr);
        !           839: 
        !           840:     if (!PhysGetUpperHook(l, path, hook)) {
        !           841:         Log(LG_PHYS, ("[%s] PPTP: can't get upper hook", l->name));
        !           842:         return(-1);
        !           843:     }
        !           844:     
        !           845:     /* Get a temporary netgraph socket node */
        !           846:     if (NgMkSockNode(NULL, &csock, NULL) == -1) {
        !           847:        Perror("PPTP: NgMkSockNode");
        !           848:        return(-1);
        !           849:     }
        !           850: 
        !           851: #ifdef NG_PPTPGRE_HOOK_SESSION_F
        !           852:     {
        !           853:        struct pptptun tmptun;
        !           854:        tmptun.self_addr = u_self_addr;
        !           855:        tmptun.peer_addr = u_peer_addr;
        !           856:        tun = ghash_get(gPptpTuns, &tmptun);
        !           857:     }
        !           858: #endif
        !           859: 
        !           860:     snprintf(pptppath, sizeof(pptppath), "%s.%s", path, hook);
        !           861:     if (tun == NULL) {
        !           862:        tun = (PptpTun)Malloc(MB_PHYS, sizeof(*tun));
        !           863:        tun->self_addr = u_self_addr;
        !           864:        tun->peer_addr = u_peer_addr;
        !           865:        if (ghash_put(gPptpTuns, tun) == -1) {
        !           866:            Perror("[%s] PPTP: ghash_put", l->name);
        !           867:            Freee(tun);
        !           868:            close(csock);
        !           869:            return(-1);
        !           870:        }
        !           871:     
        !           872:        /* Attach PPTP/GRE node to PPP node */
        !           873:        strcpy(mkp.type, NG_PPTPGRE_NODE_TYPE);
        !           874:        strlcpy(mkp.ourhook, hook, sizeof(mkp.ourhook));
        !           875: #ifdef NG_PPTPGRE_HOOK_SESSION_F
        !           876:        snprintf(mkp.peerhook, sizeof(mkp.peerhook), NG_PPTPGRE_HOOK_SESSION_F, pi->cid);
        !           877: #else
        !           878:        strcpy(mkp.peerhook, NG_PPTPGRE_HOOK_UPPER);
        !           879: #endif
        !           880:        if (NgSendMsg(csock, path, NGM_GENERIC_COOKIE,
        !           881:           NGM_MKPEER, &mkp, sizeof(mkp)) < 0) {
        !           882:            Perror("[%s] PPTP: can't attach %s node", l->name, NG_PPTPGRE_NODE_TYPE);
        !           883:            ghash_remove(gPptpTuns, tun);
        !           884:            Freee(tun);
        !           885:            close(csock);
        !           886:            return(-1);
        !           887:        }
        !           888: 
        !           889:        /* Get pptpgre node ID */
        !           890:        if ((tun->node_id = NgGetNodeID(csock, pptppath)) == 0) {
        !           891:            Perror("[%s] Cannot get %s node id", l->name, NG_PPTPGRE_NODE_TYPE);
        !           892:            ghash_remove(gPptpTuns, tun);
        !           893:            Freee(tun);
        !           894:            close(csock);
        !           895:            return(-1);
        !           896:        };
        !           897:        tun->refs++;
        !           898:        pi->tun = tun;
        !           899: 
        !           900:        /* Attach ksocket node to PPTP/GRE node */
        !           901:        strcpy(mkp.type, NG_KSOCKET_NODE_TYPE);
        !           902:        strcpy(mkp.ourhook, NG_PPTPGRE_HOOK_LOWER);
        !           903:        if (u_self_addr.family==AF_INET6) {
        !           904:            //ng_ksocket doesn't support inet6 name
        !           905:            snprintf(mkp.peerhook, sizeof(mkp.peerhook), "%d/%d/%d", PF_INET6, SOCK_RAW, IPPROTO_GRE); 
        !           906:        } else {
        !           907:            snprintf(mkp.peerhook, sizeof(mkp.peerhook), "inet/raw/gre");
        !           908:        }
        !           909:        if (NgSendMsg(csock, pptppath, NGM_GENERIC_COOKIE,
        !           910:          NGM_MKPEER, &mkp, sizeof(mkp)) < 0) {
        !           911:            Perror("[%s] PPTP: can't attach %s node", l->name, NG_KSOCKET_NODE_TYPE);
        !           912:            close(csock);
        !           913:            return(-1);
        !           914:        }
        !           915:        snprintf(ksockpath, sizeof(ksockpath),
        !           916:            "%s.%s", pptppath, NG_PPTPGRE_HOOK_LOWER);
        !           917: 
        !           918:        /* increase recvspace to avoid packet loss due to very small GRE recv buffer. */
        !           919:        ksso->level=SOL_SOCKET;
        !           920:        ksso->name=SO_RCVBUF;
        !           921:        ((int *)(ksso->value))[0]=48*1024;
        !           922:        if (NgSendMsg(csock, ksockpath, NGM_KSOCKET_COOKIE,
        !           923:            NGM_KSOCKET_SETOPT, &u, sizeof(u)) < 0) {
        !           924:                Perror("[%s] PPTP: can't setsockopt %s node",
        !           925:                    l->name, NG_KSOCKET_NODE_TYPE);
        !           926:        }
        !           927: 
        !           928:        /* Bind ksocket socket to local IP address */
        !           929:        if (NgSendMsg(csock, ksockpath, NGM_KSOCKET_COOKIE,
        !           930:           NGM_KSOCKET_BIND, &self_addr, self_addr.ss_len) < 0) {
        !           931:            Perror("[%s] PPTP: can't bind() %s node", l->name, NG_KSOCKET_NODE_TYPE);
        !           932:            close(csock);
        !           933:            return(-1);
        !           934:        }
        !           935: 
        !           936:        /* Connect ksocket socket to remote IP address */
        !           937:        if (NgSendMsg(csock, ksockpath, NGM_KSOCKET_COOKIE,
        !           938:          NGM_KSOCKET_CONNECT, &peer_addr, peer_addr.ss_len) < 0 &&
        !           939:          errno != EINPROGRESS) {       /* happens in -current (weird) */
        !           940:            Perror("[%s] PPTP: can't connect() %s node",
        !           941:                l->name, NG_KSOCKET_NODE_TYPE);
        !           942:            close(csock);
        !           943:            return(-1);
        !           944:         }
        !           945: #ifdef NG_PPTPGRE_HOOK_SESSION_F
        !           946:     } else {
        !           947:        struct ngm_connect      cn;
        !           948:        snprintf(cn.path, sizeof(cn.path), "[%x]:", tun->node_id);
        !           949:        strlcpy(cn.ourhook, hook, sizeof(mkp.ourhook));
        !           950:        snprintf(cn.peerhook, sizeof(mkp.peerhook), NG_PPTPGRE_HOOK_SESSION_F, pi->cid);
        !           951:        if (NgSendMsg(csock, path, NGM_GENERIC_COOKIE,
        !           952:           NGM_CONNECT, &cn, sizeof(cn)) < 0) {
        !           953:            Perror("[%s] PPTP: can't connect to %s node",
        !           954:                l->name, NG_PPTPGRE_NODE_TYPE);
        !           955:            close(csock);
        !           956:            return(-1);
        !           957:        }
        !           958:        tun->refs++;
        !           959:        pi->tun = tun;
        !           960: #endif
        !           961:     }
        !           962: 
        !           963:     /* Configure PPTP/GRE node */
        !           964:     gc.enabled = 1;
        !           965:     gc.enableDelayedAck = Enabled(&pi->conf.options, PPTP_CONF_DELAYED_ACK);
        !           966:     gc.enableAlwaysAck = Enabled(&pi->conf.options, PPTP_CONF_ALWAYS_ACK);
        !           967: #if NGM_PPTPGRE_COOKIE >= 1082548365
        !           968:     gc.enableWindowing = Enabled(&pi->conf.options, PPTP_CONF_WINDOWING);
        !           969: #endif
        !           970: 
        !           971:     if (NgSendMsg(csock, pptppath, NGM_PPTPGRE_COOKIE,
        !           972:       NGM_PPTPGRE_SET_CONFIG, &gc, sizeof(gc)) < 0) {
        !           973:        Perror("[%s] PPTP: can't config %s node", l->name, NG_PPTPGRE_NODE_TYPE);
        !           974:        close(csock);
        !           975:        return(-1);
        !           976:     }
        !           977:   
        !           978:     close(csock);
        !           979: 
        !           980:     return(0);
        !           981: }
        !           982: 
        !           983: /*
        !           984:  * PptpIncoming()
        !           985:  *
        !           986:  * The control code calls this function to report that some
        !           987:  * remote PPTP client has asked us if we will accept an incoming
        !           988:  * call relayed over PPTP.
        !           989:  */
        !           990: 
        !           991: static struct pptplinkinfo
        !           992: PptpIncoming(struct pptpctrlinfo *cinfo,
        !           993:        struct u_addr *self, struct u_addr *peer, in_port_t port, int bearType,
        !           994:        const char *callingNum,
        !           995:        const char *calledNum,
        !           996:        const char *subAddress)
        !           997: {
        !           998:     return(PptpPeerCall(cinfo, self, peer, port, TRUE, callingNum, calledNum, subAddress));
        !           999: }
        !          1000: 
        !          1001: /*
        !          1002:  * PptpOutgoing()
        !          1003:  *
        !          1004:  * The control code calls this function to report that some
        !          1005:  * remote PPTP client has asked us if we will dial out to some
        !          1006:  * phone number. We don't actually do this, but some clients
        !          1007:  * initiate their connections as outgoing calls for some reason.
        !          1008:  */
        !          1009: 
        !          1010: static struct pptplinkinfo
        !          1011: PptpOutgoing(struct pptpctrlinfo *cinfo,
        !          1012:        struct u_addr *self, struct u_addr *peer, in_port_t port, int bearType,
        !          1013:        int frameType, int minBps, int maxBps,
        !          1014:        const char *calledNum, const char *subAddress)
        !          1015: {
        !          1016:     return(PptpPeerCall(cinfo, self, peer, port, FALSE, "", calledNum, subAddress));
        !          1017: }
        !          1018: 
        !          1019: /*
        !          1020:  * PptpPeerCall()
        !          1021:  *
        !          1022:  * Peer has initiated a call (either incoming or outgoing; either
        !          1023:  * way it's the same to us). If we have an available link that may
        !          1024:  * accept calls from the peer's IP addresss and port, then say yes.
        !          1025:  */
        !          1026: 
        !          1027: static struct pptplinkinfo
        !          1028: PptpPeerCall(struct pptpctrlinfo *cinfo,
        !          1029:        struct u_addr *self, struct u_addr *peer, in_port_t port, int incoming,
        !          1030:        const char *callingNum,
        !          1031:        const char *calledNum,
        !          1032:        const char *subAddress)
        !          1033: {
        !          1034:     struct pptplinkinfo        linfo;
        !          1035:     Link               l = NULL;
        !          1036:     PptpInfo           pi = NULL;
        !          1037:     int                        k;
        !          1038: 
        !          1039:     memset(&linfo, 0, sizeof(linfo));
        !          1040: 
        !          1041:     linfo.cookie = NULL;
        !          1042:     linfo.result = PptpResult;
        !          1043:     linfo.setLinkInfo = PptpSetLinkInfo;
        !          1044:     linfo.cancel = PptpCancel;
        !          1045: 
        !          1046:     if (gShutdownInProgress) {
        !          1047:        Log(LG_PHYS, ("Shutdown sequence in progress, ignoring request."));
        !          1048:        return(linfo);
        !          1049:     }
        !          1050: 
        !          1051:     if (OVERLOAD()) {
        !          1052:        Log(LG_PHYS, ("Daemon overloaded, ignoring request."));
        !          1053:        return(linfo);
        !          1054:     }
        !          1055: 
        !          1056:     /* Find a suitable link; prefer the link best matching peer's IP address */
        !          1057:     for (k = 0; k < gNumLinks; k++) {
        !          1058:        Link l2;
        !          1059:        PptpInfo pi2;
        !          1060: 
        !          1061:        if (!gLinks[k] || gLinks[k]->type != &gPptpPhysType)
        !          1062:                continue;
        !          1063: 
        !          1064:        l2 = gLinks[k];
        !          1065:        pi2 = (PptpInfo)l2->info;
        !          1066: 
        !          1067:        /* See if link is feasible */
        !          1068:        if ((!PhysIsBusy(l2)) &&
        !          1069:            Enabled(&l2->conf.options, LINK_CONF_INCOMING) &&
        !          1070:            (u_addrempty(&pi2->conf.self_addr) || (u_addrcompare(&pi2->conf.self_addr, self) == 0)) &&
        !          1071:            IpAddrInRange(&pi2->conf.peer_addr, peer) &&
        !          1072:            (!pi2->conf.peer_port || pi2->conf.peer_port == port)) {
        !          1073: 
        !          1074:                /* Link is feasible; now see if it's preferable */
        !          1075:                if (!pi || pi2->conf.peer_addr.width > pi->conf.peer_addr.width) {
        !          1076:                        l = l2;
        !          1077:                        pi = pi2;
        !          1078:                        if (u_rangehost(&pi->conf.peer_addr)) {
        !          1079:                                break;  /* Nothing could be better */
        !          1080:                        }
        !          1081:                }
        !          1082:        }
        !          1083:     }
        !          1084: 
        !          1085:     if (l != NULL && l->tmpl)
        !          1086:         l = LinkInst(l, NULL, 0, 0);
        !          1087: 
        !          1088:     /* If no link is suitable, can't take the call */
        !          1089:     if (l == NULL) {
        !          1090:        Log(LG_PHYS, ("No free PPTP link with requested parameters "
        !          1091:            "was found"));
        !          1092:        return(linfo);
        !          1093:     }
        !          1094:     pi = (PptpInfo)l->info;
        !          1095: 
        !          1096:     Log(LG_PHYS, ("[%s] Accepting PPTP connection", l->name));
        !          1097: 
        !          1098:     /* Got one */
        !          1099:     linfo.cookie = l;
        !          1100:     l->state = PHYS_STATE_CONNECTING;
        !          1101:     pi->cinfo = *cinfo;
        !          1102:     pi->originate = FALSE;
        !          1103:     pi->outcall = !incoming;
        !          1104:     pi->sync = 1;
        !          1105:     pi->self_addr = *self;
        !          1106:     pi->peer_addr = *peer;
        !          1107:     pi->peer_port = port;
        !          1108:     strlcpy(pi->callingnum, callingNum, sizeof(pi->callingnum));
        !          1109:     strlcpy(pi->callednum, calledNum, sizeof(pi->callednum));
        !          1110: 
        !          1111:     PhysIncoming(l);
        !          1112:     return(linfo);
        !          1113: }
        !          1114: 
        !          1115: /*
        !          1116:  * PptpCancel()
        !          1117:  *
        !          1118:  * The control code calls this function to cancel a
        !          1119:  * local outgoing call in progress.
        !          1120:  */
        !          1121: 
        !          1122: static void
        !          1123: PptpCancel(void *cookie)
        !          1124: {
        !          1125:     PptpInfo   pi;
        !          1126:     Link       l;
        !          1127: 
        !          1128:     /* It this fake call? */
        !          1129:     if (!cookie)
        !          1130:        return;
        !          1131: 
        !          1132:     l = (Link)cookie;
        !          1133:     pi = (PptpInfo) l->info;
        !          1134: 
        !          1135:     Log(LG_PHYS, ("[%s] PPTP call cancelled in state %s",
        !          1136:        l->name, gPhysStateNames[l->state]));
        !          1137:     if (l->state == PHYS_STATE_DOWN)
        !          1138:        return;
        !          1139:     l->state = PHYS_STATE_DOWN;
        !          1140:     u_addrclear(&pi->peer_addr);
        !          1141:     pi->peer_port = 0;
        !          1142:     pi->callingnum[0]=0;
        !          1143:     pi->callednum[0]=0;
        !          1144:     pi->peer_iface[0] = 0;
        !          1145:     PhysDown(l, STR_CON_FAILED0, NULL);
        !          1146: }
        !          1147: 
        !          1148: /*
        !          1149:  * PptpListenUpdate()
        !          1150:  */
        !          1151: 
        !          1152: static void
        !          1153: PptpListenUpdate(Link l)
        !          1154: {
        !          1155:     PptpInfo   pi = (PptpInfo) l->info;
        !          1156: 
        !          1157:     if (pi->listener == NULL) {
        !          1158:        if (Enabled(&l->conf.options, LINK_CONF_INCOMING)) {
        !          1159:            /* Set up listening for incoming connections */
        !          1160:            if ((pi->listener = 
        !          1161:                PptpCtrlListen(&pi->conf.self_addr, pi->conf.self_port))
        !          1162:                    == NULL) {
        !          1163:                Log(LG_ERR, ("PPTP: Error, can't listen for connection!"));
        !          1164:            }
        !          1165:        }
        !          1166:     } else {
        !          1167:        if (!Enabled(&l->conf.options, LINK_CONF_INCOMING)) {
        !          1168:            PptpCtrlUnListen(pi->listener);
        !          1169:            pi->listener = NULL;
        !          1170:        }
        !          1171:     }
        !          1172: }
        !          1173: 
        !          1174: /*
        !          1175:  * PptpSetCommand()
        !          1176:  */
        !          1177: 
        !          1178: static int
        !          1179: PptpSetCommand(Context ctx, int ac, char *av[], void *arg)
        !          1180: {
        !          1181:     PptpInfo           const pi = (PptpInfo) ctx->lnk->info;
        !          1182:     char               **fqdn_peer_addr = &pi->conf.fqdn_peer_addr;
        !          1183:     struct u_range     rng;
        !          1184:     int                        port;
        !          1185: 
        !          1186:     switch ((intptr_t)arg) {
        !          1187:        case SET_SELFADDR:
        !          1188:        case SET_PEERADDR:
        !          1189:            if ((ac == 1 || ac == 2) && (intptr_t)arg == SET_PEERADDR) {
        !          1190:                if (*fqdn_peer_addr)
        !          1191:                    Freee(*fqdn_peer_addr);
        !          1192:                *fqdn_peer_addr = Mstrdup(MB_PHYS, av[0]);
        !          1193:            }
        !          1194:            if (ac < 1 || ac > 2 || !ParseRange(av[0], &rng, ALLOW_IPV4|ALLOW_IPV6))
        !          1195:                return(-1);
        !          1196:            if (ac > 1) {
        !          1197:                if ((port = atoi(av[1])) < 0 || port > 0xffff)
        !          1198:                    return(-1);
        !          1199:            } else {
        !          1200:                port = 0;
        !          1201:            }
        !          1202:            if ((intptr_t)arg == SET_SELFADDR) {
        !          1203:                pi->conf.self_addr = rng.addr;
        !          1204:                pi->conf.self_port = port;
        !          1205:            } else {
        !          1206:                pi->conf.peer_addr = rng;
        !          1207:                pi->conf.peer_port = port;
        !          1208:            }
        !          1209:            break;
        !          1210:        case SET_CALLINGNUM:
        !          1211:            if (ac != 1)
        !          1212:                return(-1);
        !          1213:            strlcpy(pi->conf.callingnum, av[0], sizeof(pi->conf.callingnum));
        !          1214:            break;
        !          1215:        case SET_CALLEDNUM:
        !          1216:            if (ac != 1)
        !          1217:                return(-1);
        !          1218:            strlcpy(pi->conf.callednum, av[0], sizeof(pi->conf.callednum));
        !          1219:            break;
        !          1220:        case SET_ENABLE:
        !          1221:            EnableCommand(ac, av, &pi->conf.options, gConfList);
        !          1222:            PptpListenUpdate(ctx->lnk);
        !          1223:            break;
        !          1224:        case SET_DISABLE:
        !          1225:            DisableCommand(ac, av, &pi->conf.options, gConfList);
        !          1226:            PptpListenUpdate(ctx->lnk);
        !          1227:            break;
        !          1228:        default:
        !          1229:            assert(0);
        !          1230:     }
        !          1231:     return(0);
        !          1232: }
        !          1233: 

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