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

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,
                    129:                                  struct u_addr *self, struct u_addr *peer, in_port_t port, int bearType,
                    130:                                  const char *callingNum,
                    131:                                  const char *calledNum,
                    132:                                  const char *subAddress);
                    133: 
                    134:   static struct pptplinkinfo   PptpOutgoing(struct pptpctrlinfo *cinfo,
                    135:                                  struct u_addr *self, struct u_addr *peer, in_port_t port, int bearType,
                    136:                                  int frameType, int minBps, int maxBps,
                    137:                                  const char *calledNum,
                    138:                                  const char *subAddress);
                    139: 
                    140:   static struct pptplinkinfo   PptpPeerCall(struct pptpctrlinfo *cinfo,
                    141:                                  struct u_addr *self, struct u_addr *peer, in_port_t port, int incoming,
                    142:                                  const char *callingNum,
                    143:                                  const char *calledNum,
                    144:                                  const char *subAddress);
                    145: 
                    146:   static int   PptpSetCommand(Context ctx, int ac, char *av[], void *arg);
                    147:   static int   PptpTunEQ(struct ghash *g, const void *item1, const void *item2);
                    148:   static u_int32_t     PptpTunHash(struct ghash *g, const void *item);
                    149: 
                    150: 
                    151: /*
                    152:  * GLOBAL VARIABLES
                    153:  */
                    154: 
                    155:   const struct phystype        gPptpPhysType = {
                    156:     .name              = "pptp",
                    157:     .descr             = "Point-to-Point Tunneling Protocol",
                    158:     .mtu               = PPTP_MTU,
                    159:     .mru               = PPTP_MRU,
                    160:     .tmpl              = 1,
                    161:     .tinit             = PptpTInit,
                    162:     .tshutdown         = PptpTShutdown,
                    163:     .init              = PptpInit,
                    164:     .inst              = PptpInst,
                    165:     .open              = PptpOpen,
                    166:     .close             = PptpClose,
                    167:     .update            = PptpListenUpdate,
                    168:     .shutdown          = PptpShutdown,
                    169:     .showstat          = PptpStat,
                    170:     .originate         = PptpOriginated,
                    171:     .issync            = PptpIsSync,
                    172:     .setaccm            = PptpSetAccm,
                    173:     .setcallingnum     = PptpSetCallingNum,
                    174:     .setcallednum      = PptpSetCalledNum,
                    175:     .selfname          = PptpSelfName,
                    176:     .peername          = PptpPeerName,
                    177:     .selfaddr          = PptpSelfAddr,
                    178:     .peeraddr          = PptpPeerAddr,
                    179:     .peerport          = PptpPeerPort,
                    180:     .peermacaddr       = PptpPeerMacAddr,
                    181:     .peeriface         = PptpPeerIface,
                    182:     .callingnum                = PptpCallingNum,
                    183:     .callednum         = PptpCalledNum,
                    184:   };
                    185: 
                    186:   const struct cmdtab  PptpSetCmds[] = {
                    187:     { "self {ip} [{port}]",            "Set local IP address",
                    188:        PptpSetCommand, NULL, 2, (void *) SET_SELFADDR },
                    189:     { "peer {ip} [{port}]",            "Set remote IP address",
                    190:        PptpSetCommand, NULL, 2, (void *) SET_PEERADDR },
                    191:     { "callingnum {number}",           "Set calling PPTP telephone number",
                    192:        PptpSetCommand, NULL, 2, (void *) SET_CALLINGNUM },
                    193:     { "callednum {number}",            "Set called PPTP telephone number",
                    194:        PptpSetCommand, NULL, 2, (void *) SET_CALLEDNUM },
                    195:     { "enable [opt ...]",              "Enable option",
                    196:        PptpSetCommand, NULL, 2, (void *) SET_ENABLE },
                    197:     { "disable [opt ...]",             "Disable option",
                    198:        PptpSetCommand, NULL, 2, (void *) SET_DISABLE },
                    199:     { NULL },
                    200:   };
                    201: 
                    202: /*
                    203:  * INTERNAL VARIABLES
                    204:  */
                    205: 
                    206:   static struct confinfo       gConfList[] = {
                    207:     { 0,       PPTP_CONF_OUTCALL,      "outcall"       },
                    208:     { 0,       PPTP_CONF_DELAYED_ACK,  "delayed-ack"   },
                    209:     { 0,       PPTP_CONF_ALWAYS_ACK,   "always-ack"    },
                    210:     { 0,       PPTP_CONF_RESOLVE_ONCE, "resolve-once"  },
                    211: #if NGM_PPTPGRE_COOKIE >= 1082548365
                    212:     { 0,       PPTP_CONF_WINDOWING,    "windowing"     },
                    213: #endif
                    214:     { 0,       0,                      NULL            },
                    215:   };
                    216: 
                    217: struct ghash    *gPptpTuns;
                    218: 
                    219: /*
                    220:  * PptpTInit()
                    221:  */
                    222: 
                    223: static int
                    224: PptpTInit(void)
                    225: {
                    226:     if ((gPptpTuns = ghash_create(NULL, 0, 0, MB_PHYS, PptpTunHash, PptpTunEQ, NULL, NULL))
                    227:          == NULL)
                    228:        return(-1);
                    229:     return (PptpCtrlInit(PptpIncoming, PptpOutgoing));
                    230: }
                    231: 
                    232: /*
                    233:  * PptpTShutdown()
                    234:  */
                    235: 
                    236: static void
                    237: PptpTShutdown(void)
                    238: {
                    239:     Log(LG_PHYS2, ("PPTP: Total shutdown"));
                    240:     ghash_destroy(&gPptpTuns);
                    241: }
                    242: 
                    243: /*
                    244:  * PptpInit()
                    245:  */
                    246: 
                    247: static int
                    248: PptpInit(Link l)
                    249: {
                    250:     PptpInfo   pptp;
                    251: 
                    252:     /* Initialize this link */
                    253:     pptp = (PptpInfo) (l->info = Malloc(MB_PHYS, sizeof(*pptp)));
                    254: 
                    255:     pptp->conf.self_addr.family = AF_INET;
                    256:     pptp->conf.fqdn_peer_addr = NULL;
                    257:     Enable(&pptp->conf.options, PPTP_CONF_OUTCALL);
                    258:     Enable(&pptp->conf.options, PPTP_CONF_DELAYED_ACK);
                    259:     Enable(&pptp->conf.options, PPTP_CONF_RESOLVE_ONCE);
                    260: 
                    261:     return(0);
                    262: }
                    263: 
                    264: /*
                    265:  * PptpInst()
                    266:  */
                    267: 
                    268: static int
                    269: PptpInst(Link l, Link lt)
                    270: {
                    271:     PptpInfo   pptp;
                    272:     PptpInfo   const pptpt = (PptpInfo) lt->info;
                    273: 
                    274:     /* Initialize this link */
                    275:     pptp = (PptpInfo) (l->info = Mdup(MB_PHYS, lt->info, sizeof(*pptp)));
                    276:     if (pptpt->conf.fqdn_peer_addr != NULL)
                    277:         pptp->conf.fqdn_peer_addr =
                    278:             Mstrdup(MB_PHYS, pptpt->conf.fqdn_peer_addr);
                    279:     pptp->listener = NULL;
                    280: 
                    281:     return(0);
                    282: }
                    283: 
                    284: /*
                    285:  * PptpOpen()
                    286:  */
                    287: 
                    288: static void
                    289: PptpOpen(Link l)
                    290: {
                    291:     PptpInfo           const pptp = (PptpInfo) l->info;
                    292:     struct sockaddr_dl  hwa;
                    293: 
                    294:     /* Check state */
                    295:     switch (l->state) {
                    296:        case PHYS_STATE_DOWN:
                    297:            if (PptpOriginate(l) < 0) {
                    298:                Log(LG_PHYS, ("[%s] PPTP call failed", l->name));
                    299:                PhysDown(l, STR_ERROR, NULL);
                    300:                return;
                    301:            }
                    302:            l->state = PHYS_STATE_CONNECTING;
                    303:            break;
                    304: 
                    305:        case PHYS_STATE_CONNECTING:
                    306:            if (pptp->originate)        /* our call to peer is already in progress */
                    307:                break;
                    308:            if (pptp->outcall) {
                    309: 
                    310:                /* Hook up nodes */
                    311:                Log(LG_PHYS, ("[%s] PPTP: attaching to peer's outgoing call", l->name));
                    312:                if (PptpHookUp(l) < 0) {
                    313:                    PptpDoClose(l);
                    314:                    /* We should not set state=DOWN as PptpResult() will be called once more */
                    315:                    break;
                    316:                }
                    317: 
                    318:                if (GetPeerEther(&pptp->peer_addr, &hwa)) {
                    319:                    if_indextoname(hwa.sdl_index, pptp->peer_iface);
                    320:                    memcpy(pptp->peer_mac_addr, LLADDR(&hwa), sizeof(pptp->peer_mac_addr));
                    321:                };
                    322: 
                    323:                (*pptp->cinfo.answer)(pptp->cinfo.cookie,
                    324:                    PPTP_OCR_RESL_OK, 0, 0, 64000 /*XXX*/ );
                    325: 
                    326:                /* Report UP if there was no error. */
                    327:                if (l->state == PHYS_STATE_CONNECTING) {
                    328:                    l->state = PHYS_STATE_UP;
                    329:                    PhysUp(l);
                    330:                }
                    331:                return;
                    332:            }
                    333:            return;     /* wait for peer's incoming pptp call to complete */
                    334: 
                    335:        case PHYS_STATE_UP:
                    336:            PhysUp(l);
                    337:            return;
                    338: 
                    339:        default:
                    340:            assert(0);
                    341:     }
                    342: }
                    343: 
                    344: /*
                    345:  * PptpOriginate()
                    346:  *
                    347:  * Initiate an "incoming" or an "outgoing" call to the remote site
                    348:  */
                    349: 
                    350: static int
                    351: PptpOriginate(Link l)
                    352: {
                    353:     PptpInfo           const pptp = (PptpInfo) l->info;
                    354:     struct pptplinkinfo        linfo;
                    355:     const u_short      port = pptp->conf.peer_port ?
                    356:                            pptp->conf.peer_port : PPTP_PORT;
                    357: 
                    358:     pptp->originate = TRUE;
                    359:     pptp->outcall = Enabled(&pptp->conf.options, PPTP_CONF_OUTCALL);
                    360:     memset(&linfo, 0, sizeof(linfo));
                    361:     linfo.cookie = l;
                    362:     linfo.result = PptpResult;
                    363:     linfo.setLinkInfo = PptpSetLinkInfo;
                    364:     linfo.cancel = PptpCancel;
                    365:     strlcpy(pptp->callingnum, pptp->conf.callingnum, sizeof(pptp->callingnum));
                    366:     strlcpy(pptp->callednum, pptp->conf.callednum, sizeof(pptp->callednum));
                    367:     if ((!Enabled(&pptp->conf.options, PPTP_CONF_RESOLVE_ONCE)) &&
                    368:        (pptp->conf.fqdn_peer_addr != NULL)) {
                    369:        struct u_range  rng;
                    370:        if (ParseRange(pptp->conf.fqdn_peer_addr, &rng, ALLOW_IPV4|ALLOW_IPV6))
                    371:            pptp->conf.peer_addr = rng;
                    372:     }
                    373:     if (!pptp->outcall) {
                    374:        int frameType = PPTP_FRAMECAP_SYNC;
                    375:        if (l->rep && !RepIsSync(l))
                    376:            frameType = PPTP_FRAMECAP_ASYNC;
                    377:        PptpCtrlInCall(&pptp->cinfo, &linfo, 
                    378:            &pptp->conf.self_addr, &pptp->conf.peer_addr.addr, port,
                    379:            PPTP_BEARCAP_ANY, frameType,
                    380:            PPTP_CALL_MIN_BPS, PPTP_CALL_MAX_BPS, 
                    381:            pptp->callingnum, pptp->callednum, "");
                    382:     } else {
                    383:        PptpCtrlOutCall(&pptp->cinfo, &linfo, 
                    384:            &pptp->conf.self_addr, &pptp->conf.peer_addr.addr, port,
                    385:            PPTP_BEARCAP_ANY, PPTP_FRAMECAP_ANY,
                    386:            PPTP_CALL_MIN_BPS, PPTP_CALL_MAX_BPS,
                    387:            pptp->callednum, "");
                    388:     }
                    389:     if (pptp->cinfo.cookie == NULL)
                    390:        return(-1);
                    391:     pptp->self_addr = pptp->conf.self_addr;
                    392:     pptp->peer_addr = pptp->conf.peer_addr.addr;
                    393:     pptp->peer_port = port;
                    394:     return(0);
                    395: }
                    396: 
                    397: /*
                    398:  * PptpClose()
                    399:  */
                    400: 
                    401: static void
                    402: PptpClose(Link l)
                    403: {
                    404:     PptpDoClose(l);
                    405: }
                    406: 
                    407: /*
                    408:  * PptpShutdown()
                    409:  */
                    410: 
                    411: static void
                    412: PptpShutdown(Link l)
                    413: {
                    414:     PptpInfo      const pptp = (PptpInfo) l->info;
                    415: 
                    416: 
                    417:     if (pptp->conf.fqdn_peer_addr)
                    418:         Freee(pptp->conf.fqdn_peer_addr);
                    419:     if (pptp->listener) {
                    420:        PptpCtrlUnListen(pptp->listener);
                    421:        pptp->listener = NULL;
                    422:     }
                    423:     PptpUnhook(l);
                    424:     Freee(l->info);
                    425: }
                    426: 
                    427: /*
                    428:  * PptpDoClose()
                    429:  */
                    430: 
                    431: static void
                    432: PptpDoClose(Link l)
                    433: {
                    434:     PptpInfo      const pptp = (PptpInfo) l->info;
                    435: 
                    436:     if (l->state != PHYS_STATE_DOWN)           /* avoid double close */
                    437:        (*pptp->cinfo.close)(pptp->cinfo.cookie, PPTP_CDN_RESL_ADMIN, 0, 0);
                    438: }
                    439: 
                    440: /*
                    441:  * PptpUnhook()
                    442:  */
                    443: 
                    444: static void
                    445: PptpUnhook(Link l)
                    446: {
                    447:        PptpInfo const  pptp = (PptpInfo) l->info;
                    448:        char            path[NG_PATHSIZ];
                    449:        int             csock = -1;
                    450: 
                    451:        if (pptp->tun == NULL)
                    452:                return;
                    453: 
                    454:        /* Get a temporary netgraph socket node */
                    455:        if (NgMkSockNode(NULL, &csock, NULL) == -1) {
                    456:                Perror("PPTP: NgMkSockNode");
                    457:                return;
                    458:        }
                    459:        
                    460:        pptp->tun->refs--;
                    461:        snprintf(path, sizeof(path), "[%lx]:", (u_long)pptp->tun->node_id);
                    462:        if (pptp->tun->refs == 0) {
                    463:            /* Disconnect session hook. */
                    464:            NgFuncShutdownNode(csock, l->name, path);
                    465:            ghash_remove(gPptpTuns, pptp->tun);
                    466:            Freee(pptp->tun);
                    467: #ifdef NG_PPTPGRE_HOOK_SESSION_F
                    468:        } else {
                    469:            char        hook[NG_HOOKSIZ];
                    470:            snprintf(hook, sizeof(hook), NG_PPTPGRE_HOOK_SESSION_F, pptp->cid);
                    471:            NgFuncDisconnect(csock, l->name, path, hook);
                    472: #endif
                    473:        }
                    474:        
                    475:        close(csock);
                    476:        
                    477:        pptp->tun = NULL;
                    478: }
                    479: 
                    480: /*
                    481:  * PptpOriginated()
                    482:  */
                    483: 
                    484: static int
                    485: PptpOriginated(Link l)
                    486: {
                    487:     PptpInfo   const pptp = (PptpInfo) l->info;
                    488: 
                    489:     return(pptp->originate ? LINK_ORIGINATE_LOCAL : LINK_ORIGINATE_REMOTE);
                    490: }
                    491: 
                    492: /*
                    493:  * PptpIsSync()
                    494:  */
                    495: 
                    496: static int
                    497: PptpIsSync(Link l)
                    498: {
                    499:     PptpInfo   const pptp = (PptpInfo) l->info;
                    500: 
                    501:     return (pptp->sync);
                    502: }
                    503: 
                    504: static int
                    505: PptpSetAccm(Link l, u_int32_t xmit, u_int32_t recv)
                    506: {
                    507:     PptpInfo   const pptp = (PptpInfo) l->info;
                    508:     
                    509:     if (!pptp->cinfo.close || !pptp->cinfo.cookie)
                    510:            return (-1);
                    511: 
                    512:     (*pptp->cinfo.setLinkInfo)(pptp->cinfo.cookie, xmit, recv);
                    513:     return (0);
                    514: }
                    515: 
                    516: static int
                    517: PptpSetCallingNum(Link l, void *buf)
                    518: {
                    519:     PptpInfo   const pptp = (PptpInfo) l->info;
                    520: 
                    521:     strlcpy(pptp->conf.callingnum, buf, sizeof(pptp->conf.callingnum));
                    522:     return(0);
                    523: }
                    524: 
                    525: static int
                    526: PptpSetCalledNum(Link l, void *buf)
                    527: {
                    528:     PptpInfo   const pptp = (PptpInfo) l->info;
                    529: 
                    530:     strlcpy(pptp->conf.callednum, buf, sizeof(pptp->conf.callednum));
                    531:     return(0);
                    532: }
                    533: 
                    534: static int
                    535: PptpSelfName(Link l, void *buf, size_t buf_len)
                    536: {
                    537:     PptpInfo   const pptp = (PptpInfo) l->info;
                    538: 
                    539:     if (pptp->cinfo.cookie)
                    540:        return(PptpCtrlGetSelfName(&pptp->cinfo, buf, buf_len));
                    541:     ((char*)buf)[0]=0;
                    542:     return (0);
                    543: }
                    544: 
                    545: static int
                    546: PptpPeerName(Link l, void *buf, size_t buf_len)
                    547: {
                    548:     PptpInfo   const pptp = (PptpInfo) l->info;
                    549: 
                    550:     if (pptp->cinfo.cookie)
                    551:        return(PptpCtrlGetPeerName(&pptp->cinfo, buf, buf_len));
                    552:     ((char*)buf)[0]=0;
                    553:     return (0);
                    554: }
                    555: 
                    556: static int
                    557: PptpSelfAddr(Link l, void *buf, size_t buf_len)
                    558: {
                    559:     PptpInfo   const pptp = (PptpInfo) l->info;
                    560: 
                    561:     if (u_addrtoa(&pptp->self_addr, buf, buf_len))
                    562:        return(0);
                    563:     else
                    564:        return(-1);
                    565: }
                    566: 
                    567: static int
                    568: PptpPeerAddr(Link l, void *buf, size_t buf_len)
                    569: {
                    570:     PptpInfo   const pptp = (PptpInfo) l->info;
                    571: 
                    572:     if (u_addrtoa(&pptp->peer_addr, buf, buf_len))
                    573:        return(0);
                    574:     else
                    575:        return(-1);
                    576: }
                    577: 
                    578: static int
                    579: PptpPeerPort(Link l, void *buf, size_t buf_len)
                    580: {
                    581:     PptpInfo   const pptp = (PptpInfo) l->info;
                    582: 
                    583:     if (snprintf(buf, buf_len, "%d", pptp->peer_port))
                    584:        return(0);
                    585:     else
                    586:        return(-1);
                    587: }
                    588: 
                    589: static int
                    590: PptpPeerMacAddr(Link l, void *buf, size_t buf_len)
                    591: {
                    592:     PptpInfo   const pptp = (PptpInfo) l->info;
                    593: 
                    594:     if (pptp->peer_iface[0]) {
1.1.1.2 ! misho     595:        ether_ntoa_r((struct ether_addr *)pptp->peer_mac_addr, buf);
1.1       misho     596:        return (0);
                    597:     }
                    598:     ((char*)buf)[0]=0;
                    599:     return(0);
                    600: }
                    601: 
                    602: static int
                    603: PptpPeerIface(Link l, void *buf, size_t buf_len)
                    604: {
                    605:     PptpInfo   const pptp = (PptpInfo) l->info;
                    606: 
                    607:     if (pptp->peer_iface[0]) {
                    608:        strlcpy(buf, pptp->peer_iface, buf_len);
                    609:        return (0);
                    610:     }
                    611:     ((char*)buf)[0]=0;
                    612:     return(0);
                    613: }
                    614: 
                    615: static int
                    616: PptpCallingNum(Link l, void *buf, size_t buf_len)
                    617: {
                    618:     PptpInfo   const pptp = (PptpInfo) l->info;
                    619: 
                    620:     strlcpy((char*)buf, pptp->callingnum, buf_len);
                    621:     return(0);
                    622: }
                    623: 
                    624: static int
                    625: PptpCalledNum(Link l, void *buf, size_t buf_len)
                    626: {
                    627:     PptpInfo   const pptp = (PptpInfo) l->info;
                    628: 
                    629:     strlcpy((char*)buf, pptp->callednum, buf_len);
                    630:     return(0);
                    631: }
                    632: 
                    633: /*
                    634:  * PptpStat()
                    635:  */
                    636: 
                    637: void
                    638: PptpStat(Context ctx)
                    639: {
                    640:     PptpInfo   const pptp = (PptpInfo) ctx->lnk->info;
                    641:     char       buf[32];
                    642: 
                    643:     Printf("PPTP configuration:\r\n");
                    644:     Printf("\tSelf addr    : %s",
                    645:        u_addrtoa(&pptp->conf.self_addr, buf, sizeof(buf)));
                    646:     if (pptp->conf.self_port)
                    647:        Printf(", port %u", pptp->conf.self_port);
                    648:     Printf("\r\n");
                    649:     Printf("\tPeer FQDN    : %s\r\n", pptp->conf.fqdn_peer_addr);
                    650:     Printf("\tPeer range   : %s",
                    651:        u_rangetoa(&pptp->conf.peer_addr, buf, sizeof(buf)));
                    652:     if (pptp->conf.peer_port)
                    653:        Printf(", port %u", pptp->conf.peer_port);
                    654:     Printf("\r\n");
                    655:     Printf("\tCalling number: %s\r\n", pptp->conf.callingnum);
                    656:     Printf("\tCalled number: %s\r\n", pptp->conf.callednum);
                    657:     Printf("PPTP options:\r\n");
                    658:     OptStat(ctx, &pptp->conf.options, gConfList);
                    659:     Printf("PPTP status:\r\n");
                    660:     if (ctx->lnk->state != PHYS_STATE_DOWN) {
                    661:        Printf("\tIncoming     : %s\r\n", (pptp->originate?"NO":"YES"));
                    662:        Printf("\tCurrent self : %s",
                    663:            u_addrtoa(&pptp->self_addr, buf, sizeof(buf)));
                    664:        PptpSelfName(ctx->lnk, buf, sizeof(buf));
                    665:        Printf(" (%s)\r\n", buf);
                    666:        Printf("\tCurrent peer : %s, port %u",
                    667:            u_addrtoa(&pptp->peer_addr, buf, sizeof(buf)), pptp->peer_port);
                    668:        PptpPeerName(ctx->lnk, buf, sizeof(buf));
                    669:        Printf(" (%s)\r\n", buf);
                    670:        if (pptp->peer_iface[0]) {
1.1.1.2 ! misho     671:            ether_ntoa_r((struct ether_addr *)pptp->peer_mac_addr, buf);
        !           672:            Printf("\tCurrent peer : %s at %s\r\n", buf, pptp->peer_iface);
1.1       misho     673:        }
                    674:        Printf("\tFraming      : %s\r\n", (pptp->sync?"Sync":"Async"));
                    675:        Printf("\tCalling number: %s\r\n", pptp->callingnum);
                    676:        Printf("\tCalled number: %s\r\n", pptp->callednum);
                    677:     }
                    678: }
                    679: 
                    680: /*
                    681:  * PptpResult()
                    682:  *
                    683:  * The control code calls this function to report a PPTP link
                    684:  * being connected, disconnected, or failing to connect.
                    685:  */
                    686: 
                    687: static void
                    688: PptpResult(void *cookie, const char *errmsg, int frameType)
                    689: {
                    690:     PptpInfo   pptp;
                    691:     Link       l;
                    692:     struct sockaddr_dl  hwa;
                    693: 
                    694:     /* It this fake call? */
                    695:     if (!cookie)
                    696:        return;
                    697: 
                    698:     l = (Link)cookie;
                    699:     pptp = (PptpInfo) l->info;
                    700: 
                    701:     switch (l->state) {
                    702:        case PHYS_STATE_CONNECTING:
                    703:            if (!errmsg) {
                    704: 
                    705:                /* Hook up nodes */
                    706:                Log(LG_PHYS, ("[%s] PPTP call successful", l->name));
                    707:                if (PptpHookUp(l) < 0) {
                    708:                    PptpDoClose(l);
                    709:                    /* We should not set state=DOWN as PptpResult() will be called once more */
                    710:                    break;
                    711:                }
                    712: 
                    713:                if (pptp->originate && !pptp->outcall)
                    714:                    (*pptp->cinfo.connected)(pptp->cinfo.cookie, 64000 /*XXX*/ );
                    715: 
                    716:                /* Report UP if there was no error. */
                    717:                if (l->state == PHYS_STATE_CONNECTING) {
                    718:                    if (GetPeerEther(&pptp->peer_addr, &hwa)) {
                    719:                        if_indextoname(hwa.sdl_index, pptp->peer_iface);
                    720:                        memcpy(pptp->peer_mac_addr, LLADDR(&hwa), sizeof(pptp->peer_mac_addr));
                    721:                    };
                    722: 
                    723:                    /* OK */
                    724:                    l->state = PHYS_STATE_UP;
                    725:                    pptp->sync = (frameType&PPTP_FRAMECAP_ASYNC)?0:1;
                    726:                    PhysUp(l);
                    727:                }
                    728:            } else {
                    729:                Log(LG_PHYS, ("[%s] PPTP call failed", l->name));
                    730:                PptpUnhook(l);          /* For the (*connected)() error. */
                    731:                l->state = PHYS_STATE_DOWN;
                    732:                u_addrclear(&pptp->self_addr);
                    733:                u_addrclear(&pptp->peer_addr);
                    734:                pptp->peer_port = 0;
                    735:                pptp->callingnum[0]=0;
                    736:                pptp->callednum[0]=0;
                    737:                pptp->peer_iface[0] = 0;
                    738:                PhysDown(l, STR_CON_FAILED, errmsg);
                    739:            }
                    740:            break;
                    741:        case PHYS_STATE_UP:
                    742:            assert(errmsg);
                    743:            Log(LG_PHYS, ("[%s] PPTP call terminated", l->name));
                    744:            PptpUnhook(l);
                    745:            l->state = PHYS_STATE_DOWN;
                    746:             u_addrclear(&pptp->self_addr);
                    747:            u_addrclear(&pptp->peer_addr);
                    748:            pptp->peer_port = 0;
                    749:            pptp->callingnum[0]=0;
                    750:            pptp->callednum[0]=0;
                    751:            pptp->peer_iface[0] = 0;
                    752:            PhysDown(l, STR_DROPPED, NULL);
                    753:            break;
                    754:        case PHYS_STATE_DOWN:
                    755:            return;
                    756:        default:
                    757:            assert(0);
                    758:     }
                    759: }
                    760: 
                    761: /*
                    762:  * PptpSetLinkInfo()
                    763:  *
                    764:  * Received LinkInfo from peer;
                    765:  */
                    766: 
                    767: void
                    768: PptpSetLinkInfo(void *cookie, u_int32_t sa, u_int32_t ra)
                    769: {
                    770:     Link       l;
                    771: 
                    772:     /* It this fake call? */
                    773:     if (!cookie)
                    774:            return;
                    775: 
                    776:     l = (Link)cookie;
                    777: 
                    778:     if (l->rep != NULL)
                    779:            RepSetAccm(l, sa, ra);
                    780: }
                    781: 
                    782: static int
                    783: PptpTunEQ(struct ghash *g, const void *item1, const void *item2)
                    784: {
                    785:     const struct pptptun *tun1 = item1;
                    786:     const struct pptptun *tun2 = item2;
                    787:     if (u_addrcompare(&tun1->self_addr, &tun2->self_addr) == 0 &&
                    788:        u_addrcompare(&tun1->peer_addr, &tun2->peer_addr) == 0)
                    789:            return (1);
                    790:     return (0);
                    791: }
                    792: 
                    793: static u_int32_t
                    794: PptpTunHash(struct ghash *g, const void *item)
                    795: {
                    796:     const struct pptptun *tun = item;
                    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;
                    916:        ((int *)(ksso->value))[0]=48*1024;
                    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,
                    988:        struct u_addr *self, struct u_addr *peer, in_port_t port, int bearType,
                    989:        const char *callingNum,
                    990:        const char *calledNum,
                    991:        const char *subAddress)
                    992: {
                    993:     return(PptpPeerCall(cinfo, self, peer, port, TRUE, callingNum, calledNum, subAddress));
                    994: }
                    995: 
                    996: /*
                    997:  * PptpOutgoing()
                    998:  *
                    999:  * The control code calls this function to report that some
                   1000:  * remote PPTP client has asked us if we will dial out to some
                   1001:  * phone number. We don't actually do this, but some clients
                   1002:  * initiate their connections as outgoing calls for some reason.
                   1003:  */
                   1004: 
                   1005: static struct pptplinkinfo
                   1006: PptpOutgoing(struct pptpctrlinfo *cinfo,
                   1007:        struct u_addr *self, struct u_addr *peer, in_port_t port, int bearType,
                   1008:        int frameType, int minBps, int maxBps,
                   1009:        const char *calledNum, const char *subAddress)
                   1010: {
                   1011:     return(PptpPeerCall(cinfo, self, peer, port, FALSE, "", calledNum, subAddress));
                   1012: }
                   1013: 
                   1014: /*
                   1015:  * PptpPeerCall()
                   1016:  *
                   1017:  * Peer has initiated a call (either incoming or outgoing; either
                   1018:  * way it's the same to us). If we have an available link that may
                   1019:  * accept calls from the peer's IP addresss and port, then say yes.
                   1020:  */
                   1021: 
                   1022: static struct pptplinkinfo
                   1023: PptpPeerCall(struct pptpctrlinfo *cinfo,
                   1024:        struct u_addr *self, struct u_addr *peer, in_port_t port, int incoming,
                   1025:        const char *callingNum,
                   1026:        const char *calledNum,
                   1027:        const char *subAddress)
                   1028: {
                   1029:     struct pptplinkinfo        linfo;
                   1030:     Link               l = NULL;
                   1031:     PptpInfo           pi = NULL;
                   1032:     int                        k;
                   1033: 
                   1034:     memset(&linfo, 0, sizeof(linfo));
                   1035: 
                   1036:     linfo.cookie = NULL;
                   1037:     linfo.result = PptpResult;
                   1038:     linfo.setLinkInfo = PptpSetLinkInfo;
                   1039:     linfo.cancel = PptpCancel;
                   1040: 
                   1041:     if (gShutdownInProgress) {
                   1042:        Log(LG_PHYS, ("Shutdown sequence in progress, ignoring request."));
                   1043:        return(linfo);
                   1044:     }
                   1045: 
                   1046:     if (OVERLOAD()) {
                   1047:        Log(LG_PHYS, ("Daemon overloaded, ignoring request."));
                   1048:        return(linfo);
                   1049:     }
                   1050: 
                   1051:     /* Find a suitable link; prefer the link best matching peer's IP address */
                   1052:     for (k = 0; k < gNumLinks; k++) {
                   1053:        Link l2;
                   1054:        PptpInfo pi2;
                   1055: 
                   1056:        if (!gLinks[k] || gLinks[k]->type != &gPptpPhysType)
                   1057:                continue;
                   1058: 
                   1059:        l2 = gLinks[k];
                   1060:        pi2 = (PptpInfo)l2->info;
                   1061: 
                   1062:        /* See if link is feasible */
                   1063:        if ((!PhysIsBusy(l2)) &&
                   1064:            Enabled(&l2->conf.options, LINK_CONF_INCOMING) &&
                   1065:            (u_addrempty(&pi2->conf.self_addr) || (u_addrcompare(&pi2->conf.self_addr, self) == 0)) &&
                   1066:            IpAddrInRange(&pi2->conf.peer_addr, peer) &&
                   1067:            (!pi2->conf.peer_port || pi2->conf.peer_port == port)) {
                   1068: 
                   1069:                /* Link is feasible; now see if it's preferable */
                   1070:                if (!pi || pi2->conf.peer_addr.width > pi->conf.peer_addr.width) {
                   1071:                        l = l2;
                   1072:                        pi = pi2;
                   1073:                        if (u_rangehost(&pi->conf.peer_addr)) {
                   1074:                                break;  /* Nothing could be better */
                   1075:                        }
                   1076:                }
                   1077:        }
                   1078:     }
                   1079: 
                   1080:     if (l != NULL && l->tmpl)
                   1081:         l = LinkInst(l, NULL, 0, 0);
                   1082: 
                   1083:     /* If no link is suitable, can't take the call */
                   1084:     if (l == NULL) {
                   1085:        Log(LG_PHYS, ("No free PPTP link with requested parameters "
                   1086:            "was found"));
                   1087:        return(linfo);
                   1088:     }
                   1089:     pi = (PptpInfo)l->info;
                   1090: 
                   1091:     Log(LG_PHYS, ("[%s] Accepting PPTP connection", l->name));
                   1092: 
                   1093:     /* Got one */
                   1094:     linfo.cookie = l;
                   1095:     l->state = PHYS_STATE_CONNECTING;
                   1096:     pi->cinfo = *cinfo;
                   1097:     pi->originate = FALSE;
                   1098:     pi->outcall = !incoming;
                   1099:     pi->sync = 1;
                   1100:     pi->self_addr = *self;
                   1101:     pi->peer_addr = *peer;
                   1102:     pi->peer_port = port;
                   1103:     strlcpy(pi->callingnum, callingNum, sizeof(pi->callingnum));
                   1104:     strlcpy(pi->callednum, calledNum, sizeof(pi->callednum));
                   1105: 
                   1106:     PhysIncoming(l);
                   1107:     return(linfo);
                   1108: }
                   1109: 
                   1110: /*
                   1111:  * PptpCancel()
                   1112:  *
                   1113:  * The control code calls this function to cancel a
                   1114:  * local outgoing call in progress.
                   1115:  */
                   1116: 
                   1117: static void
                   1118: PptpCancel(void *cookie)
                   1119: {
                   1120:     PptpInfo   pi;
                   1121:     Link       l;
                   1122: 
                   1123:     /* It this fake call? */
                   1124:     if (!cookie)
                   1125:        return;
                   1126: 
                   1127:     l = (Link)cookie;
                   1128:     pi = (PptpInfo) l->info;
                   1129: 
                   1130:     Log(LG_PHYS, ("[%s] PPTP call cancelled in state %s",
                   1131:        l->name, gPhysStateNames[l->state]));
                   1132:     if (l->state == PHYS_STATE_DOWN)
                   1133:        return;
                   1134:     l->state = PHYS_STATE_DOWN;
                   1135:     u_addrclear(&pi->peer_addr);
                   1136:     pi->peer_port = 0;
                   1137:     pi->callingnum[0]=0;
                   1138:     pi->callednum[0]=0;
                   1139:     pi->peer_iface[0] = 0;
                   1140:     PhysDown(l, STR_CON_FAILED0, NULL);
                   1141: }
                   1142: 
                   1143: /*
                   1144:  * PptpListenUpdate()
                   1145:  */
                   1146: 
                   1147: static void
                   1148: PptpListenUpdate(Link l)
                   1149: {
                   1150:     PptpInfo   pi = (PptpInfo) l->info;
                   1151: 
                   1152:     if (pi->listener == NULL) {
                   1153:        if (Enabled(&l->conf.options, LINK_CONF_INCOMING)) {
                   1154:            /* Set up listening for incoming connections */
                   1155:            if ((pi->listener = 
                   1156:                PptpCtrlListen(&pi->conf.self_addr, pi->conf.self_port))
                   1157:                    == NULL) {
                   1158:                Log(LG_ERR, ("PPTP: Error, can't listen for connection!"));
                   1159:            }
                   1160:        }
                   1161:     } else {
                   1162:        if (!Enabled(&l->conf.options, LINK_CONF_INCOMING)) {
                   1163:            PptpCtrlUnListen(pi->listener);
                   1164:            pi->listener = NULL;
                   1165:        }
                   1166:     }
                   1167: }
                   1168: 
                   1169: /*
                   1170:  * PptpSetCommand()
                   1171:  */
                   1172: 
                   1173: static int
                   1174: PptpSetCommand(Context ctx, int ac, char *av[], void *arg)
                   1175: {
                   1176:     PptpInfo           const pi = (PptpInfo) ctx->lnk->info;
                   1177:     char               **fqdn_peer_addr = &pi->conf.fqdn_peer_addr;
                   1178:     struct u_range     rng;
                   1179:     int                        port;
                   1180: 
                   1181:     switch ((intptr_t)arg) {
                   1182:        case SET_SELFADDR:
                   1183:        case SET_PEERADDR:
                   1184:            if ((ac == 1 || ac == 2) && (intptr_t)arg == SET_PEERADDR) {
                   1185:                if (*fqdn_peer_addr)
                   1186:                    Freee(*fqdn_peer_addr);
                   1187:                *fqdn_peer_addr = Mstrdup(MB_PHYS, av[0]);
                   1188:            }
                   1189:            if (ac < 1 || ac > 2 || !ParseRange(av[0], &rng, ALLOW_IPV4|ALLOW_IPV6))
                   1190:                return(-1);
                   1191:            if (ac > 1) {
                   1192:                if ((port = atoi(av[1])) < 0 || port > 0xffff)
                   1193:                    return(-1);
                   1194:            } else {
                   1195:                port = 0;
                   1196:            }
                   1197:            if ((intptr_t)arg == SET_SELFADDR) {
                   1198:                pi->conf.self_addr = rng.addr;
                   1199:                pi->conf.self_port = port;
                   1200:            } else {
                   1201:                pi->conf.peer_addr = rng;
                   1202:                pi->conf.peer_port = port;
                   1203:            }
                   1204:            break;
                   1205:        case SET_CALLINGNUM:
                   1206:            if (ac != 1)
                   1207:                return(-1);
                   1208:            strlcpy(pi->conf.callingnum, av[0], sizeof(pi->conf.callingnum));
                   1209:            break;
                   1210:        case SET_CALLEDNUM:
                   1211:            if (ac != 1)
                   1212:                return(-1);
                   1213:            strlcpy(pi->conf.callednum, av[0], sizeof(pi->conf.callednum));
                   1214:            break;
                   1215:        case SET_ENABLE:
                   1216:            EnableCommand(ac, av, &pi->conf.options, gConfList);
                   1217:            PptpListenUpdate(ctx->lnk);
                   1218:            break;
                   1219:        case SET_DISABLE:
                   1220:            DisableCommand(ac, av, &pi->conf.options, gConfList);
                   1221:            PptpListenUpdate(ctx->lnk);
                   1222:            break;
                   1223:        default:
                   1224:            assert(0);
                   1225:     }
                   1226:     return(0);
                   1227: }
                   1228: 

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