ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/packet.c
Revision: 4890
Committed: Wed Nov 19 17:10:46 2014 UTC (10 years, 9 months ago) by michael
Content type: text/x-csrc
File size: 10497 byte(s)
Log Message:
- Style corrections

File Contents

# User Rev Content
1 adx 30 /*
2 michael 2916 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 adx 30 *
4 michael 2916 * Copyright (c) 1997-2014 ircd-hybrid development team
5 adx 30 *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18 michael 4565 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19 adx 30 * USA
20     */
21 michael 2916
22     /*! \file packet.c
23     * \brief Packet handlers.
24     * \version $Id$
25     */
26    
27 adx 30 #include "stdinc.h"
28 michael 1011 #include "list.h"
29 adx 30 #include "s_bsd.h"
30 michael 1309 #include "conf.h"
31 michael 3347 #include "server.h"
32 adx 30 #include "client.h"
33     #include "ircd.h"
34     #include "parse.h"
35     #include "fdlist.h"
36     #include "packet.h"
37     #include "irc_string.h"
38     #include "memory.h"
39     #include "send.h"
40 michael 3347 #include "misc.h"
41 adx 30
42     #define READBUF_SIZE 16384
43    
44     static char readBuf[READBUF_SIZE];
45     static void client_dopacket(struct Client *, char *, size_t);
46    
47     /* extract_one_line()
48     *
49     * inputs - pointer to a dbuf queue
50     * - pointer to buffer to copy data to
51     * output - length of <buffer>
52     * side effects - one line is copied and removed from the dbuf
53     */
54     static int
55     extract_one_line(struct dbuf_queue *qptr, char *buffer)
56     {
57     int line_bytes = 0, empty_bytes = 0, phase = 0;
58 michael 3107 unsigned int idx = 0;
59 michael 4815 dlink_node *node = NULL;
60 adx 30
61     /*
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)
66     *
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.
70     *
71     * --adx
72     */
73 michael 4815 DLINK_FOREACH(node, qptr->blocks.head)
74 adx 30 {
75 michael 4815 struct dbuf_block *block = node->data;
76 adx 30
77 michael 4815 if (node == qptr->blocks.head)
78 michael 3107 idx = qptr->pos;
79     else
80     idx = 0;
81    
82     for (; idx < block->size; ++idx)
83 adx 30 {
84 michael 3107 char c = block->data[idx];
85    
86 adx 30 if (IsEol(c) || (c == ' ' && phase != 1))
87     {
88 michael 3107 ++empty_bytes;
89 michael 3453
90 adx 30 if (phase == 1)
91     phase = 2;
92     }
93     else switch (phase)
94     {
95     case 0: phase = 1;
96     case 1: if (line_bytes++ < IRCD_BUFSIZE - 2)
97     *buffer++ = c;
98     break;
99     case 2: *buffer = '\0';
100     dbuf_delete(qptr, line_bytes + empty_bytes);
101     return IRCD_MIN(line_bytes, IRCD_BUFSIZE - 2);
102     }
103     }
104     }
105    
106     /*
107     * Now, if we haven't reached phase 2, ignore all line bytes
108     * that we have read, since this is a partial line case.
109     */
110     if (phase != 2)
111     line_bytes = 0;
112     else
113     *buffer = '\0';
114    
115     /* Remove what is now unnecessary */
116     dbuf_delete(qptr, line_bytes + empty_bytes);
117     return IRCD_MIN(line_bytes, IRCD_BUFSIZE - 2);
118     }
119     /*
120     * parse_client_queued - parse client queued messages
121     */
122     static void
123     parse_client_queued(struct Client *client_p)
124 michael 2916 {
125 adx 30 int dolen = 0;
126     int checkflood = 1;
127 michael 4588 struct Connection *lclient_p = client_p->connection;
128 adx 30
129     if (IsUnknown(client_p))
130     {
131     int i = 0;
132    
133 michael 3453 while (1)
134 adx 30 {
135     if (IsDefunct(client_p))
136 michael 2916 return;
137 adx 30
138     /* rate unknown clients at MAX_FLOOD per loop */
139     if (i >= MAX_FLOOD)
140     break;
141    
142     dolen = extract_one_line(&lclient_p->buf_recvq, readBuf);
143 michael 4890
144 adx 30 if (dolen == 0)
145 michael 2916 break;
146 adx 30
147     client_dopacket(client_p, readBuf, dolen);
148     i++;
149    
150     /* if they've dropped out of the unknown state, break and move
151     * to the parsing for their appropriate status. --fl
152     */
153 michael 3453 if (!IsUnknown(client_p))
154 adx 30 break;
155     }
156     }
157    
158     if (IsServer(client_p) || IsConnecting(client_p) || IsHandshake(client_p))
159     {
160     while (1)
161     {
162     if (IsDefunct(client_p))
163     return;
164 michael 4890
165 michael 3453 if ((dolen = extract_one_line(&lclient_p->buf_recvq, readBuf)) == 0)
166 adx 30 break;
167 michael 3453
168 adx 30 client_dopacket(client_p, readBuf, dolen);
169     }
170     }
171 adx 163 else if (IsClient(client_p))
172 adx 30 {
173 michael 4340 if (ConfigGeneral.no_oper_flood && (HasUMode(client_p, UMODE_OPER) || IsCanFlood(client_p)))
174 adx 30 {
175 michael 4340 if (ConfigGeneral.true_no_oper_flood)
176 adx 30 checkflood = -1;
177     else
178     checkflood = 0;
179     }
180    
181     /*
182     * Handle flood protection here - if we exceed our flood limit on
183     * messages in this loop, we simply drop out of the loop prematurely.
184     * -- adrian
185     */
186 michael 3453 while (1)
187 adx 30 {
188     if (IsDefunct(client_p))
189 michael 2916 break;
190 adx 30
191     /* This flood protection works as follows:
192     *
193     * A client is given allow_read lines to send to the server. Every
194     * time a line is parsed, sent_parsed is increased. sent_parsed
195     * is decreased by 1 every time flood_recalc is called.
196     *
197     * Thus a client can 'burst' allow_read lines to the server, any
198     * excess lines will be parsed one per flood_recalc() call.
199     *
200     * Therefore a client will be penalised more if they keep flooding,
201     * as sent_parsed will always hover around the allow_read limit
202     * and no 'bursts' will be permitted.
203     */
204     if (checkflood > 0)
205 michael 3453 if (lclient_p->sent_parsed >= lclient_p->allow_read)
206 adx 30 break;
207 michael 2916
208 michael 4890 /*
209     * Allow opers 4 times the amount of messages as users. why 4?
210 adx 30 * why not. :) --fl_
211     */
212 michael 3453 else if (lclient_p->sent_parsed >= (4 * lclient_p->allow_read) && checkflood != -1)
213 adx 30 break;
214    
215     dolen = extract_one_line(&lclient_p->buf_recvq, readBuf);
216 michael 4890
217 adx 30 if (dolen == 0)
218     break;
219    
220     client_dopacket(client_p, readBuf, dolen);
221     lclient_p->sent_parsed++;
222     }
223     }
224     }
225    
226     /* flood_endgrace()
227     *
228     * marks the end of the clients grace period
229     */
230     void
231     flood_endgrace(struct Client *client_p)
232     {
233     SetFloodDone(client_p);
234    
235     /* Drop their flood limit back down */
236 michael 4588 client_p->connection->allow_read = MAX_FLOOD;
237 adx 30
238     /* sent_parsed could be way over MAX_FLOOD but under MAX_FLOOD_BURST,
239     * so reset it.
240     */
241 michael 4588 client_p->connection->sent_parsed = 0;
242 adx 30 }
243    
244     /*
245     * flood_recalc
246     *
247     * recalculate the number of allowed flood lines. this should be called
248     * once a second on any given client. We then attempt to flush some data.
249     */
250     void
251     flood_recalc(fde_t *fd, void *data)
252     {
253     struct Client *client_p = data;
254 michael 4588 struct Connection *lclient_p = client_p->connection;
255 michael 2916
256 michael 4890 /*
257     * Allow a bursting client their allocation per second, allow
258 adx 30 * a client whos flooding an extra 2 per second
259     */
260     if (IsFloodDone(client_p))
261     lclient_p->sent_parsed -= 2;
262     else
263     lclient_p->sent_parsed = 0;
264 michael 2916
265 adx 30 if (lclient_p->sent_parsed < 0)
266     lclient_p->sent_parsed = 0;
267 michael 2916
268 adx 30 parse_client_queued(client_p);
269 michael 2916
270 adx 30 /* And now, try flushing .. */
271     if (!IsDead(client_p))
272     {
273     /* and finally, reset the flood check */
274     comm_setflush(fd, 1000, flood_recalc, client_p);
275     }
276     }
277    
278     /*
279     * read_packet - Read a 'packet' of data from a connection and process it.
280     */
281     void
282     read_packet(fde_t *fd, void *data)
283     {
284     struct Client *client_p = data;
285     int length = 0;
286    
287     if (IsDefunct(client_p))
288     return;
289    
290     /*
291     * Read some data. We *used to* do anti-flood protection here, but
292     * I personally think it makes the code too hairy to make sane.
293     * -- adrian
294     */
295 michael 2916 do
296     {
297 adx 30 #ifdef HAVE_LIBCRYPTO
298     if (fd->ssl)
299     {
300 michael 3453 length = SSL_read(fd->ssl, readBuf, sizeof(readBuf));
301 adx 30
302     /* translate openssl error codes, sigh */
303     if (length < 0)
304     switch (SSL_get_error(fd->ssl, length))
305 michael 2881 {
306 adx 30 case SSL_ERROR_WANT_WRITE:
307 michael 4461 comm_setselect(fd, COMM_SELECT_WRITE, sendq_unblocked, client_p, 0);
308 michael 2881 return;
309     case SSL_ERROR_WANT_READ:
310     errno = EWOULDBLOCK;
311 adx 30 case SSL_ERROR_SYSCALL:
312 michael 2881 break;
313 michael 428 case SSL_ERROR_SSL:
314     if (errno == EAGAIN)
315     break;
316 adx 30 default:
317 michael 2881 length = errno = 0;
318     }
319 adx 30 }
320     else
321     #endif
322     {
323 michael 3453 length = recv(fd->fd, readBuf, sizeof(readBuf), 0);
324 adx 30 }
325    
326     if (length <= 0)
327     {
328     /*
329     * If true, then we can recover from this error. Just jump out of
330     * the loop and re-register a new io-request.
331     */
332     if (length < 0 && ignoreErrno(errno))
333     break;
334    
335     dead_link_on_read(client_p, length);
336     return;
337     }
338    
339 michael 4588 dbuf_put(&client_p->connection->buf_recvq, readBuf, length);
340 adx 30
341 michael 4588 if (client_p->connection->lasttime < CurrentTime)
342     client_p->connection->lasttime = CurrentTime;
343 michael 4890
344 michael 4588 if (client_p->connection->lasttime > client_p->connection->since)
345     client_p->connection->since = CurrentTime;
346 michael 3453
347 adx 30 ClearPingSent(client_p);
348    
349     /* Attempt to parse what we have */
350     parse_client_queued(client_p);
351    
352     if (IsDefunct(client_p))
353     return;
354    
355     /* Check to make sure we're not flooding */
356     if (!(IsServer(client_p) || IsHandshake(client_p) || IsConnecting(client_p))
357 michael 4588 && (dbuf_length(&client_p->connection->buf_recvq) >
358     get_recvq(&client_p->connection->confs)))
359 adx 30 {
360 michael 4340 if (!(ConfigGeneral.no_oper_flood && HasUMode(client_p, UMODE_OPER)))
361 adx 30 {
362 michael 3171 exit_client(client_p, "Excess Flood");
363 adx 30 return;
364     }
365     }
366     }
367     #ifdef HAVE_LIBCRYPTO
368     while (length == sizeof(readBuf) || fd->ssl);
369     #else
370     while (length == sizeof(readBuf));
371     #endif
372    
373     /* If we get here, we need to register for another COMM_SELECT_READ */
374     comm_setselect(fd, COMM_SELECT_READ, read_packet, client_p, 0);
375     }
376    
377     /*
378     * client_dopacket - copy packet to client buf and parse it
379     * client_p - pointer to client structure for which the buffer data
380     * applies.
381     * buffer - pointr to the buffer containing the newly read data
382     * length - number of valid bytes of data in the buffer
383     *
384     * Note:
385     * It is implicitly assumed that dopacket is called only
386     * with client_p of "local" variation, which contains all the
387     * necessary fields (buffer etc..)
388     */
389     static void
390     client_dopacket(struct Client *client_p, char *buffer, size_t length)
391     {
392 michael 2916 /*
393 adx 30 * Update messages received
394     */
395 michael 4588 ++me.connection->recv.messages;
396     ++client_p->connection->recv.messages;
397 adx 30
398 michael 2916 /*
399 adx 30 * Update bytes received
400     */
401 michael 4588 client_p->connection->recv.bytes += length;
402     me.connection->recv.bytes += length;
403 adx 30
404     parse(client_p, buffer, buffer + length);
405     }

Properties

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