New configfile parser and configuration scheme integrated
[olsrd.git] / src / parser.c
1 /*
2  * OLSR ad-hoc routing table management protocol
3  * Copyright (C) 2004 Andreas T√łnnesen (andreto@ifi.uio.no)
4  *
5  * This file is part of the olsr.org OLSR daemon.
6  *
7  * olsr.org is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * olsr.org is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with olsr.org; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  * 
21  * 
22  * $Id: parser.c,v 1.9 2004/10/18 13:13:37 kattemat Exp $
23  *
24  */
25
26 #include "parser.h"
27 #include "defs.h"
28 #include "process_package.h"
29 #include "mantissa.h"
30 #include "hysteresis.h"
31 #include "duplicate_set.h"
32 #include "mid_set.h"
33 #include "olsr.h"
34 #include "rebuild_packet.h"
35
36 //union olsr_ip_addr tmp_addr;
37 #ifdef WIN32
38 #undef EWOULDBLOCK
39 #define EWOULDBLOCK WSAEWOULDBLOCK
40 #undef errno
41 #define errno WSAGetLastError()
42 #undef strerror
43 #define strerror(x) StrError(x)
44 #endif
45
46
47 /* The outputbuffer on neighbornodes
48  * will never exceed MAXMESSAGESIZE
49  */
50 static char inbuf[MAXMESSAGESIZE+1];
51
52
53 /**
54  *Initialize the parser. 
55  *
56  *@return nada
57  */
58 void
59 olsr_init_parser()
60 {
61   olsr_printf(3, "Initializing parser...\n");
62
63   parse_functions = NULL;
64
65   /* Initialize the packet functions */
66   olsr_init_package_process();
67
68 }
69
70 void
71 olsr_parser_add_function(void (*function)(union olsr_message *, struct interface *, union olsr_ip_addr *), int type, int forwarding)
72 {
73   struct parse_function_entry *new_entry;
74
75   olsr_printf(3, "Parser: registering event for type %d\n", type);
76  
77
78   new_entry = olsr_malloc(sizeof(struct parse_function_entry), "Register parse function");
79
80   new_entry->function = function;
81   new_entry->type = type;
82   new_entry->caller_forwarding = forwarding;
83
84   /* Queue */
85   new_entry->next = parse_functions;
86   parse_functions = new_entry;
87
88   olsr_printf(3, "Register parse function: Added function for type %d\n", type);
89
90 }
91
92
93
94 int
95 olsr_parser_remove_function(void (*function)(union olsr_message *, struct interface *, union olsr_ip_addr *), int type, int forwarding)
96 {
97   struct parse_function_entry *entry, *prev;
98
99   entry = parse_functions;
100   prev = NULL;
101
102   while(entry)
103     {
104       if((entry->function == function) &&
105          (entry->type == type) &&
106          (entry->caller_forwarding == forwarding))
107         {
108           if(entry == parse_functions)
109             {
110               parse_functions = entry->next;
111             }
112           else
113             {
114               prev->next = entry->next;
115             }
116           free(entry);
117           return 1;
118         }
119
120       prev = entry;
121       entry = entry->next;
122     }
123
124   return 0;
125 }
126
127
128
129 /**
130  *Processing OLSR data from socket. Reading data, setting 
131  *wich interface recieved the message, Sends IPC(if used) 
132  *and passes the packet on to parse_packet().
133  *
134  *@param fd the filedescriptor that data should be read from.
135  *@return nada
136  */
137 void
138 olsr_input(int fd)
139 {
140   /* sockaddr_in6 is bigger than sockaddr !!!! */
141   struct sockaddr_storage from;
142   size_t fromlen;
143   int cc;
144   struct interface *olsr_in_if;
145   union olsr_ip_addr from_addr;
146
147
148   for (;;) 
149     {
150       fromlen = sizeof(struct sockaddr_storage);
151
152       cc = recvfrom(fd, 
153                     inbuf, 
154                     sizeof (inbuf), 
155                     0, 
156                     (struct sockaddr *)&from, 
157                     &fromlen);
158
159       if (cc <= 0) 
160         {
161           if (cc < 0 && errno != EWOULDBLOCK)
162             {
163               olsr_printf(1, "error recvfrom: %s", strerror(errno));
164               olsr_syslog(OLSR_LOG_ERR, "error recvfrom: %m");
165             }
166           break;
167         }
168
169       if(olsr_cnf->ip_version == AF_INET)
170         {
171           /* IPv4 sender address */
172           COPY_IP(&from_addr, &((struct sockaddr_in *)&from)->sin_addr.s_addr);
173         }
174       else
175         {
176           /* IPv6 sender address */
177           COPY_IP(&from_addr, &((struct sockaddr_in6 *)&from)->sin6_addr);
178         }
179
180       /* are we talking to ourselves? */
181       if(if_ifwithaddr(&from_addr) != NULL)
182         return;
183
184 #ifdef DEBUG
185       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));
186 #endif
187       //printf("\nCC: %d FROMLEN: %d\n\n", cc, fromlen);
188       if ((olsr_cnf->ip_version == AF_INET) && (fromlen != sizeof (struct sockaddr_in)))
189         break;
190       else if ((olsr_cnf->ip_version == AF_INET6) && (fromlen != sizeof (struct sockaddr_in6)))
191         break;
192
193       //printf("Recieved data on socket %d\n", socknr);
194
195
196       if((olsr_in_if = if_ifwithsock(fd)) == NULL)
197         {
198           olsr_printf(1, "Could not find input interface for message from %s size %d\n",
199                       olsr_ip_to_string(&from_addr),
200                       cc);
201           olsr_syslog(OLSR_LOG_ERR, "Could not find input interface for message from %s size %d\n",
202                  olsr_ip_to_string(&from_addr),
203                  cc);
204           return ;
205         }
206
207       /*
208        * &from - sender
209        * &inbuf.olsr 
210        * cc - bytes read
211        */
212       parse_packet((struct olsr *)inbuf, cc, olsr_in_if, &from_addr);
213     
214     }
215 }
216
217
218
219
220 /**
221  *Process a newly received OLSR packet. Checks the type
222  *and to the neccessary convertions and call the
223  *corresponding functions to handle the information.
224  *@param from the sockaddr struct describing the sender
225  *@param olsr the olsr struct containing the message
226  *@param size the size of the message
227  *@return nada
228  */
229
230 void
231 parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip_addr *from_addr)
232 {
233   union olsr_message *m = (union olsr_message *)olsr->olsr_msg;
234   struct unknown_message unkpacket;
235   int count;
236   int msgsize;
237   int processed;
238   struct parse_function_entry *entry;
239   char *packet = (char*)olsr;
240   int i;
241   int x = 0;
242
243   count = size - ((char *)m - (char *)olsr);
244
245   if (count < minsize)
246     return;
247
248
249   if (ntohs(olsr->olsr_packlen) != size)
250     {
251       olsr_printf(1, "Size error detected in received packet.\nRecieved %d, in packet %d\n", size, ntohs(olsr->olsr_packlen));
252             
253       olsr_syslog(OLSR_LOG_ERR, " packet length error in  packet received from %s!",
254              olsr_ip_to_string(from_addr));
255       return;
256     }
257
258   //printf("Message from %s\n\n", olsr_ip_to_string(from_addr)); 
259       
260   /* Display packet */
261   if(disp_pack_in)
262     {
263       printf("\n\tfrom: %s\n\tsize: %d\n\tcontent(decimal):\n\t", olsr_ip_to_string(from_addr), size);
264         
265       for(i = 0; i < size;i++)
266         {
267           if(x == 4)
268             {
269               x = 0;
270               printf("\n\t");
271             }
272           x++;
273           if(olsr_cnf->ip_version == AF_INET)
274             printf(" %03i", (u_char) packet[i]);
275           else
276             printf(" %02x", (u_char) packet[i]);
277         }
278             
279       printf("\n");
280     }
281
282   if(olsr_cnf->ip_version == AF_INET)
283     msgsize = ntohs(m->v4.olsr_msgsize);
284   else
285     msgsize = ntohs(m->v6.olsr_msgsize);
286
287
288   /*
289    * Hysteresis update - for every OLSR package
290    */
291   if(olsr_cnf->use_hysteresis)
292     {
293       if(olsr_cnf->ip_version == AF_INET)
294         {
295           /* IPv4 */
296           update_hysteresis_incoming(from_addr, 
297                                      &in_if->ip_addr,
298                                      ntohs(olsr->olsr_seqno));
299         }
300       else
301         {
302           /* IPv6 */
303           update_hysteresis_incoming(from_addr, 
304                                      &in_if->ip_addr, 
305                                      ntohs(olsr->olsr_seqno));
306         }
307     }
308
309   
310   for ( ; count > 0; m = (union olsr_message *)((char *)m + (msgsize)))
311     {
312
313       processed = 0;      
314       if (count < minsize)
315         break;
316       
317       if(olsr_cnf->ip_version == AF_INET)
318         msgsize = ntohs(m->v4.olsr_msgsize);
319       else
320         msgsize = ntohs(m->v6.olsr_msgsize);
321       
322       count -= msgsize;
323
324       /* Check size of message */
325       if(count < 0)
326         {
327           olsr_printf(1, "packet length error in  packet received from %s!",
328                       olsr_ip_to_string(from_addr));
329
330           olsr_syslog(OLSR_LOG_ERR, " packet length error in  packet received from %s!",
331                  olsr_ip_to_string(from_addr));
332           break;
333         }
334
335
336       /* Treat TTL hopcnt */
337       if(olsr_cnf->ip_version == AF_INET)
338         {
339           /* IPv4 */
340           if (m->v4.ttl <= 0)
341             {
342               olsr_printf(1, "Dropping packet type %d from neigh %s with TTL 0\n", 
343                           m->v4.olsr_msgtype,
344                           olsr_ip_to_string(from_addr)); 
345               continue;
346             }
347         }
348       else
349         {
350           /* IPv6 */
351           if (m->v6.ttl <= 0) 
352             {
353               olsr_printf(1, "Dropping packet type %d from %s with TTL 0\n", 
354                           m->v4.olsr_msgtype,
355                           olsr_ip_to_string(from_addr)); 
356               continue;
357             }
358         }
359
360       /*RFC 3626 section 3.4:
361        *  2    If the time to live of the message is less than or equal to
362        *  '0' (zero), or if the message was sent by the receiving node
363        *  (i.e., the Originator Address of the message is the main
364        *  address of the receiving node): the message MUST silently be
365        *  dropped.
366        */
367
368       /* Should be the same for IPv4 and IPv6 */
369       if(COMP_IP(&m->v4.originator, &main_addr))
370         {
371 #ifdef DEBUG
372           olsr_printf(3, "Not processing message originating from us!\n");
373 #endif
374           continue;
375         }
376
377
378       //printf("MESSAGETYPE: %d\n", m->v4.olsr_msgtype);
379
380       entry = parse_functions;
381
382       while(entry)
383         {
384           /* Should be the same for IPv4 and IPv6 */
385
386           /* Promiscuous or exact match */
387           if((entry->type == PROMISCUOUS) || 
388              (entry->type == m->v4.olsr_msgtype))
389             {
390               entry->function(m, in_if, from_addr);
391               if(entry->caller_forwarding)
392                 processed = 1;
393             }
394           entry = entry->next;
395         }
396
397
398       /* UNKNOWN PACKETTYPE */
399       if(processed == 0)
400         {
401           unk_chgestruct(&unkpacket, m);
402           
403           olsr_printf(1, "Unknown type: %d, size %d, from %s\n",
404                       m->v4.olsr_msgtype,
405                       size,
406                       olsr_ip_to_string(&unkpacket.originator));
407
408           /* Forward message */
409           if(!COMP_IP(&unkpacket.originator, &main_addr))
410             {         
411               /* Forward */
412               olsr_forward_message(m, 
413                                    &unkpacket.originator, 
414                                    unkpacket.seqno, 
415                                    in_if,
416                                    from_addr);
417             }
418
419         }
420
421     } /* for olsr_msg */ 
422
423
424 }
425
426
427
428