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

1.1     ! misho       1: 
        !             2: /*
        !             3:  * udp.c
        !             4:  *
        !             5:  * Written by  Alexander Motin <mav@FreeBSD.org>
        !             6:  */
        !             7: 
        !             8: #include "ppp.h"
        !             9: #include "phys.h"
        !            10: #include "mbuf.h"
        !            11: #include "udp.h"
        !            12: #include "ngfunc.h"
        !            13: #include "util.h"
        !            14: #include "log.h"
        !            15: 
        !            16: #include <netgraph/ng_message.h>
        !            17: #include <netgraph/ng_socket.h>
        !            18: #include <netgraph/ng_ksocket.h>
        !            19: #include <netgraph.h>
        !            20: 
        !            21: /*
        !            22:  * XXX this device type not completely correct, 
        !            23:  * as it can deliver out-of-order frames. This can make problems 
        !            24:  * for different compression and encryption protocols.
        !            25:  */
        !            26: 
        !            27: /*
        !            28:  * DEFINITIONS
        !            29:  */
        !            30: 
        !            31:   #define UDP_MTU              2048
        !            32:   #define UDP_MRU              2048
        !            33: 
        !            34:   #define UDP_MAXPARENTIFS     256
        !            35: 
        !            36:   struct udpinfo {
        !            37:     struct {
        !            38:        struct optinfo  options;
        !            39:        struct u_addr   self_addr;      /* Configured local IP address */
        !            40:        struct u_range  peer_addr;      /* Configured peer IP address */
        !            41:        in_port_t       self_port;      /* Configured local port */
        !            42:        in_port_t       peer_port;      /* Configured peer port */
        !            43:        char            *fqdn_peer_addr; /* FQDN Peer address */
        !            44:     } conf;
        !            45: 
        !            46:     /* State */
        !            47:     u_char             incoming;               /* incoming vs. outgoing */
        !            48:     struct UdpIf       *If;
        !            49:     struct u_addr      peer_addr;
        !            50:     in_port_t          peer_port;
        !            51:     ng_ID_t            node_id;
        !            52:   };
        !            53:   typedef struct udpinfo       *UdpInfo;
        !            54: 
        !            55: /* Set menu options */
        !            56: 
        !            57:   enum {
        !            58:     SET_PEERADDR,
        !            59:     SET_SELFADDR,
        !            60:     SET_ENABLE,
        !            61:     SET_DISABLE
        !            62:   };
        !            63: 
        !            64:   /* Binary options */
        !            65:   enum {
        !            66:     UDP_CONF_RESOLVE_ONCE      /* Only once resolve peer_addr */
        !            67:   };
        !            68: 
        !            69: /*
        !            70:  * INTERNAL FUNCTIONS
        !            71:  */
        !            72: 
        !            73:   static int   UdpInit(Link l);
        !            74:   static int   UdpInst(Link l, Link lt);
        !            75:   static void  UdpOpen(Link l);
        !            76:   static void  UdpClose(Link l);
        !            77:   static void  UdpStat(Context ctx);
        !            78:   static int   UdpOrigination(Link l);
        !            79:   static int   UdpIsSync(Link l);
        !            80:   static int   UdpSelfAddr(Link l, void *buf, size_t buf_len);
        !            81:   static int   UdpPeerAddr(Link l, void *buf, size_t buf_len);
        !            82:   static int   UdpPeerPort(Link l, void *buf, size_t buf_len);
        !            83:   static int   UdpCallingNum(Link l, void *buf, size_t buf_len);
        !            84:   static int   UdpCalledNum(Link l, void *buf, size_t buf_len);
        !            85: 
        !            86:   static void  UdpDoClose(Link l);
        !            87:   static void  UdpShutdown(Link l);
        !            88:   static int   UdpSetCommand(Context ctx, int ac, char *av[], void *arg);
        !            89:   static void  UdpNodeUpdate(Link l);
        !            90:   static int   UdpListen(Link l);
        !            91:   static int   UdpUnListen(Link l);
        !            92: 
        !            93: /*
        !            94:  * GLOBAL VARIABLES
        !            95:  */
        !            96: 
        !            97:   const struct phystype gUdpPhysType = {
        !            98:     .name              = "udp",
        !            99:     .descr             = "PPP over UDP",
        !           100:     .mtu               = UDP_MTU,
        !           101:     .mru               = UDP_MRU,
        !           102:     .tmpl              = 1,
        !           103:     .init              = UdpInit,
        !           104:     .inst              = UdpInst,
        !           105:     .open              = UdpOpen,
        !           106:     .close             = UdpClose,
        !           107:     .update            = UdpNodeUpdate,
        !           108:     .shutdown          = UdpShutdown,
        !           109:     .showstat          = UdpStat,
        !           110:     .originate         = UdpOrigination,
        !           111:     .issync            = UdpIsSync,
        !           112:     .selfaddr          = UdpSelfAddr,
        !           113:     .peeraddr          = UdpPeerAddr,
        !           114:     .peerport          = UdpPeerPort,
        !           115:     .callingnum                = UdpCallingNum,
        !           116:     .callednum         = UdpCalledNum,
        !           117:   };
        !           118: 
        !           119:   const struct cmdtab UdpSetCmds[] = {
        !           120:     { "self {ip} [{port}]",            "Set local IP address",
        !           121:        UdpSetCommand, NULL, 2, (void *) SET_SELFADDR },
        !           122:     { "peer {ip} [{port}]",            "Set remote IP address",
        !           123:        UdpSetCommand, NULL, 2, (void *) SET_PEERADDR },
        !           124:     { "enable [opt ...]",              "Enable option",
        !           125:        UdpSetCommand, NULL, 2, (void *) SET_ENABLE },
        !           126:     { "disable [opt ...]",             "Disable option",
        !           127:        UdpSetCommand, NULL, 2, (void *) SET_DISABLE },
        !           128:     { NULL },
        !           129:   };
        !           130: 
        !           131: struct UdpIf {
        !           132:     struct u_addr      self_addr;
        !           133:     in_port_t  self_port;
        !           134:     int                refs;
        !           135:     int                csock;                  /* netgraph Control socket */
        !           136:     EventRef   ctrlEvent;              /* listen for ctrl messages */
        !           137: };
        !           138: struct UdpIf UdpIfs[UDP_MAXPARENTIFS];
        !           139: 
        !           140: int UdpListenUpdateSheduled=0;
        !           141: struct pppTimer UdpListenUpdateTimer;
        !           142: 
        !           143:  /*
        !           144:  * INTERNAL VARIABLES
        !           145:  */
        !           146: 
        !           147:   static struct confinfo       gConfList[] = {
        !           148:     { 0,       UDP_CONF_RESOLVE_ONCE,  "resolve-once"  },
        !           149:     { 0,       0,                      NULL            },
        !           150:   };
        !           151: 
        !           152: 
        !           153: /*
        !           154:  * UdpInit()
        !           155:  */
        !           156: 
        !           157: static int
        !           158: UdpInit(Link l)
        !           159: {
        !           160:     UdpInfo    pi;
        !           161: 
        !           162:     pi = (UdpInfo) (l->info = Malloc(MB_PHYS, sizeof(*pi)));
        !           163: 
        !           164:     u_addrclear(&pi->conf.self_addr);
        !           165:     u_rangeclear(&pi->conf.peer_addr);
        !           166:     pi->conf.self_port=0;
        !           167:     pi->conf.peer_port=0;
        !           168: 
        !           169:     pi->incoming = 0;
        !           170:     pi->If = NULL;
        !           171: 
        !           172:     u_addrclear(&pi->peer_addr);
        !           173:     pi->peer_port=0;
        !           174:     pi->conf.fqdn_peer_addr = NULL;
        !           175:     Enable(&pi->conf.options, UDP_CONF_RESOLVE_ONCE);
        !           176: 
        !           177:     return(0);
        !           178: }
        !           179: 
        !           180: /*
        !           181:  * UdpInst()
        !           182:  */
        !           183: 
        !           184: static int
        !           185: UdpInst(Link l, Link lt)
        !           186: {
        !           187:     UdpInfo    pi;
        !           188:     UdpInfo const pit = (UdpInfo) lt->info;
        !           189: 
        !           190:     /* Initialize this link */
        !           191:     pi = (UdpInfo) (l->info = Mdup(MB_PHYS, lt->info, sizeof(*pi)));
        !           192:     if (pit->conf.fqdn_peer_addr != NULL)
        !           193:         pi->conf.fqdn_peer_addr =
        !           194:             Mstrdup(MB_PHYS, pit->conf.fqdn_peer_addr);
        !           195:     
        !           196:     if (pi->If)
        !           197:        pi->If->refs++;
        !           198: 
        !           199:     return(0);
        !           200: }
        !           201: 
        !           202: /*
        !           203:  * UdpOpen()
        !           204:  */
        !           205: 
        !           206: static void
        !           207: UdpOpen(Link l)
        !           208: {
        !           209:        UdpInfo                 const pi = (UdpInfo) l->info;
        !           210:        char                    path[NG_PATHSIZ];
        !           211:        char                    hook[NG_HOOKSIZ];
        !           212:        struct ngm_mkpeer       mkp;
        !           213:        struct ngm_name         nm;
        !           214:        struct sockaddr_storage addr;
        !           215:         union {
        !           216:             u_char buf[sizeof(struct ng_ksocket_sockopt) + sizeof(int)];
        !           217:             struct ng_ksocket_sockopt ksso;
        !           218:         } u;
        !           219:         struct ng_ksocket_sockopt *const ksso = &u.ksso;
        !           220:        int                     csock;
        !           221: 
        !           222:        /* Create a new netgraph node to control TCP ksocket node. */
        !           223:        if (NgMkSockNode(NULL, &csock, NULL) < 0) {
        !           224:                Perror("[%s] TCP can't create control socket", l->name);
        !           225:                goto fail;
        !           226:        }
        !           227:        (void)fcntl(csock, F_SETFD, 1);
        !           228: 
        !           229:         if (!PhysGetUpperHook(l, path, hook)) {
        !           230:                Log(LG_PHYS, ("[%s] UDP: can't get upper hook", l->name));
        !           231:                goto fail;
        !           232:         }
        !           233: 
        !           234:        /* Attach ksocket node to PPP node */
        !           235:        memset(&mkp, 0, sizeof(mkp));
        !           236:        strcpy(mkp.type, NG_KSOCKET_NODE_TYPE);
        !           237:        strlcpy(mkp.ourhook, hook, sizeof(mkp.ourhook));
        !           238:        if ((pi->conf.self_addr.family==AF_INET6) || 
        !           239:            (pi->conf.self_addr.family==AF_UNSPEC && pi->conf.peer_addr.addr.family==AF_INET6)) {
        !           240:                snprintf(mkp.peerhook, sizeof(mkp.peerhook), "%d/%d/%d", PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
        !           241:        } else {
        !           242:            snprintf(mkp.peerhook, sizeof(mkp.peerhook), "inet/dgram/udp");
        !           243:        }
        !           244:        if (NgSendMsg(csock, path, NGM_GENERIC_COOKIE,
        !           245:            NGM_MKPEER, &mkp, sizeof(mkp)) < 0) {
        !           246:                Perror("[%s] can't attach %s node",
        !           247:                    l->name, NG_KSOCKET_NODE_TYPE);
        !           248:                goto fail;
        !           249:        }
        !           250: 
        !           251:        strlcat(path, ".", sizeof(path));
        !           252:        strlcat(path, hook, sizeof(path));
        !           253: 
        !           254:        /* Give it a name */
        !           255:        memset(&nm, 0, sizeof(nm));
        !           256:        snprintf(nm.name, sizeof(nm.name), "mpd%d-%s-kso", gPid, l->name);
        !           257:        if (NgSendMsg(csock, path,
        !           258:            NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
        !           259:                Perror("[%s] can't name %s node", l->name, NG_KSOCKET_NODE_TYPE);
        !           260:        }
        !           261: 
        !           262:        if ((pi->node_id = NgGetNodeID(csock, path)) == 0) {
        !           263:            Perror("[%s] Cannot get %s node id", l->name, NG_KSOCKET_NODE_TYPE);
        !           264:            goto fail;
        !           265:        };
        !           266: 
        !           267:     if ((pi->incoming) || (pi->conf.self_port != 0)) {
        !           268:        /* Setsockopt socket. */
        !           269:        ksso->level=SOL_SOCKET;
        !           270:        ksso->name=SO_REUSEPORT;
        !           271:        ((int *)(ksso->value))[0]=1;
        !           272:        if (NgSendMsg(csock, path, NGM_KSOCKET_COOKIE,
        !           273:            NGM_KSOCKET_SETOPT, &u, sizeof(u)) < 0) {
        !           274:            Perror("[%s] can't setsockopt() %s node",
        !           275:                l->name, NG_KSOCKET_NODE_TYPE);
        !           276:            goto fail;
        !           277:        }
        !           278: 
        !           279:        if ((!Enabled(&pi->conf.options, UDP_CONF_RESOLVE_ONCE)) &&
        !           280:            (pi->conf.fqdn_peer_addr != NULL)) {
        !           281:            struct u_range      rng;
        !           282:            if (ParseRange(pi->conf.fqdn_peer_addr, &rng, ALLOW_IPV4|ALLOW_IPV6))
        !           283:                pi->conf.peer_addr = rng;
        !           284:        }
        !           285: 
        !           286:        /* Bind socket */
        !           287:        u_addrtosockaddr(&pi->conf.self_addr, pi->conf.self_port, &addr);
        !           288:        if (NgSendMsg(csock, path, NGM_KSOCKET_COOKIE,
        !           289:          NGM_KSOCKET_BIND, &addr, addr.ss_len) < 0) {
        !           290:            Perror("[%s] can't bind() %s node", l->name, NG_KSOCKET_NODE_TYPE);
        !           291:            goto fail;
        !           292:        }
        !           293:     }
        !           294: 
        !           295:     if (!pi->incoming) {
        !           296:        if ((!u_rangeempty(&pi->conf.peer_addr)) && (pi->conf.peer_port != 0)) {
        !           297:            u_addrcopy(&pi->conf.peer_addr.addr,&pi->peer_addr);
        !           298:            pi->peer_port = pi->conf.peer_port;
        !           299:        } else {
        !           300:            Log(LG_ERR, ("[%s] Can't connect without peer specified", l->name));
        !           301:            goto fail;
        !           302:        }
        !           303:     }
        !           304:     u_addrtosockaddr(&pi->peer_addr, pi->peer_port, &addr);
        !           305: 
        !           306:     /* Connect socket if peer address and port is specified */
        !           307:     if (NgSendMsg(csock, path, NGM_KSOCKET_COOKIE,
        !           308:       NGM_KSOCKET_CONNECT, &addr, addr.ss_len) < 0) {
        !           309:        Perror("[%s] can't connect() %s node", l->name, NG_KSOCKET_NODE_TYPE);
        !           310:        goto fail;
        !           311:     }
        !           312:   
        !           313:     close(csock);
        !           314: 
        !           315:     /* OK */
        !           316:     l->state = PHYS_STATE_UP;
        !           317:     PhysUp(l);
        !           318:     return;
        !           319: 
        !           320: fail:
        !           321:     UdpDoClose(l);
        !           322:     pi->incoming=0;
        !           323:     l->state = PHYS_STATE_DOWN;
        !           324:     u_addrclear(&pi->peer_addr);
        !           325:     pi->peer_port=0;
        !           326:     if (csock>0)
        !           327:        close(csock);
        !           328: 
        !           329:     PhysDown(l, STR_ERROR, NULL);
        !           330: }
        !           331: 
        !           332: /*
        !           333:  * UdpClose()
        !           334:  */
        !           335: 
        !           336: static void
        !           337: UdpClose(Link l)
        !           338: {
        !           339:     UdpInfo const pi = (UdpInfo) l->info;
        !           340:     if (l->state != PHYS_STATE_DOWN) {
        !           341:        UdpDoClose(l);
        !           342:        pi->incoming=0;
        !           343:        l->state = PHYS_STATE_DOWN;
        !           344:        u_addrclear(&pi->peer_addr);
        !           345:        pi->peer_port=0;
        !           346:        PhysDown(l, STR_MANUALLY, NULL);
        !           347:     }
        !           348: }
        !           349: 
        !           350: /*
        !           351:  * UdpShutdown()
        !           352:  */
        !           353: 
        !           354: static void
        !           355: UdpShutdown(Link l)
        !           356: {
        !           357:     UdpInfo const pi = (UdpInfo) l->info;
        !           358: 
        !           359:     if (pi->conf.fqdn_peer_addr)
        !           360:         Freee(pi->conf.fqdn_peer_addr);
        !           361: 
        !           362:        UdpDoClose(l);
        !           363:        UdpUnListen(l);
        !           364:        Freee(l->info);
        !           365: }
        !           366: 
        !           367: /*
        !           368:  * UdpDoClose()
        !           369:  */
        !           370: 
        !           371: static void
        !           372: UdpDoClose(Link l)
        !           373: {
        !           374:        UdpInfo const pi = (UdpInfo) l->info;
        !           375:        char    path[NG_PATHSIZ];
        !           376:        int     csock;
        !           377: 
        !           378:        if (pi->node_id == 0)
        !           379:                return;
        !           380: 
        !           381:        /* Get a temporary netgraph socket node */
        !           382:        if (NgMkSockNode(NULL, &csock, NULL) == -1) {
        !           383:                Perror("UDP: NgMkSockNode");
        !           384:                return;
        !           385:        }
        !           386:        
        !           387:        /* Disconnect session hook. */
        !           388:        snprintf(path, sizeof(path), "[%lx]:", (u_long)pi->node_id);
        !           389:        NgFuncShutdownNode(csock, l->name, path);
        !           390:        
        !           391:        close(csock);
        !           392:        
        !           393:        pi->node_id = 0;
        !           394: }
        !           395: 
        !           396: /*
        !           397:  * UdpOrigination()
        !           398:  */
        !           399: 
        !           400: static int
        !           401: UdpOrigination(Link l)
        !           402: {
        !           403:     UdpInfo    const pi = (UdpInfo) l->info;
        !           404: 
        !           405:     return (pi->incoming ? LINK_ORIGINATE_REMOTE : LINK_ORIGINATE_LOCAL);
        !           406: }
        !           407: 
        !           408: /*
        !           409:  * UdpIsSync()
        !           410:  */
        !           411: 
        !           412: static int
        !           413: UdpIsSync(Link l)
        !           414: {
        !           415:     return (1);
        !           416: }
        !           417: 
        !           418: static int
        !           419: UdpSelfAddr(Link l, void *buf, size_t buf_len)
        !           420: {
        !           421:     UdpInfo    const pi = (UdpInfo) l->info;
        !           422: 
        !           423:     if (!u_addrempty(&pi->conf.self_addr)) {
        !           424:        if (u_addrtoa(&pi->conf.self_addr, buf, buf_len))
        !           425:            return (0);
        !           426:        else {
        !           427:            ((char*)buf)[0]=0;
        !           428:            return (-1);
        !           429:        }
        !           430:     }
        !           431:     ((char*)buf)[0]=0;
        !           432:     return (0);
        !           433: }
        !           434: 
        !           435: static int
        !           436: UdpPeerAddr(Link l, void *buf, size_t buf_len)
        !           437: {
        !           438:     UdpInfo    const pi = (UdpInfo) l->info;
        !           439: 
        !           440:     if (u_addrtoa(&pi->peer_addr, buf, buf_len))
        !           441:        return(0);
        !           442:     else
        !           443:        return(-1);
        !           444: }
        !           445: 
        !           446: static int
        !           447: UdpPeerPort(Link l, void *buf, size_t buf_len)
        !           448: {
        !           449:     UdpInfo    const pi = (UdpInfo) l->info;
        !           450: 
        !           451:     if (snprintf(buf, buf_len, "%d", pi->peer_port))
        !           452:        return(0);
        !           453:     else
        !           454:        return(-1);
        !           455: }
        !           456: 
        !           457: static int
        !           458: UdpCallingNum(Link l, void *buf, size_t buf_len)
        !           459: {
        !           460:        UdpInfo const pi = (UdpInfo) l->info;
        !           461: 
        !           462:        if (pi->incoming) {
        !           463:            if (u_addrtoa(&pi->peer_addr, buf, buf_len))
        !           464:                return (0);
        !           465:            else
        !           466:                return (-1);
        !           467:        } else {
        !           468:            if (u_addrtoa(&pi->conf.self_addr, buf, buf_len))
        !           469:                return (0);
        !           470:            else
        !           471:                return (-1);
        !           472:        }
        !           473: }
        !           474: 
        !           475: static int
        !           476: UdpCalledNum(Link l, void *buf, size_t buf_len)
        !           477: {
        !           478:        UdpInfo const pi = (UdpInfo) l->info;
        !           479: 
        !           480:        if (!pi->incoming) {
        !           481:            if (u_addrtoa(&pi->peer_addr, buf, buf_len))
        !           482:                return (0);
        !           483:            else
        !           484:                return (-1);
        !           485:        } else {
        !           486:            if (u_addrtoa(&pi->conf.self_addr, buf, buf_len))
        !           487:                return (0);
        !           488:            else
        !           489:                return (-1);
        !           490:        }
        !           491: }
        !           492: 
        !           493: /*
        !           494:  * UdpStat()
        !           495:  */
        !           496: 
        !           497: void
        !           498: UdpStat(Context ctx)
        !           499: {
        !           500:        UdpInfo const pi = (UdpInfo) ctx->lnk->info;
        !           501:        char    buf[48];
        !           502: 
        !           503:        Printf("UDP configuration:\r\n");
        !           504:        Printf("\tPeer FQDN    : %s\r\n", pi->conf.fqdn_peer_addr);
        !           505:        Printf("\tSelf address : %s, port %u\r\n",
        !           506:            u_addrtoa(&pi->conf.self_addr, buf, sizeof(buf)), pi->conf.self_port);
        !           507:        Printf("\tPeer address : %s, port %u\r\n",
        !           508:            u_rangetoa(&pi->conf.peer_addr, buf, sizeof(buf)), pi->conf.peer_port);
        !           509:        Printf("UDP state:\r\n");
        !           510:        if (ctx->lnk->state != PHYS_STATE_DOWN) {
        !           511:            Printf("\tIncoming     : %s\r\n", (pi->incoming?"YES":"NO"));
        !           512:            Printf("\tCurrent peer : %s, port %u\r\n",
        !           513:                u_addrtoa(&pi->peer_addr, buf, sizeof(buf)), pi->peer_port);
        !           514:        }
        !           515: }
        !           516: 
        !           517: /*
        !           518:  * UdpAcceptEvent() triggers when we accept incoming connection.
        !           519:  */
        !           520: 
        !           521: static void
        !           522: UdpAcceptEvent(int type, void *cookie)
        !           523: {
        !           524:        struct sockaddr_storage saddr;
        !           525:        socklen_t       saddrlen;
        !           526:        struct u_addr   addr;
        !           527:        in_port_t       port;
        !           528:        char            buf[48];
        !           529:        char            buf1[48];
        !           530:        int             k;
        !           531:        struct UdpIf    *If=(struct UdpIf *)(cookie);
        !           532:        Link            l = NULL;
        !           533:        UdpInfo         pi = NULL;
        !           534: 
        !           535:        char            pktbuf[UDP_MRU+100];
        !           536:        ssize_t         pktlen;
        !           537: 
        !           538:        assert(type == EVENT_READ);
        !           539: 
        !           540:        saddrlen = sizeof(saddr);
        !           541:        if ((pktlen = recvfrom(If->csock, pktbuf, sizeof(pktbuf), MSG_DONTWAIT, (struct sockaddr *)(&saddr), &saddrlen)) < 0) {
        !           542:            Log(LG_PHYS, ("recvfrom() error: %s", strerror(errno)));
        !           543:        }
        !           544: 
        !           545:        sockaddrtou_addr(&saddr, &addr, &port);
        !           546: 
        !           547:        Log(LG_PHYS, ("Incoming UDP connection from %s %u to %s %u",
        !           548:            u_addrtoa(&addr, buf, sizeof(buf)), port,
        !           549:            u_addrtoa(&If->self_addr, buf1, sizeof(buf1)), If->self_port));
        !           550: 
        !           551:        if (gShutdownInProgress) {
        !           552:                Log(LG_PHYS, ("Shutdown sequence in progress, ignoring request."));
        !           553:                goto failed;
        !           554:        }
        !           555: 
        !           556:        if (OVERLOAD()) {
        !           557:                Log(LG_PHYS, ("Daemon overloaded, ignoring request."));
        !           558:                goto failed;
        !           559:        }
        !           560: 
        !           561:        /* Examine all UDP links. */
        !           562:        for (k = 0; k < gNumLinks; k++) {
        !           563:                Link l2;
        !           564:                UdpInfo pi2;
        !           565: 
        !           566:                if (!gLinks[k] || gLinks[k]->type != &gUdpPhysType)
        !           567:                        continue;
        !           568: 
        !           569:                l2 = gLinks[k];
        !           570:                pi2 = (UdpInfo)l2->info;
        !           571: 
        !           572:                if ((!PhysIsBusy(l2)) &&
        !           573:                    Enabled(&l2->conf.options, LINK_CONF_INCOMING) &&
        !           574:                    (pi2->If == If) &&
        !           575:                    IpAddrInRange(&pi2->conf.peer_addr, &addr) &&
        !           576:                    (pi2->conf.peer_port == 0 || pi2->conf.peer_port == port)) {
        !           577: 
        !           578:                        if (pi == NULL || pi2->conf.peer_addr.width > pi->conf.peer_addr.width) {
        !           579:                                l = l2;
        !           580:                                pi = pi2;
        !           581:                                if (u_rangehost(&pi->conf.peer_addr)) {
        !           582:                                        break;  /* Nothing could be better */
        !           583:                                }
        !           584:                        }
        !           585:                }
        !           586:        }
        !           587:        if (l != NULL && l->tmpl)
        !           588:                l = LinkInst(l, NULL, 0, 0);
        !           589: 
        !           590:        if (l != NULL) {
        !           591:                pi = (UdpInfo)l->info;
        !           592:                Log(LG_PHYS, ("[%s] Accepting UDP connection from %s %u to %s %u",
        !           593:                    l->name, u_addrtoa(&addr, buf, sizeof(buf)), port,
        !           594:                    u_addrtoa(&If->self_addr, buf1, sizeof(buf1)), If->self_port));
        !           595: 
        !           596:                sockaddrtou_addr(&saddr, &pi->peer_addr, &pi->peer_port);
        !           597: 
        !           598:                pi->incoming=1;
        !           599:                l->state = PHYS_STATE_READY;
        !           600: 
        !           601:                PhysIncoming(l);
        !           602:        } else {
        !           603:                Log(LG_PHYS, ("No free UDP link with requested parameters "
        !           604:                    "was found"));
        !           605:        }
        !           606: 
        !           607: failed:
        !           608:        EventRegister(&If->ctrlEvent, EVENT_READ, If->csock,
        !           609:            0, UdpAcceptEvent, If);
        !           610: }
        !           611: 
        !           612: static int 
        !           613: UdpListen(Link l)
        !           614: {
        !           615:        UdpInfo const pi = (UdpInfo) l->info;
        !           616:        struct sockaddr_storage addr;
        !           617:        char buf[48];
        !           618:        int opt, i, j = -1, free = -1;
        !           619:        
        !           620:        if (pi->If)
        !           621:            return(1);
        !           622: 
        !           623:        for (i = 0; i < UDP_MAXPARENTIFS; i++) {
        !           624:            if (UdpIfs[i].self_port == 0)
        !           625:                free = i;
        !           626:            else if ((u_addrcompare(&UdpIfs[i].self_addr, &pi->conf.self_addr) == 0) &&
        !           627:                (UdpIfs[i].self_port == pi->conf.self_port)) {
        !           628:                    j = i;
        !           629:                    break;
        !           630:            }
        !           631:        }
        !           632: 
        !           633:        if (j >= 0) {
        !           634:            UdpIfs[j].refs++;
        !           635:            pi->If=&UdpIfs[j];
        !           636:            return(1);
        !           637:        }
        !           638: 
        !           639:        if (free < 0) {
        !           640:            Log(LG_ERR, ("[%s] UDP: Too many different listening ports! ", 
        !           641:                l->name));
        !           642:            return (0);
        !           643:        }
        !           644: 
        !           645:        UdpIfs[free].refs = 1;
        !           646:        pi->If=&UdpIfs[free];
        !           647:        
        !           648:        u_addrcopy(&pi->conf.self_addr,&pi->If->self_addr);
        !           649:        pi->If->self_port=pi->conf.self_port;
        !           650:        
        !           651:        /* Make listening UDP socket. */
        !           652:        if (pi->If->self_addr.family==AF_INET6) {
        !           653:            pi->If->csock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
        !           654:        } else {
        !           655:            pi->If->csock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
        !           656:        }
        !           657:        (void)fcntl(pi->If->csock, F_SETFD, 1);
        !           658: 
        !           659:        /* Setsockopt socket. */
        !           660:        opt = 1;
        !           661:        if (setsockopt(pi->If->csock, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt))) {
        !           662:                Perror("UDP: can't setsockopt socket");
        !           663:                goto fail2;
        !           664:        };
        !           665: 
        !           666:        /* Bind socket. */
        !           667:        u_addrtosockaddr(&pi->If->self_addr, pi->If->self_port, &addr);
        !           668:        if (bind(pi->If->csock, (struct sockaddr *)(&addr), addr.ss_len)) {
        !           669:                Perror("UDP: can't bind socket");
        !           670:                goto fail2;
        !           671:        }
        !           672: 
        !           673:        Log(LG_PHYS, ("UDP: waiting for connection on %s %u",
        !           674:            u_addrtoa(&pi->If->self_addr, buf, sizeof(buf)), pi->If->self_port));
        !           675:        EventRegister(&pi->If->ctrlEvent, EVENT_READ, pi->If->csock,
        !           676:            0, UdpAcceptEvent, pi->If);
        !           677: 
        !           678:        return (1);
        !           679: fail2:
        !           680:        close(pi->If->csock);
        !           681:        pi->If->csock = -1;
        !           682:        pi->If->self_port = 0;
        !           683:        pi->If = NULL;
        !           684:        return (0);
        !           685: }
        !           686: 
        !           687: 
        !           688: static int 
        !           689: UdpUnListen(Link l)
        !           690: {
        !           691:        UdpInfo const pi = (UdpInfo) l->info;
        !           692:        char buf[48];
        !           693:        
        !           694:        if (!pi->If)
        !           695:            return(1);
        !           696: 
        !           697:        pi->If->refs--;
        !           698:        if (pi->If->refs == 0) {
        !           699:            Log(LG_PHYS, ("UDP: stop waiting for connection on %s %u",
        !           700:                u_addrtoa(&pi->If->self_addr, buf, sizeof(buf)), pi->If->self_port));
        !           701:            EventUnRegister(&pi->If->ctrlEvent);
        !           702:            close(pi->If->csock);
        !           703:            pi->If->csock = -1;
        !           704:            pi->If->self_port = 0;
        !           705:            pi->If = NULL;
        !           706:        }
        !           707: 
        !           708:        return (1);
        !           709: }
        !           710: 
        !           711: /*
        !           712:  * UdpNodeUpdate()
        !           713:  */
        !           714: 
        !           715: static void
        !           716: UdpNodeUpdate(Link l)
        !           717: {
        !           718:     UdpInfo const pi = (UdpInfo) l->info;
        !           719:     if (!pi->If) {
        !           720:        if (Enabled(&l->conf.options, LINK_CONF_INCOMING))
        !           721:            UdpListen(l);
        !           722:     } else {
        !           723:        if (!Enabled(&l->conf.options, LINK_CONF_INCOMING))
        !           724:            UdpUnListen(l);
        !           725:     }
        !           726: }
        !           727: 
        !           728: /*
        !           729:  * UdpSetCommand()
        !           730:  */
        !           731: 
        !           732: static int
        !           733: UdpSetCommand(Context ctx, int ac, char *av[], void *arg)
        !           734: {
        !           735:     UdpInfo            const pi = (UdpInfo) ctx->lnk->info;
        !           736:     char               **fqdn_peer_addr = &pi->conf.fqdn_peer_addr;
        !           737:     struct u_range     rng;
        !           738:     int                        port;
        !           739:        
        !           740:     switch ((intptr_t)arg) {
        !           741:        case SET_PEERADDR:
        !           742:        case SET_SELFADDR:
        !           743:            if ((ac == 1 || ac == 2) && (intptr_t)arg == SET_PEERADDR) {
        !           744:                if (*fqdn_peer_addr)
        !           745:                    Freee(*fqdn_peer_addr);
        !           746:                *fqdn_peer_addr = Mstrdup(MB_PHYS, av[0]);
        !           747:            }
        !           748:            if (ac < 1 || ac > 2 || !ParseRange(av[0], &rng, ALLOW_IPV4|ALLOW_IPV6))
        !           749:                return(-1);
        !           750:            if (ac > 1) {
        !           751:                if ((port = atoi(av[1])) < 0 || port > 0xffff)
        !           752:                    return(-1);
        !           753:            } else {
        !           754:                port = 0;
        !           755:            }
        !           756:            if ((intptr_t)arg == SET_SELFADDR) {
        !           757:                pi->conf.self_addr = rng.addr;
        !           758:                pi->conf.self_port = port;
        !           759:            } else {
        !           760:                pi->conf.peer_addr = rng;
        !           761:                pi->conf.peer_port = port;
        !           762:            }
        !           763:            if (pi->If) {
        !           764:                UdpUnListen(ctx->lnk);
        !           765:                UdpListen(ctx->lnk);
        !           766:            }
        !           767:            break;
        !           768:        case SET_ENABLE:
        !           769:            EnableCommand(ac, av, &pi->conf.options, gConfList);
        !           770:            UdpNodeUpdate(ctx->lnk);
        !           771:            break;
        !           772:        case SET_DISABLE:
        !           773:            DisableCommand(ac, av, &pi->conf.options, gConfList);
        !           774:            UdpNodeUpdate(ctx->lnk);
        !           775:            break;
        !           776:        default:
        !           777:            assert(0);
        !           778:     }
        !           779:     return(0);
        !           780: }
        !           781: 

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