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