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_wildcards(struct ccnr_handle *h)
00087 {
00088 int fd;
00089 int res;
00090 int whichpf;
00091 struct addrinfo hints = {0};
00092 struct addrinfo *addrinfo = NULL;
00093 struct addrinfo *a;
00094
00095 if (h->portstr == NULL || h->portstr[0] == 0)
00096 return(-1);
00097 hints.ai_socktype = SOCK_STREAM;
00098 hints.ai_flags = AI_PASSIVE;
00099 for (whichpf = 0; whichpf < 2; whichpf++) {
00100 hints.ai_family = whichpf ? PF_INET6 : PF_INET;
00101 res = getaddrinfo(NULL, h->portstr, &hints, &addrinfo);
00102 if (res == 0) {
00103 for (a = addrinfo; a != NULL; a = a->ai_next) {
00104 fd = socket(a->ai_family, SOCK_STREAM, 0);
00105 if (fd != -1) {
00106 int yes = 1;
00107
00108 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
00109 if (a->ai_family == AF_INET6)
00110 r_net_setsockopt_v6only(h, fd);
00111 res = bind(fd, a->ai_addr, a->ai_addrlen);
00112 if (res != 0) {
00113 close(fd);
00114 continue;
00115 }
00116 res = listen(fd, 30);
00117 if (res == -1) {
00118 close(fd);
00119 continue;
00120 }
00121 r_io_record_fd(h, fd,
00122 a->ai_addr, a->ai_addrlen,
00123 CCNR_FACE_PASSIVE);
00124 if (CCNSHOULDLOG(h, listen_on, CCNL_INFO))
00125 ccnr_msg(h, "accepting %s status connections on fd %d",
00126 af_name(a->ai_family), fd);
00127 }
00128 }
00129 freeaddrinfo(addrinfo);
00130 }
00131 }
00132 return(0);
00133 }
00134
00135 PUBLIC int
00136 r_net_listen_on_address(struct ccnr_handle *h, const char *addr)
00137 {
00138 int fd;
00139 int res;
00140 struct addrinfo hints = {0};
00141 struct addrinfo *addrinfo = NULL;
00142 struct addrinfo *a;
00143 int ok = 0;
00144
00145 if (CCNSHOULDLOG(h, listen_on_addr, CCNL_FINE))
00146 ccnr_msg(h, "listen_on %s", addr);
00147 hints.ai_socktype = SOCK_DGRAM;
00148 hints.ai_flags = AI_PASSIVE;
00149 res = getaddrinfo(addr, h->portstr, &hints, &addrinfo);
00150 if (res == 0) {
00151 for (a = addrinfo; a != NULL; a = a->ai_next) {
00152 fd = socket(a->ai_family, SOCK_STREAM, 0);
00153 if (fd != -1) {
00154 int yes = 1;
00155 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
00156 if (a->ai_family == AF_INET6)
00157 r_net_setsockopt_v6only(h, fd);
00158 res = bind(fd, a->ai_addr, a->ai_addrlen);
00159 if (res != 0) {
00160 close(fd);
00161 continue;
00162 }
00163 res = listen(fd, 30);
00164 if (res == -1) {
00165 close(fd);
00166 continue;
00167 }
00168 r_io_record_fd(h, fd,
00169 a->ai_addr, a->ai_addrlen,
00170 CCNR_FACE_PASSIVE);
00171 if (CCNSHOULDLOG(h, listen_on, CCNL_INFO))
00172 ccnr_msg(h, "accepting %s status connections on fd %d",
00173 af_name(a->ai_family), fd);
00174 ok++;
00175 }
00176 }
00177 freeaddrinfo(addrinfo);
00178 }
00179 return(ok > 0 ? 0 : -1);
00180 }
00181
00182 PUBLIC int
00183 r_net_listen_on(struct ccnr_handle *h, const char *addrs)
00184 {
00185 unsigned char ch;
00186 unsigned char dlm;
00187 int res = 0;
00188 int i;
00189 struct ccn_charbuf *addr = NULL;
00190
00191 if (h->portstr == NULL || h->portstr[0] == 0)
00192 return(-1);
00193 if (addrs == NULL || !*addrs || 0 == strcmp(addrs, "*"))
00194 return(r_net_listen_on_wildcards(h));
00195 addr = ccn_charbuf_create();
00196 for (i = 0, ch = addrs[i]; addrs[i] != 0;) {
00197 addr->length = 0;
00198 dlm = 0;
00199 if (ch == '[') {
00200 dlm = ']';
00201 ch = addrs[++i];
00202 }
00203 for (; ch > ' ' && ch != ',' && ch != ';' && ch != dlm; ch = addrs[++i])
00204 ccn_charbuf_append_value(addr, ch, 1);
00205 if (ch && ch == dlm)
00206 ch = addrs[++i];
00207 if (addr->length > 0) {
00208 res |= r_net_listen_on_address(h, ccn_charbuf_as_string(addr));
00209 }
00210 while ((0 < ch && ch <= ' ') || ch == ',' || ch == ';')
00211 ch = addrs[++i];
00212 }
00213 ccn_charbuf_destroy(&addr);
00214 return(res);
00215 }