File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mpd / src / udp.c
Revision 1.1.1.3.2.1: download - view: text, annotated - select for diffs - revision graph
Wed Sep 27 11:08:01 2023 UTC (10 months ago) by misho
Branches: v5_9p16
Diff to: branchpoint 1.1.1.3: preferred, unified
Version 5.9p16

    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: #ifndef SMALL_SYSTEM
   35: #define UDP_MAXPARENTIFS	256
   36: #else
   37: #define UDP_MAXPARENTIFS	64
   38: #endif
   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);
   92:   static int	UdpSetCommand(Context ctx, int ac, const char *const av[], const void *arg);
   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 },
  132:     { NULL, NULL, NULL, NULL, 0, NULL },
  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: };
  142: static struct UdpIf UdpIfs[UDP_MAXPARENTIFS];
  143: 
  144:  /*
  145:  * INTERNAL VARIABLES
  146:  */
  147: 
  148:   static const struct confinfo	gConfList[] = {
  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;
  272: 	((int *)(void *)(ksso->value))[0]=1;
  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: {
  358: 	UdpInfo const pi = (UdpInfo) l->info;
  359: 
  360: 	if (pi->conf.fqdn_peer_addr)
  361: 		Freee(pi->conf.fqdn_peer_addr);
  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: {
  416:     (void)l;
  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, socktype(SOCK_DGRAM), IPPROTO_UDP);
  656: 	} else {
  657: 	    pi->If->csock = socket(PF_INET, socktype(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
  735: UdpSetCommand(Context ctx, int ac, const char *const av[], const void *arg)
  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>