Annotation of embedaddon/bird2/sysdep/unix/io.c, revision 1.1.1.1
1.1 misho 1: /*
2: * BIRD Internet Routing Daemon -- Unix I/O
3: *
4: * (c) 1998--2004 Martin Mares <mj@ucw.cz>
5: * (c) 2004 Ondrej Filip <feela@network.cz>
6: *
7: * Can be freely distributed and used under the terms of the GNU GPL.
8: */
9:
10: /* Unfortunately, some glibc versions hide parts of RFC 3542 API
11: if _GNU_SOURCE is not defined. */
12: #ifndef _GNU_SOURCE
13: #define _GNU_SOURCE
14: #endif
15:
16: #include <stdio.h>
17: #include <stdlib.h>
18: #include <time.h>
19: #include <sys/time.h>
20: #include <sys/types.h>
21: #include <sys/socket.h>
22: #include <sys/uio.h>
23: #include <sys/un.h>
24: #include <poll.h>
25: #include <unistd.h>
26: #include <fcntl.h>
27: #include <errno.h>
28: #include <net/if.h>
29: #include <netinet/in.h>
30: #include <netinet/tcp.h>
31: #include <netinet/udp.h>
32: #include <netinet/icmp6.h>
33:
34: #include "nest/bird.h"
35: #include "lib/lists.h"
36: #include "lib/resource.h"
37: #include "lib/socket.h"
38: #include "lib/event.h"
39: #include "lib/timer.h"
40: #include "lib/string.h"
41: #include "nest/iface.h"
42: #include "conf/conf.h"
43:
44: #include "sysdep/unix/unix.h"
45: #include CONFIG_INCLUDE_SYSIO_H
46:
47: /* Maximum number of calls of tx handler for one socket in one
48: * poll iteration. Should be small enough to not monopolize CPU by
49: * one protocol instance.
50: */
51: #define MAX_STEPS 4
52:
53: /* Maximum number of calls of rx handler for all sockets in one poll
54: iteration. RX callbacks are often much more costly so we limit
55: this to gen small latencies */
56: #define MAX_RX_STEPS 4
57:
58:
59: /*
60: * Tracked Files
61: */
62:
63: struct rfile {
64: resource r;
65: FILE *f;
66: };
67:
68: static void
69: rf_free(resource *r)
70: {
71: struct rfile *a = (struct rfile *) r;
72:
73: fclose(a->f);
74: }
75:
76: static void
77: rf_dump(resource *r)
78: {
79: struct rfile *a = (struct rfile *) r;
80:
81: debug("(FILE *%p)\n", a->f);
82: }
83:
84: static struct resclass rf_class = {
85: "FILE",
86: sizeof(struct rfile),
87: rf_free,
88: rf_dump,
89: NULL,
90: NULL
91: };
92:
93: struct rfile *
94: rf_open(pool *p, char *name, char *mode)
95: {
96: FILE *f = fopen(name, mode);
97:
98: if (!f)
99: return NULL;
100:
101: struct rfile *r = ralloc(p, &rf_class);
102: r->f = f;
103: return r;
104: }
105:
106: void *
107: rf_file(struct rfile *f)
108: {
109: return f->f;
110: }
111:
112: int
113: rf_fileno(struct rfile *f)
114: {
115: return fileno(f->f);
116: }
117:
118:
119: /*
120: * Time clock
121: */
122:
123: btime boot_time;
124:
125: void
126: times_init(struct timeloop *loop)
127: {
128: struct timespec ts;
129: int rv;
130:
131: rv = clock_gettime(CLOCK_MONOTONIC, &ts);
132: if (rv < 0)
133: die("Monotonic clock is missing");
134:
135: if ((ts.tv_sec < 0) || (((u64) ts.tv_sec) > ((u64) 1 << 40)))
136: log(L_WARN "Monotonic clock is crazy");
137:
138: loop->last_time = ts.tv_sec S + ts.tv_nsec NS;
139: loop->real_time = 0;
140: }
141:
142: void
143: times_update(struct timeloop *loop)
144: {
145: struct timespec ts;
146: int rv;
147:
148: rv = clock_gettime(CLOCK_MONOTONIC, &ts);
149: if (rv < 0)
150: die("clock_gettime: %m");
151:
152: btime new_time = ts.tv_sec S + ts.tv_nsec NS;
153:
154: if (new_time < loop->last_time)
155: log(L_ERR "Monotonic clock is broken");
156:
157: loop->last_time = new_time;
158: loop->real_time = 0;
159: }
160:
161: void
162: times_update_real_time(struct timeloop *loop)
163: {
164: struct timespec ts;
165: int rv;
166:
167: rv = clock_gettime(CLOCK_REALTIME, &ts);
168: if (rv < 0)
169: die("clock_gettime: %m");
170:
171: loop->real_time = ts.tv_sec S + ts.tv_nsec NS;
172: }
173:
174:
175: /**
176: * DOC: Sockets
177: *
178: * Socket resources represent network connections. Their data structure (&socket)
179: * contains a lot of fields defining the exact type of the socket, the local and
180: * remote addresses and ports, pointers to socket buffers and finally pointers to
181: * hook functions to be called when new data have arrived to the receive buffer
182: * (@rx_hook), when the contents of the transmit buffer have been transmitted
183: * (@tx_hook) and when an error or connection close occurs (@err_hook).
184: *
185: * Freeing of sockets from inside socket hooks is perfectly safe.
186: */
187:
188: #ifndef SOL_IP
189: #define SOL_IP IPPROTO_IP
190: #endif
191:
192: #ifndef SOL_IPV6
193: #define SOL_IPV6 IPPROTO_IPV6
194: #endif
195:
196: #ifndef SOL_ICMPV6
197: #define SOL_ICMPV6 IPPROTO_ICMPV6
198: #endif
199:
200:
201: /*
202: * Sockaddr helper functions
203: */
204:
205: static inline int UNUSED sockaddr_length(int af)
206: { return (af == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); }
207:
208: static inline void
209: sockaddr_fill4(struct sockaddr_in *sa, ip_addr a, uint port)
210: {
211: memset(sa, 0, sizeof(struct sockaddr_in));
212: #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
213: sa->sin_len = sizeof(struct sockaddr_in);
214: #endif
215: sa->sin_family = AF_INET;
216: sa->sin_port = htons(port);
217: sa->sin_addr = ipa_to_in4(a);
218: }
219:
220: static inline void
221: sockaddr_fill6(struct sockaddr_in6 *sa, ip_addr a, struct iface *ifa, uint port)
222: {
223: memset(sa, 0, sizeof(struct sockaddr_in6));
224: #ifdef SIN6_LEN
225: sa->sin6_len = sizeof(struct sockaddr_in6);
226: #endif
227: sa->sin6_family = AF_INET6;
228: sa->sin6_port = htons(port);
229: sa->sin6_flowinfo = 0;
230: sa->sin6_addr = ipa_to_in6(a);
231:
232: if (ifa && ipa_is_link_local(a))
233: sa->sin6_scope_id = ifa->index;
234: }
235:
236: void
237: sockaddr_fill(sockaddr *sa, int af, ip_addr a, struct iface *ifa, uint port)
238: {
239: if (af == AF_INET)
240: sockaddr_fill4((struct sockaddr_in *) sa, a, port);
241: else if (af == AF_INET6)
242: sockaddr_fill6((struct sockaddr_in6 *) sa, a, ifa, port);
243: else
244: bug("Unknown AF");
245: }
246:
247: static inline void
248: sockaddr_read4(struct sockaddr_in *sa, ip_addr *a, uint *port)
249: {
250: *port = ntohs(sa->sin_port);
251: *a = ipa_from_in4(sa->sin_addr);
252: }
253:
254: static inline void
255: sockaddr_read6(struct sockaddr_in6 *sa, ip_addr *a, struct iface **ifa, uint *port)
256: {
257: *port = ntohs(sa->sin6_port);
258: *a = ipa_from_in6(sa->sin6_addr);
259:
260: if (ifa && ipa_is_link_local(*a))
261: *ifa = if_find_by_index(sa->sin6_scope_id);
262: }
263:
264: int
265: sockaddr_read(sockaddr *sa, int af, ip_addr *a, struct iface **ifa, uint *port)
266: {
267: if (sa->sa.sa_family != af)
268: goto fail;
269:
270: if (af == AF_INET)
271: sockaddr_read4((struct sockaddr_in *) sa, a, port);
272: else if (af == AF_INET6)
273: sockaddr_read6((struct sockaddr_in6 *) sa, a, ifa, port);
274: else
275: goto fail;
276:
277: return 0;
278:
279: fail:
280: *a = IPA_NONE;
281: *port = 0;
282: return -1;
283: }
284:
285:
286: /*
287: * IPv6 multicast syscalls
288: */
289:
290: /* Fortunately standardized in RFC 3493 */
291:
292: #define INIT_MREQ6(maddr,ifa) \
293: { .ipv6mr_multiaddr = ipa_to_in6(maddr), .ipv6mr_interface = ifa->index }
294:
295: static inline int
296: sk_setup_multicast6(sock *s)
297: {
298: int index = s->iface->index;
299: int ttl = s->ttl;
300: int n = 0;
301:
302: if (setsockopt(s->fd, SOL_IPV6, IPV6_MULTICAST_IF, &index, sizeof(index)) < 0)
303: ERR("IPV6_MULTICAST_IF");
304:
305: if (setsockopt(s->fd, SOL_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)) < 0)
306: ERR("IPV6_MULTICAST_HOPS");
307:
308: if (setsockopt(s->fd, SOL_IPV6, IPV6_MULTICAST_LOOP, &n, sizeof(n)) < 0)
309: ERR("IPV6_MULTICAST_LOOP");
310:
311: return 0;
312: }
313:
314: static inline int
315: sk_join_group6(sock *s, ip_addr maddr)
316: {
317: struct ipv6_mreq mr = INIT_MREQ6(maddr, s->iface);
318:
319: if (setsockopt(s->fd, SOL_IPV6, IPV6_JOIN_GROUP, &mr, sizeof(mr)) < 0)
320: ERR("IPV6_JOIN_GROUP");
321:
322: return 0;
323: }
324:
325: static inline int
326: sk_leave_group6(sock *s, ip_addr maddr)
327: {
328: struct ipv6_mreq mr = INIT_MREQ6(maddr, s->iface);
329:
330: if (setsockopt(s->fd, SOL_IPV6, IPV6_LEAVE_GROUP, &mr, sizeof(mr)) < 0)
331: ERR("IPV6_LEAVE_GROUP");
332:
333: return 0;
334: }
335:
336:
337: /*
338: * IPv6 packet control messages
339: */
340:
341: /* Also standardized, in RFC 3542 */
342:
343: /*
344: * RFC 2292 uses IPV6_PKTINFO for both the socket option and the cmsg
345: * type, RFC 3542 changed the socket option to IPV6_RECVPKTINFO. If we
346: * don't have IPV6_RECVPKTINFO we suppose the OS implements the older
347: * RFC and we use IPV6_PKTINFO.
348: */
349: #ifndef IPV6_RECVPKTINFO
350: #define IPV6_RECVPKTINFO IPV6_PKTINFO
351: #endif
352: /*
353: * Same goes for IPV6_HOPLIMIT -> IPV6_RECVHOPLIMIT.
354: */
355: #ifndef IPV6_RECVHOPLIMIT
356: #define IPV6_RECVHOPLIMIT IPV6_HOPLIMIT
357: #endif
358:
359:
360: #define CMSG6_SPACE_PKTINFO CMSG_SPACE(sizeof(struct in6_pktinfo))
361: #define CMSG6_SPACE_TTL CMSG_SPACE(sizeof(int))
362:
363: static inline int
364: sk_request_cmsg6_pktinfo(sock *s)
365: {
366: int y = 1;
367:
368: if (setsockopt(s->fd, SOL_IPV6, IPV6_RECVPKTINFO, &y, sizeof(y)) < 0)
369: ERR("IPV6_RECVPKTINFO");
370:
371: return 0;
372: }
373:
374: static inline int
375: sk_request_cmsg6_ttl(sock *s)
376: {
377: int y = 1;
378:
379: if (setsockopt(s->fd, SOL_IPV6, IPV6_RECVHOPLIMIT, &y, sizeof(y)) < 0)
380: ERR("IPV6_RECVHOPLIMIT");
381:
382: return 0;
383: }
384:
385: static inline void
386: sk_process_cmsg6_pktinfo(sock *s, struct cmsghdr *cm)
387: {
388: if (cm->cmsg_type == IPV6_PKTINFO)
389: {
390: struct in6_pktinfo *pi = (struct in6_pktinfo *) CMSG_DATA(cm);
391: s->laddr = ipa_from_in6(pi->ipi6_addr);
392: s->lifindex = pi->ipi6_ifindex;
393: }
394: }
395:
396: static inline void
397: sk_process_cmsg6_ttl(sock *s, struct cmsghdr *cm)
398: {
399: if (cm->cmsg_type == IPV6_HOPLIMIT)
400: s->rcv_ttl = * (int *) CMSG_DATA(cm);
401: }
402:
403: static inline void
404: sk_prepare_cmsgs6(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
405: {
406: struct cmsghdr *cm;
407: struct in6_pktinfo *pi;
408: int controllen = 0;
409:
410: msg->msg_control = cbuf;
411: msg->msg_controllen = cbuflen;
412:
413: cm = CMSG_FIRSTHDR(msg);
414: cm->cmsg_level = SOL_IPV6;
415: cm->cmsg_type = IPV6_PKTINFO;
416: cm->cmsg_len = CMSG_LEN(sizeof(*pi));
417: controllen += CMSG_SPACE(sizeof(*pi));
418:
419: pi = (struct in6_pktinfo *) CMSG_DATA(cm);
420: pi->ipi6_ifindex = s->iface ? s->iface->index : 0;
421: pi->ipi6_addr = ipa_to_in6(s->saddr);
422:
423: msg->msg_controllen = controllen;
424: }
425:
426:
427: /*
428: * Miscellaneous socket syscalls
429: */
430:
431: static inline int
432: sk_set_ttl4(sock *s, int ttl)
433: {
434: if (setsockopt(s->fd, SOL_IP, IP_TTL, &ttl, sizeof(ttl)) < 0)
435: ERR("IP_TTL");
436:
437: return 0;
438: }
439:
440: static inline int
441: sk_set_ttl6(sock *s, int ttl)
442: {
443: if (setsockopt(s->fd, SOL_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl)) < 0)
444: ERR("IPV6_UNICAST_HOPS");
445:
446: return 0;
447: }
448:
449: static inline int
450: sk_set_tos4(sock *s, int tos)
451: {
452: if (setsockopt(s->fd, SOL_IP, IP_TOS, &tos, sizeof(tos)) < 0)
453: ERR("IP_TOS");
454:
455: return 0;
456: }
457:
458: static inline int
459: sk_set_tos6(sock *s, int tos)
460: {
461: if (setsockopt(s->fd, SOL_IPV6, IPV6_TCLASS, &tos, sizeof(tos)) < 0)
462: ERR("IPV6_TCLASS");
463:
464: return 0;
465: }
466:
467: static inline int
468: sk_set_high_port(sock *s UNUSED)
469: {
470: /* Port range setting is optional, ignore it if not supported */
471:
472: #ifdef IP_PORTRANGE
473: if (sk_is_ipv4(s))
474: {
475: int range = IP_PORTRANGE_HIGH;
476: if (setsockopt(s->fd, SOL_IP, IP_PORTRANGE, &range, sizeof(range)) < 0)
477: ERR("IP_PORTRANGE");
478: }
479: #endif
480:
481: #ifdef IPV6_PORTRANGE
482: if (sk_is_ipv6(s))
483: {
484: int range = IPV6_PORTRANGE_HIGH;
485: if (setsockopt(s->fd, SOL_IPV6, IPV6_PORTRANGE, &range, sizeof(range)) < 0)
486: ERR("IPV6_PORTRANGE");
487: }
488: #endif
489:
490: return 0;
491: }
492:
493: static inline byte *
494: sk_skip_ip_header(byte *pkt, int *len)
495: {
496: if ((*len < 20) || ((*pkt & 0xf0) != 0x40))
497: return NULL;
498:
499: int hlen = (*pkt & 0x0f) * 4;
500: if ((hlen < 20) || (hlen > *len))
501: return NULL;
502:
503: *len -= hlen;
504: return pkt + hlen;
505: }
506:
507: byte *
508: sk_rx_buffer(sock *s, int *len)
509: {
510: if (sk_is_ipv4(s) && (s->type == SK_IP))
511: return sk_skip_ip_header(s->rbuf, len);
512: else
513: return s->rbuf;
514: }
515:
516:
517: /*
518: * Public socket functions
519: */
520:
521: /**
522: * sk_setup_multicast - enable multicast for given socket
523: * @s: socket
524: *
525: * Prepare transmission of multicast packets for given datagram socket.
526: * The socket must have defined @iface.
527: *
528: * Result: 0 for success, -1 for an error.
529: */
530:
531: int
532: sk_setup_multicast(sock *s)
533: {
534: ASSERT(s->iface);
535:
536: if (sk_is_ipv4(s))
537: return sk_setup_multicast4(s);
538: else
539: return sk_setup_multicast6(s);
540: }
541:
542: /**
543: * sk_join_group - join multicast group for given socket
544: * @s: socket
545: * @maddr: multicast address
546: *
547: * Join multicast group for given datagram socket and associated interface.
548: * The socket must have defined @iface.
549: *
550: * Result: 0 for success, -1 for an error.
551: */
552:
553: int
554: sk_join_group(sock *s, ip_addr maddr)
555: {
556: if (sk_is_ipv4(s))
557: return sk_join_group4(s, maddr);
558: else
559: return sk_join_group6(s, maddr);
560: }
561:
562: /**
563: * sk_leave_group - leave multicast group for given socket
564: * @s: socket
565: * @maddr: multicast address
566: *
567: * Leave multicast group for given datagram socket and associated interface.
568: * The socket must have defined @iface.
569: *
570: * Result: 0 for success, -1 for an error.
571: */
572:
573: int
574: sk_leave_group(sock *s, ip_addr maddr)
575: {
576: if (sk_is_ipv4(s))
577: return sk_leave_group4(s, maddr);
578: else
579: return sk_leave_group6(s, maddr);
580: }
581:
582: /**
583: * sk_setup_broadcast - enable broadcast for given socket
584: * @s: socket
585: *
586: * Allow reception and transmission of broadcast packets for given datagram
587: * socket. The socket must have defined @iface. For transmission, packets should
588: * be send to @brd address of @iface.
589: *
590: * Result: 0 for success, -1 for an error.
591: */
592:
593: int
594: sk_setup_broadcast(sock *s)
595: {
596: int y = 1;
597:
598: if (setsockopt(s->fd, SOL_SOCKET, SO_BROADCAST, &y, sizeof(y)) < 0)
599: ERR("SO_BROADCAST");
600:
601: return 0;
602: }
603:
604: /**
605: * sk_set_ttl - set transmit TTL for given socket
606: * @s: socket
607: * @ttl: TTL value
608: *
609: * Set TTL for already opened connections when TTL was not set before. Useful
610: * for accepted connections when different ones should have different TTL.
611: *
612: * Result: 0 for success, -1 for an error.
613: */
614:
615: int
616: sk_set_ttl(sock *s, int ttl)
617: {
618: s->ttl = ttl;
619:
620: if (sk_is_ipv4(s))
621: return sk_set_ttl4(s, ttl);
622: else
623: return sk_set_ttl6(s, ttl);
624: }
625:
626: /**
627: * sk_set_min_ttl - set minimal accepted TTL for given socket
628: * @s: socket
629: * @ttl: TTL value
630: *
631: * Set minimal accepted TTL for given socket. Can be used for TTL security.
632: * implementations.
633: *
634: * Result: 0 for success, -1 for an error.
635: */
636:
637: int
638: sk_set_min_ttl(sock *s, int ttl)
639: {
640: if (sk_is_ipv4(s))
641: return sk_set_min_ttl4(s, ttl);
642: else
643: return sk_set_min_ttl6(s, ttl);
644: }
645:
646: #if 0
647: /**
648: * sk_set_md5_auth - add / remove MD5 security association for given socket
649: * @s: socket
650: * @local: IP address of local side
651: * @remote: IP address of remote side
652: * @ifa: Interface for link-local IP address
653: * @passwd: Password used for MD5 authentication
654: * @setkey: Update also system SA/SP database
655: *
656: * In TCP MD5 handling code in kernel, there is a set of security associations
657: * used for choosing password and other authentication parameters according to
658: * the local and remote address. This function is useful for listening socket,
659: * for active sockets it may be enough to set s->password field.
660: *
661: * When called with passwd != NULL, the new pair is added,
662: * When called with passwd == NULL, the existing pair is removed.
663: *
664: * Note that while in Linux, the MD5 SAs are specific to socket, in BSD they are
665: * stored in global SA/SP database (but the behavior also must be enabled on
666: * per-socket basis). In case of multiple sockets to the same neighbor, the
667: * socket-specific state must be configured for each socket while global state
668: * just once per src-dst pair. The @setkey argument controls whether the global
669: * state (SA/SP database) is also updated.
670: *
671: * Result: 0 for success, -1 for an error.
672: */
673:
674: int
675: sk_set_md5_auth(sock *s, ip_addr local, ip_addr remote, struct iface *ifa, char *passwd, int setkey)
676: { DUMMY; }
677: #endif
678:
679: /**
680: * sk_set_ipv6_checksum - specify IPv6 checksum offset for given socket
681: * @s: socket
682: * @offset: offset
683: *
684: * Specify IPv6 checksum field offset for given raw IPv6 socket. After that, the
685: * kernel will automatically fill it for outgoing packets and check it for
686: * incoming packets. Should not be used on ICMPv6 sockets, where the position is
687: * known to the kernel.
688: *
689: * Result: 0 for success, -1 for an error.
690: */
691:
692: int
693: sk_set_ipv6_checksum(sock *s, int offset)
694: {
695: if (setsockopt(s->fd, SOL_IPV6, IPV6_CHECKSUM, &offset, sizeof(offset)) < 0)
696: ERR("IPV6_CHECKSUM");
697:
698: return 0;
699: }
700:
701: int
702: sk_set_icmp6_filter(sock *s, int p1, int p2)
703: {
704: /* a bit of lame interface, but it is here only for Radv */
705: struct icmp6_filter f;
706:
707: ICMP6_FILTER_SETBLOCKALL(&f);
708: ICMP6_FILTER_SETPASS(p1, &f);
709: ICMP6_FILTER_SETPASS(p2, &f);
710:
711: if (setsockopt(s->fd, SOL_ICMPV6, ICMP6_FILTER, &f, sizeof(f)) < 0)
712: ERR("ICMP6_FILTER");
713:
714: return 0;
715: }
716:
717: void
718: sk_log_error(sock *s, const char *p)
719: {
720: log(L_ERR "%s: Socket error: %s%#m", p, s->err);
721: }
722:
723:
724: /*
725: * Actual struct birdsock code
726: */
727:
728: static list sock_list;
729: static struct birdsock *current_sock;
730: static struct birdsock *stored_sock;
731:
732: static inline sock *
733: sk_next(sock *s)
734: {
735: if (!s->n.next->next)
736: return NULL;
737: else
738: return SKIP_BACK(sock, n, s->n.next);
739: }
740:
741: static void
742: sk_alloc_bufs(sock *s)
743: {
744: if (!s->rbuf && s->rbsize)
745: s->rbuf = s->rbuf_alloc = xmalloc(s->rbsize);
746: s->rpos = s->rbuf;
747: if (!s->tbuf && s->tbsize)
748: s->tbuf = s->tbuf_alloc = xmalloc(s->tbsize);
749: s->tpos = s->ttx = s->tbuf;
750: }
751:
752: static void
753: sk_free_bufs(sock *s)
754: {
755: if (s->rbuf_alloc)
756: {
757: xfree(s->rbuf_alloc);
758: s->rbuf = s->rbuf_alloc = NULL;
759: }
760: if (s->tbuf_alloc)
761: {
762: xfree(s->tbuf_alloc);
763: s->tbuf = s->tbuf_alloc = NULL;
764: }
765: }
766:
767: #ifdef HAVE_LIBSSH
768: static void
769: sk_ssh_free(sock *s)
770: {
771: struct ssh_sock *ssh = s->ssh;
772:
773: if (s->ssh == NULL)
774: return;
775:
776: s->ssh = NULL;
777:
778: if (ssh->channel)
779: {
780: if (ssh_channel_is_open(ssh->channel))
781: ssh_channel_close(ssh->channel);
782: ssh_channel_free(ssh->channel);
783: ssh->channel = NULL;
784: }
785:
786: if (ssh->session)
787: {
788: ssh_disconnect(ssh->session);
789: ssh_free(ssh->session);
790: ssh->session = NULL;
791: }
792: }
793: #endif
794:
795: static void
796: sk_free(resource *r)
797: {
798: sock *s = (sock *) r;
799:
800: sk_free_bufs(s);
801:
802: #ifdef HAVE_LIBSSH
803: if (s->type == SK_SSH || s->type == SK_SSH_ACTIVE)
804: sk_ssh_free(s);
805: #endif
806:
807: if (s->fd < 0)
808: return;
809:
810: /* FIXME: we should call sk_stop() for SKF_THREAD sockets */
811: if (!(s->flags & SKF_THREAD))
812: {
813: if (s == current_sock)
814: current_sock = sk_next(s);
815: if (s == stored_sock)
816: stored_sock = sk_next(s);
817: rem_node(&s->n);
818: }
819:
820: if (s->type != SK_SSH && s->type != SK_SSH_ACTIVE)
821: close(s->fd);
822:
823: s->fd = -1;
824: }
825:
826: void
827: sk_set_rbsize(sock *s, uint val)
828: {
829: ASSERT(s->rbuf_alloc == s->rbuf);
830:
831: if (s->rbsize == val)
832: return;
833:
834: s->rbsize = val;
835: xfree(s->rbuf_alloc);
836: s->rbuf_alloc = xmalloc(val);
837: s->rpos = s->rbuf = s->rbuf_alloc;
838: }
839:
840: void
841: sk_set_tbsize(sock *s, uint val)
842: {
843: ASSERT(s->tbuf_alloc == s->tbuf);
844:
845: if (s->tbsize == val)
846: return;
847:
848: byte *old_tbuf = s->tbuf;
849:
850: s->tbsize = val;
851: s->tbuf = s->tbuf_alloc = xrealloc(s->tbuf_alloc, val);
852: s->tpos = s->tbuf + (s->tpos - old_tbuf);
853: s->ttx = s->tbuf + (s->ttx - old_tbuf);
854: }
855:
856: void
857: sk_set_tbuf(sock *s, void *tbuf)
858: {
859: s->tbuf = tbuf ?: s->tbuf_alloc;
860: s->ttx = s->tpos = s->tbuf;
861: }
862:
863: void
864: sk_reallocate(sock *s)
865: {
866: sk_free_bufs(s);
867: sk_alloc_bufs(s);
868: }
869:
870: static void
871: sk_dump(resource *r)
872: {
873: sock *s = (sock *) r;
874: static char *sk_type_names[] = { "TCP<", "TCP>", "TCP", "UDP", NULL, "IP", NULL, "MAGIC", "UNIX<", "UNIX", "SSH>", "SSH", "DEL!" };
875:
876: debug("(%s, ud=%p, sa=%I, sp=%d, da=%I, dp=%d, tos=%d, ttl=%d, if=%s)\n",
877: sk_type_names[s->type],
878: s->data,
879: s->saddr,
880: s->sport,
881: s->daddr,
882: s->dport,
883: s->tos,
884: s->ttl,
885: s->iface ? s->iface->name : "none");
886: }
887:
888: static struct resclass sk_class = {
889: "Socket",
890: sizeof(sock),
891: sk_free,
892: sk_dump,
893: NULL,
894: NULL
895: };
896:
897: /**
898: * sk_new - create a socket
899: * @p: pool
900: *
901: * This function creates a new socket resource. If you want to use it,
902: * you need to fill in all the required fields of the structure and
903: * call sk_open() to do the actual opening of the socket.
904: *
905: * The real function name is sock_new(), sk_new() is a macro wrapper
906: * to avoid collision with OpenSSL.
907: */
908: sock *
909: sock_new(pool *p)
910: {
911: sock *s = ralloc(p, &sk_class);
912: s->pool = p;
913: // s->saddr = s->daddr = IPA_NONE;
914: s->tos = s->priority = s->ttl = -1;
915: s->fd = -1;
916: return s;
917: }
918:
919: static int
920: sk_setup(sock *s)
921: {
922: int y = 1;
923: int fd = s->fd;
924:
925: if (s->type == SK_SSH_ACTIVE)
926: return 0;
927:
928: if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
929: ERR("O_NONBLOCK");
930:
931: if (!s->af)
932: return 0;
933:
934: if (ipa_nonzero(s->saddr) && !(s->flags & SKF_BIND))
935: s->flags |= SKF_PKTINFO;
936:
937: #ifdef CONFIG_USE_HDRINCL
938: if (sk_is_ipv4(s) && (s->type == SK_IP) && (s->flags & SKF_PKTINFO))
939: {
940: s->flags &= ~SKF_PKTINFO;
941: s->flags |= SKF_HDRINCL;
942: if (setsockopt(fd, SOL_IP, IP_HDRINCL, &y, sizeof(y)) < 0)
943: ERR("IP_HDRINCL");
944: }
945: #endif
946:
947: if (s->vrf && !s->iface)
948: {
949: /* Bind socket to associated VRF interface.
950: This is Linux-specific, but so is SO_BINDTODEVICE. */
951: #ifdef SO_BINDTODEVICE
952: struct ifreq ifr = {};
953: strcpy(ifr.ifr_name, s->vrf->name);
954: if (setsockopt(s->fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0)
955: ERR("SO_BINDTODEVICE");
956: #endif
957: }
958:
959: if (s->iface)
960: {
961: #ifdef SO_BINDTODEVICE
962: struct ifreq ifr = {};
963: strcpy(ifr.ifr_name, s->iface->name);
964: if (setsockopt(s->fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0)
965: ERR("SO_BINDTODEVICE");
966: #endif
967:
968: #ifdef CONFIG_UNIX_DONTROUTE
969: if (setsockopt(s->fd, SOL_SOCKET, SO_DONTROUTE, &y, sizeof(y)) < 0)
970: ERR("SO_DONTROUTE");
971: #endif
972: }
973:
974: if (sk_is_ipv4(s))
975: {
976: if (s->flags & SKF_LADDR_RX)
977: if (sk_request_cmsg4_pktinfo(s) < 0)
978: return -1;
979:
980: if (s->flags & SKF_TTL_RX)
981: if (sk_request_cmsg4_ttl(s) < 0)
982: return -1;
983:
984: if ((s->type == SK_UDP) || (s->type == SK_IP))
985: if (sk_disable_mtu_disc4(s) < 0)
986: return -1;
987:
988: if (s->ttl >= 0)
989: if (sk_set_ttl4(s, s->ttl) < 0)
990: return -1;
991:
992: if (s->tos >= 0)
993: if (sk_set_tos4(s, s->tos) < 0)
994: return -1;
995: }
996:
997: if (sk_is_ipv6(s))
998: {
999: if ((s->type == SK_TCP_PASSIVE) || (s->type == SK_TCP_ACTIVE) || (s->type == SK_UDP))
1000: if (setsockopt(fd, SOL_IPV6, IPV6_V6ONLY, &y, sizeof(y)) < 0)
1001: ERR("IPV6_V6ONLY");
1002:
1003: if (s->flags & SKF_LADDR_RX)
1004: if (sk_request_cmsg6_pktinfo(s) < 0)
1005: return -1;
1006:
1007: if (s->flags & SKF_TTL_RX)
1008: if (sk_request_cmsg6_ttl(s) < 0)
1009: return -1;
1010:
1011: if ((s->type == SK_UDP) || (s->type == SK_IP))
1012: if (sk_disable_mtu_disc6(s) < 0)
1013: return -1;
1014:
1015: if (s->ttl >= 0)
1016: if (sk_set_ttl6(s, s->ttl) < 0)
1017: return -1;
1018:
1019: if (s->tos >= 0)
1020: if (sk_set_tos6(s, s->tos) < 0)
1021: return -1;
1022: }
1023:
1024: /* Must be after sk_set_tos4() as setting ToS on Linux also mangles priority */
1025: if (s->priority >= 0)
1026: if (sk_set_priority(s, s->priority) < 0)
1027: return -1;
1028:
1029: return 0;
1030: }
1031:
1032: static void
1033: sk_insert(sock *s)
1034: {
1035: add_tail(&sock_list, &s->n);
1036: }
1037:
1038: static void
1039: sk_tcp_connected(sock *s)
1040: {
1041: sockaddr sa;
1042: int sa_len = sizeof(sa);
1043:
1044: if ((getsockname(s->fd, &sa.sa, &sa_len) < 0) ||
1045: (sockaddr_read(&sa, s->af, &s->saddr, &s->iface, &s->sport) < 0))
1046: log(L_WARN "SOCK: Cannot get local IP address for TCP>");
1047:
1048: s->type = SK_TCP;
1049: sk_alloc_bufs(s);
1050: s->tx_hook(s);
1051: }
1052:
1053: #ifdef HAVE_LIBSSH
1054: static void
1055: sk_ssh_connected(sock *s)
1056: {
1057: sk_alloc_bufs(s);
1058: s->type = SK_SSH;
1059: s->tx_hook(s);
1060: }
1061: #endif
1062:
1063: static int
1064: sk_passive_connected(sock *s, int type)
1065: {
1066: sockaddr loc_sa, rem_sa;
1067: int loc_sa_len = sizeof(loc_sa);
1068: int rem_sa_len = sizeof(rem_sa);
1069:
1070: int fd = accept(s->fd, ((type == SK_TCP) ? &rem_sa.sa : NULL), &rem_sa_len);
1071: if (fd < 0)
1072: {
1073: if ((errno != EINTR) && (errno != EAGAIN))
1074: s->err_hook(s, errno);
1075: return 0;
1076: }
1077:
1078: sock *t = sk_new(s->pool);
1079: t->type = type;
1080: t->data = s->data;
1081: t->af = s->af;
1082: t->fd = fd;
1083: t->ttl = s->ttl;
1084: t->tos = s->tos;
1085: t->vrf = s->vrf;
1086: t->rbsize = s->rbsize;
1087: t->tbsize = s->tbsize;
1088:
1089: if (type == SK_TCP)
1090: {
1091: if ((getsockname(fd, &loc_sa.sa, &loc_sa_len) < 0) ||
1092: (sockaddr_read(&loc_sa, s->af, &t->saddr, &t->iface, &t->sport) < 0))
1093: log(L_WARN "SOCK: Cannot get local IP address for TCP<");
1094:
1095: if (sockaddr_read(&rem_sa, s->af, &t->daddr, &t->iface, &t->dport) < 0)
1096: log(L_WARN "SOCK: Cannot get remote IP address for TCP<");
1097: }
1098:
1099: if (sk_setup(t) < 0)
1100: {
1101: /* FIXME: Call err_hook instead ? */
1102: log(L_ERR "SOCK: Incoming connection: %s%#m", t->err);
1103:
1104: /* FIXME: handle it better in rfree() */
1105: close(t->fd);
1106: t->fd = -1;
1107: rfree(t);
1108: return 1;
1109: }
1110:
1111: sk_insert(t);
1112: sk_alloc_bufs(t);
1113: s->rx_hook(t, 0);
1114: return 1;
1115: }
1116:
1117: #ifdef HAVE_LIBSSH
1118: /*
1119: * Return SSH_OK or SSH_AGAIN or SSH_ERROR
1120: */
1121: static int
1122: sk_ssh_connect(sock *s)
1123: {
1124: s->fd = ssh_get_fd(s->ssh->session);
1125:
1126: /* Big fall thru automata */
1127: switch (s->ssh->state)
1128: {
1129: case SK_SSH_CONNECT:
1130: {
1131: switch (ssh_connect(s->ssh->session))
1132: {
1133: case SSH_AGAIN:
1134: /* A quick look into libSSH shows that ssh_get_fd() should return non-(-1)
1135: * after SSH_AGAIN is returned by ssh_connect(). This is however nowhere
1136: * documented but our code relies on that.
1137: */
1138: return SSH_AGAIN;
1139:
1140: case SSH_OK:
1141: break;
1142:
1143: default:
1144: return SSH_ERROR;
1145: }
1146: } /* fallthrough */
1147:
1148: case SK_SSH_SERVER_KNOWN:
1149: {
1150: s->ssh->state = SK_SSH_SERVER_KNOWN;
1151:
1152: if (s->ssh->server_hostkey_path)
1153: {
1154: int server_identity_is_ok = 1;
1155:
1156: /* Check server identity */
1157: switch (ssh_is_server_known(s->ssh->session))
1158: {
1159: #define LOG_WARN_ABOUT_SSH_SERVER_VALIDATION(s,msg,args...) log(L_WARN "SSH Identity %s@%s:%u: " msg, (s)->ssh->username, (s)->host, (s)->dport, ## args);
1160: case SSH_SERVER_KNOWN_OK:
1161: /* The server is known and has not changed. */
1162: break;
1163:
1164: case SSH_SERVER_NOT_KNOWN:
1165: LOG_WARN_ABOUT_SSH_SERVER_VALIDATION(s, "The server is unknown, its public key was not found in the known host file %s", s->ssh->server_hostkey_path);
1166: break;
1167:
1168: case SSH_SERVER_KNOWN_CHANGED:
1169: LOG_WARN_ABOUT_SSH_SERVER_VALIDATION(s, "The server key has changed. Either you are under attack or the administrator changed the key.");
1170: server_identity_is_ok = 0;
1171: break;
1172:
1173: case SSH_SERVER_FILE_NOT_FOUND:
1174: LOG_WARN_ABOUT_SSH_SERVER_VALIDATION(s, "The known host file %s does not exist", s->ssh->server_hostkey_path);
1175: server_identity_is_ok = 0;
1176: break;
1177:
1178: case SSH_SERVER_ERROR:
1179: LOG_WARN_ABOUT_SSH_SERVER_VALIDATION(s, "Some error happened");
1180: server_identity_is_ok = 0;
1181: break;
1182:
1183: case SSH_SERVER_FOUND_OTHER:
1184: LOG_WARN_ABOUT_SSH_SERVER_VALIDATION(s, "The server gave use a key of a type while we had an other type recorded. " \
1185: "It is a possible attack.");
1186: server_identity_is_ok = 0;
1187: break;
1188: }
1189:
1190: if (!server_identity_is_ok)
1191: return SSH_ERROR;
1192: }
1193: } /* fallthrough */
1194:
1195: case SK_SSH_USERAUTH:
1196: {
1197: s->ssh->state = SK_SSH_USERAUTH;
1198: switch (ssh_userauth_publickey_auto(s->ssh->session, NULL, NULL))
1199: {
1200: case SSH_AUTH_AGAIN:
1201: return SSH_AGAIN;
1202:
1203: case SSH_AUTH_SUCCESS:
1204: break;
1205:
1206: default:
1207: return SSH_ERROR;
1208: }
1209: } /* fallthrough */
1210:
1211: case SK_SSH_CHANNEL:
1212: {
1213: s->ssh->state = SK_SSH_CHANNEL;
1214: s->ssh->channel = ssh_channel_new(s->ssh->session);
1215: if (s->ssh->channel == NULL)
1216: return SSH_ERROR;
1217: } /* fallthrough */
1218:
1219: case SK_SSH_SESSION:
1220: {
1221: s->ssh->state = SK_SSH_SESSION;
1222: switch (ssh_channel_open_session(s->ssh->channel))
1223: {
1224: case SSH_AGAIN:
1225: return SSH_AGAIN;
1226:
1227: case SSH_OK:
1228: break;
1229:
1230: default:
1231: return SSH_ERROR;
1232: }
1233: } /* fallthrough */
1234:
1235: case SK_SSH_SUBSYSTEM:
1236: {
1237: s->ssh->state = SK_SSH_SUBSYSTEM;
1238: if (s->ssh->subsystem)
1239: {
1240: switch (ssh_channel_request_subsystem(s->ssh->channel, s->ssh->subsystem))
1241: {
1242: case SSH_AGAIN:
1243: return SSH_AGAIN;
1244:
1245: case SSH_OK:
1246: break;
1247:
1248: default:
1249: return SSH_ERROR;
1250: }
1251: }
1252: } /* fallthrough */
1253:
1254: case SK_SSH_ESTABLISHED:
1255: s->ssh->state = SK_SSH_ESTABLISHED;
1256: }
1257:
1258: return SSH_OK;
1259: }
1260:
1261: /*
1262: * Return file descriptor number if success
1263: * Return -1 if failed
1264: */
1265: static int
1266: sk_open_ssh(sock *s)
1267: {
1268: if (!s->ssh)
1269: bug("sk_open() sock->ssh is not allocated");
1270:
1271: ssh_session sess = ssh_new();
1272: if (sess == NULL)
1273: ERR2("Cannot create a ssh session");
1274: s->ssh->session = sess;
1275:
1276: const int verbosity = SSH_LOG_NOLOG;
1277: ssh_options_set(sess, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
1278: ssh_options_set(sess, SSH_OPTIONS_HOST, s->host);
1279: ssh_options_set(sess, SSH_OPTIONS_PORT, &(s->dport));
1280: /* TODO: Add SSH_OPTIONS_BINDADDR */
1281: ssh_options_set(sess, SSH_OPTIONS_USER, s->ssh->username);
1282:
1283: if (s->ssh->server_hostkey_path)
1284: ssh_options_set(sess, SSH_OPTIONS_KNOWNHOSTS, s->ssh->server_hostkey_path);
1285:
1286: if (s->ssh->client_privkey_path)
1287: ssh_options_set(sess, SSH_OPTIONS_IDENTITY, s->ssh->client_privkey_path);
1288:
1289: ssh_set_blocking(sess, 0);
1290:
1291: switch (sk_ssh_connect(s))
1292: {
1293: case SSH_AGAIN:
1294: break;
1295:
1296: case SSH_OK:
1297: sk_ssh_connected(s);
1298: break;
1299:
1300: case SSH_ERROR:
1301: ERR2(ssh_get_error(sess));
1302: break;
1303: }
1304:
1305: return ssh_get_fd(sess);
1306:
1307: err:
1308: return -1;
1309: }
1310: #endif
1311:
1312: /**
1313: * sk_open - open a socket
1314: * @s: socket
1315: *
1316: * This function takes a socket resource created by sk_new() and
1317: * initialized by the user and binds a corresponding network connection
1318: * to it.
1319: *
1320: * Result: 0 for success, -1 for an error.
1321: */
1322: int
1323: sk_open(sock *s)
1324: {
1325: int af = AF_UNSPEC;
1326: int fd = -1;
1327: int do_bind = 0;
1328: int bind_port = 0;
1329: ip_addr bind_addr = IPA_NONE;
1330: sockaddr sa;
1331:
1332: if (s->type <= SK_IP)
1333: {
1334: /*
1335: * For TCP/IP sockets, Address family (IPv4 or IPv6) can be specified either
1336: * explicitly (SK_IPV4 or SK_IPV6) or implicitly (based on saddr, daddr).
1337: * But the specifications have to be consistent.
1338: */
1339:
1340: switch (s->subtype)
1341: {
1342: case 0:
1343: ASSERT(ipa_zero(s->saddr) || ipa_zero(s->daddr) ||
1344: (ipa_is_ip4(s->saddr) == ipa_is_ip4(s->daddr)));
1345: af = (ipa_is_ip4(s->saddr) || ipa_is_ip4(s->daddr)) ? AF_INET : AF_INET6;
1346: break;
1347:
1348: case SK_IPV4:
1349: ASSERT(ipa_zero(s->saddr) || ipa_is_ip4(s->saddr));
1350: ASSERT(ipa_zero(s->daddr) || ipa_is_ip4(s->daddr));
1351: af = AF_INET;
1352: break;
1353:
1354: case SK_IPV6:
1355: ASSERT(ipa_zero(s->saddr) || !ipa_is_ip4(s->saddr));
1356: ASSERT(ipa_zero(s->daddr) || !ipa_is_ip4(s->daddr));
1357: af = AF_INET6;
1358: break;
1359:
1360: default:
1361: bug("Invalid subtype %d", s->subtype);
1362: }
1363: }
1364:
1365: switch (s->type)
1366: {
1367: case SK_TCP_ACTIVE:
1368: s->ttx = ""; /* Force s->ttx != s->tpos */
1369: /* Fall thru */
1370: case SK_TCP_PASSIVE:
1371: fd = socket(af, SOCK_STREAM, IPPROTO_TCP);
1372: bind_port = s->sport;
1373: bind_addr = s->saddr;
1374: do_bind = bind_port || ipa_nonzero(bind_addr);
1375: break;
1376:
1377: #ifdef HAVE_LIBSSH
1378: case SK_SSH_ACTIVE:
1379: s->ttx = ""; /* Force s->ttx != s->tpos */
1380: fd = sk_open_ssh(s);
1381: break;
1382: #endif
1383:
1384: case SK_UDP:
1385: fd = socket(af, SOCK_DGRAM, IPPROTO_UDP);
1386: bind_port = s->sport;
1387: bind_addr = (s->flags & SKF_BIND) ? s->saddr : IPA_NONE;
1388: do_bind = 1;
1389: break;
1390:
1391: case SK_IP:
1392: fd = socket(af, SOCK_RAW, s->dport);
1393: bind_port = 0;
1394: bind_addr = (s->flags & SKF_BIND) ? s->saddr : IPA_NONE;
1395: do_bind = ipa_nonzero(bind_addr);
1396: break;
1397:
1398: case SK_MAGIC:
1399: af = 0;
1400: fd = s->fd;
1401: break;
1402:
1403: default:
1404: bug("sk_open() called for invalid sock type %d", s->type);
1405: }
1406:
1407: if (fd < 0)
1408: ERR("socket");
1409:
1410: s->af = af;
1411: s->fd = fd;
1412:
1413: if (sk_setup(s) < 0)
1414: goto err;
1415:
1416: if (do_bind)
1417: {
1418: if (bind_port)
1419: {
1420: int y = 1;
1421:
1422: if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &y, sizeof(y)) < 0)
1423: ERR2("SO_REUSEADDR");
1424:
1425: #ifdef CONFIG_NO_IFACE_BIND
1426: /* Workaround missing ability to bind to an iface */
1427: if ((s->type == SK_UDP) && s->iface && ipa_zero(bind_addr))
1428: {
1429: if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &y, sizeof(y)) < 0)
1430: ERR2("SO_REUSEPORT");
1431: }
1432: #endif
1433: }
1434: else
1435: if (s->flags & SKF_HIGH_PORT)
1436: if (sk_set_high_port(s) < 0)
1437: log(L_WARN "Socket error: %s%#m", s->err);
1438:
1439: sockaddr_fill(&sa, s->af, bind_addr, s->iface, bind_port);
1440: if (bind(fd, &sa.sa, SA_LEN(sa)) < 0)
1441: ERR2("bind");
1442: }
1443:
1444: if (s->password)
1445: if (sk_set_md5_auth(s, s->saddr, s->daddr, s->iface, s->password, 0) < 0)
1446: goto err;
1447:
1448: switch (s->type)
1449: {
1450: case SK_TCP_ACTIVE:
1451: sockaddr_fill(&sa, s->af, s->daddr, s->iface, s->dport);
1452: if (connect(fd, &sa.sa, SA_LEN(sa)) >= 0)
1453: sk_tcp_connected(s);
1454: else if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS &&
1455: errno != ECONNREFUSED && errno != EHOSTUNREACH && errno != ENETUNREACH)
1456: ERR2("connect");
1457: break;
1458:
1459: case SK_TCP_PASSIVE:
1460: if (listen(fd, 8) < 0)
1461: ERR2("listen");
1462: break;
1463:
1464: case SK_SSH_ACTIVE:
1465: case SK_MAGIC:
1466: break;
1467:
1468: default:
1469: sk_alloc_bufs(s);
1470: }
1471:
1472: if (!(s->flags & SKF_THREAD))
1473: sk_insert(s);
1474:
1475: return 0;
1476:
1477: err:
1478: close(fd);
1479: s->fd = -1;
1480: return -1;
1481: }
1482:
1483: int
1484: sk_open_unix(sock *s, char *name)
1485: {
1486: struct sockaddr_un sa;
1487: int fd;
1488:
1489: /* We are sloppy during error (leak fd and not set s->err), but we die anyway */
1490:
1491: fd = socket(AF_UNIX, SOCK_STREAM, 0);
1492: if (fd < 0)
1493: return -1;
1494:
1495: if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
1496: return -1;
1497:
1498: /* Path length checked in test_old_bird() */
1499: sa.sun_family = AF_UNIX;
1500: strcpy(sa.sun_path, name);
1501:
1502: if (bind(fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) < 0)
1503: return -1;
1504:
1505: if (listen(fd, 8) < 0)
1506: return -1;
1507:
1508: s->fd = fd;
1509: sk_insert(s);
1510: return 0;
1511: }
1512:
1513:
1514: #define CMSG_RX_SPACE MAX(CMSG4_SPACE_PKTINFO+CMSG4_SPACE_TTL, \
1515: CMSG6_SPACE_PKTINFO+CMSG6_SPACE_TTL)
1516: #define CMSG_TX_SPACE MAX(CMSG4_SPACE_PKTINFO,CMSG6_SPACE_PKTINFO)
1517:
1518: static void
1519: sk_prepare_cmsgs(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
1520: {
1521: if (sk_is_ipv4(s))
1522: sk_prepare_cmsgs4(s, msg, cbuf, cbuflen);
1523: else
1524: sk_prepare_cmsgs6(s, msg, cbuf, cbuflen);
1525: }
1526:
1527: static void
1528: sk_process_cmsgs(sock *s, struct msghdr *msg)
1529: {
1530: struct cmsghdr *cm;
1531:
1532: s->laddr = IPA_NONE;
1533: s->lifindex = 0;
1534: s->rcv_ttl = -1;
1535:
1536: for (cm = CMSG_FIRSTHDR(msg); cm != NULL; cm = CMSG_NXTHDR(msg, cm))
1537: {
1538: if ((cm->cmsg_level == SOL_IP) && sk_is_ipv4(s))
1539: {
1540: sk_process_cmsg4_pktinfo(s, cm);
1541: sk_process_cmsg4_ttl(s, cm);
1542: }
1543:
1544: if ((cm->cmsg_level == SOL_IPV6) && sk_is_ipv6(s))
1545: {
1546: sk_process_cmsg6_pktinfo(s, cm);
1547: sk_process_cmsg6_ttl(s, cm);
1548: }
1549: }
1550: }
1551:
1552:
1553: static inline int
1554: sk_sendmsg(sock *s)
1555: {
1556: struct iovec iov = {s->tbuf, s->tpos - s->tbuf};
1557: byte cmsg_buf[CMSG_TX_SPACE];
1558: sockaddr dst;
1559: int flags = 0;
1560:
1561: sockaddr_fill(&dst, s->af, s->daddr, s->iface, s->dport);
1562:
1563: struct msghdr msg = {
1564: .msg_name = &dst.sa,
1565: .msg_namelen = SA_LEN(dst),
1566: .msg_iov = &iov,
1567: .msg_iovlen = 1
1568: };
1569:
1570: #ifdef CONFIG_DONTROUTE_UNICAST
1571: /* FreeBSD silently changes TTL to 1 when MSG_DONTROUTE is used, therefore we
1572: cannot use it for other cases (e.g. when TTL security is used). */
1573: if (ipa_is_ip4(s->daddr) && ip4_is_unicast(ipa_to_ip4(s->daddr)) && (s->ttl == 1))
1574: flags = MSG_DONTROUTE;
1575: #endif
1576:
1577: #ifdef CONFIG_USE_HDRINCL
1578: byte hdr[20];
1579: struct iovec iov2[2] = { {hdr, 20}, iov };
1580:
1581: if (s->flags & SKF_HDRINCL)
1582: {
1583: sk_prepare_ip_header(s, hdr, iov.iov_len);
1584: msg.msg_iov = iov2;
1585: msg.msg_iovlen = 2;
1586: }
1587: #endif
1588:
1589: if (s->flags & SKF_PKTINFO)
1590: sk_prepare_cmsgs(s, &msg, cmsg_buf, sizeof(cmsg_buf));
1591:
1592: return sendmsg(s->fd, &msg, flags);
1593: }
1594:
1595: static inline int
1596: sk_recvmsg(sock *s)
1597: {
1598: struct iovec iov = {s->rbuf, s->rbsize};
1599: byte cmsg_buf[CMSG_RX_SPACE];
1600: sockaddr src;
1601:
1602: struct msghdr msg = {
1603: .msg_name = &src.sa,
1604: .msg_namelen = sizeof(src), // XXXX ??
1605: .msg_iov = &iov,
1606: .msg_iovlen = 1,
1607: .msg_control = cmsg_buf,
1608: .msg_controllen = sizeof(cmsg_buf),
1609: .msg_flags = 0
1610: };
1611:
1612: int rv = recvmsg(s->fd, &msg, 0);
1613: if (rv < 0)
1614: return rv;
1615:
1616: //ifdef IPV4
1617: // if (cf_type == SK_IP)
1618: // rv = ipv4_skip_header(pbuf, rv);
1619: //endif
1620:
1621: sockaddr_read(&src, s->af, &s->faddr, NULL, &s->fport);
1622: sk_process_cmsgs(s, &msg);
1623:
1624: if (msg.msg_flags & MSG_TRUNC)
1625: s->flags |= SKF_TRUNCATED;
1626: else
1627: s->flags &= ~SKF_TRUNCATED;
1628:
1629: return rv;
1630: }
1631:
1632:
1633: static inline void reset_tx_buffer(sock *s) { s->ttx = s->tpos = s->tbuf; }
1634:
1635: static int
1636: sk_maybe_write(sock *s)
1637: {
1638: int e;
1639:
1640: switch (s->type)
1641: {
1642: case SK_TCP:
1643: case SK_MAGIC:
1644: case SK_UNIX:
1645: while (s->ttx != s->tpos)
1646: {
1647: e = write(s->fd, s->ttx, s->tpos - s->ttx);
1648:
1649: if (e < 0)
1650: {
1651: if (errno != EINTR && errno != EAGAIN)
1652: {
1653: reset_tx_buffer(s);
1654: /* EPIPE is just a connection close notification during TX */
1655: s->err_hook(s, (errno != EPIPE) ? errno : 0);
1656: return -1;
1657: }
1658: return 0;
1659: }
1660: s->ttx += e;
1661: }
1662: reset_tx_buffer(s);
1663: return 1;
1664:
1665: #ifdef HAVE_LIBSSH
1666: case SK_SSH:
1667: while (s->ttx != s->tpos)
1668: {
1669: e = ssh_channel_write(s->ssh->channel, s->ttx, s->tpos - s->ttx);
1670:
1671: if (e < 0)
1672: {
1673: s->err = ssh_get_error(s->ssh->session);
1674: s->err_hook(s, ssh_get_error_code(s->ssh->session));
1675:
1676: reset_tx_buffer(s);
1677: /* EPIPE is just a connection close notification during TX */
1678: s->err_hook(s, (errno != EPIPE) ? errno : 0);
1679: return -1;
1680: }
1681: s->ttx += e;
1682: }
1683: reset_tx_buffer(s);
1684: return 1;
1685: #endif
1686:
1687: case SK_UDP:
1688: case SK_IP:
1689: {
1690: if (s->tbuf == s->tpos)
1691: return 1;
1692:
1693: e = sk_sendmsg(s);
1694:
1695: if (e < 0)
1696: {
1697: if (errno != EINTR && errno != EAGAIN)
1698: {
1699: reset_tx_buffer(s);
1700: s->err_hook(s, errno);
1701: return -1;
1702: }
1703:
1704: if (!s->tx_hook)
1705: reset_tx_buffer(s);
1706: return 0;
1707: }
1708: reset_tx_buffer(s);
1709: return 1;
1710: }
1711:
1712: default:
1713: bug("sk_maybe_write: unknown socket type %d", s->type);
1714: }
1715: }
1716:
1717: int
1718: sk_rx_ready(sock *s)
1719: {
1720: int rv;
1721: struct pollfd pfd = { .fd = s->fd };
1722: pfd.events |= POLLIN;
1723:
1724: redo:
1725: rv = poll(&pfd, 1, 0);
1726:
1727: if ((rv < 0) && (errno == EINTR || errno == EAGAIN))
1728: goto redo;
1729:
1730: return rv;
1731: }
1732:
1733: /**
1734: * sk_send - send data to a socket
1735: * @s: socket
1736: * @len: number of bytes to send
1737: *
1738: * This function sends @len bytes of data prepared in the
1739: * transmit buffer of the socket @s to the network connection.
1740: * If the packet can be sent immediately, it does so and returns
1741: * 1, else it queues the packet for later processing, returns 0
1742: * and calls the @tx_hook of the socket when the tranmission
1743: * takes place.
1744: */
1745: int
1746: sk_send(sock *s, unsigned len)
1747: {
1748: s->ttx = s->tbuf;
1749: s->tpos = s->tbuf + len;
1750: return sk_maybe_write(s);
1751: }
1752:
1753: /**
1754: * sk_send_to - send data to a specific destination
1755: * @s: socket
1756: * @len: number of bytes to send
1757: * @addr: IP address to send the packet to
1758: * @port: port to send the packet to
1759: *
1760: * This is a sk_send() replacement for connection-less packet sockets
1761: * which allows destination of the packet to be chosen dynamically.
1762: * Raw IP sockets should use 0 for @port.
1763: */
1764: int
1765: sk_send_to(sock *s, unsigned len, ip_addr addr, unsigned port)
1766: {
1767: s->daddr = addr;
1768: if (port)
1769: s->dport = port;
1770:
1771: s->ttx = s->tbuf;
1772: s->tpos = s->tbuf + len;
1773: return sk_maybe_write(s);
1774: }
1775:
1776: /*
1777: int
1778: sk_send_full(sock *s, unsigned len, struct iface *ifa,
1779: ip_addr saddr, ip_addr daddr, unsigned dport)
1780: {
1781: s->iface = ifa;
1782: s->saddr = saddr;
1783: s->daddr = daddr;
1784: s->dport = dport;
1785: s->ttx = s->tbuf;
1786: s->tpos = s->tbuf + len;
1787: return sk_maybe_write(s);
1788: }
1789: */
1790:
1791: static void
1792: call_rx_hook(sock *s, int size)
1793: {
1794: if (s->rx_hook(s, size))
1795: {
1796: /* We need to be careful since the socket could have been deleted by the hook */
1797: if (current_sock == s)
1798: s->rpos = s->rbuf;
1799: }
1800: }
1801:
1802: #ifdef HAVE_LIBSSH
1803: static int
1804: sk_read_ssh(sock *s)
1805: {
1806: ssh_channel rchans[2] = { s->ssh->channel, NULL };
1807: struct timeval timev = { 1, 0 };
1808:
1809: if (ssh_channel_select(rchans, NULL, NULL, &timev) == SSH_EINTR)
1810: return 1; /* Try again */
1811:
1812: if (ssh_channel_is_eof(s->ssh->channel) != 0)
1813: {
1814: /* The remote side is closing the connection */
1815: s->err_hook(s, 0);
1816: return 0;
1817: }
1818:
1819: if (rchans[0] == NULL)
1820: return 0; /* No data is available on the socket */
1821:
1822: const uint used_bytes = s->rpos - s->rbuf;
1823: const int read_bytes = ssh_channel_read_nonblocking(s->ssh->channel, s->rpos, s->rbsize - used_bytes, 0);
1824: if (read_bytes > 0)
1825: {
1826: /* Received data */
1827: s->rpos += read_bytes;
1828: call_rx_hook(s, used_bytes + read_bytes);
1829: return 1;
1830: }
1831: else if (read_bytes == 0)
1832: {
1833: if (ssh_channel_is_eof(s->ssh->channel) != 0)
1834: {
1835: /* The remote side is closing the connection */
1836: s->err_hook(s, 0);
1837: }
1838: }
1839: else
1840: {
1841: s->err = ssh_get_error(s->ssh->session);
1842: s->err_hook(s, ssh_get_error_code(s->ssh->session));
1843: }
1844:
1845: return 0; /* No data is available on the socket */
1846: }
1847: #endif
1848:
1849: /* sk_read() and sk_write() are called from BFD's event loop */
1850:
1851: int
1852: sk_read(sock *s, int revents)
1853: {
1854: switch (s->type)
1855: {
1856: case SK_TCP_PASSIVE:
1857: return sk_passive_connected(s, SK_TCP);
1858:
1859: case SK_UNIX_PASSIVE:
1860: return sk_passive_connected(s, SK_UNIX);
1861:
1862: case SK_TCP:
1863: case SK_UNIX:
1864: {
1865: int c = read(s->fd, s->rpos, s->rbuf + s->rbsize - s->rpos);
1866:
1867: if (c < 0)
1868: {
1869: if (errno != EINTR && errno != EAGAIN)
1870: s->err_hook(s, errno);
1871: else if (errno == EAGAIN && !(revents & POLLIN))
1872: {
1873: log(L_ERR "Got EAGAIN from read when revents=%x (without POLLIN)", revents);
1874: s->err_hook(s, 0);
1875: }
1876: }
1877: else if (!c)
1878: s->err_hook(s, 0);
1879: else
1880: {
1881: s->rpos += c;
1882: call_rx_hook(s, s->rpos - s->rbuf);
1883: return 1;
1884: }
1885: return 0;
1886: }
1887:
1888: #ifdef HAVE_LIBSSH
1889: case SK_SSH:
1890: return sk_read_ssh(s);
1891: #endif
1892:
1893: case SK_MAGIC:
1894: return s->rx_hook(s, 0);
1895:
1896: default:
1897: {
1898: int e = sk_recvmsg(s);
1899:
1900: if (e < 0)
1901: {
1902: if (errno != EINTR && errno != EAGAIN)
1903: s->err_hook(s, errno);
1904: return 0;
1905: }
1906:
1907: s->rpos = s->rbuf + e;
1908: s->rx_hook(s, e);
1909: return 1;
1910: }
1911: }
1912: }
1913:
1914: int
1915: sk_write(sock *s)
1916: {
1917: switch (s->type)
1918: {
1919: case SK_TCP_ACTIVE:
1920: {
1921: sockaddr sa;
1922: sockaddr_fill(&sa, s->af, s->daddr, s->iface, s->dport);
1923:
1924: if (connect(s->fd, &sa.sa, SA_LEN(sa)) >= 0 || errno == EISCONN)
1925: sk_tcp_connected(s);
1926: else if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS)
1927: s->err_hook(s, errno);
1928: return 0;
1929: }
1930:
1931: #ifdef HAVE_LIBSSH
1932: case SK_SSH_ACTIVE:
1933: {
1934: switch (sk_ssh_connect(s))
1935: {
1936: case SSH_OK:
1937: sk_ssh_connected(s);
1938: break;
1939:
1940: case SSH_AGAIN:
1941: return 1;
1942:
1943: case SSH_ERROR:
1944: s->err = ssh_get_error(s->ssh->session);
1945: s->err_hook(s, ssh_get_error_code(s->ssh->session));
1946: break;
1947: }
1948: return 0;
1949: }
1950: #endif
1951:
1952: default:
1953: if (s->ttx != s->tpos && sk_maybe_write(s) > 0)
1954: {
1955: if (s->tx_hook)
1956: s->tx_hook(s);
1957: return 1;
1958: }
1959: return 0;
1960: }
1961: }
1962:
1963: int sk_is_ipv4(sock *s)
1964: { return s->af == AF_INET; }
1965:
1966: int sk_is_ipv6(sock *s)
1967: { return s->af == AF_INET6; }
1968:
1969: void
1970: sk_err(sock *s, int revents)
1971: {
1972: int se = 0, sse = sizeof(se);
1973: if ((s->type != SK_MAGIC) && (revents & POLLERR))
1974: if (getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &se, &sse) < 0)
1975: {
1976: log(L_ERR "IO: Socket error: SO_ERROR: %m");
1977: se = 0;
1978: }
1979:
1980: s->err_hook(s, se);
1981: }
1982:
1983: void
1984: sk_dump_all(void)
1985: {
1986: node *n;
1987: sock *s;
1988:
1989: debug("Open sockets:\n");
1990: WALK_LIST(n, sock_list)
1991: {
1992: s = SKIP_BACK(sock, n, n);
1993: debug("%p ", s);
1994: sk_dump(&s->r);
1995: }
1996: debug("\n");
1997: }
1998:
1999:
2000: /*
2001: * Internal event log and watchdog
2002: */
2003:
2004: #define EVENT_LOG_LENGTH 32
2005:
2006: struct event_log_entry
2007: {
2008: void *hook;
2009: void *data;
2010: btime timestamp;
2011: btime duration;
2012: };
2013:
2014: static struct event_log_entry event_log[EVENT_LOG_LENGTH];
2015: static struct event_log_entry *event_open;
2016: static int event_log_pos, event_log_num, watchdog_active;
2017: static btime last_time;
2018: static btime loop_time;
2019:
2020: static void
2021: io_update_time(void)
2022: {
2023: struct timespec ts;
2024: int rv;
2025:
2026: /*
2027: * This is third time-tracking procedure (after update_times() above and
2028: * times_update() in BFD), dedicated to internal event log and latency
2029: * tracking. Hopefully, we consolidate these sometimes.
2030: */
2031:
2032: rv = clock_gettime(CLOCK_MONOTONIC, &ts);
2033: if (rv < 0)
2034: die("clock_gettime: %m");
2035:
2036: last_time = ts.tv_sec S + ts.tv_nsec NS;
2037:
2038: if (event_open)
2039: {
2040: event_open->duration = last_time - event_open->timestamp;
2041:
2042: if (event_open->duration > config->latency_limit)
2043: log(L_WARN "Event 0x%p 0x%p took %d ms",
2044: event_open->hook, event_open->data, (int) (event_open->duration TO_MS));
2045:
2046: event_open = NULL;
2047: }
2048: }
2049:
2050: /**
2051: * io_log_event - mark approaching event into event log
2052: * @hook: event hook address
2053: * @data: event data address
2054: *
2055: * Store info (hook, data, timestamp) about the following internal event into
2056: * a circular event log (@event_log). When latency tracking is enabled, the log
2057: * entry is kept open (in @event_open) so the duration can be filled later.
2058: */
2059: void
2060: io_log_event(void *hook, void *data)
2061: {
2062: if (config->latency_debug)
2063: io_update_time();
2064:
2065: struct event_log_entry *en = event_log + event_log_pos;
2066:
2067: en->hook = hook;
2068: en->data = data;
2069: en->timestamp = last_time;
2070: en->duration = 0;
2071:
2072: event_log_num++;
2073: event_log_pos++;
2074: event_log_pos %= EVENT_LOG_LENGTH;
2075:
2076: event_open = config->latency_debug ? en : NULL;
2077: }
2078:
2079: static inline void
2080: io_close_event(void)
2081: {
2082: if (event_open)
2083: io_update_time();
2084: }
2085:
2086: void
2087: io_log_dump(void)
2088: {
2089: int i;
2090:
2091: log(L_DEBUG "Event log:");
2092: for (i = 0; i < EVENT_LOG_LENGTH; i++)
2093: {
2094: struct event_log_entry *en = event_log + (event_log_pos + i) % EVENT_LOG_LENGTH;
2095: if (en->hook)
2096: log(L_DEBUG " Event 0x%p 0x%p at %8d for %d ms", en->hook, en->data,
2097: (int) ((last_time - en->timestamp) TO_MS), (int) (en->duration TO_MS));
2098: }
2099: }
2100:
2101: void
2102: watchdog_sigalrm(int sig UNUSED)
2103: {
2104: /* Update last_time and duration, but skip latency check */
2105: config->latency_limit = 0xffffffff;
2106: io_update_time();
2107:
2108: /* We want core dump */
2109: abort();
2110: }
2111:
2112: static inline void
2113: watchdog_start1(void)
2114: {
2115: io_update_time();
2116:
2117: loop_time = last_time;
2118: }
2119:
2120: static inline void
2121: watchdog_start(void)
2122: {
2123: io_update_time();
2124:
2125: loop_time = last_time;
2126: event_log_num = 0;
2127:
2128: if (config->watchdog_timeout)
2129: {
2130: alarm(config->watchdog_timeout);
2131: watchdog_active = 1;
2132: }
2133: }
2134:
2135: static inline void
2136: watchdog_stop(void)
2137: {
2138: io_update_time();
2139:
2140: if (watchdog_active)
2141: {
2142: alarm(0);
2143: watchdog_active = 0;
2144: }
2145:
2146: btime duration = last_time - loop_time;
2147: if (duration > config->watchdog_warning)
2148: log(L_WARN "I/O loop cycle took %d ms for %d events",
2149: (int) (duration TO_MS), event_log_num);
2150: }
2151:
2152:
2153: /*
2154: * Main I/O Loop
2155: */
2156:
2157: void
2158: io_init(void)
2159: {
2160: init_list(&sock_list);
2161: init_list(&global_event_list);
2162: krt_io_init();
2163: // XXX init_times();
2164: // XXX update_times();
2165: boot_time = current_time();
2166:
2167: u64 now = (u64) current_real_time();
2168: srandom((uint) (now ^ (now >> 32)));
2169: }
2170:
2171: static int short_loops = 0;
2172: #define SHORT_LOOP_MAX 10
2173:
2174: void
2175: io_loop(void)
2176: {
2177: int poll_tout, timeout;
2178: int nfds, events, pout;
2179: timer *t;
2180: sock *s;
2181: node *n;
2182: int fdmax = 256;
2183: struct pollfd *pfd = xmalloc(fdmax * sizeof(struct pollfd));
2184:
2185: watchdog_start1();
2186: for(;;)
2187: {
2188: times_update(&main_timeloop);
2189: events = ev_run_list(&global_event_list);
2190: timers_fire(&main_timeloop);
2191: io_close_event();
2192:
2193: // FIXME
2194: poll_tout = (events ? 0 : 3000); /* Time in milliseconds */
2195: if (t = timers_first(&main_timeloop))
2196: {
2197: times_update(&main_timeloop);
2198: timeout = (tm_remains(t) TO_MS) + 1;
2199: poll_tout = MIN(poll_tout, timeout);
2200: }
2201:
2202: nfds = 0;
2203: WALK_LIST(n, sock_list)
2204: {
2205: pfd[nfds] = (struct pollfd) { .fd = -1 }; /* everything other set to 0 by this */
2206: s = SKIP_BACK(sock, n, n);
2207: if (s->rx_hook)
2208: {
2209: pfd[nfds].fd = s->fd;
2210: pfd[nfds].events |= POLLIN;
2211: }
2212: if (s->tx_hook && s->ttx != s->tpos)
2213: {
2214: pfd[nfds].fd = s->fd;
2215: pfd[nfds].events |= POLLOUT;
2216: }
2217: if (pfd[nfds].fd != -1)
2218: {
2219: s->index = nfds;
2220: nfds++;
2221: }
2222: else
2223: s->index = -1;
2224:
2225: if (nfds >= fdmax)
2226: {
2227: fdmax *= 2;
2228: pfd = xrealloc(pfd, fdmax * sizeof(struct pollfd));
2229: }
2230: }
2231:
2232: /*
2233: * Yes, this is racy. But even if the signal comes before this test
2234: * and entering poll(), it gets caught on the next timer tick.
2235: */
2236:
2237: if (async_config_flag)
2238: {
2239: io_log_event(async_config, NULL);
2240: async_config();
2241: async_config_flag = 0;
2242: continue;
2243: }
2244: if (async_dump_flag)
2245: {
2246: io_log_event(async_dump, NULL);
2247: async_dump();
2248: async_dump_flag = 0;
2249: continue;
2250: }
2251: if (async_shutdown_flag)
2252: {
2253: io_log_event(async_shutdown, NULL);
2254: async_shutdown();
2255: async_shutdown_flag = 0;
2256: continue;
2257: }
2258:
2259: /* And finally enter poll() to find active sockets */
2260: watchdog_stop();
2261: pout = poll(pfd, nfds, poll_tout);
2262: watchdog_start();
2263:
2264: if (pout < 0)
2265: {
2266: if (errno == EINTR || errno == EAGAIN)
2267: continue;
2268: die("poll: %m");
2269: }
2270: if (pout)
2271: {
2272: times_update(&main_timeloop);
2273:
2274: /* guaranteed to be non-empty */
2275: current_sock = SKIP_BACK(sock, n, HEAD(sock_list));
2276:
2277: while (current_sock)
2278: {
2279: sock *s = current_sock;
2280: if (s->index == -1)
2281: {
2282: current_sock = sk_next(s);
2283: goto next;
2284: }
2285:
2286: int e;
2287: int steps;
2288:
2289: steps = MAX_STEPS;
2290: if (s->fast_rx && (pfd[s->index].revents & POLLIN) && s->rx_hook)
2291: do
2292: {
2293: steps--;
2294: io_log_event(s->rx_hook, s->data);
2295: e = sk_read(s, pfd[s->index].revents);
2296: if (s != current_sock)
2297: goto next;
2298: }
2299: while (e && s->rx_hook && steps);
2300:
2301: steps = MAX_STEPS;
2302: if (pfd[s->index].revents & POLLOUT)
2303: do
2304: {
2305: steps--;
2306: io_log_event(s->tx_hook, s->data);
2307: e = sk_write(s);
2308: if (s != current_sock)
2309: goto next;
2310: }
2311: while (e && steps);
2312:
2313: current_sock = sk_next(s);
2314: next: ;
2315: }
2316:
2317: short_loops++;
2318: if (events && (short_loops < SHORT_LOOP_MAX))
2319: continue;
2320: short_loops = 0;
2321:
2322: int count = 0;
2323: current_sock = stored_sock;
2324: if (current_sock == NULL)
2325: current_sock = SKIP_BACK(sock, n, HEAD(sock_list));
2326:
2327: while (current_sock && count < MAX_RX_STEPS)
2328: {
2329: sock *s = current_sock;
2330: if (s->index == -1)
2331: {
2332: current_sock = sk_next(s);
2333: goto next2;
2334: }
2335:
2336: if (!s->fast_rx && (pfd[s->index].revents & POLLIN) && s->rx_hook)
2337: {
2338: count++;
2339: io_log_event(s->rx_hook, s->data);
2340: sk_read(s, pfd[s->index].revents);
2341: if (s != current_sock)
2342: goto next2;
2343: }
2344:
2345: if (pfd[s->index].revents & (POLLHUP | POLLERR))
2346: {
2347: sk_err(s, pfd[s->index].revents);
2348: if (s != current_sock)
2349: goto next2;
2350: }
2351:
2352: current_sock = sk_next(s);
2353: next2: ;
2354: }
2355:
2356:
2357: stored_sock = current_sock;
2358: }
2359: }
2360: }
2361:
2362: void
2363: test_old_bird(char *path)
2364: {
2365: int fd;
2366: struct sockaddr_un sa;
2367:
2368: fd = socket(AF_UNIX, SOCK_STREAM, 0);
2369: if (fd < 0)
2370: die("Cannot create socket: %m");
2371: if (strlen(path) >= sizeof(sa.sun_path))
2372: die("Socket path too long");
2373: bzero(&sa, sizeof(sa));
2374: sa.sun_family = AF_UNIX;
2375: strcpy(sa.sun_path, path);
2376: if (connect(fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) == 0)
2377: die("I found another BIRD running.");
2378: close(fd);
2379: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>