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>