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

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

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