tlsgate

TLS proxy
git clone git://git.akobets.xyz/tlsgate
Log | Files | Refs | README | LICENSE

sock.c (3929B)


      1 #include <fcntl.h>
      2 #include <errno.h>
      3 #include <stdio.h>
      4 #include <sys/stat.h>
      5 #include <sys/time.h>
      6 #include <unistd.h>
      7 
      8 #include <arpa/inet.h>
      9 #include <netinet/in.h>
     10 #include <netdb.h>
     11 #include <sys/un.h>
     12 
     13 #include "sock.h"
     14 #include "util.h"
     15 
     16 int
     17 sock_proxy_ips(const char *host, const char *port)
     18 {
     19   struct addrinfo hints = {
     20     .ai_flags    = AI_NUMERICSERV,
     21     .ai_family   = AF_UNSPEC,
     22     .ai_socktype = SOCK_STREAM,
     23   };
     24   int ret;
     25   struct addrinfo *ai, *p;
     26   int fd = -1;
     27   int optval = 1;
     28 
     29   if ((ret = getaddrinfo(host, port, &hints, &ai)) != 0)
     30     errx("getaddrinfo: %s", gai_strerror(ret));
     31 
     32   for (p = ai; p != NULL; p = p->ai_next) {
     33     fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
     34     if (fd == -1)
     35       continue;
     36     if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1)
     37       err("setsockopt");
     38     if (bind(fd, p->ai_addr, p->ai_addrlen) == -1) {
     39       close(fd);
     40     } else {
     41       break;
     42     }
     43   }
     44   freeaddrinfo(ai);
     45   if (p == NULL)
     46     errx(
     47       "bind: Can not bind to address: %s:%s",
     48       host,
     49       port
     50     );
     51 
     52   if (listen(fd, SOMAXCONN) == -1)
     53     err("listen");
     54 
     55   return fd;
     56 }
     57 
     58 int
     59 sock_proxy_uds(const char *file)
     60 {
     61   int fd;
     62   struct sockaddr_un addr;
     63   int saved_errno;
     64   // 0666 file permissions
     65   int perms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
     66 
     67   if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
     68     err("socket");
     69 
     70   addr.sun_family = AF_UNIX;
     71   snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", file);
     72 
     73   if (bind(fd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un)) == -1)
     74     err("bind");
     75 
     76   if (chmod(file, perms) == -1) {
     77     saved_errno = errno;
     78     sock_remove_uds(file);
     79     errno = saved_errno;
     80     err("chmod");
     81   }
     82 
     83   if (listen(fd, SOMAXCONN) == -1) {
     84     saved_errno = errno;
     85     sock_remove_uds(file);
     86     errno = saved_errno;
     87     err("listen");
     88   }
     89 
     90   return fd;
     91 }
     92 
     93 void
     94 sock_remove_uds(const char *file)
     95 {
     96   if (unlink(file) == -1)
     97     err("unlink");
     98 }
     99 
    100 int
    101 sock_server_ips(const char *host, const char *port)
    102 {
    103   struct addrinfo hints = {
    104     .ai_flags    = AI_NUMERICSERV,
    105     .ai_family   = AF_UNSPEC,
    106     .ai_socktype = SOCK_STREAM,
    107   };
    108   int ret;
    109   struct addrinfo *ai, *p;
    110   int fd = -1;
    111 
    112   if ((ret = getaddrinfo(host, port, &hints, &ai)) != 0) {
    113     warnx("getaddrinfo: %s", gai_strerror(ret));
    114     return -1;
    115   }
    116 
    117   for (p = ai; p != NULL; p = p->ai_next) {
    118     fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
    119     if (fd == -1)
    120       continue;
    121     if (connect(fd, p->ai_addr, p->ai_addrlen) == -1) {
    122       close(fd);
    123     } else {
    124       break;
    125     }
    126   }
    127   freeaddrinfo(ai);
    128   if (p == NULL) {
    129     warnx(
    130       "connect: Can not connect to address: %s:%s",
    131       host,
    132       port
    133     );
    134     return -1;
    135   }
    136 
    137   return fd;
    138 }
    139 
    140 int
    141 sock_server_uds(const char *file)
    142 {
    143   int fd;
    144   struct sockaddr_un addr;
    145 
    146   if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
    147     warn("socket");
    148     return -1;
    149   }
    150 
    151   addr.sun_family = AF_UNIX;
    152   snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", file);
    153 
    154   if (connect(fd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un)) == -1) {
    155     warn("connect");
    156     return -1;
    157   }
    158 
    159   return fd;
    160 }
    161 
    162 int
    163 sock_set_nonblock(int fd)
    164 {
    165   int flags;
    166 
    167   if ((flags = fcntl(fd, F_GETFL)) == -1) {
    168     warn("fcntl");
    169     return -1;
    170   }
    171   if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
    172     warn("fcntl");
    173     return -1;
    174   }
    175 
    176   return 0;
    177 }
    178 
    179 int
    180 sock_get_addr_str(const struct sockaddr_storage *addr, char *str, size_t len) {
    181   switch (addr->ss_family) {
    182   case AF_INET:
    183     if (!inet_ntop(AF_INET, &(((struct sockaddr_in *) addr)->sin_addr), str, len)) {
    184       warn("inet_ntop:");
    185       return -1;
    186     }
    187     break;
    188   case AF_INET6:
    189     if (!inet_ntop(AF_INET6, &(((struct sockaddr_in6 *) addr)->sin6_addr), str, len)) {
    190       warn("inet_ntop:");
    191       return -1;
    192     }
    193     break;
    194   default:
    195     snprintf(str, len, "uds");
    196     break;
    197   }
    198 
    199   return 0;
    200 }