00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "stdinc.h"
00026 #include "listener.h"
00027 #include "client.h"
00028 #include "fdlist.h"
00029 #include "irc_string.h"
00030 #include "sprintf_irc.h"
00031 #include "ircd.h"
00032 #include "ircd_defs.h"
00033 #include "s_bsd.h"
00034 #include "irc_getnameinfo.h"
00035 #include "irc_getaddrinfo.h"
00036 #include "numeric.h"
00037 #include "s_conf.h"
00038 #include "s_stats.h"
00039 #include "send.h"
00040 #include "memory.h"
00041 #include "tools.h"
00042 #ifdef HAVE_LIBCRYPTO
00043 #include <openssl/bio.h>
00044 #endif
00045
00046
00047 static PF accept_connection;
00048
00049 static dlink_list ListenerPollList = { NULL, NULL, 0 };
00050 static void close_listener(struct Listener *listener);
00051
00052 static struct Listener *
00053 make_listener(int port, struct irc_ssaddr *addr)
00054 {
00055 struct Listener *listener = MyMalloc(sizeof(struct Listener));
00056 assert(listener != 0);
00057
00058 listener->name = me.name;
00059 listener->port = port;
00060 memcpy(&listener->addr, addr, sizeof(struct irc_ssaddr));
00061
00062 return listener;
00063 }
00064
00065 void
00066 free_listener(struct Listener *listener)
00067 {
00068 assert(listener != NULL);
00069
00070 if (listener == NULL)
00071 return;
00072
00073 dlinkDelete(&listener->listener_node, &ListenerPollList);
00074 MyFree(listener);
00075 }
00076
00077
00078
00079
00080
00081 const char *
00082 get_listener_name(const struct Listener *listener)
00083 {
00084 static char buf[HOSTLEN + HOSTLEN + PORTNAMELEN + 4];
00085
00086 assert(listener != NULL);
00087
00088 if (listener == NULL)
00089 return(NULL);
00090
00091 ircsprintf(buf, "%s[%s/%u]",
00092 me.name, listener->name, listener->port);
00093 return(buf);
00094 }
00095
00096
00097
00098
00099
00100
00101
00102 void
00103 show_ports(struct Client *source_p)
00104 {
00105 char buf[4];
00106 char *p = NULL;
00107 dlink_node *ptr;
00108
00109 DLINK_FOREACH(ptr, ListenerPollList.head)
00110 {
00111 const struct Listener *listener = ptr->data;
00112 p = buf;
00113
00114 if (listener->flags & LISTENER_HIDDEN) {
00115 if (!IsAdmin(source_p))
00116 continue;
00117 *p++ = 'H';
00118 }
00119
00120 if (listener->flags & LISTENER_SSL)
00121 *p++ = 's';
00122 *p = '\0';
00123 sendto_one(source_p, form_str(RPL_STATSPLINE),
00124 me.name, source_p->name, 'P', listener->port,
00125 IsAdmin(source_p) ? listener->name : me.name,
00126 listener->ref_count, buf,
00127 listener->active ? "active" : "disabled");
00128 }
00129 }
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 #ifdef SOMAXCONN
00140 #undef HYBRID_SOMAXCONN
00141 #define HYBRID_SOMAXCONN SOMAXCONN
00142 #endif
00143
00144 static int
00145 inetport(struct Listener *listener)
00146 {
00147 struct irc_ssaddr lsin;
00148 socklen_t opt = 1;
00149
00150
00151
00152
00153 if (comm_open(&listener->fd, listener->addr.ss.ss_family, SOCK_STREAM, 0,
00154 "Listener socket") == -1)
00155 {
00156 report_error(L_ALL, "opening listener socket %s:%s",
00157 get_listener_name(listener), errno);
00158 return 0;
00159 }
00160
00161 memset(&lsin, 0, sizeof(lsin));
00162 memcpy(&lsin, &listener->addr, sizeof(struct irc_ssaddr));
00163
00164 irc_getnameinfo((struct sockaddr*)&lsin, lsin.ss_len, listener->vhost,
00165 HOSTLEN, NULL, 0, NI_NUMERICHOST);
00166 listener->name = listener->vhost;
00167
00168
00169
00170
00171
00172 if (setsockopt(listener->fd.fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)))
00173 {
00174 #ifdef _WIN32
00175 errno = WSAGetLastError();
00176 #endif
00177 report_error(L_ALL, "setting SO_REUSEADDR for listener %s:%s",
00178 get_listener_name(listener), errno);
00179 fd_close(&listener->fd);
00180 return(0);
00181 }
00182
00183
00184
00185
00186
00187 lsin.ss_port = htons(listener->port);
00188
00189 if (bind(listener->fd.fd, (struct sockaddr *)&lsin, lsin.ss_len))
00190 {
00191 #ifdef _WIN32
00192 errno = WSAGetLastError();
00193 #endif
00194 report_error(L_ALL, "binding listener socket %s:%s",
00195 get_listener_name(listener), errno);
00196 fd_close(&listener->fd);
00197 return(0);
00198 }
00199
00200 if (listen(listener->fd.fd, HYBRID_SOMAXCONN))
00201 {
00202 #ifdef _WIN32
00203 errno = WSAGetLastError();
00204 #endif
00205 report_error(L_ALL, "listen failed for %s:%s",
00206 get_listener_name(listener), errno);
00207 fd_close(&listener->fd);
00208 return(0);
00209 }
00210
00211
00212
00213 accept_connection(&listener->fd, listener);
00214 return 1;
00215 }
00216
00217 static struct Listener *
00218 find_listener(int port, struct irc_ssaddr *addr)
00219 {
00220 dlink_node *ptr;
00221 struct Listener *listener = NULL;
00222 struct Listener *last_closed = NULL;
00223
00224 DLINK_FOREACH(ptr, ListenerPollList.head)
00225 {
00226 listener = ptr->data;
00227
00228 if ((port == listener->port) &&
00229 (!memcmp(addr, &listener->addr, sizeof(struct irc_ssaddr))))
00230 {
00231
00232 if (!listener->fd.flags.open)
00233 last_closed = listener;
00234 else
00235 return (listener);
00236 }
00237 }
00238
00239 return (last_closed);
00240 }
00241
00242
00243
00244
00245
00246
00247
00248 void
00249 add_listener(int port, const char *vhost_ip, unsigned int flags)
00250 {
00251 struct Listener *listener;
00252 struct irc_ssaddr vaddr;
00253 struct addrinfo hints, *res;
00254 char portname[PORTNAMELEN + 1];
00255 #ifdef IPV6
00256 static short int pass = 0;
00257
00258 #endif
00259
00260
00261
00262
00263 if (!(port > 0 && port <= 0xFFFF))
00264 return;
00265
00266 memset(&vaddr, 0, sizeof(vaddr));
00267
00268
00269 memset(&hints, 0, sizeof(hints));
00270 hints.ai_family = AF_UNSPEC;
00271 hints.ai_socktype = SOCK_STREAM;
00272
00273 hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
00274
00275 #ifdef IPV6
00276 if (ServerInfo.can_use_v6)
00277 {
00278 snprintf(portname, PORTNAMELEN, "%d", port);
00279 irc_getaddrinfo("::", portname, &hints, &res);
00280 vaddr.ss.ss_family = AF_INET6;
00281 assert(res != NULL);
00282
00283 memcpy((struct sockaddr*)&vaddr, res->ai_addr, res->ai_addrlen);
00284 vaddr.ss_port = port;
00285 vaddr.ss_len = res->ai_addrlen;
00286 irc_freeaddrinfo(res);
00287 }
00288 else
00289 #endif
00290 {
00291 struct sockaddr_in *v4 = (struct sockaddr_in*) &vaddr;
00292 v4->sin_addr.s_addr = INADDR_ANY;
00293 vaddr.ss.ss_family = AF_INET;
00294 vaddr.ss_len = sizeof(struct sockaddr_in);
00295 v4->sin_port = htons(port);
00296 }
00297
00298 snprintf(portname, PORTNAMELEN, "%d", port);
00299
00300 if (vhost_ip)
00301 {
00302 if (irc_getaddrinfo(vhost_ip, portname, &hints, &res))
00303 return;
00304
00305 assert(res != NULL);
00306
00307 memcpy((struct sockaddr*)&vaddr, res->ai_addr, res->ai_addrlen);
00308 vaddr.ss_port = port;
00309 vaddr.ss_len = res->ai_addrlen;
00310 irc_freeaddrinfo(res);
00311 }
00312 #ifdef IPV6
00313 else if (pass == 0 && ServerInfo.can_use_v6)
00314 {
00315
00316 pass = 1;
00317 add_listener(port, "0.0.0.0", flags);
00318 }
00319 pass = 0;
00320 #endif
00321
00322 if ((listener = find_listener(port, &vaddr)))
00323 {
00324 listener->flags = flags;
00325 if (listener->fd.flags.open)
00326 return;
00327 }
00328 else
00329 {
00330 listener = make_listener(port, &vaddr);
00331 dlinkAdd(listener, &listener->listener_node, &ListenerPollList);
00332 listener->flags = flags;
00333 }
00334
00335 if (inetport(listener))
00336 listener->active = 1;
00337 else
00338 close_listener(listener);
00339 }
00340
00341
00342
00343
00344 static void
00345 close_listener(struct Listener *listener)
00346 {
00347 assert(listener != NULL);
00348
00349 if (listener == NULL)
00350 return;
00351
00352 if (listener->fd.flags.open)
00353 fd_close(&listener->fd);
00354
00355 listener->active = 0;
00356
00357 if (listener->ref_count)
00358 return;
00359
00360 free_listener(listener);
00361 }
00362
00363
00364
00365
00366 void
00367 close_listeners(void)
00368 {
00369 dlink_node *ptr;
00370 dlink_node *next_ptr;
00371
00372
00373 DLINK_FOREACH_SAFE(ptr, next_ptr, ListenerPollList.head)
00374 close_listener(ptr->data);
00375 }
00376
00377 #define TOOFAST_WARNING "ERROR :Trying to reconnect too fast.\r\n"
00378 #define DLINE_WARNING "ERROR :You have been D-lined.\r\n"
00379
00380 static void
00381 accept_connection(fde_t *pfd, void *data)
00382 {
00383 static time_t last_oper_notice = 0;
00384 struct irc_ssaddr addr;
00385 int fd;
00386 int pe;
00387 struct Listener *listener = data;
00388
00389 memset(&addr, 0, sizeof(addr));
00390
00391 assert(listener != NULL);
00392 if (listener == NULL)
00393 return;
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405 while ((fd = comm_accept(listener, &addr)) != -1)
00406 {
00407
00408
00409
00410 if (number_fd > hard_fdlimit - 10)
00411 {
00412 ++ServerStats->is_ref;
00413
00414
00415
00416
00417 if ((last_oper_notice + 20) <= CurrentTime)
00418 {
00419 sendto_realops_flags(UMODE_ALL, L_ALL, "All connections in use. (%s)",
00420 get_listener_name(listener));
00421 last_oper_notice = CurrentTime;
00422 }
00423
00424 if (!(listener->flags & LISTENER_SSL))
00425 send(fd, "ERROR :All connections in use\r\n", 32, 0);
00426 #ifdef _WIN32
00427 closesocket(fd);
00428 #else
00429 close(fd);
00430 #endif
00431 break;
00432 }
00433
00434
00435
00436
00437
00438 if ((pe = conf_connect_allowed(&addr, addr.ss.ss_family)) != 0)
00439 {
00440 ++ServerStats->is_ref;
00441 if (!(listener->flags & LISTENER_SSL))
00442 switch (pe)
00443 {
00444 case BANNED_CLIENT:
00445 send(fd, DLINE_WARNING, sizeof(DLINE_WARNING)-1, 0);
00446 break;
00447 case TOO_FAST:
00448 send(fd, TOOFAST_WARNING, sizeof(TOOFAST_WARNING)-1, 0);
00449 break;
00450 }
00451
00452 #ifdef _WIN32
00453 closesocket(fd);
00454 #else
00455 close(fd);
00456 #endif
00457 continue;
00458 }
00459
00460 ++ServerStats->is_ac;
00461 add_connection(listener, &addr, fd);
00462 }
00463
00464
00465 comm_setselect(&listener->fd, COMM_SELECT_READ, accept_connection,
00466 listener, 0);
00467 }