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