ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/branches/newio/src/s_bsd.c
Revision: 2396
Committed: Mon Jul 15 19:51:03 2013 UTC (10 years, 8 months ago) by michael
Content type: text/x-csrc
File size: 37744 byte(s)
Log Message:
- ioengine changes as of 15JUL13

File Contents

# User Rev Content
1 adx 30 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * s_bsd.c: Network functions.
4     *
5     * Copyright (C) 2002 by the past and present ircd coders, and others.
6 michael 2391 * Copyright (C) 1999 Thomas Helvey
7 adx 30 *
8     * This program is free software; you can redistribute it and/or modify
9     * it under the terms of the GNU General Public License as published by
10     * the Free Software Foundation; either version 2 of the License, or
11     * (at your option) any later version.
12     *
13     * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17     *
18     * You should have received a copy of the GNU General Public License
19     * along with this program; if not, write to the Free Software
20     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21     * USA
22     *
23 knight 31 * $Id$
24 adx 30 */
25    
26     #include "stdinc.h"
27     #include <netinet/in_systm.h>
28     #include <netinet/ip.h>
29     #include <netinet/tcp.h>
30 michael 1011 #include "list.h"
31 adx 30 #include "s_bsd.h"
32     #include "client.h"
33     #include "dbuf.h"
34     #include "irc_string.h"
35     #include "ircd.h"
36     #include "listener.h"
37     #include "numeric.h"
38     #include "packet.h"
39     #include "irc_res.h"
40     #include "restart.h"
41     #include "s_auth.h"
42 michael 1309 #include "conf.h"
43     #include "log.h"
44 adx 30 #include "s_serv.h"
45     #include "send.h"
46     #include "memory.h"
47     #include "s_user.h"
48 michael 2391 #include "msgq.h"
49 michael 2392 #include "ioengine.h"
50 adx 30
51    
52 michael 2389 dlink_list connection_list;
53 adx 30
54 michael 2389 static void client_sock_callback(struct Event *);
55     static void client_timer_callback(struct Event *);
56 adx 30
57 michael 2389 /** Temporary buffer for reading data from a peer. */
58     static char readbuf[SERVER_TCP_WINDOW];
59 adx 30
60 michael 2389 /*
61     * report_error text constants
62     */
63     const char* const ACCEPT_ERROR_MSG = "error accepting connection for %s: %s";
64     const char* const BIND_ERROR_MSG = "bind error for %s: %s";
65     const char* const CONNECT_ERROR_MSG = "connect to host %s failed: %s";
66     const char* const CONNLIMIT_ERROR_MSG = "connect limit exceeded for %s: %s";
67     const char* const LISTEN_ERROR_MSG = "listen error for %s: %s";
68     const char* const NONB_ERROR_MSG = "error setting non-blocking for %s: %s";
69     const char* const PEERNAME_ERROR_MSG = "getpeername failed for %s: %s";
70     const char* const POLL_ERROR_MSG = "poll error for %s: %s";
71     const char* const REGISTER_ERROR_MSG = "registering %s: %s";
72     const char* const REUSEADDR_ERROR_MSG = "error setting SO_REUSEADDR for %s: %s";
73     const char* const SELECT_ERROR_MSG = "select error for %s: %s";
74     const char* const SETBUFS_ERROR_MSG = "error setting buffer size for %s: %s";
75     const char* const SOCKET_ERROR_MSG = "error creating socket for %s: %s";
76     const char* const TOS_ERROR_MSG = "error setting TOS for %s: %s";
77    
78    
79 michael 2391 static int
80     is_blocked(int error)
81 adx 30 {
82 michael 2391 return EWOULDBLOCK == error
83     #ifdef ENOMEM
84     || ENOMEM == error
85 adx 30 #endif
86 michael 2391 #ifdef ENOBUFS
87     || ENOBUFS == error
88     #endif
89     || EAGAIN == error;
90 adx 30 }
91    
92     /* get_sockerr - get the error value from the socket or the current errno
93     *
94     * Get the *real* error from the socket (well try to anyway..).
95     * This may only work when SO_DEBUG is enabled but its worth the
96     * gamble anyway.
97     */
98     int
99     get_sockerr(int fd)
100     {
101     int errtmp = errno;
102     #ifdef SO_ERROR
103     int err = 0;
104     socklen_t len = sizeof(err);
105    
106 michael 967 if (-1 < fd && !getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &len))
107 adx 30 {
108     if (err)
109     errtmp = err;
110     }
111     errno = errtmp;
112     #endif
113     return errtmp;
114     }
115    
116 michael 2391 /** Mark a socket's address as reusable.
117     * @param[in] fd %Socket file descriptor to manipulate.
118     * @return Non-zero on success, or zero on failure.
119     */
120     int
121     os_set_reuseaddr(int fd)
122     {
123     unsigned int opt = 1;
124    
125     return !setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
126     }
127    
128     /** Set a socket's send and receive buffer sizes.
129     * @param[in] fd %Socket file descriptor to manipulate.
130     * @param[in] ssize New send buffer size.
131     * @param[in] rsize New receive buffer size.
132     * @return Non-zero on success, or zero on failure.
133     */
134     int
135     os_set_sockbufs(int fd, unsigned int ssize, unsigned int rsize)
136     {
137     unsigned int sopt = ssize;
138     unsigned int ropt = rsize;
139    
140     return !setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &ropt, sizeof(ropt)) &&
141     !setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sopt, sizeof(sopt));
142     }
143    
144     /** Set a socket's "type of service" value.
145     * @param[in] fd %Socket file descriptor to manipulate.
146     * @param[in] tos New type of service value to use.
147     * @return Non-zero on success, or zero on failure.
148     */
149     int
150     os_set_tos(int fd, int tos)
151     {
152     #if defined(IP_TOS) && defined(IPPROTO_IP)
153     unsigned int opt = tos;
154    
155     return !setsockopt(fd, IPPROTO_IP, IP_TOS, &opt, sizeof(opt));
156     #else
157     return 1;
158     #endif
159     }
160    
161     /** Disable IP options on a socket.
162     * @param[in] fd %Socket file descriptor to manipulate.
163     * @return Non-zero on success, or zero on failure.
164     */
165     int
166     os_disable_options(int fd)
167     {
168     #if defined(IP_OPTIONS) && defined(IPPROTO_IP)
169     return !setsockopt(fd, IPPROTO_IP, IP_OPTIONS, NULL, 0);
170     #else
171     return 1;
172     #endif
173     }
174    
175     /** Start listening on a socket.
176     * @param[in] fd Disconnected file descriptor.
177     * @param[in] backlog Maximum number of un-accept()ed connections to keep.
178     * @return Non-zero on success; zero on error.
179     */
180     int
181     os_set_listen(int fd, int backlog)
182     {
183     return !listen(fd, backlog);
184     }
185    
186     /** Attempt to read from a non-blocking socket.
187     * @param[in] fd File descriptor to read from.
188     * @param[out] buf Output buffer to read into.
189     * @param[in] length Number of bytes to read.
190     * @param[out] count_out Receives number of bytes actually read.
191     * @return An IOResult value indicating status.
192     */
193     IOResult
194     os_recv_nonb(int fd, char *buf, unsigned int length, unsigned int *count_out)
195     {
196     int res = 0;
197    
198     assert(buf);
199     assert(count_out);
200    
201     if ((res = recv(fd, buf, length, 0)) > 0)
202     {
203     *count_out = (unsigned int)res;
204     return IO_SUCCESS;
205     }
206    
207     if (res == 0)
208     {
209     *count_out = 0;
210     errno = 0; /* Or ECONNRESET? */
211     return IO_FAILURE;
212     }
213    
214     *count_out = 0;
215     return is_blocked(errno) ? IO_BLOCKED : IO_FAILURE;
216     }
217    
218     /** Attempt to read from a non-blocking UDP socket.
219     * @param[in] fd File descriptor to read from.
220     * @param[out] buf Output buffer to read into.
221     * @param[in] length Number of bytes to read.
222     * @param[out] length_out Receives number of bytes actually read.
223     * @param[out] addr_out Peer address that sent the message.
224     * @return An IOResult value indicating status.
225     */
226     IOResult
227     os_recvfrom_nonb(int fd, char *buf, unsigned int length,
228     unsigned int *length_out,
229     struct irc_ssaddr *addr)
230     {
231     unsigned int len = sizeof(struct irc_ssaddr);
232     int res = 0;
233    
234     assert(buf);
235     assert(length_out);
236     assert(addr_out);
237    
238     res = recvfrom(fd, buf, length, 0, (struct sockaddr *)addr, &len);
239    
240     if (res > -1)
241     {
242 michael 2392 *length_out = (unsigned int)res;
243 michael 2391 return IO_SUCCESS;
244     }
245    
246     *length_out = 0;
247     return is_blocked(errno) ? IO_BLOCKED : IO_FAILURE;
248     }
249    
250     /** Attempt to write on a connected socket.
251     * @param[in] fd File descriptor to write to.
252     * @param[in] buf Output buffer to send from.
253     * @param[in] length Number of bytes to write.
254     * @param[out] count_out Receives number of bytes actually written.
255     * @return An IOResult value indicating status.
256     */
257     IOResult
258     os_send_nonb(int fd, const char *buf, unsigned int length,
259     unsigned int *count_out)
260     {
261     int res = 0;
262    
263     assert(buf);
264     assert(count_out);
265    
266     if ((res = send(fd, buf, length, 0)) > -1)
267     {
268 michael 2392 *count_out = (unsigned int)res;
269 michael 2391 return IO_SUCCESS;
270     }
271    
272     *count_out = 0;
273     return is_blocked(errno) ? IO_BLOCKED : IO_FAILURE;
274     }
275    
276     /** Attempt a vectored write on a connected socket.
277     * @param[in] fd File descriptor to write to.
278     * @param[in] buf Message queue to send from.
279     * @param[out] count_in Number of bytes mapped from \a buf.
280     * @param[out] count_out Receives number of bytes actually written.
281     * @return An IOResult value indicating status.
282     */
283     IOResult
284     os_sendv_nonb(int fd, struct MsgQ *buf, unsigned int *count_in,
285     unsigned int *count_out)
286     {
287     int res = 0, count = 0;
288     struct iovec iov[IOV_MAX];
289    
290     assert(buf);
291     assert(count_in);
292     assert(count_out);
293    
294     *count_in = 0;
295     count = msgq_mapiov(buf, iov, IOV_MAX, count_in);
296    
297     if ((res = writev(fd, iov, count)) > -1)
298     {
299     *count_out = (unsigned int)res;
300     return IO_SUCCESS;
301     }
302    
303     *count_out = 0;
304     return is_blocked(errno) ? IO_BLOCKED : IO_FAILURE;
305     }
306    
307 michael 2392 /** Attempt to write on a non-blocking UDP socket.
308     * @param[in] fd File descriptor to write to.
309     * @param[in] buf Output buffer to send from.
310     * @param[in] length Number of bytes to write.
311     * @param[out] count_out Receives number of bytes actually written.
312     * @param[in] flags Flags for call to sendto().
313     * @param[in] peer Destination address of the message.
314     * @return An IOResult value indicating status.
315     */
316     IOResult os_sendto_nonb(int fd, const char *buf, unsigned int length,
317     unsigned int *count_out, unsigned int flags,
318     struct irc_ssaddr *peer)
319     {
320     int res = 0, size = 0;
321    
322     assert(buf);
323    
324     if ((res = sendto(fd, buf, length, flags, (struct sockaddr *)&peer, peer->ss_len)) > -1)
325     {
326     if (count_out)
327     *count_out = (unsigned int)res;
328     return IO_SUCCESS;
329     }
330    
331     if (count_out)
332     *count_out = 0;
333     return is_blocked(errno) ? IO_BLOCKED : IO_FAILURE;
334     }
335    
336     /** Start a non-blocking connection.
337     * @param[in] fd Disconnected file descriptor.
338     * @param[in] sin Target address for connection.
339     * @return IOResult code indicating status.
340     */
341     IOResult os_connect_nonb(int fd, const struct irc_ssaddr *addr)
342     {
343     int size;
344    
345     size = sockaddr_from_irc(&addr, sin, fd);
346     if (connect(fd, (struct sockaddr*) &addr, size))
347     return (errno == EINPROGRESS) ? IO_BLOCKED : IO_FAILURE;
348     return IO_SUCCESS;
349     }
350    
351     int
352     os_accept(int fd, struct irc_ssaddr *addr)
353     {
354     int new_fd = 0;
355     socklen_t addrlen = sizeof(struct irc_ssaddr);
356    
357     new_fd = accept(fd, (struct sockaddr *)addr, &addrlen);
358     if (new_fd < 0)
359     return -1;
360    
361     #ifdef IPV6
362     remove_ipv6_mapping(addr);
363     #else
364     addr->ss_len = addrlen;
365     #endif
366     setup_socket(new_fd);
367     return new_fd;
368     }
369    
370     int
371     os_socket(int family, int sock_type, int proto)
372     {
373     int fd;
374    
375     fd = socket(family, sock_type, proto);
376     if (fd < 0)
377     return -1;
378     setup_socket(fd);
379     return fd;
380     }
381    
382 adx 30 /*
383     * report_error - report an error from an errno.
384     * Record error to log and also send a copy to all *LOCAL* opers online.
385     *
386     * text is a *format* string for outputing error. It must
387     * contain only two '%s', the first will be replaced
388     * by the sockhost from the client_p, and the latter will
389     * be taken from sys_errlist[errno].
390     *
391     * client_p if not NULL, is the *LOCAL* client associated with
392     * the error.
393     *
394     * Cannot use perror() within daemon. stderr is closed in
395     * ircd and cannot be used. And, worse yet, it might have
396     * been reassigned to a normal connection...
397     *
398     * Actually stderr is still there IFF ircd was run with -s --Rodder
399     */
400    
401     void
402 michael 2389 report_error(int level, const char *text, const char *who, int error)
403 adx 30 {
404 michael 2389 int errtmp = errno; /* debug may change 'errno' */
405     const char *errmsg = (error) ? strerror(error) : "";
406 adx 30
407 michael 2389 if (!errmsg)
408     errmsg = "Unknown error";
409    
410     if (EmptyString(who))
411     who = "unknown";
412    
413 michael 1618 sendto_realops_flags(UMODE_DEBUG, level, SEND_NOTICE,
414 michael 2389 text, who, errmsg);
415     ilog(LOG_TYPE_IRCD, text, who, errmsg);
416     errno = errtmp;
417 adx 30 }
418    
419     /*
420     * setup_socket()
421     *
422     * Set the socket non-blocking, and other wonderful bits.
423     */
424 michael 2389 static void
425     setup_socket(int fd)
426 adx 30 {
427     int opt = 1;
428    
429 michael 967 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
430 adx 30
431     #ifdef IPTOS_LOWDELAY
432     opt = IPTOS_LOWDELAY;
433 michael 967 setsockopt(fd, IPPROTO_IP, IP_TOS, &opt, sizeof(opt));
434 adx 30 #endif
435    
436     fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
437     }
438    
439     /*
440     * close_connection
441     * Close the physical connection. This function must make
442     * MyConnect(client_p) == FALSE, and set client_p->from == NULL.
443     */
444     void
445     close_connection(struct Client *client_p)
446     {
447 michael 1391 dlink_node *ptr = NULL;
448 adx 30
449 michael 1391 assert(client_p);
450 adx 30
451 michael 1143 if (IsClient(client_p))
452 adx 30 {
453 michael 1143 ++ServerStats.is_cl;
454     ServerStats.is_cbs += client_p->localClient->send.bytes;
455     ServerStats.is_cbr += client_p->localClient->recv.bytes;
456 michael 1241 ServerStats.is_cti += CurrentTime - client_p->localClient->firsttime;
457 michael 1143 }
458     else if (IsServer(client_p))
459     {
460 michael 896 ++ServerStats.is_sv;
461     ServerStats.is_sbs += client_p->localClient->send.bytes;
462     ServerStats.is_sbr += client_p->localClient->recv.bytes;
463 michael 1241 ServerStats.is_sti += CurrentTime - client_p->localClient->firsttime;
464 adx 30
465 michael 1391 DLINK_FOREACH(ptr, server_items.head)
466 adx 30 {
467 michael 1632 struct MaskItem *conf = ptr->data;
468 michael 1391
469     if (irccmp(conf->name, client_p->name))
470     continue;
471    
472 adx 30 /*
473 michael 1391 * Reset next-connect cycle of all connect{} blocks that match
474     * this servername.
475 adx 30 */
476 michael 1649 conf->until = CurrentTime + conf->class->con_freq;
477 adx 30 }
478     }
479     else
480 michael 896 ++ServerStats.is_ni;
481 adx 30
482 michael 2389 if (s_fd(&client_p->localClient->socket)> -1)
483 michael 451 {
484 michael 2389 flush_connections(client_p);
485     dlinkDelete(&client_p->localClient->node, &connection_list);
486     close(s_fd(&client_p->localClient->socket));
487     socket_del(&client_p->localClient->socket); /* Queue a socket delete */
488     s_fd(&client_p->localClient->socket) = -1;
489 michael 451 }
490 adx 30
491 michael 2389 AddFlag(client_p, FLAGS_DEADSOCKET);
492    
493     MsgQClear(&client_p->localClient->sendQ);
494     client_drop_sendq(client_p->localClient);
495     DBufClear(&client_p->localClient->recvQ);
496    
497 adx 30 MyFree(client_p->localClient->passwd);
498 michael 2396 client_p->localClient->passwd = NULL;
499    
500 michael 1632 detach_conf(client_p, CONF_CLIENT|CONF_OPER|CONF_SERVER);
501 adx 30 client_p->from = NULL; /* ...this should catch them! >:) --msa */
502 michael 2389
503     if (client_p->localClient->listener)
504     {
505     assert(0 < client_p->localClient->listener->ref_count);
506 michael 2396 listener_release(client_p->localClient->listener);
507     client_p->localClient->listener = NULL;
508 michael 2389 }
509 adx 30 }
510    
511     #ifdef HAVE_LIBCRYPTO
512     /*
513     * ssl_handshake - let OpenSSL initialize the protocol. Register for
514     * read/write events if necessary.
515     */
516     static void
517     ssl_handshake(int fd, struct Client *client_p)
518     {
519 michael 2228 X509 *cert = NULL;
520 adx 30 int ret = SSL_accept(client_p->localClient->fd.ssl);
521 michael 2228 int err = SSL_get_error(client_p->localClient->fd.ssl, ret);
522 adx 30
523 michael 2228 ilog(LOG_TYPE_IRCD, "SSL Error %d %s", err, ERR_error_string(err, NULL));
524    
525     if ((cert = SSL_get_peer_certificate(client_p->localClient->fd.ssl)))
526     {
527     int res = SSL_get_verify_result(client_p->localClient->fd.ssl);
528 michael 2235 char buf[EVP_MAX_MD_SIZE * 2 + 1] = { '\0' };
529 michael 2287 unsigned char md[EVP_MAX_MD_SIZE] = { '\0' };
530 michael 2228
531     if (res == X509_V_OK || res == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN ||
532     res == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE ||
533     res == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)
534 michael 2229 {
535 michael 2235 unsigned int i = 0, n = 0;
536    
537     if (X509_digest(cert, EVP_sha256(), md, &n))
538     {
539     for (; i < n; ++i)
540     snprintf(buf + 2 * i, 3, "%02X", md[i]);
541     client_p->certfp = xstrdup(buf);
542     }
543 michael 2229 }
544 michael 2228 else
545     ilog(LOG_TYPE_IRCD, "Client %s!%s@%s gave bad SSL client certificate: %d",
546     client_p->name, client_p->username, client_p->host, res);
547     X509_free(cert);
548     }
549    
550 adx 30 if (ret <= 0)
551 michael 2228 {
552 adx 30 switch (SSL_get_error(client_p->localClient->fd.ssl, ret))
553     {
554     case SSL_ERROR_WANT_WRITE:
555     comm_setselect(&client_p->localClient->fd, COMM_SELECT_WRITE,
556     (PF *) ssl_handshake, client_p, 0);
557     return;
558    
559     case SSL_ERROR_WANT_READ:
560     comm_setselect(&client_p->localClient->fd, COMM_SELECT_READ,
561     (PF *) ssl_handshake, client_p, 0);
562     return;
563    
564     default:
565     exit_client(client_p, client_p, "Error during SSL handshake");
566     return;
567     }
568 michael 2228 }
569 adx 30
570 michael 2181 start_auth(client_p);
571 adx 30 }
572     #endif
573    
574     /*
575     * add_connection - creates a client which has just connected to us on
576     * the given fd. The sockhost field is initialized with the ip# of the host.
577     * An unique id is calculated now, in case it is needed for auth.
578     * The client is sent to the auth module for verification, and not put in
579     * any client list yet.
580     */
581     void
582 michael 549 add_connection(struct Listener *listener, struct irc_ssaddr *irn, int fd)
583 adx 30 {
584 michael 1123 struct Client *new_client = make_client(NULL);
585 michael 549
586 adx 30 fd_open(&new_client->localClient->fd, fd, 1,
587     (listener->flags & LISTENER_SSL) ?
588     "Incoming SSL connection" : "Incoming connection");
589    
590 michael 1123 /*
591 adx 30 * copy address to 'sockhost' as a string, copy it to host too
592     * so we have something valid to put into error messages...
593     */
594 michael 549 memcpy(&new_client->localClient->ip, irn, sizeof(struct irc_ssaddr));
595 adx 30
596 michael 1123 getnameinfo((struct sockaddr *)&new_client->localClient->ip,
597     new_client->localClient->ip.ss_len, new_client->sockhost,
598     sizeof(new_client->sockhost), NULL, 0, NI_NUMERICHOST);
599 adx 30 new_client->localClient->aftype = new_client->localClient->ip.ss.ss_family;
600 michael 1072
601 michael 1858 #ifdef HAVE_LIBGEOIP
602     /* XXX IPV6 SUPPORT XXX */
603     if (irn->ss.ss_family == AF_INET && geoip_ctx)
604     {
605     const struct sockaddr_in *v4 = (const struct sockaddr_in *)&new_client->localClient->ip;
606     new_client->localClient->country_id = GeoIP_id_by_ipnum(geoip_ctx, (unsigned long)ntohl(v4->sin_addr.s_addr));
607     }
608     #endif
609    
610 michael 1123 if (new_client->sockhost[0] == ':' && new_client->sockhost[1] == ':')
611 adx 30 {
612 michael 1072 strlcpy(new_client->host, "0", sizeof(new_client->host));
613     strlcpy(new_client->host+1, new_client->sockhost, sizeof(new_client->host)-1);
614 michael 1123 memmove(new_client->sockhost+1, new_client->sockhost, sizeof(new_client->sockhost)-1);
615     new_client->sockhost[0] = '0';
616 michael 549 }
617     else
618 michael 1072 strlcpy(new_client->host, new_client->sockhost, sizeof(new_client->host));
619 adx 30
620     new_client->localClient->listener = listener;
621     ++listener->ref_count;
622    
623     #ifdef HAVE_LIBCRYPTO
624 michael 549 if (listener->flags & LISTENER_SSL)
625 adx 30 {
626 michael 967 if ((new_client->localClient->fd.ssl = SSL_new(ServerInfo.server_ctx)) == NULL)
627 adx 30 {
628 michael 1247 ilog(LOG_TYPE_IRCD, "SSL_new() ERROR! -- %s",
629 adx 30 ERR_error_string(ERR_get_error(), NULL));
630    
631     SetDead(new_client);
632     exit_client(new_client, new_client, "SSL_new failed");
633     return;
634     }
635    
636 michael 2246 AddFlag(new_client, FLAGS_SSL);
637 adx 30 SSL_set_fd(new_client->localClient->fd.ssl, fd);
638     ssl_handshake(0, new_client);
639     }
640     else
641     #endif
642 michael 2181 start_auth(new_client);
643 michael 2389 #ifdef NEWIO
644    
645     s_fd(&new_client->localClient->socket) = fd;
646     if (!socket_add(&new_client->localClient->socket, client_sock_callback,
647     new_client->localClient, SS_CONNECTED, 0, fd))
648     {
649     ++ServerStats.is_ref;
650     write(fd, register_message, strlen(register_message));
651     close(fd);
652     s_fd(&new_client->localClient->socket) = -1;
653     return;
654     }
655    
656     new_client->localClient->freeflag |= FREEFLAG_SOCKET;
657     new_client->localClient->listener = listener;
658     ++listener->ref_count;
659    
660     /* if we've made it this far we can put the client on the auth query pile */
661     start_auth(new_client);
662     #endif
663 adx 30 }
664    
665 michael 2389 /** Determines whether to tell the events engine we're interested in
666     * writable events.
667     * \param client_p Client for which to decide this.
668     */
669     void
670     update_write(struct Client *client_p)
671     {
672     /*
673     * If there are messages that need to be sent along, or if the client
674     * is in the middle of a /list, then we need to tell the engine that
675     * we're interested in writable events--otherwise, we need to drop
676     * that interest.
677     */
678     socket_events(&client_p->localClient->socket,
679     ((MsgQLength(&client_p->localClient->sendQ) || client_p->localClient->list_task) ?
680     SOCK_ACTION_ADD : SOCK_ACTION_DEL) | SOCK_EVENT_WRITABLE);
681     }
682    
683     /** Read a 'packet' of data from a connection and process it. Read in
684     * 8k chunks to give a better performance rating (for server
685     * connections). Do some tricky stuff for client connections to make
686     * sure they don't do any flooding >:-) -avalon
687     * @param client_p Client from which to read data.
688     * @param socket_ready If non-zero, more data can be read from the client's socket.
689     * @return Positive number on success, zero on connection-fatal failure, negative
690     * if user is killed.
691     */
692     static int
693     read_packet(struct Client *client_p, int socket_ready)
694     {
695     unsigned int dolen = 0, length = 0;
696    
697     if (socket_ready && !(IsClient(client_p) &&
698 michael 2396 DBufLength&(client_p->localClient->recvQ) > get_recvq(&client_p->localClient->confs)))
699 michael 2389 {
700     switch (os_recv_nonb(cli_fd(client_p), readbuf, sizeof(readbuf), &length))
701     {
702     case IO_SUCCESS:
703     if (length)
704     {
705     client_p->localClient->lasttime = CurrentTime;
706    
707     if (client_p->localClient->lasttime > client_p->localClient->since)
708     client_p->localClient->since = CurrentTime;
709    
710     ClearPingSent(client_p);
711     DelFlag(client_p, FLAGS_NOEWLINE);
712     }
713     break;
714    
715     case IO_BLOCKED:
716     break;
717     case IO_FAILURE:
718     client_p->localClient->error = errno;
719     /* AddFlag(client_p, FLAG_DEADSOCKET); */
720     return 0;
721     }
722     }
723    
724     /*
725     * For server connections, we process as many as we can without
726     * worrying about the time of day or anything :)
727     */
728     if (length > 0 && IsServer(client_p))
729     return server_dopacket(client_p, readbuf, length);
730     else if (length > 0 && (IsHandshake(client_p) || IsConnecting(client_p)))
731     return connect_dopacket(client_p, readbuf, length);
732     else
733     {
734     /*
735     * Before we even think of parsing what we just read, stick
736     * it on the end of the receive queue and do it when its
737     * turn comes around.
738     */
739     if (length > 0 && !dbuf_put(&client_p->localClient->recvQ, readbuf, length))
740     return exit_client(client_p, client_p, "dbuf_put fail");
741    
742 michael 2396 if (DBufLength(&client_p->localClient_recvQ) > get_recvq(&client_p->localClient->confs))
743 michael 2389 return exit_client(client_p, client_p, "Excess Flood");
744    
745     while (DBufLength(&client_p->localClient->recvQ) && !NoNewLine(client_p) &&
746     (IsTrusted(client_p) || cli_since(client_p) - CurrentTime < 10))
747     {
748     dolen = dbuf_getmsg(&client_p->localClient->recvQ,
749     client_p->localClient->buffer, IRCD_BUFSIZE);
750    
751     /*
752     * Devious looking...whats it do ? well..if a client
753     * sends a *long* message without any CR or LF, then
754     * dbuf_getmsg fails and we pull it out using this
755     * loop which just gets the next 512 bytes and then
756     * deletes the rest of the buffer contents.
757     * -avalon
758     */
759     if (dolen == 0)
760     {
761     if (DBufLength(&client_p->localClient->recvQ) < 510)
762     AddFlag(client_p, FLAGS_NONEWLINE);
763     else
764     {
765     /*
766     * More than 512 bytes in the line - drop the input and yell
767     * at the client.
768     */
769     DBufClear(&client_p->localClient->recvQ);
770 michael 2396 sendto_one(client_p, form_str(ERR_INPUTTOOLONG), me.name,
771     client_p->name[0] ? client_p->name : "*");
772 michael 2389 }
773     }
774     else if (client_dopacket(client_p, dolen) == CPTR_KILLED)
775     return CPTR_KILLED;
776    
777     /*
778     * If it has become registered as a Server
779     * then skip the per-message parsing below.
780     */
781     if (IsHandshake(client_p) || IsServer(client_p))
782     {
783     while (-1)
784     {
785     dolen = dbuf_get(&client_p->localClient->recvQ, readbuf, sizeof(readbuf));
786    
787     if (dolen <= 0)
788     return 1;
789     if (dolen == 0)
790     {
791     if (DBufLength(&client_p->localClient->recvQ) < 510)
792     AddFlag(client_p, FLAGS_NONEWLINE);
793     else
794     DBufClear(&client_p->localClient->recvQ);
795     }
796     else if ((IsServer(client_p) &&
797     server_dopacket(client_p, readbuf, dolen) == CPTR_KILLED) ||
798     (!IsServer(client_p) &&
799     connect_dopacket(client_p, readbuf, dolen) == CPTR_KILLED))
800     return CPTR_KILLED;
801     }
802     }
803     }
804    
805     /* If there's still data to process, wait 2 seconds first */
806     if (DBufLength(&client_p->localClient->recvQ) && !HasFlag(client_p, FLAGS_NONEWLINE) &&
807     !t_onqueue(&client_p->localClient->proc))
808     {
809     client_p->localClient->freeflag |= FREEFLAG_TIMER;
810     timer_add(&client_p->localClient->proc, client_timer_callback, client_p->localClient,
811     TT_RELATIVE, 2);
812     }
813     }
814     return 1;
815     }
816    
817     /** Attempt to send a sequence of bytes to the connection.
818     * As a side effect, updates \a cptr's FLAG_BLOCKED setting
819     * and sendB/sendK fields.
820     * @param cptr Client that should receive data.
821     * @param buf Message buffer to send to client.
822     * @return Negative on connection-fatal error; otherwise
823     * number of bytes sent.
824     */
825     unsigned int
826     deliver_it(struct Client *client_p, struct MsgQ *buf)
827     {
828     unsigned int bytes_written = 0, bytes_count = 0;
829    
830     assert(client_p);
831    
832     switch (os_sendv_nonb(cli_fd(cptr), buf, &bytes_count, &bytes_written))
833     {
834     case IO_SUCCESS:
835     DelFlag(client_p, FLAG_BLOCKED);
836    
837     client_p->localClient->send.bytes += bytes_written;
838     me.localClient->send.bytes += bytes_written;
839    
840     /* A partial write implies that future writes will block. */
841     if (bytes_written < bytes_count)
842     AddFlag(client_p, FLAG_BLOCKED);
843     break;
844     case IO_BLOCKED:
845     AddFlag(client_p, FLAG_BLOCKED);
846     break;
847     case IO_FAILURE:
848     client_p->localClient->error = errno;
849     AddFlag(client_p, FLAG_DEADSOCKET);
850     break;
851     }
852    
853     return bytes_written;
854     }
855    
856 adx 30 /*
857     * stolen from squid - its a neat (but overused! :) routine which we
858     * can use to see whether we can ignore this errno or not. It is
859     * generally useful for non-blocking network IO related errnos.
860     * -- adrian
861     */
862     int
863     ignoreErrno(int ierrno)
864     {
865     switch (ierrno)
866     {
867     case EINPROGRESS:
868     case EWOULDBLOCK:
869     #if EAGAIN != EWOULDBLOCK
870     case EAGAIN:
871     #endif
872     case EALREADY:
873     case EINTR:
874     #ifdef ERESTART
875     case ERESTART:
876     #endif
877     return 1;
878     default:
879     return 0;
880     }
881     }
882    
883     /*
884     * comm_settimeout() - set the socket timeout
885     *
886     * Set the timeout for the fd
887     */
888     void
889     comm_settimeout(fde_t *fd, time_t timeout, PF *callback, void *cbdata)
890     {
891     assert(fd->flags.open);
892    
893     fd->timeout = CurrentTime + (timeout / 1000);
894     fd->timeout_handler = callback;
895     fd->timeout_data = cbdata;
896     }
897    
898     /*
899     * comm_setflush() - set a flush function
900     *
901     * A flush function is simply a function called if found during
902     * comm_timeouts(). Its basically a second timeout, except in this case
903     * I'm too lazy to implement multiple timeout functions! :-)
904     * its kinda nice to have it separate, since this is designed for
905     * flush functions, and when comm_close() is implemented correctly
906     * with close functions, we _actually_ don't call comm_close() here ..
907     * -- originally Adrian's notes
908     * comm_close() is replaced with fd_close() in fdlist.c
909     */
910     void
911     comm_setflush(fde_t *fd, time_t timeout, PF *callback, void *cbdata)
912     {
913     assert(fd->flags.open);
914    
915     fd->flush_timeout = CurrentTime + (timeout / 1000);
916     fd->flush_handler = callback;
917     fd->flush_data = cbdata;
918     }
919    
920     /*
921     * void comm_connect_tcp(int fd, const char *host, unsigned short port,
922     * struct sockaddr *clocal, int socklen,
923     * CNCB *callback, void *data, int aftype, int timeout)
924     * Input: An fd to connect with, a host and port to connect to,
925     * a local sockaddr to connect from + length(or NULL to use the
926     * default), a callback, the data to pass into the callback, the
927     * address family.
928     * Output: None.
929     * Side-effects: A non-blocking connection to the host is started, and
930     * if necessary, set up for selection. The callback given
931     * may be called now, or it may be called later.
932     */
933     void
934     comm_connect_tcp(fde_t *fd, const char *host, unsigned short port,
935     struct sockaddr *clocal, int socklen, CNCB *callback,
936     void *data, int aftype, int timeout)
937     {
938     struct addrinfo hints, *res;
939 michael 992 char portname[PORTNAMELEN + 1];
940 adx 30
941     assert(callback);
942     fd->connect.callback = callback;
943     fd->connect.data = data;
944    
945     fd->connect.hostaddr.ss.ss_family = aftype;
946     fd->connect.hostaddr.ss_port = htons(port);
947    
948     /* Note that we're using a passed sockaddr here. This is because
949     * generally you'll be bind()ing to a sockaddr grabbed from
950     * getsockname(), so this makes things easier.
951     * XXX If NULL is passed as local, we should later on bind() to the
952     * virtual host IP, for completeness.
953     * -- adrian
954     */
955     if ((clocal != NULL) && (bind(fd->fd, clocal, socklen) < 0))
956     {
957     /* Failure, call the callback with COMM_ERR_BIND */
958     comm_connect_callback(fd, COMM_ERR_BIND);
959     /* ... and quit */
960     return;
961     }
962    
963     /* Next, if we have been given an IP, get the addr and skip the
964     * DNS check (and head direct to comm_connect_tryconnect().
965     */
966     memset(&hints, 0, sizeof(hints));
967     hints.ai_family = AF_UNSPEC;
968     hints.ai_socktype = SOCK_STREAM;
969     hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
970    
971 michael 992 snprintf(portname, sizeof(portname), "%d", port);
972 adx 30
973 michael 1123 if (getaddrinfo(host, portname, &hints, &res))
974 adx 30 {
975     /* Send the DNS request, for the next level */
976 db 871 if (aftype == AF_INET6)
977 michael 992 gethost_byname_type(comm_connect_dns_callback, fd, host, T_AAAA);
978 db 871 else
979 michael 992 gethost_byname_type(comm_connect_dns_callback, fd, host, T_A);
980 adx 30 }
981     else
982     {
983     /* We have a valid IP, so we just call tryconnect */
984     /* Make sure we actually set the timeout here .. */
985     assert(res != NULL);
986     memcpy(&fd->connect.hostaddr, res->ai_addr, res->ai_addrlen);
987     fd->connect.hostaddr.ss_len = res->ai_addrlen;
988     fd->connect.hostaddr.ss.ss_family = res->ai_family;
989 michael 1123 freeaddrinfo(res);
990 adx 30 comm_settimeout(fd, timeout*1000, comm_connect_timeout, NULL);
991     comm_connect_tryconnect(fd, NULL);
992     }
993     }
994    
995     /*
996     * comm_connect_callback() - call the callback, and continue with life
997     */
998     static void
999     comm_connect_callback(fde_t *fd, int status)
1000     {
1001     CNCB *hdl;
1002    
1003     /* This check is gross..but probably necessary */
1004     if (fd->connect.callback == NULL)
1005     return;
1006    
1007     /* Clear the connect flag + handler */
1008     hdl = fd->connect.callback;
1009     fd->connect.callback = NULL;
1010    
1011     /* Clear the timeout handler */
1012     comm_settimeout(fd, 0, NULL, NULL);
1013    
1014     /* Call the handler */
1015     hdl(fd, status, fd->connect.data);
1016     }
1017    
1018     /*
1019     * comm_connect_timeout() - this gets called when the socket connection
1020     * times out. This *only* can be called once connect() is initially
1021     * called ..
1022     */
1023     static void
1024     comm_connect_timeout(fde_t *fd, void *notused)
1025     {
1026     /* error! */
1027     comm_connect_callback(fd, COMM_ERR_TIMEOUT);
1028     }
1029    
1030     /*
1031     * comm_connect_dns_callback() - called at the completion of the DNS request
1032     *
1033     * The DNS request has completed, so if we've got an error, return it,
1034     * otherwise we initiate the connect()
1035     */
1036     static void
1037 michael 992 comm_connect_dns_callback(void *vptr, const struct irc_ssaddr *addr, const char *name)
1038 adx 30 {
1039     fde_t *F = vptr;
1040    
1041 michael 992 if (name == NULL)
1042 adx 30 {
1043     comm_connect_callback(F, COMM_ERR_DNS);
1044     return;
1045     }
1046    
1047     /* No error, set a 10 second timeout */
1048     comm_settimeout(F, 30*1000, comm_connect_timeout, NULL);
1049    
1050     /* Copy over the DNS reply info so we can use it in the connect() */
1051     /*
1052     * Note we don't fudge the refcount here, because we aren't keeping
1053     * the DNS record around, and the DNS cache is gone anyway..
1054     * -- adrian
1055     */
1056 michael 992 memcpy(&F->connect.hostaddr, addr, addr->ss_len);
1057 adx 30 /* The cast is hacky, but safe - port offset is same on v4 and v6 */
1058     ((struct sockaddr_in *) &F->connect.hostaddr)->sin_port =
1059     F->connect.hostaddr.ss_port;
1060 michael 992 F->connect.hostaddr.ss_len = addr->ss_len;
1061 adx 30
1062     /* Now, call the tryconnect() routine to try a connect() */
1063     comm_connect_tryconnect(F, NULL);
1064     }
1065    
1066     /* static void comm_connect_tryconnect(int fd, void *notused)
1067     * Input: The fd, the handler data(unused).
1068     * Output: None.
1069     * Side-effects: Try and connect with pending connect data for the FD. If
1070     * we succeed or get a fatal error, call the callback.
1071     * Otherwise, it is still blocking or something, so register
1072     * to select for a write event on this FD.
1073     */
1074     static void
1075     comm_connect_tryconnect(fde_t *fd, void *notused)
1076     {
1077     int retval;
1078    
1079     /* This check is needed or re-entrant s_bsd_* like sigio break it. */
1080     if (fd->connect.callback == NULL)
1081     return;
1082    
1083     /* Try the connect() */
1084     retval = connect(fd->fd, (struct sockaddr *) &fd->connect.hostaddr,
1085     fd->connect.hostaddr.ss_len);
1086    
1087     /* Error? */
1088     if (retval < 0)
1089     {
1090     /*
1091     * If we get EISCONN, then we've already connect()ed the socket,
1092     * which is a good thing.
1093     * -- adrian
1094     */
1095     if (errno == EISCONN)
1096     comm_connect_callback(fd, COMM_OK);
1097     else if (ignoreErrno(errno))
1098     /* Ignore error? Reschedule */
1099     comm_setselect(fd, COMM_SELECT_WRITE, comm_connect_tryconnect,
1100     NULL, 0);
1101     else
1102     /* Error? Fail with COMM_ERR_CONNECT */
1103     comm_connect_callback(fd, COMM_ERR_CONNECT);
1104     return;
1105     }
1106    
1107     /* If we get here, we've suceeded, so call with COMM_OK */
1108     comm_connect_callback(fd, COMM_OK);
1109     }
1110    
1111     /*
1112     * comm_errorstr() - return an error string for the given error condition
1113     */
1114     const char *
1115     comm_errstr(int error)
1116     {
1117     if (error < 0 || error >= COMM_ERR_MAX)
1118     return "Invalid error number!";
1119     return comm_err_str[error];
1120     }
1121    
1122     /*
1123     * remove_ipv6_mapping() - Removes IPv4-In-IPv6 mapping from an address
1124 michael 1122 * OSes with IPv6 mapping listening on both
1125 adx 30 * AF_INET and AF_INET6 map AF_INET connections inside AF_INET6 structures
1126     *
1127     */
1128     #ifdef IPV6
1129     void
1130     remove_ipv6_mapping(struct irc_ssaddr *addr)
1131     {
1132     if (addr->ss.ss_family == AF_INET6)
1133     {
1134 michael 1122 if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)addr)->sin6_addr))
1135     {
1136     struct sockaddr_in6 v6;
1137     struct sockaddr_in *v4 = (struct sockaddr_in *)addr;
1138 adx 30
1139 michael 1122 memcpy(&v6, addr, sizeof(v6));
1140     memset(v4, 0, sizeof(struct sockaddr_in));
1141     memcpy(&v4->sin_addr, &v6.sin6_addr.s6_addr[12], sizeof(v4->sin_addr));
1142    
1143 adx 30 addr->ss.ss_family = AF_INET;
1144     addr->ss_len = sizeof(struct sockaddr_in);
1145     }
1146     else
1147     addr->ss_len = sizeof(struct sockaddr_in6);
1148     }
1149     else
1150     addr->ss_len = sizeof(struct sockaddr_in);
1151     }
1152     #endif
1153 michael 2389
1154     /** Process events on a client socket.
1155     * @param ev Socket event structure that has a struct Connection as
1156     * its associated data.
1157     */
1158     static void
1159     client_sock_callback(struct Event *ev)
1160     {
1161     struct Client *client_p = NULL;
1162     struct Connection *con = NULL;
1163     const char *fmt = "%s";
1164     const char *fallback = NULL;
1165    
1166     assert(ev_socket(ev));
1167     assert(s_data(ev_socket(ev)));
1168    
1169 michael 2396 con = s_data(ev_socket(ev));
1170 michael 2389
1171     assert(con->localClient || ev_type(ev) == ET_DESTROY);
1172    
1173 michael 2396 client_p = con->from;
1174 michael 2389
1175     assert(!client_p || con == client_p->localClient);
1176    
1177     switch (ev_type(ev))
1178     {
1179     case ET_DESTROY:
1180     con->freeflag &= ~FREEFLAG_SOCKET;
1181    
1182     if (!con_freeflag(con) && !client_p)
1183     free_connection(con);
1184     break;
1185    
1186     case ET_CONNECT: /* Socket connection completed */
1187     if (!completed_connection(client_p) || IsDead(client_p))
1188     fallback = client_p->info;
1189     break;
1190    
1191     case ET_ERROR: /* An error occurred */
1192     fallback = client_p->info;
1193     client_p->error = ev_data(ev);
1194    
1195     /*
1196     * If the OS told us we have a bad file descriptor, we should
1197     * record that for future reference.
1198     */
1199 michael 2396 if (client_p->localClient->error == EBADF)
1200 michael 2389 s_fd(&client_p->localClient->socket) = -1;
1201    
1202     if (s_state(&con->socket) == SS_CONNECTING)
1203     {
1204     completed_connection(client_p);
1205    
1206     /*
1207     * For some reason, the os_get_sockerr() in completed_connect()
1208     * can return 0 even when ev_data(ev) indicates a real error, so
1209     * re-assign the client error here.
1210     */
1211 michael 2396 client_p->localClient->error = ev_data(ev);
1212 michael 2389 break;
1213     }
1214    
1215     /*FALLTHROUGH*/
1216     case ET_EOF: /* End of file on socket */
1217     SetFlag(client_p, FLAG_DEADSOCKET);
1218    
1219 michael 2396 if ((IsServer(client_p) || IsHandshake(client_p)) && client_p->localClient->error == 0)
1220 michael 2389 {
1221     exit_client_msg(client_p, client_p, "Server %s closed the connection (%s)",
1222     client_p->name, client_p->servptr->->last_error_msg);
1223     return;
1224     }
1225     else
1226     {
1227     fmt = "Read error: %s";
1228     fallback = "EOF from client";
1229     }
1230    
1231     break;
1232    
1233     case ET_WRITE: /* Socket is writable */
1234     DelFlag(client_p, FLAGS_BLOCKED);
1235    
1236 michael 2396 if (client_p->localClient->list_task && MsgQLength(&client_p->localClient->sendQ) < 2048)
1237 michael 2389 list_next_channels(client_p);
1238     send_queued(client_p);
1239     break;
1240    
1241     case ET_READ: /* Socket is readable */
1242     if (!IsDead(client_p))
1243     {
1244     if (read_packet(client_p, 1) == 0) /* Error while reading packet */
1245     fallback = "EOF from client";
1246     }
1247    
1248     break;
1249    
1250     default:
1251     assert(0 && "Unrecognized socket event in client_sock_callback()");
1252     break;
1253     }
1254    
1255     assert(!client_p || !client_p->localClient || con == client_p->localClient);
1256    
1257     if (fallback)
1258     {
1259 michael 2396 const char *msg = (client_p->localClient->error) ? strerror(client_p->localClient->error) : fallback;
1260 michael 2389
1261     if (!msg)
1262     msg = "Unknown error";
1263     exit_client_msg(client_p, client_p, fmt, msg);
1264     }
1265     }
1266    
1267     /** Process a timer on client socket.
1268     * @param ev Timer event that has a struct Connection as its
1269     * associated data.
1270     */
1271     static void
1272     client_timer_callback(struct Event *ev)
1273     {
1274     struct Client *client_p = NULL;
1275     struct Connection *con = NULL;
1276    
1277     assert(ev_timer(ev));
1278     assert(t_data(ev_timer(ev)));
1279     assert(ET_DESTROY == ev_type(ev) || ET_EXPIRE == ev_type(ev));
1280    
1281 michael 2396 con = t_data(ev_timer(ev));
1282 michael 2389
1283     assert(con->client || ev_type(ev) == ET_DESTROY);
1284    
1285 michael 2396 client_p = con->from;
1286 michael 2389
1287     assert(!client_p || con == client_p->localClient);
1288    
1289     if (ev_type(ev) == ET_DESTROY)
1290     {
1291     conf->freeflag &= ~FREEFLAG_TIMER; /* Timer has expired... */
1292    
1293     if (!con->freeflag && !client_p)
1294     free_connection(con); /* Client is being destroyed */
1295     }
1296     else
1297     read_packet(client_p, 0); /* read_packet will re-add timer if needed */
1298    
1299     assert(!client_p || !client_p->localClient || con == client_p->localClient);
1300     }

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision