Licence change... man that was boring work...
[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.14 2004/11/21 11:28:56 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   parse_functions = NULL;
80
81   /* Initialize the packet functions */
82   olsr_init_package_process();
83
84 }
85
86 void
87 olsr_parser_add_function(void (*function)(union olsr_message *, struct interface *, union olsr_ip_addr *), int type, int forwarding)
88 {
89   struct parse_function_entry *new_entry;
90
91   olsr_printf(3, "Parser: registering event for type %d\n", type);
92  
93
94   new_entry = olsr_malloc(sizeof(struct parse_function_entry), "Register parse function");
95
96   new_entry->function = function;
97   new_entry->type = type;
98   new_entry->caller_forwarding = forwarding;
99
100   /* Queue */
101   new_entry->next = parse_functions;
102   parse_functions = new_entry;
103
104   olsr_printf(3, "Register parse function: Added function for type %d\n", type);
105
106 }
107
108
109
110 int
111 olsr_parser_remove_function(void (*function)(union olsr_message *, struct interface *, union olsr_ip_addr *), int type, int forwarding)
112 {
113   struct parse_function_entry *entry, *prev;
114
115   entry = parse_functions;
116   prev = NULL;
117
118   while(entry)
119     {
120       if((entry->function == function) &&
121          (entry->type == type) &&
122          (entry->caller_forwarding == forwarding))
123         {
124           if(entry == parse_functions)
125             {
126               parse_functions = entry->next;
127             }
128           else
129             {
130               prev->next = entry->next;
131             }
132           free(entry);
133           return 1;
134         }
135
136       prev = entry;
137       entry = entry->next;
138     }
139
140   return 0;
141 }
142
143
144
145 /**
146  *Processing OLSR data from socket. Reading data, setting 
147  *wich interface recieved the message, Sends IPC(if used) 
148  *and passes the packet on to parse_packet().
149  *
150  *@param fd the filedescriptor that data should be read from.
151  *@return nada
152  */
153 void
154 olsr_input(int fd)
155 {
156   /* sockaddr_in6 is bigger than sockaddr !!!! */
157   struct sockaddr_storage from;
158   size_t fromlen;
159   int cc;
160   struct interface *olsr_in_if;
161   union olsr_ip_addr from_addr;
162
163
164   for (;;) 
165     {
166       fromlen = sizeof(struct sockaddr_storage);
167
168       cc = recvfrom(fd, 
169                     inbuf, 
170                     sizeof (inbuf), 
171                     0, 
172                     (struct sockaddr *)&from, 
173                     &fromlen);
174
175       if (cc <= 0) 
176         {
177           if (cc < 0 && errno != EWOULDBLOCK)
178             {
179               olsr_printf(1, "error recvfrom: %s", strerror(errno));
180               olsr_syslog(OLSR_LOG_ERR, "error recvfrom: %m");
181             }
182           break;
183         }
184
185       if(olsr_cnf->ip_version == AF_INET)
186         {
187           /* IPv4 sender address */
188           COPY_IP(&from_addr, &((struct sockaddr_in *)&from)->sin_addr.s_addr);
189         }
190       else
191         {
192           /* IPv6 sender address */
193           COPY_IP(&from_addr, &((struct sockaddr_in6 *)&from)->sin6_addr);
194         }
195
196       /* are we talking to ourselves? */
197       if(if_ifwithaddr(&from_addr) != NULL)
198         return;
199
200 #ifdef DEBUG
201       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));
202 #endif
203       //printf("\nCC: %d FROMLEN: %d\n\n", cc, fromlen);
204       if ((olsr_cnf->ip_version == AF_INET) && (fromlen != sizeof (struct sockaddr_in)))
205         break;
206       else if ((olsr_cnf->ip_version == AF_INET6) && (fromlen != sizeof (struct sockaddr_in6)))
207         break;
208
209       //printf("Recieved data on socket %d\n", socknr);
210
211
212       if((olsr_in_if = if_ifwithsock(fd)) == NULL)
213         {
214           olsr_printf(1, "Could not find input interface for message from %s size %d\n",
215                       olsr_ip_to_string(&from_addr),
216                       cc);
217           olsr_syslog(OLSR_LOG_ERR, "Could not find input interface for message from %s size %d\n",
218                  olsr_ip_to_string(&from_addr),
219                  cc);
220           return ;
221         }
222
223       /*
224        * &from - sender
225        * &inbuf.olsr 
226        * cc - bytes read
227        */
228       parse_packet((struct olsr *)inbuf, cc, olsr_in_if, &from_addr);
229     
230     }
231 }
232
233
234
235
236 /**
237  *Process a newly received OLSR packet. Checks the type
238  *and to the neccessary convertions and call the
239  *corresponding functions to handle the information.
240  *@param from the sockaddr struct describing the sender
241  *@param olsr the olsr struct containing the message
242  *@param size the size of the message
243  *@return nada
244  */
245
246 void
247 parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip_addr *from_addr)
248 {
249   union olsr_message *m = (union olsr_message *)olsr->olsr_msg;
250   struct unknown_message unkpacket;
251   int count;
252   int msgsize;
253   int processed;
254   struct parse_function_entry *entry;
255   char *packet = (char*)olsr;
256   int i;
257   int x = 0;
258
259   count = size - ((char *)m - (char *)olsr);
260
261   if (count < minsize)
262     return;
263
264   if (ntohs(olsr->olsr_packlen) != size)
265     {
266       olsr_printf(1, "Size error detected in received packet.\nRecieved %d, in packet %d\n", size, ntohs(olsr->olsr_packlen));
267             
268       olsr_syslog(OLSR_LOG_ERR, " packet length error in  packet received from %s!",
269              olsr_ip_to_string(from_addr));
270       return;
271     }
272
273   //printf("Message from %s\n\n", olsr_ip_to_string(from_addr)); 
274       
275   /* Display packet */
276   if(disp_pack_in)
277     {
278       printf("\n\tfrom: %s\n\tsize: %d\n\tcontent(decimal):\n\t", olsr_ip_to_string(from_addr), size);
279         
280       for(i = 0; i < size;i++)
281         {
282           if(x == 4)
283             {
284               x = 0;
285               printf("\n\t");
286             }
287           x++;
288           if(olsr_cnf->ip_version == AF_INET)
289             printf(" %03i", (u_char) packet[i]);
290           else
291             printf(" %02x", (u_char) packet[i]);
292         }
293             
294       printf("\n");
295     }
296
297   if(olsr_cnf->ip_version == AF_INET)
298     msgsize = ntohs(m->v4.olsr_msgsize);
299   else
300     msgsize = ntohs(m->v6.olsr_msgsize);
301
302
303   /*
304    * Hysteresis update - for every OLSR package
305    */
306   if(olsr_cnf->use_hysteresis)
307     {
308       if(olsr_cnf->ip_version == AF_INET)
309         {
310           /* IPv4 */
311           update_hysteresis_incoming(from_addr, 
312                                      &in_if->ip_addr,
313                                      ntohs(olsr->olsr_seqno));
314         }
315       else
316         {
317           /* IPv6 */
318           update_hysteresis_incoming(from_addr, 
319                                      &in_if->ip_addr, 
320                                      ntohs(olsr->olsr_seqno));
321         }
322     }
323
324 #if defined USE_LINK_QUALITY
325   if (olsr_cnf->lq_level > 0)
326     {
327       olsr_update_packet_loss(from_addr, &in_if->ip_addr,
328                               ntohs(olsr->olsr_seqno));
329     }
330 #endif
331   
332   for ( ; count > 0; m = (union olsr_message *)((char *)m + (msgsize)))
333     {
334
335       processed = 0;      
336       if (count < minsize)
337         break;
338       
339       if(olsr_cnf->ip_version == AF_INET)
340         msgsize = ntohs(m->v4.olsr_msgsize);
341       else
342         msgsize = ntohs(m->v6.olsr_msgsize);
343       
344       count -= msgsize;
345
346       /* Check size of message */
347       if(count < 0)
348         {
349           olsr_printf(1, "packet length error in  packet received from %s!",
350                       olsr_ip_to_string(from_addr));
351
352           olsr_syslog(OLSR_LOG_ERR, " packet length error in  packet received from %s!",
353                  olsr_ip_to_string(from_addr));
354           break;
355         }
356
357
358       /* Treat TTL hopcnt */
359       if(olsr_cnf->ip_version == AF_INET)
360         {
361           /* IPv4 */
362           if (m->v4.ttl <= 0)
363             {
364               olsr_printf(2, "Dropping packet type %d from neigh %s with TTL 0\n", 
365                           m->v4.olsr_msgtype,
366                           olsr_ip_to_string(from_addr)); 
367               continue;
368             }
369         }
370       else
371         {
372           /* IPv6 */
373           if (m->v6.ttl <= 0) 
374             {
375               olsr_printf(2, "Dropping packet type %d from %s with TTL 0\n", 
376                           m->v4.olsr_msgtype,
377                           olsr_ip_to_string(from_addr)); 
378               continue;
379             }
380         }
381
382       /*RFC 3626 section 3.4:
383        *  2    If the time to live of the message is less than or equal to
384        *  '0' (zero), or if the message was sent by the receiving node
385        *  (i.e., the Originator Address of the message is the main
386        *  address of the receiving node): the message MUST silently be
387        *  dropped.
388        */
389
390       /* Should be the same for IPv4 and IPv6 */
391       if(COMP_IP(&m->v4.originator, &main_addr))
392         {
393 #ifdef DEBUG
394           olsr_printf(3, "Not processing message originating from us!\n");
395 #endif
396           continue;
397         }
398
399
400       //printf("MESSAGETYPE: %d\n", m->v4.olsr_msgtype);
401
402       entry = parse_functions;
403
404       while(entry)
405         {
406           /* Should be the same for IPv4 and IPv6 */
407
408           /* Promiscuous or exact match */
409           if((entry->type == PROMISCUOUS) || 
410              (entry->type == m->v4.olsr_msgtype))
411             {
412               entry->function(m, in_if, from_addr);
413               if(entry->caller_forwarding)
414                 processed = 1;
415             }
416           entry = entry->next;
417         }
418
419
420       /* UNKNOWN PACKETTYPE */
421       if(processed == 0)
422         {
423           unk_chgestruct(&unkpacket, m);
424           
425           olsr_printf(3, "Unknown type: %d, size %d, from %s\n",
426                       m->v4.olsr_msgtype,
427                       size,
428                       olsr_ip_to_string(&unkpacket.originator));
429
430           /* Forward message */
431           if(!COMP_IP(&unkpacket.originator, &main_addr))
432             {         
433               /* Forward */
434               olsr_forward_message(m, 
435                                    &unkpacket.originator, 
436                                    unkpacket.seqno, 
437                                    in_if,
438                                    from_addr);
439             }
440
441         }
442
443     } /* for olsr_msg */ 
444
445
446 }
447
448
449
450