From Henning Rogge <rogge@fgan.de>: parser refactoring
[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  */
40
41 #include "parser.h"
42 #include "ipcalc.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 #include "net_os.h"
52 #include "log.h"
53 #include "print_packet.h"
54 #include "net_olsr.h"
55
56 #ifdef WIN32
57 #undef EWOULDBLOCK
58 #define EWOULDBLOCK WSAEWOULDBLOCK
59 #undef errno
60 #define errno WSAGetLastError()
61 #undef strerror
62 #define strerror(x) StrError(x)
63 #endif
64
65 /* Sven-Ola: On very slow devices used in huge networks
66  * the amount of lq_tc messages is so high, that the 
67  * recv() loop never ends. This is a small hack to end
68  * the loop in this cases
69  */
70  
71 unsigned int cpu_overload_exit = 0;
72
73 struct parse_function_entry *parse_functions;
74 struct preprocessor_function_entry *preprocessor_functions;
75
76 static char inbuf[MAXMESSAGESIZE+1];
77
78 static olsr_bool disp_pack_in = OLSR_FALSE;
79
80 void
81 parser_set_disp_pack_in(olsr_bool val)
82 {
83   disp_pack_in = val;
84 }
85
86 /**
87  *Initialize the parser. 
88  *
89  *@return nada
90  */
91 void
92 olsr_init_parser(void)
93 {
94   OLSR_PRINTF(3, "Initializing parser...\n");
95
96   /* Initialize the packet functions */
97   olsr_init_package_process();
98
99 }
100
101 void
102 olsr_parser_add_function(parse_function *function, olsr_u32_t type, int forwarding)
103 {
104   struct parse_function_entry *new_entry;
105
106   OLSR_PRINTF(3, "Parser: registering event for type %d\n", type);
107  
108
109   new_entry = olsr_malloc(sizeof(struct parse_function_entry), "Register parse function");
110
111   new_entry->function = function;
112   new_entry->type = type;
113   new_entry->caller_forwarding = forwarding;
114
115   /* Queue */
116   new_entry->next = parse_functions;
117   parse_functions = new_entry;
118
119   OLSR_PRINTF(3, "Register parse function: Added function for type %d\n", type);
120
121 }
122
123
124
125 int
126 olsr_parser_remove_function(parse_function *function, olsr_u32_t type, int forwarding)
127 {
128   struct parse_function_entry *entry, *prev;
129
130   entry = parse_functions;
131   prev = NULL;
132
133   while(entry)
134     {
135       if((entry->function == function) &&
136          (entry->type == type) &&
137          (entry->caller_forwarding == forwarding))
138         {
139           if(entry == parse_functions)
140             {
141               parse_functions = entry->next;
142             }
143           else
144             {
145               prev->next = entry->next;
146             }
147           free(entry);
148           return 1;
149         }
150
151       prev = entry;
152       entry = entry->next;
153     }
154
155   return 0;
156 }
157
158 void
159 olsr_preprocessor_add_function(preprocessor_function *function)
160 {
161   struct preprocessor_function_entry *new_entry;
162
163   OLSR_PRINTF(3, "Parser: registering preprocessor\n");
164  
165
166   new_entry = olsr_malloc(sizeof(struct preprocessor_function_entry), "Register preprocessor function");
167
168   new_entry->function = function;
169
170   /* Queue */
171   new_entry->next = preprocessor_functions;
172   preprocessor_functions = new_entry;
173
174   OLSR_PRINTF(3, "Registered preprocessor function\n");
175
176 }
177
178
179
180 int
181 olsr_preprocessor_remove_function(preprocessor_function *function)
182 {
183   struct preprocessor_function_entry *entry, *prev;
184
185   entry = preprocessor_functions;
186   prev = NULL;
187
188   while(entry)
189     {
190       if(entry->function == function)
191         {
192           if(entry == preprocessor_functions)
193             {
194                   preprocessor_functions = entry->next;
195             }
196           else
197             {
198               prev->next = entry->next;
199             }
200           free(entry);
201           return 1;
202         }
203
204       prev = entry;
205       entry = entry->next;
206     }
207
208   return 0;
209 }
210
211
212 /**
213  *Process a newly received OLSR packet. Checks the type
214  *and to the neccessary convertions and call the
215  *corresponding functions to handle the information.
216  *@param from the sockaddr struct describing the sender
217  *@param olsr the olsr struct containing the message
218  *@param size the size of the message
219  *@return nada
220  */
221
222 void
223 parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip_addr *from_addr)
224 {
225   union olsr_message *m = (union olsr_message *)olsr->olsr_msg;
226   struct unknown_message unkpacket;
227   int count;
228   int msgsize;
229   int processed;
230   struct parse_function_entry *entry;
231
232   count = size - ((char *)m - (char *)olsr);
233
234   if (count < MIN_PACKET_SIZE(olsr_cnf->ip_version))
235     return;
236
237   if (ntohs(olsr->olsr_packlen) != size)
238     {
239       struct ipaddr_str buf;
240       OLSR_PRINTF(1, "Size error detected in received packet.\nRecieved %d, in packet %d\n", size, ntohs(olsr->olsr_packlen));
241             
242       olsr_syslog(OLSR_LOG_ERR, " packet length error in  packet received from %s!",
243              olsr_ip_to_string(&buf, from_addr));
244       return;
245     }
246
247   //printf("Message from %s\n\n", olsr_ip_to_string(&buf, from_addr)); 
248       
249   /* Display packet */
250   if(disp_pack_in)
251     print_olsr_serialized_packet(stdout, (union olsr_packet *)olsr, size, from_addr);
252
253   if(olsr_cnf->ip_version == AF_INET)
254     msgsize = ntohs(m->v4.olsr_msgsize);
255   else
256     msgsize = ntohs(m->v6.olsr_msgsize);
257
258
259   /*
260    * Hysteresis update - for every OLSR package
261    */
262   if(olsr_cnf->use_hysteresis)
263     {
264       if(olsr_cnf->ip_version == AF_INET)
265         {
266           /* IPv4 */
267           update_hysteresis_incoming(from_addr, 
268                                      in_if,
269                                      ntohs(olsr->olsr_seqno));
270         }
271       else
272         {
273           /* IPv6 */
274           update_hysteresis_incoming(from_addr, 
275                                      in_if, 
276                                      ntohs(olsr->olsr_seqno));
277         }
278     }
279
280   if (olsr_cnf->lq_level > 0)
281     {
282       olsr_update_packet_loss(from_addr, in_if,
283                               ntohs(olsr->olsr_seqno));
284     }
285   
286   for ( ; count > 0; m = (union olsr_message *)((char *)m + (msgsize)))
287     {
288
289       processed = 0;      
290       if (count < MIN_PACKET_SIZE(olsr_cnf->ip_version))
291         break;
292       
293       if(olsr_cnf->ip_version == AF_INET)
294         msgsize = ntohs(m->v4.olsr_msgsize);
295       else
296         msgsize = ntohs(m->v6.olsr_msgsize);
297       
298       count -= msgsize;
299
300       /* Check size of message */
301       if(count < 0)
302         {
303           struct ipaddr_str buf;
304           OLSR_PRINTF(1, "packet length error in  packet received from %s!",
305                       olsr_ip_to_string(&buf, from_addr));
306
307           olsr_syslog(OLSR_LOG_ERR, " packet length error in  packet received from %s!",
308                  olsr_ip_to_string(&buf, from_addr));
309           break;
310         }
311
312
313 #if 0
314       /*
315        * Sven-Ola: This code leads to flooding our meshes with invalid /
316        * overdue messages if lq_fish is enabled (which is true since 2005)
317        * because there was no "do not forward"-check in olsr.c. If a message
318        * (yes: ttl=0 is invalid) is received, we should say: Welcome message,
319        * let us evaluate! But: if TTL < 2 or TTL + hopcount is higher than
320        * plausible, we should not forward. See olsr.c:olsr_forward_message()
321        */
322        
323       /* Treat TTL hopcnt */
324       if(olsr_cnf->ip_version == AF_INET)
325         {
326           /* IPv4 */
327           if (m->v4.ttl <= 0 && olsr_cnf->lq_fish == 0)
328             {
329 #ifndef NODEBUG
330               struct ipaddr_str buf;
331 #endif
332               OLSR_PRINTF(2, "Dropping packet type %d from neigh %s with TTL 0\n", 
333                           m->v4.olsr_msgtype,
334                           olsr_ip_to_string(&buf, from_addr));
335               continue;
336             }
337         }
338       else
339         {
340           /* IPv6 */
341           if (m->v6.ttl <= 0 && olsr_cnf->lq_fish == 0) 
342             {
343 #ifndef NODEBUG
344               struct ipaddr_str buf;
345 #endif
346               OLSR_PRINTF(2, "Dropping packet type %d from %s with TTL 0\n", 
347                           m->v4.olsr_msgtype,
348                           olsr_ip_to_string(&buf, from_addr));
349               continue;
350             }
351         }
352 #endif
353
354       /*RFC 3626 section 3.4:
355        *  2    If the time to live of the message is less than or equal to
356        *  '0' (zero), or if the message was sent by the receiving node
357        *  (i.e., the Originator Address of the message is the main
358        *  address of the receiving node): the message MUST silently be
359        *  dropped.
360        */
361
362       /* Should be the same for IPv4 and IPv6 */
363       if(ipequal((union olsr_ip_addr *)&m->v4.originator, &olsr_cnf->main_addr) || !olsr_validate_address((union olsr_ip_addr *)&m->v4.originator))
364         {
365 #if !defined(NODEBUG) && defined(DEBUG)
366           struct ipaddr_str buf;
367 #endif
368 #ifdef DEBUG
369           OLSR_PRINTF(3, "Not processing message originating from %s!\n",
370             olsr_ip_to_string(&buf,(union olsr_ip_addr *)&m->v4.originator));
371 #endif
372           continue;
373         }
374
375
376       //printf("MESSAGETYPE: %d\n", m->v4.olsr_msgtype);
377
378       entry = parse_functions;
379
380       while(entry)
381         {
382           /* Should be the same for IPv4 and IPv6 */
383
384           /* Promiscuous or exact match */
385           if((entry->type == PROMISCUOUS) || 
386              (entry->type == m->v4.olsr_msgtype))
387             {
388               entry->function(m, in_if, from_addr);
389               if(entry->caller_forwarding)
390                 processed = 1;
391             }
392           entry = entry->next;
393         }
394
395
396       /* UNKNOWN PACKETTYPE */
397       if(processed == 0)
398         {
399 #ifndef NODEBUG
400           struct ipaddr_str buf;
401 #endif
402           unk_chgestruct(&unkpacket, m);
403           
404           OLSR_PRINTF(3, "Unknown type: %d, size %d, from %s\n",
405                       m->v4.olsr_msgtype,
406                       size,
407                       olsr_ip_to_string(&buf, &unkpacket.originator));
408
409           /* Forward message */
410           if(!ipequal(&unkpacket.originator, &olsr_cnf->main_addr))
411             {         
412               /* Forward */
413               olsr_forward_message(m, 
414                                    &unkpacket.originator, 
415                                    unkpacket.seqno, 
416                                    in_if,
417                                    from_addr);
418             }
419
420           /* Cancel loop here, otherwise olsrd just hangs forever at this point */
421           break;
422         }
423
424     } /* for olsr_msg */ 
425
426
427 }
428
429
430
431
432 /**
433  *Processing OLSR data from socket. Reading data, setting 
434  *wich interface recieved the message, Sends IPC(if used) 
435  *and passes the packet on to parse_packet().
436  *
437  *@param fd the filedescriptor that data should be read from.
438  *@return nada
439  */
440 void
441 olsr_input(int fd)
442 {
443   struct interface *olsr_in_if;
444   union olsr_ip_addr from_addr;
445   struct preprocessor_function_entry *entry;
446   char *packet;
447   
448   cpu_overload_exit = 0;
449   
450   for (;;) 
451     {
452 #if !defined(NODEBUG) && defined(DEBUG)
453       struct ipaddr_str buf;
454 #endif
455       /* sockaddr_in6 is bigger than sockaddr !!!! */
456       struct sockaddr_storage from;
457       socklen_t fromlen;
458       int cc;
459
460       if (32 < ++cpu_overload_exit)
461       {
462         OLSR_PRINTF(1, "CPU overload detected, ending olsr_input() loop\n");
463         break;
464       }
465       
466       fromlen = sizeof(struct sockaddr_storage);
467       cc = olsr_recvfrom(fd, 
468                          inbuf, 
469                          sizeof (inbuf), 
470                          0, 
471                          (struct sockaddr *)&from, 
472                          &fromlen);
473
474       if (cc <= 0) 
475         {
476           if (cc < 0 && errno != EWOULDBLOCK)
477             {
478               OLSR_PRINTF(1, "error recvfrom: %s", strerror(errno));
479               olsr_syslog(OLSR_LOG_ERR, "error recvfrom: %m");
480             }
481           break;
482         }
483       if(olsr_cnf->ip_version == AF_INET)
484         {
485           /* IPv4 sender address */
486           from_addr.v4 = ((struct sockaddr_in *)&from)->sin_addr;
487         }
488       else
489         {
490           /* IPv6 sender address */
491           from_addr.v6 = ((struct sockaddr_in6 *)&from)->sin6_addr;
492         }
493       
494       
495 #ifdef DEBUG
496       OLSR_PRINTF(5, "Recieved a packet from %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&((struct sockaddr_in *)&from)->sin_addr.s_addr));
497 #endif
498         
499         if ((olsr_cnf->ip_version == AF_INET) && (fromlen != sizeof (struct sockaddr_in)))
500           break;
501         else if ((olsr_cnf->ip_version == AF_INET6) && (fromlen != sizeof (struct sockaddr_in6)))
502           break;
503       
504       /* are we talking to ourselves? */
505       if(if_ifwithaddr(&from_addr) != NULL)
506         return;
507       
508       if((olsr_in_if = if_ifwithsock(fd)) == NULL)
509         {
510           struct ipaddr_str buf;
511           OLSR_PRINTF(1, "Could not find input interface for message from %s size %d\n",
512                       olsr_ip_to_string(&buf, &from_addr),
513                       cc);
514           olsr_syslog(OLSR_LOG_ERR, "Could not find input interface for message from %s size %d\n",
515                  olsr_ip_to_string(&buf, &from_addr),
516                  cc);
517           return ;
518         }
519
520       // call preprocessors
521       entry = preprocessor_functions;
522       packet = &inbuf[0];
523       
524       while(entry)
525         {
526               packet = entry->function(packet, olsr_in_if, &from_addr, &cc);
527               // discard package ?
528               if (packet == NULL) {
529                 return;
530               }
531               entry = entry->next;
532         }
533       
534       /*
535        * &from - sender
536        * &inbuf.olsr 
537        * cc - bytes read
538        */
539       parse_packet((struct olsr *)packet, cc, olsr_in_if, &from_addr);
540     
541     }
542 }
543
544
545
546
547 /**
548  *Processing OLSR data from socket. Reading data, setting 
549  *wich interface recieved the message, Sends IPC(if used) 
550  *and passes the packet on to parse_packet().
551  *
552  *@param fd the filedescriptor that data should be read from.
553  *@return nada
554  */
555 void
556 olsr_input_hostemu(int fd)
557 {
558   /* sockaddr_in6 is bigger than sockaddr !!!! */
559   struct sockaddr_storage from;
560   socklen_t fromlen;
561   struct interface *olsr_in_if;
562   union olsr_ip_addr from_addr;
563   olsr_u16_t pcklen;
564   struct preprocessor_function_entry *entry;
565   char *packet;
566
567   /* Host emulator receives IP address first to emulate
568      direct link */
569
570   int cc = recv(fd, from_addr.v6.s6_addr, olsr_cnf->ipsize, 0);
571   if(cc != (int)olsr_cnf->ipsize)
572     {
573       fprintf(stderr, "Error receiving host-client IP hook(%d) %s!\n", cc, strerror(errno));
574       memcpy(&from_addr, &((struct olsr *)inbuf)->olsr_msg->originator, olsr_cnf->ipsize);
575     }
576
577   /* are we talking to ourselves? */
578   if(if_ifwithaddr(&from_addr) != NULL)
579     return;
580       
581   /* Extract size */
582   if((cc = recv(fd, (void *)&pcklen, 2, MSG_PEEK)) != 2) /* Win needs a cast */
583     {
584       if(cc <= 0)
585         {
586           fprintf(stderr, "Lost olsr_switch connection - exit!\n");
587           olsr_exit(__func__, EXIT_FAILURE);
588         }
589       fprintf(stderr, "[hust-emu] error extracting size(%d) %s!\n", cc, strerror(errno));
590       return;
591     }
592   else
593     {
594       pcklen = ntohs(pcklen);
595     }
596
597   fromlen = sizeof(struct sockaddr_storage);
598   
599   cc = olsr_recvfrom(fd, 
600                      inbuf, 
601                      pcklen, 
602                      0, 
603                      (struct sockaddr *)&from, 
604                      &fromlen);
605
606   if (cc <= 0) 
607     {
608       if (cc < 0 && errno != EWOULDBLOCK)
609         {
610           const char * const err_msg = strerror(errno);
611           OLSR_PRINTF(1, "error recvfrom: %s", err_msg);
612           olsr_syslog(OLSR_LOG_ERR, "error recvfrom: %s", err_msg);
613         }
614       return;
615     }
616   
617   if(cc != pcklen)
618     {
619       printf("Could not read whole packet(size %d, read %d)\n", pcklen, cc);
620       return;
621     }
622
623   if((olsr_in_if = if_ifwithsock(fd)) == NULL)
624     {
625       struct ipaddr_str buf;
626       OLSR_PRINTF(1, "Could not find input interface for message from %s size %d\n",
627                   olsr_ip_to_string(&buf, &from_addr),
628                   cc);
629       olsr_syslog(OLSR_LOG_ERR, "Could not find input interface for message from %s size %d\n",
630                   olsr_ip_to_string(&buf, &from_addr),
631                   cc);
632       return;
633     }
634   
635   // call preprocessors
636   entry = preprocessor_functions;
637   packet = &inbuf[0];
638   
639   while(entry)
640     {
641       packet = entry->function(packet, olsr_in_if, &from_addr, &cc);
642       // discard package ?
643       if (packet == NULL) {
644         return;
645       }
646       entry = entry->next;
647     }
648   
649   /*
650    * &from - sender
651    * &inbuf.olsr 
652    * cc - bytes read
653    */
654   parse_packet((struct olsr *)inbuf, cc, olsr_in_if, &from_addr);
655   
656 }
657
658