muhstik

- irc flooding solution
git clone git://git.acid.vegas/muhstik.git
Log | Files | Refs | Archive | README

net.c (5443B)

      1 /* Muhstik, Copyright (C) 2001-2002, Louis Bavoil <mulder@gmx.fr>       */
      2 /*                        2009-2011, Leon Kaiser <literalka@gnaa.eu>    */
      3 /*                                                                      */
      4 /* This program is free software; you can redistribute it and/or        */
      5 /* modify it under the terms of the GNU Library General Public License  */
      6 /* as published by the Free Software Foundation; either version 2       */
      7 /* of the License, or (at your option) any later version.               */
      8 /*                                                                      */
      9 /* This program is distributed in the hope that it will be useful,      */
     10 /* but WITHOUT ANY WARRANTY; without even the implied warranty of       */
     11 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        */
     12 /* GNU Library General Public License for more details.                 */
     13 
     14 /* {{{ Header includes */
     15 #include <fcntl.h>
     16 #include <stdio.h>
     17 #include <stdlib.h>
     18 #include <unistd.h>
     19 #include <stdarg.h>
     20 
     21 #include "../include/net.h"
     22 #include "../include/proxy.h"
     23 #include "../include/string.h"
     24 #include "../include/print.h"
     25 /* }}} */
     26 /* {{{ Variables */
     27 /* {{{ Global Variables */
     28 int maxsock;
     29 /* }}} */
     30 /* }}} */
     31 /* {{{ Hard-wired, compile-time constants */
     32 #ifndef INADDR_NONE
     33 #define INADDR_NONE -1
     34 #endif
     35 
     36 #define MAX_HOSTNAME 256
     37 /* }}} */
     38 /* {{{ lookup_*() */
     39 /* ``he->h_addrtype == AF_INET6`` */
     40 int lookup_host(char *host, struct in_addr *addr)
     41 {
     42      struct hostent *he;
     43 
     44      if ((he = gethostbyname(host)) == NULL)
     45      {
     46           return 1; /* In ``telnet.c'' it was ``return 0;''... -- Leon */
     47      }
     48 
     49      memcpy(addr, he->h_addr, he->h_length);
     50      return 0; /* In ``telnet.c'' it was ``return 1;''... -- Leon */
     51 }
     52 
     53 int lookup_ip(char *host, struct in_addr *addr)
     54 { /* XXX: Does this support IPv6 IPs? -- Leon */
     55      /* Use inet_addr for portability to Solaris */
     56      /* Fuck Solaris -- Leon */
     57      return (((*addr).s_addr = inet_addr(host)) == INADDR_NONE);
     58 }
     59 /* }}} */
     60 /* {{{ DNS-related functions */
     61 int resolve(char *host, struct in_addr *addr)
     62 {
     63      return (lookup_host(host,addr) && lookup_ip(host,addr));
     64 }
     65 
     66 void host2ip(char *s, char *host, int size)
     67 { /* TODO: Support IPv6 IPs, I guess. -- Leon */
     68      struct in_addr addr;
     69      u_char *p;
     70 
     71      if (resolve(host, &addr))
     72      {
     73           StrCopy(s, host, size);
     74           return;
     75      }
     76      p = (u_char *) &addr.s_addr;
     77      snprintf(s, size, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
     78 }
     79 /* }}} */
     80 /* {{{ net_*() */
     81 /* {{{ net_set-type shit */
     82 void net_set_socket_options(int sock)
     83 {
     84      int sw;
     85      sw = 1;
     86      setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &sw, sizeof(sw));
     87      sw = 1;
     88      setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *) &sw, sizeof(sw));
     89      sw = 0;
     90      setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *) &sw, sizeof(sw));
     91 }
     92 
     93 void set_nonblocking(int sock)
     94 {
     95      int opts;
     96 
     97      opts = fcntl(sock, F_GETFL);
     98      if (opts < 0)
     99      {
    100           print_error("fcntl(F_GETFL)");
    101           exit(EXIT_FAILURE);
    102      }
    103 
    104      opts = (opts | O_NONBLOCK);
    105      if (fcntl(sock, F_SETFL, opts) < 0)
    106      {
    107           print_error("fcntl(F_SETFL)");
    108           exit(EXIT_FAILURE);
    109      }
    110 }
    111 /* }}} */
    112 /* {{{ net_store*() */
    113 netstore *net_store_new()
    114 {
    115      netstore *ns;
    116      ns = xmalloc(sizeof(netstore));
    117      memset(ns, 0, sizeof(netstore));
    118      return ns;
    119 }
    120 
    121 void net_store_destroy(netstore *ns)
    122 {
    123      if (ns->ip6_hostent)
    124      {
    125           freeaddrinfo(ns->ip6_hostent);
    126      }
    127      free(ns);
    128 }
    129 /* }}} */
    130 /* {{{ net_socket() */
    131 int net_socket(int *sock, int type)
    132 {
    133      if ((*sock = socket(type, SOCK_STREAM, IPPROTO_TCP)) == -1)
    134      {
    135           return 1;
    136      }
    137      maxsock = max(*sock, maxsock);
    138      net_set_socket_options(*sock);
    139      set_nonblocking(*sock);
    140      return 0;
    141 }
    142 /* }}} */
    143 /* {{{ Resloving, connecting, binding functions */
    144 int net_resolve(netstore *ns, char *hostname, unsigned short port)
    145 {
    146      struct addrinfo hints;
    147      char portstring[MAX_HOSTNAME];
    148 
    149      snprintf(portstring, MAX_HOSTNAME, "%d", port);
    150      memset(&hints, 0, sizeof (struct addrinfo));
    151      hints.ai_family = PF_UNSPEC; /* support IPv6 and IPv4 */
    152      hints.ai_flags = AI_CANONNAME;
    153      hints.ai_socktype = SOCK_STREAM;
    154 
    155      return getaddrinfo(hostname, port ? portstring : NULL, &hints, &ns->ip6_hostent);
    156 }
    157 
    158 int net_connect(netstore *ns, int *sock, char *vhost)
    159 {
    160      struct addrinfo *res;
    161      struct addrinfo *res0;
    162 
    163      res0 = ns->ip6_hostent;
    164      for (res = res0; res; res = res->ai_next)
    165      {
    166           switch (res->ai_family)
    167           {
    168                case AF_INET:
    169                case AF_INET6:
    170                     if (net_socket(sock, res->ai_family))
    171                     {
    172                          return -1;
    173                     }
    174 
    175                     if (vhost && init_vhost(*sock, vhost))
    176                     {
    177                          return -1;
    178                     }
    179 
    180                     return connect(*sock, res->ai_addr, res->ai_addrlen);
    181           }
    182      }
    183      return -1;
    184 }
    185 
    186 int net_bind(netstore *ns, int sock)
    187 {
    188      return bind(sock, ns->ip6_hostent->ai_addr, ns->ip6_hostent->ai_addrlen);
    189 }
    190 /* }}} */
    191 /* }}} */
    192 /* {{{ send_sock() */
    193 void send_sock(int sock, const char *fmt, ...)
    194 {
    195      char buffer[BIGBUF];
    196      int n;
    197      va_list ap;
    198 
    199      va_start(ap, fmt);
    200      n = vsnprintf(buffer, sizeof(buffer), fmt, ap);
    201      va_end(ap);
    202 
    203      send(sock, buffer, strlen(buffer), 0);
    204 }
    205 /* }}} */