General cleanups
[olsrd.git] / src / parser.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004, Andreas T√łnnesen(andreto@olsr.org)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright 
11  *   notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright 
13  *   notice, this list of conditions and the following disclaimer in 
14  *   the documentation and/or other materials provided with the 
15  *   distribution.
16  * * Neither the name of olsr.org, olsrd nor the names of its 
17  *   contributors may be used to endorse or promote products derived 
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Visit http://www.olsr.org for more information.
34  *
35  * If you find this software useful feel free to make a donation
36  * to the project. For more information see the website or contact
37  * the copyright holders.
38  *
39  * $Id: parser.c,v 1.15 2004/11/21 14:22:33 kattemat Exp $
40  */
41
42 #include "parser.h"
43 #include "defs.h"
44 #include "process_package.h"
45 #include "mantissa.h"
46 #include "hysteresis.h"
47 #include "duplicate_set.h"
48 #include "mid_set.h"
49 #include "olsr.h"
50 #include "rebuild_packet.h"
51
52 //union olsr_ip_addr tmp_addr;
53 #ifdef WIN32
54 #undef EWOULDBLOCK
55 #define EWOULDBLOCK WSAEWOULDBLOCK
56 #undef errno
57 #define errno WSAGetLastError()
58 #undef strerror
59 #define strerror(x) StrError(x)
60 #endif
61
62
63 /* The outputbuffer on neighbornodes
64  * will never exceed MAXMESSAGESIZE
65  */
66 static char inbuf[MAXMESSAGESIZE+1];
67
68
69 /**
70  *Initialize the parser. 
71  *
72  *@return nada
73  */
74 void
75 olsr_init_parser()
76 {
77   olsr_printf(3, "Initializing parser...\n");
78
79   /* Initialize the packet functions */
80   olsr_init_package_process();
81
82 }
83
84 void
85 olsr_parser_add_function(void (*function)(union olsr_message *, struct interface *, union olsr_ip_addr *), int type, int forwarding)
86 {
87   struct parse_function_entry *new_entry;
88
89   olsr_printf(3, "Parser: registering event for type %d\n", type);
90  
91
92   new_entry = olsr_malloc(sizeof(struct parse_function_entry), "Register parse function");
93
94   new_entry->function = function;
95   new_entry->type = type;
96   new_entry->caller_forwarding = forwarding;
97
98   /* Queue */
99   new_entry->next = parse_functions;
100   parse_functions = new_entry;
101
102   olsr_printf(3, "Register parse function: Added function for type %d\n", type);
103
104 }
105
106
107
108 int
109 olsr_parser_remove_function(void (*function)(union olsr_message *, struct interface *, union olsr_ip_addr *), int type, int forwarding)
110 {
111   struct parse_function_entry *entry, *prev;
112
113   entry = parse_functions;
114   prev = NULL;
115
116   while(entry)
117     {
118       if((entry->function == function) &&
119          (entry->type == type) &&
120          (entry->caller_forwarding == forwarding))
121         {
122           if(entry == parse_functions)
123             {
124               parse_functions = entry->next;
125             }
126           else
127             {
128               prev->next = entry->next;
129             }
130           free(entry);
131           return 1;
132         }
133
134       prev = entry;
135       entry = entry->next;
136     }
137
138   return 0;
139 }
140
141
142
143 /**
144  *Processing OLSR data from socket. Reading data, setting 
145  *wich interface recieved the message, Sends IPC(if used) 
146  *and passes the packet on to parse_packet().
147  *
148  *@param fd the filedescriptor that data should be read from.
149  *@return nada
150  */
151 void
152 olsr_input(int fd)
153 {
154   /* sockaddr_in6 is bigger than sockaddr !!!! */
155   struct sockaddr_storage from;
156   size_t fromlen;
157   int cc;
158   struct interface *olsr_in_if;
159   union olsr_ip_addr from_addr;
160
161
162   for (;;) 
163     {
164       fromlen = sizeof(struct sockaddr_storage);
165
166       cc = recvfrom(fd, 
167                     inbuf, 
168                     sizeof (inbuf), 
169                     0, 
170                     (struct sockaddr *)&from, 
171                     &fromlen);
172
173       if (cc <= 0) 
174         {
175           if (cc < 0 && errno != EWOULDBLOCK)
176             {
177               olsr_printf(1, "error recvfrom: %s", strerror(errno));
178               olsr_syslog(OLSR_LOG_ERR, "error recvfrom: %m");
179             }
180           break;
181         }
182
183       if(olsr_cnf->ip_version == AF_INET)
184         {
185           /* IPv4 sender address */
186           COPY_IP(&from_addr, &((struct sockaddr_in *)&from)->sin_addr.s_addr);
187         }
188       else
189         {
190           /* IPv6 sender address */
191           COPY_IP(&from_addr, &((struct sockaddr_in6 *)&from)->sin6_addr);
192         }
193
194       /* are we talking to ourselves? */
195       if(if_ifwithaddr(&from_addr) != NULL)
196         return;
197
198 #ifdef DEBUG
199       olsr_printf(5, "Recieved a packet from %s\n", olsr_ip_to_string((union olsr_ip_addr *)&((struct sockaddr_in *)&from)->sin_addr.s_addr));
200 #endif
201       //printf("\nCC: %d FROMLEN: %d\n\n", cc, fromlen);
202       if ((olsr_cnf->ip_version == AF_INET) && (fromlen != sizeof (struct sockaddr_in)))
203         break;
204       else if ((olsr_cnf->ip_version == AF_INET6) && (fromlen != sizeof (struct sockaddr_in6)))
205         break;
206
207       //printf("Recieved data on socket %d\n", socknr);
208
209
210       if((olsr_in_if = if_ifwithsock(fd)) == NULL)
211         {
212           olsr_printf(1, "Could not find input interface for message from %s size %d\n",
213                       olsr_ip_to_string(&from_addr),
214                       cc);
215           olsr_syslog(OLSR_LOG_ERR, "Could not find input interface for message from %s size %d\n",
216                  olsr_ip_to_string(&from_addr),
217                  cc);
218           return ;
219         }
220
221       /*
222        * &from - sender
223        * &inbuf.olsr 
224        * cc - bytes read
225        */
226       parse_packet((struct olsr *)inbuf, cc, olsr_in_if, &from_addr);
227     
228     }
229 }
230
231
232
233
234 /**
235  *Process a newly received OLSR packet. Checks the type
236  *and to the neccessary convertions and call the
237  *corresponding functions to handle the information.
238  *@param from the sockaddr struct describing the sender
239  *@param olsr the olsr struct containing the message
240  *@param size the size of the message
241  *@return nada
242  */
243
244 void
245 parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip_addr *from_addr)
246 {
247   union olsr_message *m = (union olsr_message *)olsr->olsr_msg;
248   struct unknown_message unkpacket;
249   int count;
250   int msgsize;
251   int processed;
252   struct parse_function_entry *entry;
253   char *packet = (char*)olsr;
254   int i;
255   int x = 0;
256
257   count = size - ((char *)m - (char *)olsr);
258
259   if (count < minsize)
260     return;
261
262   if (ntohs(olsr->olsr_packlen) != size)
263     {
264       olsr_printf(1, "Size error detected in received packet.\nRecieved %d, in packet %d\n", size, ntohs(olsr->olsr_packlen));
265             
266       olsr_syslog(OLSR_LOG_ERR, " packet length error in  packet received from %s!",
267              olsr_ip_to_string(from_addr));
268       return;
269     }
270
271   //printf("Message from %s\n\n", olsr_ip_to_string(from_addr)); 
272       
273   /* Display packet */
274   if(disp_pack_in)
275     {
276       printf("\n\tfrom: %s\n\tsize: %d\n\tcontent(decimal):\n\t", olsr_ip_to_string(from_addr), size);
277         
278       for(i = 0; i < size;i++)
279         {
280           if(x == 4)
281             {
282               x = 0;
283               printf("\n\t");
284             }
285           x++;
286           if(olsr_cnf->ip_version == AF_INET)
287             printf(" %03i", (u_char) packet[i]);
288           else
289             printf(" %02x", (u_char) packet[i]);
290         }
291             
292       printf("\n");
293     }
294
295   if(olsr_cnf->ip_version == AF_INET)
296     msgsize = ntohs(m->v4.olsr_msgsize);
297   else
298     msgsize = ntohs(m->v6.olsr_msgsize);
299
300
301   /*
302    * Hysteresis update - for every OLSR package
303    */
304   if(olsr_cnf->use_hysteresis)
305     {
306       if(olsr_cnf->ip_version == AF_INET)
307         {
308           /* IPv4 */
309           update_hysteresis_incoming(from_addr, 
310                                      &in_if->ip_addr,
311                                      ntohs(olsr->olsr_seqno));
312         }
313       else
314         {
315           /* IPv6 */
316           update_hysteresis_incoming(from_addr, 
317                                      &in_if->ip_addr, 
318                                      ntohs(olsr->olsr_seqno));
319         }
320     }
321
322 #if defined USE_LINK_QUALITY
323   if (olsr_cnf->lq_level > 0)
324     {
325       olsr_update_packet_loss(from_addr, &in_if->ip_addr,
326                               ntohs(olsr->olsr_seqno));
327     }
328 #endif
329   
330   for ( ; count > 0; m = (union olsr_message *)((char *)m + (msgsize)))
331     {
332
333       processed = 0;      
334       if (count < minsize)
335         break;
336       
337       if(olsr_cnf->ip_version == AF_INET)
338         msgsize = ntohs(m->v4.olsr_msgsize);
339       else
340         msgsize = ntohs(m->v6.olsr_msgsize);
341       
342       count -= msgsize;
343
344       /* Check size of message */
345       if(count < 0)
346         {
347           olsr_printf(1, "packet length error in  packet received from %s!",
348                       olsr_ip_to_string(from_addr));
349
350           olsr_syslog(OLSR_LOG_ERR, " packet length error in  packet received from %s!",
351                  olsr_ip_to_string(from_addr));
352           break;
353         }
354
355
356       /* Treat TTL hopcnt */
357       if(olsr_cnf->ip_version == AF_INET)
358         {
359           /* IPv4 */
360           if (m->v4.ttl <= 0)
361             {
362               olsr_printf(2, "Dropping packet type %d from neigh %s with TTL 0\n", 
363                           m->v4.olsr_msgtype,
364                           olsr_ip_to_string(from_addr)); 
365               continue;
366             }
367         }
368       else
369         {
370           /* IPv6 */
371           if (m->v6.ttl <= 0) 
372             {
373               olsr_printf(2, "Dropping packet type %d from %s with TTL 0\n", 
374                           m->v4.olsr_msgtype,
375                           olsr_ip_to_string(from_addr)); 
376               continue;
377             }
378         }
379
380       /*RFC 3626 section 3.4:
381        *  2    If the time to live of the message is less than or equal to
382        *  '0' (zero), or if the message was sent by the receiving node
383        *  (i.e., the Originator Address of the message is the main
384        *  address of the receiving node): the message MUST silently be
385        *  dropped.
386        */
387
388       /* Should be the same for IPv4 and IPv6 */
389       if(COMP_IP(&m->v4.originator, &main_addr))
390         {
391 #ifdef DEBUG
392           olsr_printf(3, "Not processing message originating from us!\n");
393 #endif
394           continue;
395         }
396
397
398       //printf("MESSAGETYPE: %d\n", m->v4.olsr_msgtype);
399
400       entry = parse_functions;
401
402       while(entry)
403         {
404           /* Should be the same for IPv4 and IPv6 */
405
406           /* Promiscuous or exact match */
407           if((entry->type == PROMISCUOUS) || 
408              (entry->type == m->v4.olsr_msgtype))
409             {
410               entry->function(m, in_if, from_addr);
411               if(entry->caller_forwarding)
412                 processed = 1;
413             }
414           entry = entry->next;
415         }
416
417
418       /* UNKNOWN PACKETTYPE */
419       if(processed == 0)
420         {
421           unk_chgestruct(&unkpacket, m);
422           
423           olsr_printf(3, "Unknown type: %d, size %d, from %s\n",
424                       m->v4.olsr_msgtype,
425                       size,
426                       olsr_ip_to_string(&unkpacket.originator));
427
428           /* Forward message */
429           if(!COMP_IP(&unkpacket.originator, &main_addr))
430             {         
431               /* Forward */
432               olsr_forward_message(m, 
433                                    &unkpacket.originator, 
434                                    unkpacket.seqno, 
435                                    in_if,
436                                    from_addr);
437             }
438
439         }
440
441     } /* for olsr_msg */ 
442
443
444 }
445
446
447
448