2 * The olsr.org Optimized Link-State Routing daemon(olsrd)
3 * Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org)
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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
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.
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.
33 * Visit http://www.olsr.org for more information.
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.
44 #include "process_package.h"
46 #include "hysteresis.h"
47 #include "duplicate_set.h"
50 #include "rebuild_packet.h"
53 #include "print_packet.h"
58 #define EWOULDBLOCK WSAEWOULDBLOCK
60 #define errno WSAGetLastError()
62 #define strerror(x) StrError(x)
65 /* Sven-Ola: On very slow devices used in huge networks
66 * the amount of lq_tc messages is so high, that the
67 * recv() loop never ends. This is a small hack to end
68 * the loop in this cases
71 unsigned int cpu_overload_exit = 0;
73 struct parse_function_entry *parse_functions;
74 struct preprocessor_function_entry *preprocessor_functions;
75 struct packetparser_function_entry *packetparser_functions;
77 static char inbuf[MAXMESSAGESIZE+1];
79 static olsr_bool disp_pack_in = OLSR_FALSE;
81 void parser_set_disp_pack_in(olsr_bool val) {
86 *Initialize the parser.
90 void olsr_init_parser(void) {
91 OLSR_PRINTF(3, "Initializing parser...\n");
93 /* Initialize the packet functions */
94 olsr_init_package_process();
98 void olsr_parser_add_function(parse_function *function, olsr_u32_t type, int forwarding) {
99 struct parse_function_entry *new_entry;
101 OLSR_PRINTF(3, "Parser: registering event for type %d\n", type);
103 new_entry = olsr_malloc(sizeof(struct parse_function_entry), "Register parse function");
105 new_entry->function = function;
106 new_entry->type = type;
107 new_entry->caller_forwarding = forwarding;
110 new_entry->next = parse_functions;
111 parse_functions = new_entry;
113 OLSR_PRINTF(3, "Register parse function: Added function for type %d\n", type);
117 int olsr_parser_remove_function(parse_function *function, olsr_u32_t type, int forwarding) {
118 struct parse_function_entry *entry, *prev;
120 entry = parse_functions;
124 if ((entry->function == function) && (entry->type == type) && (entry->caller_forwarding == forwarding)) {
125 if (entry == parse_functions) {
126 parse_functions = entry->next;
128 prev->next = entry->next;
141 void olsr_preprocessor_add_function(preprocessor_function *function) {
142 struct preprocessor_function_entry *new_entry;
144 OLSR_PRINTF(3, "Parser: registering preprocessor\n");
146 new_entry = olsr_malloc(sizeof(struct preprocessor_function_entry), "Register preprocessor function");
148 new_entry->function = function;
151 new_entry->next = preprocessor_functions;
152 preprocessor_functions = new_entry;
154 OLSR_PRINTF(3, "Registered preprocessor function\n");
158 int olsr_preprocessor_remove_function(preprocessor_function *function) {
159 struct preprocessor_function_entry *entry, *prev;
161 entry = preprocessor_functions;
165 if (entry->function == function) {
166 if (entry == preprocessor_functions) {
167 preprocessor_functions = entry->next;
169 prev->next = entry->next;
182 void olsr_packetparser_add_function(packetparser_function *function) {
183 struct packetparser_function_entry *new_entry;
185 OLSR_PRINTF(3, "Parser: registering packetparser\n");
187 new_entry = olsr_malloc(sizeof(struct packetparser_function_entry), "Register packetparser function");
189 new_entry->function = function;
192 new_entry->next = packetparser_functions;
193 packetparser_functions = new_entry;
195 OLSR_PRINTF(3, "Registered packetparser function\n");
199 int olsr_packetparser_remove_function(packetparser_function *function) {
200 struct packetparser_function_entry *entry, *prev;
202 entry = packetparser_functions;
206 if (entry->function == function) {
207 if (entry == packetparser_functions) {
208 packetparser_functions = entry->next;
210 prev->next = entry->next;
224 *Process a newly received OLSR packet. Checks the type
225 *and to the neccessary convertions and call the
226 *corresponding functions to handle the information.
227 *@param from the sockaddr struct describing the sender
228 *@param olsr the olsr struct containing the message
229 *@param size the size of the message
233 void parse_packet(struct olsr *olsr, int size, struct interface *in_if, union olsr_ip_addr *from_addr) {
234 union olsr_message *m = (union olsr_message *)olsr->olsr_msg;
235 struct unknown_message unkpacket;
239 struct parse_function_entry *entry;
240 struct packetparser_function_entry *packetparser;
242 count = size - ((char *)m - (char *)olsr);
244 if (count < MIN_PACKET_SIZE(olsr_cnf->ip_version))
247 if (ntohs(olsr->olsr_packlen) != size) {
248 struct ipaddr_str buf;
249 OLSR_PRINTF(1, "Size error detected in received packet.\nRecieved %d, in packet %d\n", size, ntohs(olsr->olsr_packlen));
251 olsr_syslog(OLSR_LOG_ERR, " packet length error in packet received from %s!",
252 olsr_ip_to_string(&buf, from_addr));
256 // translate sequence number to host order
257 olsr->olsr_seqno = ntohs(olsr->olsr_seqno);
260 packetparser = packetparser_functions;
261 while (packetparser) {
262 packetparser->function(olsr, in_if, from_addr);
263 packetparser = packetparser->next;
266 //printf("Message from %s\n\n", olsr_ip_to_string(&buf, from_addr));
270 print_olsr_serialized_packet(stdout, (union olsr_packet *)olsr, size, from_addr);
272 if (olsr_cnf->ip_version == AF_INET)
273 msgsize = ntohs(m->v4.olsr_msgsize);
275 msgsize = ntohs(m->v6.olsr_msgsize);
278 * Hysteresis update - for every OLSR package
280 if (olsr_cnf->use_hysteresis) {
281 if (olsr_cnf->ip_version == AF_INET) {
283 update_hysteresis_incoming(from_addr, in_if, ntohs(olsr->olsr_seqno));
286 update_hysteresis_incoming(from_addr, in_if, ntohs(olsr->olsr_seqno));
290 for (; count > 0; m = (union olsr_message *)((char *)m + (msgsize))) {
293 if (count < MIN_PACKET_SIZE(olsr_cnf->ip_version))
296 if (olsr_cnf->ip_version == AF_INET)
297 msgsize = ntohs(m->v4.olsr_msgsize);
299 msgsize = ntohs(m->v6.olsr_msgsize);
303 /* Check size of message */
305 struct ipaddr_str buf;
306 OLSR_PRINTF(1, "packet length error in packet received from %s!",
307 olsr_ip_to_string(&buf, from_addr));
309 olsr_syslog(OLSR_LOG_ERR, " packet length error in packet received from %s!",
310 olsr_ip_to_string(&buf, from_addr));
316 * Sven-Ola: This code leads to flooding our meshes with invalid /
317 * overdue messages if lq_fish is enabled (which is true since 2005)
318 * because there was no "do not forward"-check in olsr.c. If a message
319 * (yes: ttl=0 is invalid) is received, we should say: Welcome message,
320 * let us evaluate! But: if TTL < 2 or TTL + hopcount is higher than
321 * plausible, we should not forward. See olsr.c:olsr_forward_message()
324 /* Treat TTL hopcnt */
325 if(olsr_cnf->ip_version == AF_INET)
328 if (m->v4.ttl <= 0 && olsr_cnf->lq_fish == 0)
331 struct ipaddr_str buf;
333 OLSR_PRINTF(2, "Dropping packet type %d from neigh %s with TTL 0\n",
335 olsr_ip_to_string(&buf, from_addr));
342 if (m->v6.ttl <= 0 && olsr_cnf->lq_fish == 0)
345 struct ipaddr_str buf;
347 OLSR_PRINTF(2, "Dropping packet type %d from %s with TTL 0\n",
349 olsr_ip_to_string(&buf, from_addr));
355 /*RFC 3626 section 3.4:
356 * 2 If the time to live of the message is less than or equal to
357 * '0' (zero), or if the message was sent by the receiving node
358 * (i.e., the Originator Address of the message is the main
359 * address of the receiving node): the message MUST silently be
363 /* Should be the same for IPv4 and IPv6 */
364 if (ipequal((union olsr_ip_addr *)&m->v4.originator, &olsr_cnf->main_addr)
365 || !olsr_validate_address((union olsr_ip_addr *)&m->v4.originator)) {
366 #if !defined(NODEBUG) && defined(DEBUG)
367 struct ipaddr_str buf;
370 OLSR_PRINTF(3, "Not processing message originating from %s!\n",
371 olsr_ip_to_string(&buf,(union olsr_ip_addr *)&m->v4.originator));
376 /* check for message duplicates */
377 if (olsr_cnf->ip_version == AF_INET) {
379 if (olsr_shall_process_message(&m->v4.originator, ntohs(m->v4.seqno)) == 0) {
384 if (olsr_shall_process_message(&m->v6.originator, ntohs(m->v6.seqno)) == 0) {
389 //printf("MESSAGETYPE: %d\n", m->v4.olsr_msgtype);
391 entry = parse_functions;
394 /* Should be the same for IPv4 and IPv6 */
396 /* Promiscuous or exact match */
397 if ((entry->type == PROMISCUOUS) || (entry->type == m->v4.olsr_msgtype)) {
398 entry->function(m, in_if, from_addr);
399 if (entry->caller_forwarding)
405 /* UNKNOWN PACKETTYPE */
406 if (processed == 0) {
408 struct ipaddr_str buf;
410 unk_chgestruct(&unkpacket, m);
412 OLSR_PRINTF(3, "Unknown type: %d, size %d, from %s\n",
415 olsr_ip_to_string(&buf, &unkpacket.originator));
417 /* Forward message */
418 if (!ipequal(&unkpacket.originator, &olsr_cnf->main_addr)) {
420 olsr_forward_message(m, from_addr);
423 /* Cancel loop here, otherwise olsrd just hangs forever at this point */
431 *Processing OLSR data from socket. Reading data, setting
432 *wich interface recieved the message, Sends IPC(if used)
433 *and passes the packet on to parse_packet().
435 *@param fd the filedescriptor that data should be read from.
438 void olsr_input(int fd) {
439 struct interface *olsr_in_if;
440 union olsr_ip_addr from_addr;
441 struct preprocessor_function_entry *entry;
444 cpu_overload_exit = 0;
447 #if !defined(NODEBUG) && defined(DEBUG)
448 struct ipaddr_str buf;
450 /* sockaddr_in6 is bigger than sockaddr !!!! */
451 struct sockaddr_storage from;
455 if (32 < ++cpu_overload_exit) {
456 OLSR_PRINTF(1, "CPU overload detected, ending olsr_input() loop\n");
460 fromlen = sizeof(struct sockaddr_storage);
461 cc = olsr_recvfrom(fd, inbuf, sizeof (inbuf), 0, (struct sockaddr *)&from, &fromlen);
464 if (cc < 0 && errno != EWOULDBLOCK) {
465 OLSR_PRINTF(1, "error recvfrom: %s", strerror(errno));
466 olsr_syslog(OLSR_LOG_ERR, "error recvfrom: %m");
470 if (olsr_cnf->ip_version == AF_INET) {
471 /* IPv4 sender address */
472 from_addr.v4 = ((struct sockaddr_in *)&from)->sin_addr;
474 /* IPv6 sender address */
475 from_addr.v6 = ((struct sockaddr_in6 *)&from)->sin6_addr;
479 OLSR_PRINTF(5, "Recieved a packet from %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&((struct sockaddr_in *)&from)->sin_addr.s_addr));
482 if ((olsr_cnf->ip_version == AF_INET) && (fromlen != sizeof(struct sockaddr_in)))
484 else if ((olsr_cnf->ip_version == AF_INET6) && (fromlen != sizeof(struct sockaddr_in6)))
487 /* are we talking to ourselves? */
488 if (if_ifwithaddr(&from_addr) != NULL)
491 if ((olsr_in_if = if_ifwithsock(fd)) == NULL) {
492 struct ipaddr_str buf;
493 OLSR_PRINTF(1, "Could not find input interface for message from %s size %d\n",
494 olsr_ip_to_string(&buf, &from_addr),
496 olsr_syslog(OLSR_LOG_ERR, "Could not find input interface for message from %s size %d\n",
497 olsr_ip_to_string(&buf, &from_addr),
502 // call preprocessors
503 entry = preprocessor_functions;
507 packet = entry->function(packet, olsr_in_if, &from_addr, &cc);
509 if (packet == NULL) {
520 parse_packet((struct olsr *)packet, cc, olsr_in_if, &from_addr);
526 *Processing OLSR data from socket. Reading data, setting
527 *wich interface recieved the message, Sends IPC(if used)
528 *and passes the packet on to parse_packet().
530 *@param fd the filedescriptor that data should be read from.
533 void olsr_input_hostemu(int fd) {
534 /* sockaddr_in6 is bigger than sockaddr !!!! */
535 struct sockaddr_storage from;
537 struct interface *olsr_in_if;
538 union olsr_ip_addr from_addr;
540 struct preprocessor_function_entry *entry;
543 /* Host emulator receives IP address first to emulate
546 int cc = recv(fd, from_addr.v6.s6_addr, olsr_cnf->ipsize, 0);
547 if (cc != (int)olsr_cnf->ipsize) {
548 fprintf(stderr, "Error receiving host-client IP hook(%d) %s!\n", cc, strerror(errno));
549 memcpy(&from_addr, &((struct olsr *)inbuf)->olsr_msg->originator, olsr_cnf->ipsize);
552 /* are we talking to ourselves? */
553 if (if_ifwithaddr(&from_addr) != NULL)
557 if ((cc = recv(fd, (void *)&pcklen, 2, MSG_PEEK)) != 2) /* Win needs a cast */
560 fprintf(stderr, "Lost olsr_switch connection - exit!\n");
561 olsr_exit(__func__, EXIT_FAILURE);
563 fprintf(stderr, "[hust-emu] error extracting size(%d) %s!\n", cc, strerror(errno));
566 pcklen = ntohs(pcklen);
569 fromlen = sizeof(struct sockaddr_storage);
571 cc = olsr_recvfrom(fd, inbuf, pcklen, 0, (struct sockaddr *)&from, &fromlen);
574 if (cc < 0 && errno != EWOULDBLOCK) {
575 const char * const err_msg = strerror(errno);
576 OLSR_PRINTF(1, "error recvfrom: %s", err_msg);
577 olsr_syslog(OLSR_LOG_ERR, "error recvfrom: %s", err_msg);
583 printf("Could not read whole packet(size %d, read %d)\n", pcklen, cc);
587 if ((olsr_in_if = if_ifwithsock(fd)) == NULL) {
588 struct ipaddr_str buf;
589 OLSR_PRINTF(1, "Could not find input interface for message from %s size %d\n",
590 olsr_ip_to_string(&buf, &from_addr),
592 olsr_syslog(OLSR_LOG_ERR, "Could not find input interface for message from %s size %d\n",
593 olsr_ip_to_string(&buf, &from_addr),
598 // call preprocessors
599 entry = preprocessor_functions;
603 packet = entry->function(packet, olsr_in_if, &from_addr, &cc);
605 if (packet == NULL) {
616 parse_packet((struct olsr *)inbuf, cc, olsr_in_if, &from_addr);