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