1f804f7714ed86c6a1631f70e8ad580ec5daf249
[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.31 2006/12/14 11:29:20 bernd67 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 #include "net_os.h"
52 #include "log.h"
53 #include "print_packet.h"
54
55 #ifdef WIN32
56 #undef EWOULDBLOCK
57 #define EWOULDBLOCK WSAEWOULDBLOCK
58 #undef errno
59 #define errno WSAGetLastError()
60 #undef strerror
61 #define strerror(x) StrError(x)
62 #endif
63
64 struct parse_function_entry *parse_functions;
65
66 static char inbuf[MAXMESSAGESIZE+1];
67
68 static olsr_bool disp_pack_in = OLSR_FALSE;
69
70 void
71 parser_set_disp_pack_in(olsr_bool val)
72 {
73   disp_pack_in = val;
74 }
75
76 /**
77  *Initialize the parser. 
78  *
79  *@return nada
80  */
81 void
82 olsr_init_parser()
83 {
84   OLSR_PRINTF(3, "Initializing parser...\n")
85
86   /* Initialize the packet functions */
87   olsr_init_package_process();
88
89 }
90
91 void
92 olsr_parser_add_function(void (*function)(union olsr_message *, struct interface *, union olsr_ip_addr *), olsr_u32_t type, int forwarding)
93 {
94   struct parse_function_entry *new_entry;
95
96   OLSR_PRINTF(3, "Parser: registering event for type %d\n", type)
97  
98
99   new_entry = olsr_malloc(sizeof(struct parse_function_entry), "Register parse function");
100
101   new_entry->function = function;
102   new_entry->type = type;
103   new_entry->caller_forwarding = forwarding;
104
105   /* Queue */
106   new_entry->next = parse_functions;
107   parse_functions = new_entry;
108
109   OLSR_PRINTF(3, "Register parse function: Added function for type %d\n", type)
110
111 }
112
113
114
115 int
116 olsr_parser_remove_function(void (*function)(union olsr_message *, struct interface *, union olsr_ip_addr *), olsr_u32_t type, int forwarding)
117 {
118   struct parse_function_entry *entry, *prev;
119
120   entry = parse_functions;
121   prev = NULL;
122
123   while(entry)
124     {
125       if((entry->function == function) &&
126          (entry->type == type) &&
127          (entry->caller_forwarding == forwarding))
128         {
129           if(entry == parse_functions)
130             {
131               parse_functions = entry->next;
132             }
133           else
134             {
135               prev->next = entry->next;
136             }
137           free(entry);
138           return 1;
139         }
140
141       prev = entry;
142       entry = entry->next;
143     }
144
145   return 0;
146 }
147
148
149 /**
150  *Process a newly received OLSR packet. Checks the type
151  *and to the neccessary convertions and call the
152  *corresponding functions to handle the information.
153  *@param from the sockaddr struct describing the sender
154  *@param olsr the olsr struct containing the message
155  *@param size the size of the message
156  *@return nada
157  */
158
159 void
160 parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip_addr *from_addr)
161 {
162   union olsr_message *m = (union olsr_message *)olsr->olsr_msg;
163   struct unknown_message unkpacket;
164   int count;
165   int msgsize;
166   int processed;
167   struct parse_function_entry *entry;
168
169   count = size - ((char *)m - (char *)olsr);
170
171   if (count < MIN_PACKET_SIZE(olsr_cnf->ip_version))
172     return;
173
174   if (ntohs(olsr->olsr_packlen) != size)
175     {
176       OLSR_PRINTF(1, "Size error detected in received packet.\nRecieved %d, in packet %d\n", size, ntohs(olsr->olsr_packlen))
177             
178       olsr_syslog(OLSR_LOG_ERR, " packet length error in  packet received from %s!",
179              olsr_ip_to_string(from_addr));
180       return;
181     }
182
183   //printf("Message from %s\n\n", olsr_ip_to_string(from_addr)); 
184       
185   /* Display packet */
186   if(disp_pack_in)
187     print_olsr_serialized_packet(stdout, (union olsr_packet *)olsr, size, from_addr);
188
189   if(olsr_cnf->ip_version == AF_INET)
190     msgsize = ntohs(m->v4.olsr_msgsize);
191   else
192     msgsize = ntohs(m->v6.olsr_msgsize);
193
194
195   /*
196    * Hysteresis update - for every OLSR package
197    */
198   if(olsr_cnf->use_hysteresis)
199     {
200       if(olsr_cnf->ip_version == AF_INET)
201         {
202           /* IPv4 */
203           update_hysteresis_incoming(from_addr, 
204                                      in_if,
205                                      ntohs(olsr->olsr_seqno));
206         }
207       else
208         {
209           /* IPv6 */
210           update_hysteresis_incoming(from_addr, 
211                                      in_if, 
212                                      ntohs(olsr->olsr_seqno));
213         }
214     }
215
216   if (olsr_cnf->lq_level > 0)
217     {
218       olsr_update_packet_loss(from_addr, in_if,
219                               ntohs(olsr->olsr_seqno));
220     }
221   
222   for ( ; count > 0; m = (union olsr_message *)((char *)m + (msgsize)))
223     {
224
225       processed = 0;      
226       if (count < MIN_PACKET_SIZE(olsr_cnf->ip_version))
227         break;
228       
229       if(olsr_cnf->ip_version == AF_INET)
230         msgsize = ntohs(m->v4.olsr_msgsize);
231       else
232         msgsize = ntohs(m->v6.olsr_msgsize);
233       
234       count -= msgsize;
235
236       /* Check size of message */
237       if(count < 0)
238         {
239           OLSR_PRINTF(1, "packet length error in  packet received from %s!",
240                       olsr_ip_to_string(from_addr))
241
242           olsr_syslog(OLSR_LOG_ERR, " packet length error in  packet received from %s!",
243                  olsr_ip_to_string(from_addr));
244           break;
245         }
246
247
248       /* Treat TTL hopcnt */
249       if(olsr_cnf->ip_version == AF_INET)
250         {
251           /* IPv4 */
252           if (m->v4.ttl <= 0 && olsr_cnf->lq_fish == 0)
253             {
254               OLSR_PRINTF(2, "Dropping packet type %d from neigh %s with TTL 0\n", 
255                           m->v4.olsr_msgtype,
256                           olsr_ip_to_string(from_addr))
257               continue;
258             }
259         }
260       else
261         {
262           /* IPv6 */
263           if (m->v6.ttl <= 0 && olsr_cnf->lq_fish == 0) 
264             {
265               OLSR_PRINTF(2, "Dropping packet type %d from %s with TTL 0\n", 
266                           m->v4.olsr_msgtype,
267                           olsr_ip_to_string(from_addr))
268               continue;
269             }
270         }
271
272       /*RFC 3626 section 3.4:
273        *  2    If the time to live of the message is less than or equal to
274        *  '0' (zero), or if the message was sent by the receiving node
275        *  (i.e., the Originator Address of the message is the main
276        *  address of the receiving node): the message MUST silently be
277        *  dropped.
278        */
279
280       /* Should be the same for IPv4 and IPv6 */
281       if(COMP_IP(&m->v4.originator, &olsr_cnf->main_addr))
282         {
283 #ifdef DEBUG
284           OLSR_PRINTF(3, "Not processing message originating from us!\n")
285 #endif
286           continue;
287         }
288
289
290       //printf("MESSAGETYPE: %d\n", m->v4.olsr_msgtype);
291
292       entry = parse_functions;
293
294       while(entry)
295         {
296           /* Should be the same for IPv4 and IPv6 */
297
298           /* Promiscuous or exact match */
299           if((entry->type == PROMISCUOUS) || 
300              (entry->type == m->v4.olsr_msgtype))
301             {
302               entry->function(m, in_if, from_addr);
303               if(entry->caller_forwarding)
304                 processed = 1;
305             }
306           entry = entry->next;
307         }
308
309
310       /* UNKNOWN PACKETTYPE */
311       if(processed == 0)
312         {
313           unk_chgestruct(&unkpacket, m);
314           
315           OLSR_PRINTF(3, "Unknown type: %d, size %d, from %s\n",
316                       m->v4.olsr_msgtype,
317                       size,
318                       olsr_ip_to_string(&unkpacket.originator))
319
320           /* Forward message */
321           if(!COMP_IP(&unkpacket.originator, &olsr_cnf->main_addr))
322             {         
323               /* Forward */
324               olsr_forward_message(m, 
325                                    &unkpacket.originator, 
326                                    unkpacket.seqno, 
327                                    in_if,
328                                    from_addr);
329             }
330
331         }
332
333     } /* for olsr_msg */ 
334
335
336 }
337
338
339
340
341 /**
342  *Processing OLSR data from socket. Reading data, setting 
343  *wich interface recieved the message, Sends IPC(if used) 
344  *and passes the packet on to parse_packet().
345  *
346  *@param fd the filedescriptor that data should be read from.
347  *@return nada
348  */
349 void
350 olsr_input(int fd)
351 {
352   /* sockaddr_in6 is bigger than sockaddr !!!! */
353   struct sockaddr_storage from;
354   socklen_t fromlen;
355   int cc;
356   struct interface *olsr_in_if;
357   union olsr_ip_addr from_addr;
358
359   for (;;) 
360     {
361       fromlen = sizeof(struct sockaddr_storage);
362
363       cc = olsr_recvfrom(fd, 
364                          inbuf, 
365                          sizeof (inbuf), 
366                          0, 
367                          (struct sockaddr *)&from, 
368                          &fromlen);
369
370       if (cc <= 0) 
371         {
372           if (cc < 0 && errno != EWOULDBLOCK)
373             {
374               OLSR_PRINTF(1, "error recvfrom: %s", strerror(errno))
375               olsr_syslog(OLSR_LOG_ERR, "error recvfrom: %m");
376             }
377           break;
378         }
379
380       if(olsr_cnf->ip_version == AF_INET)
381         {
382           /* IPv4 sender address */
383           COPY_IP(&from_addr, &((struct sockaddr_in *)&from)->sin_addr.s_addr);
384         }
385       else
386         {
387           /* IPv6 sender address */
388           COPY_IP(&from_addr, &((struct sockaddr_in6 *)&from)->sin6_addr);
389         }
390       
391       
392 #ifdef DEBUG
393       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))
394 #endif
395         
396         if ((olsr_cnf->ip_version == AF_INET) && (fromlen != sizeof (struct sockaddr_in)))
397           break;
398         else if ((olsr_cnf->ip_version == AF_INET6) && (fromlen != sizeof (struct sockaddr_in6)))
399           break;
400       
401       /* are we talking to ourselves? */
402       if(if_ifwithaddr(&from_addr) != NULL)
403         return;
404       
405       if((olsr_in_if = if_ifwithsock(fd)) == NULL)
406         {
407           OLSR_PRINTF(1, "Could not find input interface for message from %s size %d\n",
408                       olsr_ip_to_string(&from_addr),
409                       cc)
410           olsr_syslog(OLSR_LOG_ERR, "Could not find input interface for message from %s size %d\n",
411                  olsr_ip_to_string(&from_addr),
412                  cc);
413           return ;
414         }
415
416       /*
417        * &from - sender
418        * &inbuf.olsr 
419        * cc - bytes read
420        */
421       parse_packet((struct olsr *)inbuf, cc, olsr_in_if, &from_addr);
422     
423     }
424 }
425
426
427
428
429 /**
430  *Processing OLSR data from socket. Reading data, setting 
431  *wich interface recieved the message, Sends IPC(if used) 
432  *and passes the packet on to parse_packet().
433  *
434  *@param fd the filedescriptor that data should be read from.
435  *@return nada
436  */
437 void
438 olsr_input_hostemu(int fd)
439 {
440   /* sockaddr_in6 is bigger than sockaddr !!!! */
441   struct sockaddr_storage from;
442   socklen_t fromlen;
443   int cc;
444   struct interface *olsr_in_if;
445   union olsr_ip_addr from_addr;
446   olsr_u16_t pcklen;
447
448   /* Host emulator receives IP address first to emulate
449      direct link */
450
451   if((cc = recv(fd, from_addr.v6.s6_addr, olsr_cnf->ipsize, 0)) != (int)olsr_cnf->ipsize)
452     {
453       fprintf(stderr, "Error receiving host-client IP hook(%d) %s!\n", cc, strerror(errno));
454       COPY_IP(&from_addr, &((struct olsr *)inbuf)->olsr_msg->originator);
455     }
456
457   /* are we talking to ourselves? */
458   if(if_ifwithaddr(&from_addr) != NULL)
459     return;
460       
461   /* Extract size */
462   if((cc = recv(fd, &pcklen, 2, MSG_PEEK)) != 2)
463     {
464       if(cc <= 0)
465         {
466           fprintf(stderr, "Lost olsr_switch connection - exit!\n");
467           olsr_exit(__func__, EXIT_FAILURE);
468         }
469       fprintf(stderr, "[hust-emu] error extracting size(%d) %s!\n", cc, strerror(errno));
470       return;
471     }
472   else
473     {
474       pcklen = ntohs(pcklen);
475     }
476
477   fromlen = sizeof(struct sockaddr_storage);
478   
479   cc = olsr_recvfrom(fd, 
480                      inbuf, 
481                      pcklen, 
482                      0, 
483                      (struct sockaddr *)&from, 
484                      &fromlen);
485
486   if (cc <= 0) 
487     {
488       if (cc < 0 && errno != EWOULDBLOCK)
489         {
490           OLSR_PRINTF(1, "error recvfrom: %s", strerror(errno))
491             olsr_syslog(OLSR_LOG_ERR, "error recvfrom: %m");
492         }
493       return;
494     }
495   
496   if(cc != pcklen)
497     {
498       printf("Could not read whole packet(size %d, read %d)\n", pcklen, cc);
499       return;
500     }
501
502   if((olsr_in_if = if_ifwithsock(fd)) == NULL)
503     {
504       OLSR_PRINTF(1, "Could not find input interface for message from %s size %d\n",
505                   olsr_ip_to_string(&from_addr),
506                   cc)
507         olsr_syslog(OLSR_LOG_ERR, "Could not find input interface for message from %s size %d\n",
508                     olsr_ip_to_string(&from_addr),
509                     cc);
510       return;
511     }
512   
513   /*
514    * &from - sender
515    * &inbuf.olsr 
516    * cc - bytes read
517    */
518   parse_packet((struct olsr *)inbuf, cc, olsr_in_if, &from_addr);
519   
520 }
521
522