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