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