"Fossies" - the Fresh Open Source Software Archive

Member "lessfs-1.7.0/lib_net.c" (30 Sep 2011, 11317 Bytes) of package /linux/misc/old/lessfs-1.7.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "lib_net.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  *   Lessfs: A data deduplicating filesystem.
    3  *   Copyright (C) 2008 Mark Ruijter <mruijter@lessfs.com>
    4  *
    5  *   This program is free software.
    6  *   You can redistribute lessfs and/or modify it under the terms of either
    7  *   (1) the GNU General Public License; either version 3 of the License,
    8  *   or (at your option) any later version as published by
    9  *   the Free Software Foundation; or (2) obtain a commercial license
   10  *   by contacting the Author.
   11  *
   12  *   This program is distributed in the hope that it will be useful,
   13  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
   14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
   15  *   the GNU General Public License for more details.
   16  *
   17  *   You should have received a copy of the GNU General Public License
   18  *   along with this program;  if not, write to the Free Software
   19  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
   20  */
   21 
   22 #include <ctype.h>
   23 #include <stdlib.h>
   24 #include <sys/time.h>
   25 #include <sys/types.h>
   26 #include <unistd.h>
   27 #include <sys/types.h>
   28 #include <sys/socket.h>
   29 #include <netinet/in.h>
   30 #include <netdb.h>
   31 #include <arpa/inet.h>
   32 #include <string.h>
   33 #include <fcntl.h>
   34 #include <stdio.h>
   35 #include <malloc.h>
   36 #include <errno.h>
   37 #include "lib_log.h"
   38 #include "lib_safe.h"
   39 #include "lib_net.h"
   40 #include "retcodes.h"
   41 
   42 extern pid_t mypid;
   43 extern char *logname;
   44 extern char *function;
   45 
   46 void die_nomem()
   47 {
   48     LFATAL("Out of memory\n");
   49     exit(EXIT_SYSTEM);
   50 }
   51 
   52 void exitWriteLine()
   53 {
   54     LFATAL("writeLine failed in writeHeader.\n");
   55     exit(EXIT_SYSTEM);
   56 }
   57 
   58 /* Reads a string with an arbitrary ending delimiter. */
   59 
   60 int readdelimstring(int sec, int sockid, char *buf, int maxlen, char delim)
   61 {
   62     int count = 0, status;
   63 
   64     while (count <= maxlen) {
   65         status =
   66             fulltimRead(sec, sockid, (unsigned char *) buf + count, 1);
   67         if (status < 0)
   68             return status;
   69         if (status < 1) {
   70             return status;
   71         }
   72         if (buf[count] == delim) {      /* Found the delimiter */
   73             buf[count] = 0;
   74             return 0;
   75         }
   76         count++;
   77     }
   78     return 0;
   79 }
   80 
   81 /* Reads a string from the network, terminated by a null. */
   82 
   83 int readstring(int sec, int sockid, char *buf, int maxlen)
   84 {
   85     return readdelimstring(sec, sockid, buf, maxlen, 0);
   86 }
   87 
   88 /* Reads a string terminated by a newline */
   89 
   90 int readnlstring(int sec, int sockid, char *buf, int maxlen)
   91 {
   92     return readdelimstring(sec, sockid, buf, maxlen, '\n');
   93 }
   94 
   95 int timeoutRead(int t, int fd, char *b, int l)
   96 {
   97     int rc = TIMEOUT;
   98     fd_set fds;
   99     struct timeval tv;
  100 
  101     FD_ZERO(&fds);
  102     FD_SET(fd, &fds);
  103     tv.tv_sec = t;
  104     tv.tv_usec = 0;
  105 
  106     if (select(fd + 1, &fds, NULL, NULL, &tv)) {
  107       again:
  108         if ((rc = read(fd, b, l)) < 0) {
  109             if (errno == EINTR || EAGAIN == errno)
  110                 goto again;
  111         }
  112     }
  113     return (rc);
  114 }
  115 
  116 int timeoutWrite(int t, int fd, char *b, int l)
  117 {
  118     int rc = TIMEOUT;
  119     fd_set fds;
  120     struct timeval tv;
  121 
  122     if (fd < 0)
  123         return (fd);
  124 
  125     FD_ZERO(&fds);
  126     FD_SET(fd, &fds);
  127     tv.tv_sec = t;
  128     tv.tv_usec = 0;
  129 
  130     if (select(fd + 1, NULL, &fds, NULL, &tv)) {
  131       again:
  132         if ((rc = write(fd, b, l)) < 0) {
  133             if (errno == EINTR || EAGAIN == errno)
  134                 goto again;
  135         }
  136     }
  137     return (rc);
  138 }
  139 
  140 char *readMsg(int fd)
  141 {
  142     int bufcount = BUFSIZE;
  143     int bytes = 0;
  144     int rc = -1;
  145     static char *mg_msg, *mg_msg2;
  146 
  147     mg_msg = s_malloc(bufcount);
  148     mg_msg2 = mg_msg;
  149     while (1) {
  150         rc = timeoutRead(30, fd, mg_msg2, 1);
  151         if (rc < 0)
  152             return NULL;
  153         if (rc == 0)
  154             break;
  155         bytes = bytes + rc;
  156         bufcount = bufcount + rc;
  157         if (NULL == (mg_msg = realloc(mg_msg, bufcount)))
  158             die_nomem();
  159         mg_msg2 = mg_msg + bytes;
  160     }
  161     mg_msg[bytes] = 0;
  162     return mg_msg;
  163 }
  164 
  165 int resolveproto(const char *proto)
  166 {
  167     struct protoent *protocol;
  168     protocol = getprotobyname(proto);
  169     if (!protocol) {
  170         LFATAL("resolveproto : getprotobyname failed for %s", proto);
  171         return -1;
  172     }
  173 
  174     return protocol->p_proto;
  175 }
  176 
  177 static int checkstring(const char *string);
  178 
  179 /* checkstring() is a private function used only by this library.  It checks
  180     the passed string.  It returns false if there are no nonnumeric
  181     characters  in the string, or true if there are such characters. */
  182 
  183 static int checkstring(const char *string)
  184 {
  185     int counter;
  186     for (counter = 0; counter < strlen(string); counter++)
  187         if (!(isdigit(string[counter])))
  188             return 1;
  189     return 0;
  190 }
  191 
  192 int prototype(const char *proto)
  193 {
  194     if (strcmp(proto, "tcp") == 0)
  195         return SOCK_STREAM;
  196     if (strcmp(proto, "udp") == 0)
  197         return SOCK_DGRAM;
  198     return -1;
  199 }
  200 
  201 int socketaddr_host(struct sockaddr_in *socketaddr, const char *host)
  202 {
  203     struct hostent *hostaddr;
  204     hostaddr = gethostbyname(host);
  205     if (!hostaddr) {
  206         LFATAL("socketaddr_host: gethostbyname failed for %s", host);
  207         return -1;
  208     }
  209 
  210     memcpy(&socketaddr->sin_addr, hostaddr->h_addr, hostaddr->h_length);
  211     return 0;
  212 }
  213 
  214 int
  215 socketaddr_service(struct sockaddr_in *socketaddr,
  216                    const char *service, const char *proto)
  217 {
  218     struct servent *serviceaddr;
  219 
  220     /* Need to allow numeric as well as textual data. */
  221 
  222     /* 0: pass right through. */
  223 
  224     if (strcmp(service, "0") == 0)
  225         socketaddr->sin_port = 0;
  226     else {                      /* nonzero port */
  227         serviceaddr = getservbyname(service, proto);
  228         if (serviceaddr) {
  229             socketaddr->sin_port = serviceaddr->s_port;
  230         } else {                /* name did not resolve, try number */
  231             if (checkstring(service)) { /* and it's a text name, fail. */
  232                 LFATAL("socketaddr_service no lookup for %s/%s", service,
  233                        proto);
  234                 return -1;
  235             }
  236             if ((socketaddr->sin_port =
  237                  htons((u_short) atoi(service))) == 0) {
  238                 LFATAL("socketaddr_service : numeric conversion failed");
  239                 return -1;
  240             }
  241         }
  242     }
  243     return 0;
  244 }
  245 
  246 
  247 void socketaddr_init(struct sockaddr_in *socketaddr)
  248 {
  249     bzero((char *) socketaddr, sizeof(*socketaddr));
  250     socketaddr->sin_family = AF_INET;
  251 }
  252 
  253 int clientconnect(const char *host, const char *port, const char *proto)
  254 {
  255     struct sockaddr_in socketaddr;
  256     int sockid;
  257     int trueval = 1;
  258 
  259     socketaddr_init(&socketaddr);
  260     socketaddr_service(&socketaddr, port, proto);
  261     socketaddr_host(&socketaddr, host);
  262 
  263     sockid = socket(PF_INET, prototype(proto), resolveproto(proto));
  264     if (sockid < 0) {
  265         return -1;
  266     }
  267 
  268     setsockopt(sockid, SOL_SOCKET, SO_REUSEADDR, &trueval,
  269                sizeof(trueval));
  270     if (connect
  271         (sockid, (struct sockaddr *) &socketaddr,
  272          sizeof(socketaddr)) < 0) {
  273         return -1;
  274     }
  275     return sockid;
  276 }
  277 
  278 int scanaddr(const char *s, unsigned long *ip, unsigned long *mask)
  279 {
  280     unsigned d1, d2, d3, d4, m;
  281     int res;
  282     if ((res =
  283          sscanf((char *) s, "%u.%u.%u.%u/%u", &d1, &d2, &d3, &d4, &m)) < 4)
  284         return 0;
  285     if (mask && res == 4)
  286         *mask = 0xFFFFFFFF;
  287     else if (mask)
  288         *mask = htonl(0xFFFFFFFF << (32 - m));
  289     *ip = htonl((d1 << 24) ^ (d2 << 16) ^ (d3 << 8) ^ d4);
  290     return res;
  291 }
  292 
  293 int serverinit(const char *addr, const char *port, const char *proto)
  294 {
  295     struct sockaddr_in socketaddr;
  296     int mastersock;
  297     int trueval = 1;
  298     struct hostent *hostinfo;
  299     unsigned long ip;
  300     struct linger slinger;
  301 
  302     socketaddr_init(&socketaddr);
  303 
  304     if (NULL == addr) {
  305         socketaddr.sin_addr.s_addr = INADDR_ANY;
  306     } else {
  307         if (scanaddr(addr, &ip, NULL) != 4) {
  308             LFATAL("Invalid address : %s provided", addr);
  309             return -1;
  310         }
  311         hostinfo = gethostbyaddr((char *) &ip, 4, AF_INET);
  312         if (NULL == hostinfo) {
  313             LFATAL("gethostbyaddr : %s failed", addr);
  314             return -1;
  315         }
  316         socketaddr.sin_addr = *(struct in_addr *) *hostinfo->h_addr_list;
  317     }
  318     socketaddr_service(&socketaddr, port, proto);
  319 
  320     mastersock = socket(PF_INET, prototype(proto), resolveproto(proto));
  321     if (mastersock < 0) {
  322         LFATAL("couldn't create socket");
  323         return -1;
  324     }
  325 
  326     if (bind
  327         (mastersock, (struct sockaddr *) &socketaddr,
  328          sizeof(socketaddr)) < 0) {
  329         return -1;
  330     }
  331 
  332     setsockopt(mastersock, SOL_SOCKET, SO_REUSEADDR, &trueval,
  333                sizeof(trueval));
  334     slinger.l_onoff = 1;
  335     slinger.l_linger = 0;
  336     setsockopt(mastersock, SOL_SOCKET, SO_LINGER, (char *) &slinger,
  337                sizeof(slinger));
  338 
  339     if (prototype(proto) == SOCK_STREAM) {
  340         if (listen(mastersock, 5) < 0) {
  341             LFATAL("listen on port %d failed", socketaddr.sin_port);
  342             return -1;
  343         }
  344     }
  345     return mastersock;
  346 }
  347 
  348 int fulltimRead(int sec, int fd, unsigned char *buf, int len)
  349 {
  350     int total;
  351     int thistime;
  352 
  353     for (total = 0; total < len;) {
  354         thistime = timeoutRead(sec, fd, (char *) buf + total, len - total);
  355         if (thistime == TIMEOUT)
  356             return (thistime);
  357         if (thistime < 0) {
  358             if (EINTR == errno || EAGAIN == errno)
  359                 continue;
  360             return -1;
  361         } else if (thistime == 0) {
  362             /* EOF, but we didn't read the minimum.  return what we've read
  363              * so far and next read (if there is one) will return 0. */
  364             return total;
  365         }
  366         total += thistime;
  367     }
  368     return total;
  369 }
  370 
  371 int fulltimWrite(int sec, int fd, unsigned char *buf, int len)
  372 {
  373     int total;
  374     int thistime;
  375 
  376     for (total = 0; total < len;) {
  377         thistime =
  378             timeoutWrite(sec, fd, (char *) buf + total, len - total);
  379         if (thistime == TIMEOUT)
  380             return (thistime);
  381         if (thistime < 0) {
  382             if (EINTR == errno || EAGAIN == errno)
  383                 continue;
  384             return -1;
  385         } else if (thistime == 0) {
  386             /* EOF, but we didn't read the minimum.  return what we've read
  387              * so far and next read (if there is one) will return 0. */
  388             return total;
  389         }
  390         total += thistime;
  391     }
  392     return total;
  393 }
  394 
  395 
  396 
  397 int fullRead(int fd, unsigned char *buf, int len)
  398 {
  399     int total;
  400     int thistime;
  401 
  402     for (total = 0; total < len;) {
  403         thistime = read(fd, buf + total, len - total);
  404 
  405         if (thistime < 0) {
  406             if (EINTR == errno || EAGAIN == errno)
  407                 continue;
  408             return -1;
  409         } else if (thistime == 0) {
  410             /* EOF, but we didn't read the minimum.  return what we've read
  411              * so far and next read (if there is one) will return 0. */
  412             return total;
  413         }
  414         total += thistime;
  415     }
  416     return total;
  417 }
  418 
  419 int fullWrite(int fd, unsigned char *buf, int len)
  420 {
  421     int total;
  422     int thistime;
  423 
  424     for (total = 0; total < len;) {
  425         thistime = write(fd, buf + total, len - total);
  426 
  427         if (thistime < 0) {
  428             if (EINTR == errno || EAGAIN == errno)
  429                 continue;
  430             return thistime;    /* always an error for writes */
  431         }
  432         total += thistime;
  433     }
  434     return total;
  435 }