ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/packet.c
Revision: 3453
Committed: Thu May 1 19:31:11 2014 UTC (11 years, 3 months ago) by michael
Content type: text/x-csrc
File size: 10513 byte(s)
Log Message:
- packet.c: 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     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19     * 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     dlink_node *ptr = 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     DLINK_FOREACH(ptr, qptr->blocks.head)
74     {
75 michael 3107 struct dbuf_block *block = ptr->data;
76 adx 30
77 michael 3107 if (ptr == qptr->blocks.head)
78     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     struct LocalUser *lclient_p = client_p->localClient;
128    
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     if (dolen == 0)
144 michael 2916 break;
145 adx 30
146     client_dopacket(client_p, readBuf, dolen);
147     i++;
148    
149     /* if they've dropped out of the unknown state, break and move
150     * to the parsing for their appropriate status. --fl
151     */
152 michael 3453 if (!IsUnknown(client_p))
153 adx 30 break;
154     }
155     }
156    
157     if (IsServer(client_p) || IsConnecting(client_p) || IsHandshake(client_p))
158     {
159     while (1)
160     {
161     if (IsDefunct(client_p))
162     return;
163 michael 3453 if ((dolen = extract_one_line(&lclient_p->buf_recvq, readBuf)) == 0)
164 adx 30 break;
165 michael 3453
166 adx 30 client_dopacket(client_p, readBuf, dolen);
167     }
168     }
169 adx 163 else if (IsClient(client_p))
170 adx 30 {
171 michael 1219 if (ConfigFileEntry.no_oper_flood && (HasUMode(client_p, UMODE_OPER) || IsCanFlood(client_p)))
172 adx 30 {
173     if (ConfigFileEntry.true_no_oper_flood)
174     checkflood = -1;
175     else
176     checkflood = 0;
177     }
178    
179     /*
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.
182     * -- adrian
183     */
184 michael 3453 while (1)
185 adx 30 {
186     if (IsDefunct(client_p))
187 michael 2916 break;
188 adx 30
189     /* This flood protection works as follows:
190     *
191     * A client is given allow_read lines to send to the server. Every
192     * time a line is parsed, sent_parsed is increased. sent_parsed
193     * is decreased by 1 every time flood_recalc is called.
194     *
195     * Thus a client can 'burst' allow_read lines to the server, any
196     * excess lines will be parsed one per flood_recalc() call.
197     *
198     * Therefore a client will be penalised more if they keep flooding,
199     * as sent_parsed will always hover around the allow_read limit
200     * and no 'bursts' will be permitted.
201     */
202     if (checkflood > 0)
203     {
204 michael 3453 if (lclient_p->sent_parsed >= lclient_p->allow_read)
205 adx 30 break;
206     }
207 michael 2916
208 adx 30 /* allow opers 4 times the amount of messages as users. why 4?
209     * why not. :) --fl_
210     */
211 michael 3453 else if (lclient_p->sent_parsed >= (4 * lclient_p->allow_read) && checkflood != -1)
212 adx 30 break;
213    
214     dolen = extract_one_line(&lclient_p->buf_recvq, readBuf);
215     if (dolen == 0)
216     break;
217    
218     client_dopacket(client_p, readBuf, dolen);
219     lclient_p->sent_parsed++;
220     }
221     }
222     }
223    
224     /* flood_endgrace()
225     *
226     * marks the end of the clients grace period
227     */
228     void
229     flood_endgrace(struct Client *client_p)
230     {
231     SetFloodDone(client_p);
232    
233     /* Drop their flood limit back down */
234     client_p->localClient->allow_read = MAX_FLOOD;
235    
236     /* sent_parsed could be way over MAX_FLOOD but under MAX_FLOOD_BURST,
237     * so reset it.
238     */
239     client_p->localClient->sent_parsed = 0;
240     }
241    
242     /*
243     * flood_recalc
244     *
245     * recalculate the number of allowed flood lines. this should be called
246     * once a second on any given client. We then attempt to flush some data.
247     */
248     void
249     flood_recalc(fde_t *fd, void *data)
250     {
251     struct Client *client_p = data;
252     struct LocalUser *lclient_p = client_p->localClient;
253 michael 2916
254 adx 30 /* allow a bursting client their allocation per second, allow
255     * a client whos flooding an extra 2 per second
256     */
257     if (IsFloodDone(client_p))
258     lclient_p->sent_parsed -= 2;
259     else
260     lclient_p->sent_parsed = 0;
261 michael 2916
262 adx 30 if (lclient_p->sent_parsed < 0)
263     lclient_p->sent_parsed = 0;
264 michael 2916
265 adx 30 parse_client_queued(client_p);
266 michael 2916
267 adx 30 /* And now, try flushing .. */
268     if (!IsDead(client_p))
269     {
270     /* and finally, reset the flood check */
271     comm_setflush(fd, 1000, flood_recalc, client_p);
272     }
273     }
274    
275     /*
276     * read_packet - Read a 'packet' of data from a connection and process it.
277     */
278     void
279     read_packet(fde_t *fd, void *data)
280     {
281     struct Client *client_p = data;
282     int length = 0;
283    
284     if (IsDefunct(client_p))
285     return;
286    
287     /*
288     * Read some data. We *used to* do anti-flood protection here, but
289     * I personally think it makes the code too hairy to make sane.
290     * -- adrian
291     */
292 michael 2916 do
293     {
294 adx 30 #ifdef HAVE_LIBCRYPTO
295     if (fd->ssl)
296     {
297 michael 3453 length = SSL_read(fd->ssl, readBuf, sizeof(readBuf));
298 adx 30
299     /* translate openssl error codes, sigh */
300     if (length < 0)
301     switch (SSL_get_error(fd->ssl, length))
302 michael 2881 {
303 adx 30 case SSL_ERROR_WANT_WRITE:
304 michael 2881 comm_setselect(fd, COMM_SELECT_WRITE, (PF *)sendq_unblocked, client_p, 0);
305     return;
306     case SSL_ERROR_WANT_READ:
307     errno = EWOULDBLOCK;
308 adx 30 case SSL_ERROR_SYSCALL:
309 michael 2881 break;
310 michael 428 case SSL_ERROR_SSL:
311     if (errno == EAGAIN)
312     break;
313 adx 30 default:
314 michael 2881 length = errno = 0;
315     }
316 adx 30 }
317     else
318     #endif
319     {
320 michael 3453 length = recv(fd->fd, readBuf, sizeof(readBuf), 0);
321 adx 30 }
322    
323     if (length <= 0)
324     {
325     /*
326     * If true, then we can recover from this error. Just jump out of
327     * the loop and re-register a new io-request.
328     */
329     if (length < 0 && ignoreErrno(errno))
330     break;
331    
332     dead_link_on_read(client_p, length);
333     return;
334     }
335    
336 michael 3113 dbuf_put(&client_p->localClient->buf_recvq, readBuf, length);
337 adx 30
338 michael 1241 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;
342 michael 3453
343 adx 30 ClearPingSent(client_p);
344    
345     /* Attempt to parse what we have */
346     parse_client_queued(client_p);
347    
348     if (IsDefunct(client_p))
349     return;
350    
351     /* 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 michael 1632 get_recvq(&client_p->localClient->confs)))
355 adx 30 {
356 michael 1219 if (!(ConfigFileEntry.no_oper_flood && HasUMode(client_p, UMODE_OPER)))
357 adx 30 {
358 michael 3171 exit_client(client_p, "Excess Flood");
359 adx 30 return;
360     }
361     }
362     }
363     #ifdef HAVE_LIBCRYPTO
364     while (length == sizeof(readBuf) || fd->ssl);
365     #else
366     while (length == sizeof(readBuf));
367     #endif
368    
369     /* If we get here, we need to register for another COMM_SELECT_READ */
370     comm_setselect(fd, COMM_SELECT_READ, read_packet, client_p, 0);
371     }
372    
373     /*
374     * client_dopacket - copy packet to client buf and parse it
375     * client_p - pointer to client structure for which the buffer data
376     * applies.
377     * buffer - pointr to the buffer containing the newly read data
378     * length - number of valid bytes of data in the buffer
379     *
380     * Note:
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..)
384     */
385     static void
386     client_dopacket(struct Client *client_p, char *buffer, size_t length)
387     {
388 michael 2916 /*
389 adx 30 * Update messages received
390     */
391     ++me.localClient->recv.messages;
392     ++client_p->localClient->recv.messages;
393    
394 michael 2916 /*
395 adx 30 * Update bytes received
396     */
397     client_p->localClient->recv.bytes += length;
398     me.localClient->recv.bytes += length;
399    
400     parse(client_p, buffer, buffer + length);
401     }

Properties

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