2
2
* ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
4
* Copyright (c) 1997-2014 ircd-hybrid development team
4
* Copyright (c) 1997-2015 ircd-hybrid development team
6
6
* This program is free software; you can redistribute it and/or modify
7
7
* it under the terms of the GNU General Public License as published by
42
42
#define READBUF_SIZE 16384
44
44
static char readBuf[READBUF_SIZE];
45
static void client_dopacket(struct Client *, char *, size_t);
48
* client_dopacket - copy packet to client buf and parse it
49
* client_p - pointer to client structure for which the buffer data
51
* buffer - pointr to the buffer containing the newly read data
52
* length - number of valid bytes of data in the buffer
55
* It is implicitly assumed that client_dopacket() is called only
56
* with client_p of "local" variation, which contains all the
57
* necessary fields (buffer etc..)
60
client_dopacket(struct Client *client_p, char *buffer, unsigned int length)
62
/* Update messages received */
63
++me.connection->recv.messages;
64
++client_p->connection->recv.messages;
66
/* Update bytes received */
67
client_p->connection->recv.bytes += length;
68
me.connection->recv.bytes += length;
70
parse(client_p, buffer, buffer + length);
47
73
/* extract_one_line()
51
77
* output - length of <buffer>
52
78
* side effects - one line is copied and removed from the dbuf
55
81
extract_one_line(struct dbuf_queue *qptr, char *buffer)
57
int line_bytes = 0, empty_bytes = 0, phase = 0;
59
dlink_node *ptr = NULL;
83
unsigned int line_bytes = 0, eol_bytes = 0;
62
* Phase 0: "empty" characters before the line
63
* Phase 1: copying the line
64
* Phase 2: "empty" characters after the line
65
* (delete them as well and free some space in the dbuf)
67
* Empty characters are CR, LF and space (but, of course, not
68
* in the middle of a line). We try to remove as much of them as we can,
69
* since they simply eat server memory.
73
DLINK_FOREACH(ptr, qptr->blocks.head)
86
DLINK_FOREACH(node, qptr->blocks.head)
75
struct dbuf_block *block = ptr->data;
88
const struct dbuf_block *block = node->data;
77
if (ptr == qptr->blocks.head)
91
if (node == qptr->blocks.head)
84
98
char c = block->data[idx];
86
if (IsEol(c) || (c == ' ' && phase != 1))
96
case 1: if (line_bytes++ < IRCD_BUFSIZE - 2)
99
case 2: *buffer = '\0';
100
dbuf_delete(qptr, line_bytes + empty_bytes);
101
return IRCD_MIN(line_bytes, IRCD_BUFSIZE - 2);
104
/* Allow 2 eol bytes per message */
110
else if (line_bytes++ < IRCD_BUFSIZE - 2)
107
* Now, if we haven't reached phase 2, ignore all line bytes
118
* Now, if we haven't found an EOL, ignore all line bytes
108
119
* that we have read, since this is a partial line case.
115
126
/* Remove what is now unnecessary */
116
dbuf_delete(qptr, line_bytes + empty_bytes);
127
dbuf_delete(qptr, line_bytes + eol_bytes);
117
129
return IRCD_MIN(line_bytes, IRCD_BUFSIZE - 2);
120
133
* parse_client_queued - parse client queued messages
123
136
parse_client_queued(struct Client *client_p)
127
struct LocalUser *lclient_p = client_p->localClient;
138
unsigned int dolen = 0;
129
140
if (IsUnknown(client_p))
135
146
if (IsDefunct(client_p))
138
/* rate unknown clients at MAX_FLOOD per loop */
149
/* Rate unknown clients at MAX_FLOOD per loop */
139
150
if (i >= MAX_FLOOD)
142
dolen = extract_one_line(&lclient_p->buf_recvq, readBuf);
153
dolen = extract_one_line(&client_p->connection->buf_recvq, readBuf);
146
158
client_dopacket(client_p, readBuf, dolen);
149
/* if they've dropped out of the unknown state, break and move
162
* If they've dropped out of the unknown state, break and move
150
163
* to the parsing for their appropriate status. --fl
152
165
if (!IsUnknown(client_p))
161
174
if (IsDefunct(client_p))
163
if ((dolen = extract_one_line(&lclient_p->buf_recvq, readBuf)) == 0)
177
if ((dolen = extract_one_line(&client_p->connection->buf_recvq, readBuf)) == 0)
166
180
client_dopacket(client_p, readBuf, dolen);
169
183
else if (IsClient(client_p))
171
if (ConfigGeneral.no_oper_flood && (HasUMode(client_p, UMODE_OPER) || IsCanFlood(client_p)))
173
if (ConfigGeneral.true_no_oper_flood)
185
unsigned int checkflood = 1;
187
if (ConfigGeneral.no_oper_flood && HasUMode(client_p, UMODE_OPER))
189
else if (IsCanFlood(client_p))
180
* Handle flood protection here - if we exceed our flood limit on
181
* messages in this loop, we simply drop out of the loop prematurely.
193
* Handle flood protection here - if we exceed our flood limit on messages
194
* in this loop, we simply drop out of the loop prematurely.
186
199
if (IsDefunct(client_p))
189
/* This flood protection works as follows:
203
* This flood protection works as follows:
191
205
* A client is given allow_read lines to send to the server. Every
192
206
* time a line is parsed, sent_parsed is increased. sent_parsed
199
213
* as sent_parsed will always hover around the allow_read limit
200
214
* and no 'bursts' will be permitted.
204
if (lclient_p->sent_parsed >= lclient_p->allow_read)
217
if (client_p->connection->sent_parsed >= client_p->connection->allow_read)
208
/* allow opers 4 times the amount of messages as users. why 4?
211
else if (lclient_p->sent_parsed >= (4 * lclient_p->allow_read) && checkflood != -1)
214
dolen = extract_one_line(&lclient_p->buf_recvq, readBuf);
220
dolen = extract_one_line(&client_p->connection->buf_recvq, readBuf);
218
225
client_dopacket(client_p, readBuf, dolen);
219
lclient_p->sent_parsed++;
226
++client_p->connection->sent_parsed;
231
238
SetFloodDone(client_p);
233
240
/* Drop their flood limit back down */
234
client_p->localClient->allow_read = MAX_FLOOD;
241
client_p->connection->allow_read = MAX_FLOOD;
236
/* sent_parsed could be way over MAX_FLOOD but under MAX_FLOOD_BURST,
244
* sent_parsed could be way over MAX_FLOOD but under MAX_FLOOD_BURST,
239
client_p->localClient->sent_parsed = 0;
247
client_p->connection->sent_parsed = 0;
249
257
flood_recalc(fde_t *fd, void *data)
251
struct Client *client_p = data;
252
struct LocalUser *lclient_p = client_p->localClient;
259
struct Client *const client_p = data;
254
/* allow a bursting client their allocation per second, allow
262
* Allow a bursting client their allocation per second, allow
255
263
* a client whos flooding an extra 2 per second
257
265
if (IsFloodDone(client_p))
258
lclient_p->sent_parsed -= 2;
266
client_p->connection->sent_parsed -= 2;
260
lclient_p->sent_parsed = 0;
268
client_p->connection->sent_parsed = 0;
262
if (lclient_p->sent_parsed < 0)
263
lclient_p->sent_parsed = 0;
270
if (client_p->connection->sent_parsed < 0)
271
client_p->connection->sent_parsed = 0;
265
273
parse_client_queued(client_p);
326
* If true, then we can recover from this error. Just jump out of
334
* If true, then we can recover from this error. Just jump out of
327
335
* the loop and re-register a new io-request.
329
337
if (length < 0 && ignoreErrno(errno))
336
dbuf_put(&client_p->localClient->buf_recvq, readBuf, length);
338
if (client_p->localClient->lasttime < CurrentTime)
339
client_p->localClient->lasttime = CurrentTime;
340
if (client_p->localClient->lasttime > client_p->localClient->since)
341
client_p->localClient->since = CurrentTime;
344
dbuf_put(&client_p->connection->buf_recvq, readBuf, length);
346
if (client_p->connection->lasttime < CurrentTime)
347
client_p->connection->lasttime = CurrentTime;
349
if (client_p->connection->lasttime > client_p->connection->since)
350
client_p->connection->since = CurrentTime;
343
352
ClearPingSent(client_p);
351
360
/* Check to make sure we're not flooding */
352
if (!(IsServer(client_p) || IsHandshake(client_p) || IsConnecting(client_p))
353
&& (dbuf_length(&client_p->localClient->buf_recvq) >
354
get_recvq(&client_p->localClient->confs)))
361
if (!(IsServer(client_p) || IsHandshake(client_p) || IsConnecting(client_p)) &&
362
(dbuf_length(&client_p->connection->buf_recvq) >
363
get_recvq(&client_p->connection->confs)))
356
if (!(ConfigGeneral.no_oper_flood && HasUMode(client_p, UMODE_OPER)))
358
exit_client(client_p, "Excess Flood");
365
exit_client(client_p, "Excess Flood");
363
369
#ifdef HAVE_LIBCRYPTO
369
375
/* If we get here, we need to register for another COMM_SELECT_READ */
370
376
comm_setselect(fd, COMM_SELECT_READ, read_packet, client_p, 0);
374
* client_dopacket - copy packet to client buf and parse it
375
* client_p - pointer to client structure for which the buffer data
377
* buffer - pointr to the buffer containing the newly read data
378
* length - number of valid bytes of data in the buffer
381
* It is implicitly assumed that dopacket is called only
382
* with client_p of "local" variation, which contains all the
383
* necessary fields (buffer etc..)
386
client_dopacket(struct Client *client_p, char *buffer, size_t length)
389
* Update messages received
391
++me.localClient->recv.messages;
392
++client_p->localClient->recv.messages;
395
* Update bytes received
397
client_p->localClient->recv.bytes += length;
398
me.localClient->recv.bytes += length;
400
parse(client_p, buffer, buffer + length);