ccnr_net.c

Go to the documentation of this file.
00001 /**
00002  * @file ccnr_net.c
00003  * 
00004  * Part of ccnr -  CCNx Repository Daemon.
00005  *
00006  */
00007 
00008 /*
00009  * Copyright (C) 2011-2012 Palo Alto Research Center, Inc.
00010  *
00011  * This work is free software; you can redistribute it and/or modify it under
00012  * the terms of the GNU General Public License version 2 as published by the
00013  * Free Software Foundation.
00014  * This work is distributed in the hope that it will be useful, but WITHOUT ANY
00015  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
00016  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
00017  * for more details. You should have received a copy of the GNU General Public
00018  * License along with this program; if not, write to the
00019  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00020  * Boston, MA 02110-1301, USA.
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 }
Generated on Tue Aug 21 14:54:15 2012 for Content-Centric Networking in C by  doxygen 1.6.3