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 /* }}} */