00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <errno.h>
00024 #include <fcntl.h>
00025 #include <limits.h>
00026 #include <netdb.h>
00027 #include <poll.h>
00028 #include <signal.h>
00029 #include <stddef.h>
00030 #include <stdint.h>
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include <time.h>
00035 #include <unistd.h>
00036 #include <arpa/inet.h>
00037 #include <sys/time.h>
00038 #include <sys/socket.h>
00039 #include <sys/stat.h>
00040 #include <sys/types.h>
00041 #include <sys/un.h>
00042 #include <netinet/in.h>
00043
00044 #include "ccnr_private.h"
00045
00046 #include "ccnr_net.h"
00047
00048 #include "ccnr_io.h"
00049 #include "ccnr_msg.h"
00050
00051 PUBLIC char *
00052 r_net_get_local_sockname(void)
00053 {
00054 struct sockaddr_un sa;
00055 ccn_setup_sockaddr_un(NULL, &sa);
00056 return(strdup(sa.sun_path));
00057 }
00058
00059 PUBLIC void
00060 r_net_setsockopt_v6only(struct ccnr_handle *h, int fd)
00061 {
00062 int yes = 1;
00063 int res = 0;
00064 #ifdef IPV6_V6ONLY
00065 res = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(yes));
00066 #endif
00067 if (res == -1)
00068 ccnr_msg(h, "warning - could not set IPV6_V6ONLY on fd %d: %s",
00069 fd, strerror(errno));
00070 }
00071
00072 static const char *
00073 af_name(int family)
00074 {
00075 switch (family) {
00076 case AF_INET:
00077 return("ipv4");
00078 case AF_INET6:
00079 return("ipv6");
00080 default:
00081 return("");
00082 }
00083 }
00084
00085 PUBLIC int
00086 r_net_listen_on_address(struct ccnr_handle *h, const char *addr)
00087 {
00088 int fd;
00089 int res;
00090 struct addrinfo hints = {0};
00091 struct addrinfo *addrinfo = NULL;
00092 struct addrinfo *a;
00093 int ok = 0;
00094
00095 if (CCNSHOULDLOG(h, listen_on_addr, CCNL_FINE))
00096 ccnr_msg(h, "listen_on %s", addr);
00097 hints.ai_socktype = SOCK_DGRAM;
00098 hints.ai_flags = AI_PASSIVE;
00099 res = getaddrinfo(addr, h->portstr, &hints, &addrinfo);
00100 if (res == 0) {
00101 for (a = addrinfo; a != NULL; a = a->ai_next) {
00102 fd = socket(a->ai_family, SOCK_STREAM, 0);
00103 if (fd != -1) {
00104 int yes = 1;
00105 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
00106 if (a->ai_family == AF_INET6)
00107 r_net_setsockopt_v6only(h, fd);
00108 res = bind(fd, a->ai_addr, a->ai_addrlen);
00109 if (res != 0) {
00110 close(fd);
00111 continue;
00112 }
00113 res = listen(fd, 30);
00114 if (res == -1) {
00115 close(fd);
00116 continue;
00117 }
00118 r_io_record_fd(h, fd,
00119 a->ai_addr, a->ai_addrlen,
00120 CCNR_FACE_PASSIVE);
00121 if (CCNSHOULDLOG(h, listen_on, CCNL_INFO))
00122 ccnr_msg(h, "accepting %s status connections on fd %d",
00123 af_name(a->ai_family), fd);
00124 ok++;
00125 }
00126 }
00127 freeaddrinfo(addrinfo);
00128 }
00129 return(ok > 0 ? 0 : -1);
00130 }
00131
00132 PUBLIC int
00133 r_net_listen_on(struct ccnr_handle *h, const char *addrs)
00134 {
00135 unsigned char ch;
00136 unsigned char dlm;
00137 int res = 0;
00138 int i;
00139 struct ccn_charbuf *addr = NULL;
00140
00141 if (h->portstr == NULL || h->portstr[0] == 0)
00142 return(-1);
00143 if (addrs == NULL || !*addrs)
00144 addrs="127.0.0.1,[::1]";
00145 else if (0 == strcmp(addrs, "*"))
00146 addrs="0.0.0.0,[::]";
00147 addr = ccn_charbuf_create();
00148 for (i = 0, ch = addrs[i]; addrs[i] != 0;) {
00149 addr->length = 0;
00150 dlm = 0;
00151 if (ch == '[') {
00152 dlm = ']';
00153 ch = addrs[++i];
00154 }
00155 for (; ch > ' ' && ch != ',' && ch != ';' && ch != dlm; ch = addrs[++i])
00156 ccn_charbuf_append_value(addr, ch, 1);
00157 if (ch && ch == dlm)
00158 ch = addrs[++i];
00159 if (addr->length > 0) {
00160 res |= r_net_listen_on_address(h, ccn_charbuf_as_string(addr));
00161 }
00162 while ((0 < ch && ch <= ' ') || ch == ',' || ch == ';')
00163 ch = addrs[++i];
00164 }
00165 ccn_charbuf_destroy(&addr);
00166 return(res);
00167 }