22 |
|
* $Id$ |
23 |
|
*/ |
24 |
|
#include "stdinc.h" |
25 |
< |
#include "tools.h" |
25 |
> |
#include "list.h" |
26 |
|
#include "s_bsd.h" |
27 |
< |
#include "s_conf.h" |
27 |
> |
#include "conf.h" |
28 |
|
#include "s_serv.h" |
29 |
|
#include "client.h" |
30 |
– |
#include "common.h" |
30 |
|
#include "ircd.h" |
32 |
– |
#include "list.h" |
31 |
|
#include "parse.h" |
32 |
|
#include "fdlist.h" |
33 |
|
#include "packet.h" |
35 |
|
#include "memory.h" |
36 |
|
#include "hook.h" |
37 |
|
#include "send.h" |
38 |
< |
#include "irc_getnameinfo.h" |
38 |
> |
#include "s_misc.h" |
39 |
|
|
40 |
|
#define READBUF_SIZE 16384 |
41 |
|
|
44 |
– |
struct Callback *iorecv_cb = NULL; |
45 |
– |
struct Callback *iorecvctrl_cb = NULL; |
46 |
– |
|
42 |
|
static char readBuf[READBUF_SIZE]; |
43 |
|
static void client_dopacket(struct Client *, char *, size_t); |
44 |
|
|
161 |
|
client_dopacket(client_p, readBuf, dolen); |
162 |
|
} |
163 |
|
} |
164 |
< |
else if(IsClient(client_p)) |
164 |
> |
else if (IsClient(client_p)) |
165 |
|
{ |
166 |
< |
if (ConfigFileEntry.no_oper_flood && (IsOper(client_p) || IsCanFlood(client_p))) |
166 |
> |
if (ConfigFileEntry.no_oper_flood && (HasUMode(client_p, UMODE_OPER) || IsCanFlood(client_p))) |
167 |
|
{ |
168 |
|
if (ConfigFileEntry.true_no_oper_flood) |
169 |
|
checkflood = -1; |
269 |
|
} |
270 |
|
|
271 |
|
/* |
277 |
– |
* read_ctrl_packet - Read a 'packet' of data from a servlink control |
278 |
– |
* link and process it. |
279 |
– |
*/ |
280 |
– |
void |
281 |
– |
read_ctrl_packet(fde_t *fd, void *data) |
282 |
– |
{ |
283 |
– |
struct Client *server = data; |
284 |
– |
struct LocalUser *lserver = server->localClient; |
285 |
– |
struct SlinkRpl *reply; |
286 |
– |
int length = 0; |
287 |
– |
unsigned char tmp[2]; |
288 |
– |
unsigned char *len = tmp; |
289 |
– |
struct SlinkRplDef *replydef; |
290 |
– |
|
291 |
– |
assert(lserver != NULL); |
292 |
– |
|
293 |
– |
reply = &lserver->slinkrpl; |
294 |
– |
|
295 |
– |
if (IsDefunct(server)) |
296 |
– |
return; |
297 |
– |
|
298 |
– |
if (!reply->command) |
299 |
– |
{ |
300 |
– |
reply->gotdatalen = 0; |
301 |
– |
reply->readdata = 0; |
302 |
– |
reply->data = NULL; |
303 |
– |
|
304 |
– |
length = recv(fd->fd, tmp, 1, 0); |
305 |
– |
|
306 |
– |
if (length <= 0) |
307 |
– |
{ |
308 |
– |
if ((length == -1) && ignoreErrno(errno)) |
309 |
– |
goto nodata; |
310 |
– |
dead_link_on_read(server, length); |
311 |
– |
return; |
312 |
– |
} |
313 |
– |
reply->command = tmp[0]; |
314 |
– |
} |
315 |
– |
|
316 |
– |
for (replydef = slinkrpltab; replydef->handler; replydef++) |
317 |
– |
{ |
318 |
– |
if (replydef->replyid == (unsigned int)reply->command) |
319 |
– |
break; |
320 |
– |
} |
321 |
– |
|
322 |
– |
/* we should be able to trust a local slink process... |
323 |
– |
* and if it sends an invalid command, that's a bug.. */ |
324 |
– |
assert(replydef->handler); |
325 |
– |
|
326 |
– |
if ((replydef->flags & SLINKRPL_FLAG_DATA) && (reply->gotdatalen < 2)) |
327 |
– |
{ |
328 |
– |
/* we need a datalen u16 which we don't have yet... */ |
329 |
– |
length = recv(fd->fd, len, (2 - reply->gotdatalen), 0); |
330 |
– |
if (length <= 0) |
331 |
– |
{ |
332 |
– |
if ((length == -1) && ignoreErrno(errno)) |
333 |
– |
goto nodata; |
334 |
– |
dead_link_on_read(server, length); |
335 |
– |
return; |
336 |
– |
} |
337 |
– |
|
338 |
– |
if (reply->gotdatalen == 0) |
339 |
– |
{ |
340 |
– |
reply->datalen = *len << 8; |
341 |
– |
reply->gotdatalen++; |
342 |
– |
length--; |
343 |
– |
len++; |
344 |
– |
} |
345 |
– |
if (length && (reply->gotdatalen == 1)) |
346 |
– |
{ |
347 |
– |
reply->datalen |= *len; |
348 |
– |
reply->gotdatalen++; |
349 |
– |
if (reply->datalen > 0) |
350 |
– |
reply->data = MyMalloc(reply->datalen); |
351 |
– |
} |
352 |
– |
|
353 |
– |
if (reply->gotdatalen < 2) |
354 |
– |
return; /* wait for more data */ |
355 |
– |
} |
356 |
– |
|
357 |
– |
if (reply->readdata < reply->datalen) /* try to get any remaining data */ |
358 |
– |
{ |
359 |
– |
length = recv(fd->fd, (reply->data + reply->readdata), |
360 |
– |
(reply->datalen - reply->readdata), 0); |
361 |
– |
if (length <= 0) |
362 |
– |
{ |
363 |
– |
if ((length == -1) && ignoreErrno(errno)) |
364 |
– |
goto nodata; |
365 |
– |
dead_link_on_read(server, length); |
366 |
– |
return; |
367 |
– |
} |
368 |
– |
|
369 |
– |
reply->readdata += length; |
370 |
– |
if (reply->readdata < reply->datalen) |
371 |
– |
return; /* wait for more data */ |
372 |
– |
} |
373 |
– |
|
374 |
– |
execute_callback(iorecvctrl_cb, server, reply->command); |
375 |
– |
|
376 |
– |
/* we now have the command and any data, pass it off to the handler */ |
377 |
– |
(*replydef->handler)(reply->command, reply->datalen, reply->data, server); |
378 |
– |
|
379 |
– |
/* reset SlinkRpl */ |
380 |
– |
if (reply->datalen > 0) |
381 |
– |
MyFree(reply->data); |
382 |
– |
reply->command = 0; |
383 |
– |
|
384 |
– |
if (IsDead(server)) |
385 |
– |
return; |
386 |
– |
|
387 |
– |
nodata: |
388 |
– |
/* If we get here, we need to register for another COMM_SELECT_READ */ |
389 |
– |
comm_setselect(fd, COMM_SELECT_READ, read_ctrl_packet, server, 0); |
390 |
– |
} |
391 |
– |
|
392 |
– |
/* |
272 |
|
* read_packet - Read a 'packet' of data from a connection and process it. |
273 |
|
*/ |
274 |
|
void |
294 |
|
/* translate openssl error codes, sigh */ |
295 |
|
if (length < 0) |
296 |
|
switch (SSL_get_error(fd->ssl, length)) |
297 |
< |
{ |
297 |
> |
{ |
298 |
|
case SSL_ERROR_WANT_WRITE: |
299 |
< |
fd->flags.pending_read = 1; |
300 |
< |
SetSendqBlocked(client_p); |
301 |
< |
comm_setselect(fd, COMM_SELECT_WRITE, (PF *) sendq_unblocked, |
302 |
< |
client_p, 0); |
424 |
< |
return; |
425 |
< |
case SSL_ERROR_WANT_READ: |
426 |
< |
errno = EWOULDBLOCK; |
299 |
> |
comm_setselect(fd, COMM_SELECT_WRITE, (PF *)sendq_unblocked, client_p, 0); |
300 |
> |
return; |
301 |
> |
case SSL_ERROR_WANT_READ: |
302 |
> |
errno = EWOULDBLOCK; |
303 |
|
case SSL_ERROR_SYSCALL: |
304 |
< |
break; |
304 |
> |
break; |
305 |
> |
case SSL_ERROR_SSL: |
306 |
> |
if (errno == EAGAIN) |
307 |
> |
break; |
308 |
|
default: |
309 |
< |
length = errno = 0; |
310 |
< |
} |
309 |
> |
length = errno = 0; |
310 |
> |
} |
311 |
|
} |
312 |
|
else |
313 |
|
#endif |
314 |
|
{ |
315 |
|
length = recv(fd->fd, readBuf, READBUF_SIZE, 0); |
437 |
– |
#ifdef _WIN32 |
438 |
– |
if (length < 0) |
439 |
– |
errno = WSAGetLastError(); |
440 |
– |
#endif |
316 |
|
} |
317 |
|
|
318 |
|
if (length <= 0) |
328 |
|
return; |
329 |
|
} |
330 |
|
|
331 |
< |
execute_callback(iorecv_cb, client_p, length, readBuf); |
331 |
> |
dbuf_put(&client_p->localClient->buf_recvq, readBuf, length); |
332 |
|
|
333 |
< |
if (client_p->lasttime < CurrentTime) |
334 |
< |
client_p->lasttime = CurrentTime; |
335 |
< |
if (client_p->lasttime > client_p->since) |
336 |
< |
client_p->since = CurrentTime; |
333 |
> |
if (client_p->localClient->lasttime < CurrentTime) |
334 |
> |
client_p->localClient->lasttime = CurrentTime; |
335 |
> |
if (client_p->localClient->lasttime > client_p->localClient->since) |
336 |
> |
client_p->localClient->since = CurrentTime; |
337 |
|
ClearPingSent(client_p); |
338 |
|
|
464 |
– |
dbuf_put(&client_p->localClient->buf_recvq, readBuf, length); |
465 |
– |
|
339 |
|
/* Attempt to parse what we have */ |
340 |
|
parse_client_queued(client_p); |
341 |
|
|
343 |
|
return; |
344 |
|
|
345 |
|
/* Check to make sure we're not flooding */ |
473 |
– |
/* TBD - ConfigFileEntry.client_flood should be a size_t */ |
346 |
|
if (!(IsServer(client_p) || IsHandshake(client_p) || IsConnecting(client_p)) |
347 |
|
&& (dbuf_length(&client_p->localClient->buf_recvq) > |
348 |
< |
(unsigned int)ConfigFileEntry.client_flood)) |
348 |
> |
get_recvq(&client_p->localClient->confs))) |
349 |
|
{ |
350 |
< |
if (!(ConfigFileEntry.no_oper_flood && IsOper(client_p))) |
350 |
> |
if (!(ConfigFileEntry.no_oper_flood && HasUMode(client_p, UMODE_OPER))) |
351 |
|
{ |
352 |
|
exit_client(client_p, client_p, "Excess Flood"); |
353 |
|
return; |