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

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

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