void olsr_reconfigure(int signo __attribute__ ((unused))) { /* if we are started with -nofork, we do not weant to go into the * background here. So we can simply stop on -HUP */ olsr_syslog(OLSR_LOG_INFO, "sot: olsr_reconfigure()\n"); if (!olsr_cnf->no_fork) { if (!fork()) { int i; sigset_t sigs; /* New process */ sleep(3); sigemptyset(&sigs); sigaddset(&sigs, SIGHUP); sigprocmask(SIG_UNBLOCK, &sigs, NULL); for (i = sysconf(_SC_OPEN_MAX); --i > STDERR_FILENO;) { close(i); } printf("Restarting %s\n", olsr_argv[0]); olsr_syslog(OLSR_LOG_INFO, "Restarting %s\n", olsr_argv[0]); execv(olsr_argv[0], olsr_argv); olsr_syslog(OLSR_LOG_ERR, "execv(%s) fails: %s!\n", olsr_argv[0], strerror(errno)); } else { olsr_syslog(OLSR_LOG_INFO, "RECONFIGURING!\n"); } } olsr_shutdown(0); }
static int delete_all_inet_gws(void) { int s; char buf[BUFSIZ], *cp, *cplim; struct ifconf ifc; struct ifreq *ifr; OLSR_PRINTF(1, "Internet gateway detected...\nTrying to delete default gateways\n"); /* Get a socket */ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { olsr_syslog(OLSR_LOG_ERR, "socket: %m"); return -1; } ifc.ifc_len = sizeof(buf); ifc.ifc_buf = buf; if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { olsr_syslog(OLSR_LOG_ERR, "ioctl (get interface configuration)"); close(s); return -1; } ifr = ifc.ifc_req; cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */ for (cp = buf; cp < cplim; cp += sizeof(ifr->ifr_name) + sizeof(ifr->ifr_addr)) { struct rtentry kernel_route; ifr = (struct ifreq *)cp; if (strcmp(ifr->ifr_ifrn.ifrn_name, "lo") == 0) { OLSR_PRINTF(1, "Skipping loopback...\n"); continue; } OLSR_PRINTF(1, "Trying 0.0.0.0/0 %s...", ifr->ifr_ifrn.ifrn_name); memset(&kernel_route, 0, sizeof(struct rtentry)); ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = 0; ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family = AF_INET; ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = 0; ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family = AF_INET; ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr.s_addr = INADDR_ANY; ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_family = AF_INET; kernel_route.rt_flags = RTF_UP | RTF_GATEWAY; kernel_route.rt_dev = ifr->ifr_ifrn.ifrn_name; if ((ioctl(s, SIOCDELRT, &kernel_route)) < 0) OLSR_PRINTF(1, "NO\n"); else OLSR_PRINTF(1, "YES\n"); } close(s); return 0; }
/** * creates an ipip tunnel (for ipv4 or ipv6) * * @param name interface name * @param target pointer to tunnel target IP, NULL if tunnel should be removed. * Must be of type 'in_addr_t *' for ipv4 and of type 'struct in6_addr *' for * ipv6 * @return 0 if an error happened, * if_index for successful created tunnel, 1 for successful deleted tunnel */ static int os_ip_tunnel(const char *name, void *target) { struct ifreq ifr; int err; void * p; char buffer[INET6_ADDRSTRLEN]; struct ip_tunnel_parm p4; #ifdef LINUX_IPV6_TUNNEL struct ip6_tnl_parm p6; #endif assert (name != NULL); memset(&ifr, 0, sizeof(ifr)); if (olsr_cnf->ip_version == AF_INET) { p = &p4; memset(&p4, 0, sizeof(p4)); p4.iph.version = 4; p4.iph.ihl = 5; p4.iph.ttl = 64; p4.iph.protocol = IPPROTO_IPIP; if (target) { p4.iph.daddr = *((in_addr_t *) target); } strncpy(p4.name, name, IFNAMSIZ); } else { #ifdef LINUX_IPV6_TUNNEL p = (void *) &p6; memset(&p6, 0, sizeof(p6)); p6.proto = 0; /* any protocol */ if (target) { p6.raddr = *((struct in6_addr *) target); } strncpy(p6.name, name, IFNAMSIZ); #else return 0; #endif } strncpy(ifr.ifr_name, name, IFNAMSIZ); ifr.ifr_ifru.ifru_data = p; if ((err = ioctl(olsr_cnf->ioctl_s, target != NULL ? SIOCADDTUNNEL : SIOCDELTUNNEL, &ifr))) { olsr_syslog(OLSR_LOG_ERR, "Cannot %s tunnel %s to %s: %s (%d)\n", target != NULL ? "add" : "remove", name, target != NULL ? inet_ntop(olsr_cnf->ip_version, target, buffer, sizeof(buffer)) : "-", strerror(errno), errno); return 0; } olsr_syslog(OLSR_LOG_INFO, "Tunnel %s %s, to %s", name, target != NULL ? "added" : "removed", target != NULL ? inet_ntop(olsr_cnf->ip_version, target, buffer, sizeof(buffer)) : "-"); return target != NULL ? if_nametoindex(name) : 1; }
static int os_ip6_tunnel(const char *name, struct in6_addr *target) { struct ifreq ifr; int err; struct ip6_tnl_parm p; /* only IP6 tunnel if OLSR runs with IPv6 */ assert (olsr_cnf->ip_version == AF_INET6); memset(&p, 0, sizeof(p)); p.proto = 0; /* any protocol */ if (target) { p.raddr = *target; } strncpy(p.name, name, IFNAMSIZ); memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, target != NULL ? DEV_IPV6_TUNNEL : name, IFNAMSIZ); ifr.ifr_ifru.ifru_data = (void *) &p; if ((err = ioctl(olsr_cnf->ioctl_s, target != NULL ? SIOCADDTUNNEL : SIOCDELTUNNEL, &ifr))) { char buffer[INET6_ADDRSTRLEN]; olsr_syslog(OLSR_LOG_ERR, "Cannot %s a tunnel %s to %s: %s (%d)\n", target != NULL ? "add" : "remove", name, target != NULL ? inet_ntop(olsr_cnf->ip_version, target, buffer, sizeof(buffer)) : "-", strerror(errno), errno); return 0; } return target != NULL ? if_nametoindex(name) : 1; }
/** * Process a route from the kernel deletion list. * *@return -1 on error, else 0 */ static int olsr_delete_kernel_route(struct rt_entry *rt) { if (rt->rt_metric.hops > 1) { /* multihop route */ if (ip_is_linklocal(&rt->rt_dst.prefix)) { /* do not delete a route with a LL IP as a destination */ return 0; } } if (!olsr_cnf->host_emul) { int16_t error = olsr_cnf->ip_version == AF_INET ? olsr_delroute_function(rt) : olsr_delroute6_function(rt); if (error != 0) { const char *const err_msg = strerror(errno); const char *const routestr = olsr_rt_to_string(rt); OLSR_PRINTF(1, "KERN: ERROR deleting %s: %s\n", routestr, err_msg); olsr_syslog(OLSR_LOG_ERR, "Delete route %s: %s", routestr, err_msg); return -1; } #ifdef linux /* call NIIT handler (always)*/ if (olsr_cnf->use_niit) { olsr_niit_handle_route(rt, false); } #endif } return 0; }
/** * Process a route from the kernel addition list. * *@return nada */ static void olsr_add_kernel_route(struct rt_entry *rt) { if (rt->rt_best->rtp_metric.hops > 1) { /* multihop route */ if (ip_is_linklocal(&rt->rt_best->rtp_dst.prefix)) { /* do not create a route with a LL IP as a destination */ return; } } if (!olsr_cnf->host_emul) { int16_t error = (olsr_cnf->ip_version == AF_INET) ? olsr_addroute_function(rt) : olsr_addroute6_function(rt); if (error != 0) { const char *const err_msg = strerror(errno); const char *const routestr = olsr_rtp_to_string(rt->rt_best); OLSR_PRINTF(1, "KERN: ERROR adding %s: %s\n", routestr, err_msg); olsr_syslog(OLSR_LOG_ERR, "Add route %s: %s", routestr, err_msg); } else { /* route addition has suceeded */ /* save the nexthop and metric in the route entry */ rt->rt_nexthop = rt->rt_best->rtp_nexthop; rt->rt_metric = rt->rt_best->rtp_metric; #ifdef linux /* call NIIT handler */ if (olsr_cnf->use_niit) { olsr_niit_handle_route(rt, true); } #endif } } }
/** Report a plugin error. @param useErrno when true then errno is used in the error message; the error reason is also reported. @param format a pointer to the format string @param ... arguments to the format string */ void pudError(bool useErrno, const char *format, ...) { char strDesc[256]; const char *colon; const char *stringErr; if ((format == NULL) || (*format == '\0')) { strDesc[0] = '\0'; colon = ""; if (!useErrno) { stringErr = "Unknown error"; } else { stringErr = strerror(errno); } } else { va_list arglist; va_start(arglist, format); vsnprintf(strDesc, sizeof(strDesc), format, arglist); va_end(arglist); if (useErrno) { colon = ": "; stringErr = strerror(errno); } else { colon = ""; stringErr = ""; } } if (!pudErrorUseSysLog) olsr_printf(0, "%s: %s%s%s\n", PUD_PLUGIN_ABBR, strDesc, colon, stringErr); else olsr_syslog(OLSR_LOG_ERR, "%s: %s%s%s\n", PUD_PLUGIN_ABBR, strDesc, colon, stringErr); }
void ipc_accept(int fd) { socklen_t addrlen; struct sockaddr_in pin; char *addr; addrlen = sizeof (struct sockaddr_in); if ((ipc_conn = accept(fd, (struct sockaddr *) &pin, &addrlen)) == -1) { perror("IPC accept"); olsr_exit("IPC accept", EXIT_FAILURE); } else { OLSR_PRINTF(1, "Front end connected\n"); addr = inet_ntoa(pin.sin_addr); if(ipc_check_allowed_ip((union olsr_ip_addr *)&pin.sin_addr.s_addr)) { ipc_active = OLSR_TRUE; ipc_send_net_info(ipc_conn); ipc_send_all_routes(ipc_conn); OLSR_PRINTF(1, "Connection from %s\n",addr); } else { OLSR_PRINTF(1, "Front end-connection from foregin host(%s) not allowed!\n", addr); olsr_syslog(OLSR_LOG_ERR, "OLSR: Front end-connection from foregin host(%s) not allowed!\n", addr); CLOSE(ipc_conn); } } }
/** * demands an ipip tunnel to a certain target. If no tunnel exists it will be created * @param target ip address of the target * @param transportV4 true if IPv4 traffic is used, false for IPv6 traffic * @return NULL if an error happened, pointer to olsr_iptunnel_entry otherwise */ struct olsr_iptunnel_entry *olsr_os_add_ipip_tunnel(union olsr_ip_addr *target, bool transportV4 __attribute__ ((unused))) { struct olsr_iptunnel_entry *t; assert(olsr_cnf->ip_version == AF_INET6 || transportV4); t = (struct olsr_iptunnel_entry *)avl_find(&tunnel_tree, target); if (t == NULL) { char name[IFNAMSIZ]; int if_idx; struct ipaddr_str buf; memset(name, 0, sizeof(name)); generate_iptunnel_name(target, name); if (olsr_cnf->ip_version == AF_INET) { if_idx = os_ip4_tunnel(name, &target->v4.s_addr); } else { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) if_idx = os_ip6_tunnel(name, &target->v6); #else if_idx = 0; #endif } if (if_idx == 0) { // cannot create tunnel olsr_syslog(OLSR_LOG_ERR, "Cannot create tunnel %s\n", name); return NULL; } if (olsr_if_set_state(name, true)) { if (olsr_cnf->ip_version == AF_INET) { os_ip4_tunnel(name, NULL); } else { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) os_ip6_tunnel(name, NULL); #endif } return NULL; } /* set originator IP for tunnel */ olsr_os_ifip(if_idx, &olsr_cnf->main_addr, true); t = olsr_cookie_malloc(tunnel_cookie); memcpy(&t->target, target, sizeof(*target)); t->node.key = &t->target; strncpy(t->if_name, name, IFNAMSIZ); t->if_index = if_idx; avl_insert(&tunnel_tree, &t->node, AVL_DUP_NO); } t->usage++; return t; }
static void check_buffspace(int msgsize, int buffsize, const char *type) { if (msgsize > buffsize) { OLSR_PRINTF(1, "%s build, outputbuffer to small(%d/%u)!\n", type, msgsize, buffsize); olsr_syslog(OLSR_LOG_ERR, "%s build, outputbuffer to small(%d/%u)!\n", type, msgsize, buffsize); olsr_exit(__func__, EXIT_FAILURE); } }
static void default_lq_parser_ffeth(struct olsr *olsr, struct interface *in_if, union olsr_ip_addr *from_addr) { const union olsr_ip_addr *main_addr; struct link_entry *lnk; struct default_lq_ffeth_hello *lq; uint32_t seq_diff; /* Find main address */ main_addr = mid_lookup_main_addr(from_addr); /* Loopup link entry */ lnk = lookup_link_entry(from_addr, main_addr, in_if); if (lnk == NULL) { return; } lq = (struct default_lq_ffeth_hello *)lnk->linkquality; /* ignore double package */ if (lq->last_seq_nr == olsr->olsr_seqno) { struct ipaddr_str buf; olsr_syslog(OLSR_LOG_INFO, "detected duplicate packet with seqnr %d from %s on %s (%d Bytes)", olsr->olsr_seqno,olsr_ip_to_string(&buf, from_addr),in_if->int_name,ntohs(olsr->olsr_packlen)); return; } if (lq->last_seq_nr > olsr->olsr_seqno) { seq_diff = (uint32_t) olsr->olsr_seqno + 65536 - lq->last_seq_nr; } else { seq_diff = olsr->olsr_seqno - lq->last_seq_nr; } /* Jump in sequence numbers ? */ if (seq_diff > 256) { seq_diff = 1; } lq->received[lq->activePtr]++; lq->total[lq->activePtr] += seq_diff; lq->last_seq_nr = olsr->olsr_seqno; lq->missed_hellos = 0; }
static int writeToProc(const char *file, char *old, char value) { int fd; char rv; if ((fd = open(file, O_RDWR)) < 0) { OLSR_PRINTF(0, "Error, cannot open proc entry %s: %s (%d)\n", file, strerror(errno), errno); return -1; } if (read(fd, &rv, 1) != 1) { OLSR_PRINTF(0, "Error, cannot read proc entry %s: %s (%d)\n", file, strerror(errno), errno); return -1; } if (rv != value && value != 0) { if (lseek(fd, SEEK_SET, 0) == -1) { OLSR_PRINTF(0, "Error, cannot rewind proc entry %s: %s (%d)\n", file, strerror(errno), errno); return -1; } if (write(fd, &value, 1) != 1) { OLSR_PRINTF(0, "Error, cannot write proc entry %s: %s (%d)\n", file, strerror(errno), errno); return -1; } } if (close(fd) != 0) { OLSR_PRINTF(0, "Error while closing proc entry %s: %s (%d)\n", file, strerror(errno), errno); return -1; } if (old) { *old = rv; } if (value) { olsr_syslog(OLSR_LOG_INFO, "Writing '%c' (was %c) to %s", value, rv, file); } return 0; }
/** *Sends a packet on a given interface. * *@param ifp the interface to send on. * *@return negative on error */ int net_output(struct interface_olsr *ifp) { struct sockaddr_in *sin = NULL; struct sockaddr_in6 *sin6 = NULL; struct sockaddr_in dst; struct sockaddr_in6 dst6; struct ptf *tmp_ptf_list; union olsr_packet *outmsg; int retval; if (!ifp->netbuf.pending) return 0; ifp->netbuf.pending += OLSR_HEADERSIZE; retval = ifp->netbuf.pending; outmsg = (union olsr_packet *)ifp->netbuf.buff; /* Add the Packet seqno */ outmsg->v4.olsr_seqno = htons(ifp->olsr_seqnum++); /* Set the packetlength */ outmsg->v4.olsr_packlen = htons(ifp->netbuf.pending); if (olsr_cnf->ip_version == AF_INET) { /* IP version 4 */ sin = (struct sockaddr_in *)&ifp->int_broadaddr; /* Copy sin */ dst = *sin; sin = &dst; if (sin->sin_port == 0) sin->sin_port = htons(olsr_cnf->olsrport); } else { /* IP version 6 */ sin6 = (struct sockaddr_in6 *)&ifp->int6_multaddr; /* Copy sin */ dst6 = *sin6; sin6 = &dst6; } /* *Call possible packet transform functions registered by plugins */ for (tmp_ptf_list = ptf_list; tmp_ptf_list != NULL; tmp_ptf_list = tmp_ptf_list->next) { tmp_ptf_list->function(ifp->netbuf.buff, &ifp->netbuf.pending); } if (olsr_cnf->ip_version == AF_INET) { /* IP version 4 */ if (olsr_sendto(ifp->send_socket, ifp->netbuf.buff, ifp->netbuf.pending, MSG_DONTROUTE, (struct sockaddr *)sin, sizeof(*sin)) < 0) { perror("sendto(v4)"); #ifndef _WIN32 olsr_syslog(OLSR_LOG_ERR, "OLSR: sendto IPv4 '%s' on interface %s", strerror(errno), ifp->int_name); #endif /* _WIN32 */ retval = -1; } } else { /* IP version 6 */ if (olsr_sendto(ifp->send_socket, ifp->netbuf.buff, ifp->netbuf.pending, MSG_DONTROUTE, (struct sockaddr *)sin6, sizeof(*sin6)) < 0) { struct ipaddr_str buf; perror("sendto(v6)"); #ifndef _WIN32 olsr_syslog(OLSR_LOG_ERR, "OLSR: sendto IPv6 '%s' on interface %s", strerror(errno), ifp->int_name); #endif /* _WIN32 */ fprintf(stderr, "Socket: %d interface: %d\n", ifp->olsr_socket, ifp->if_index); fprintf(stderr, "To: %s (size: %u)\n", ip6_to_string(&buf, &sin6->sin6_addr), (unsigned int)sizeof(*sin6)); fprintf(stderr, "Outputsize: %d\n", ifp->netbuf.pending); retval = -1; } } ifp->netbuf.pending = 0; /* * if we've just transmitted a TC message, let Dijkstra use the current * link qualities for the links to our neighbours */ lq_tc_pending = false; return retval; }
void olsr_hello_tap(struct hello_message *message, struct interface *in_if, const union olsr_ip_addr *from_addr) { struct neighbor_entry *neighbor; /* * Update link status */ struct link_entry *lnk = update_link_entry(&in_if->ip_addr, from_addr, message, in_if); /*check alias message->source_addr*/ if (!ipequal(&message->source_addr,from_addr)){ /*new alias of new neighbour are thrown in the mid table to speed up routing*/ if (olsr_validate_address(from_addr)) { union olsr_ip_addr * main_addr = mid_lookup_main_addr(from_addr); if ((main_addr==NULL)||(ipequal(&message->source_addr, main_addr))){ /*struct ipaddr_str srcbuf, origbuf; olsr_syslog(OLSR_LOG_INFO, "got hello from unknown alias ip of direct neighbour: ip: %s main-ip: %s", olsr_ip_to_string(&origbuf,&message->source_addr), olsr_ip_to_string(&srcbuf,from_addr));*/ insert_mid_alias(&message->source_addr, from_addr, message->vtime); } else { struct ipaddr_str srcbuf, origbuf; olsr_syslog(OLSR_LOG_INFO, "got hello with invalid from and originator adress pair (%s, %s) Duplicate Ips?\n", olsr_ip_to_string(&origbuf,&message->source_addr), olsr_ip_to_string(&srcbuf,from_addr)); } } } if (olsr_cnf->lq_level > 0) { struct hello_neighbor *walker; /* just in case our neighbor has changed its HELLO interval */ olsr_update_packet_loss_hello_int(lnk, message->htime); /* find the input interface in the list of neighbor interfaces */ for (walker = message->neighbors; walker != NULL; walker = walker->next) { if (walker->link != UNSPEC_LINK && ipequal(&walker->address, &in_if->ip_addr)) { break; } } /* * memorize our neighbour's idea of the link quality, so that we * know the link quality in both directions * * walker is NULL if there the current interface was not included in * the message (or was included as an UNSPEC_LINK) */ olsr_memorize_foreign_hello_lq(lnk, walker); /* update packet loss for link quality calculation */ olsr_received_hello_handler(lnk); } neighbor = lnk->neighbor; /* * Hysteresis */ if (olsr_cnf->use_hysteresis) { /* Update HELLO timeout */ /* printf("MESSAGE HTIME: %f\n", message->htime); */ olsr_update_hysteresis_hello(lnk, message->htime); } /* Check if we are chosen as MPR */ if (lookup_mpr_status(message, in_if)) /* source_addr is always the main addr of a node! */ olsr_update_mprs_set(&message->source_addr, message->vtime); /* Check willingness */ if (neighbor->willingness != message->willingness) { struct ipaddr_str buf; OLSR_PRINTF(1, "Willingness for %s changed from %d to %d - UPDATING\n", olsr_ip_to_string(&buf, &neighbor->neighbor_main_addr), neighbor->willingness, message->willingness); /* *If willingness changed - recalculate */ neighbor->willingness = message->willingness; changes_neighborhood = true; changes_topology = true; } /* Don't register neighbors of neighbors that announces WILL_NEVER */ if (neighbor->willingness != WILL_NEVER) process_message_neighbors(neighbor, message); /* Process changes immedeatly in case of MPR updates */ olsr_process_changes(); olsr_free_hello_packet(message); return; }
/* * Allocate a fixed amount of memory based on a passed in cookie type. */ void * olsr_cookie_malloc(struct olsr_cookie_info *ci) { void *ptr; struct olsr_cookie_mem_brand *branding; struct list_node *free_list_node; #ifdef OLSR_COOKIE_DEBUG bool reuse = false; #endif /* * Check first if we have reusable memory. */ if (!ci->ci_free_list_usage) { /* * No reusable memory block on the free_list. */ ptr = calloc(1, ci->ci_size + sizeof(struct olsr_cookie_mem_brand)); if (!ptr) { const char *const err_msg = strerror(errno); OLSR_PRINTF(1, "OUT OF MEMORY: %s\n", err_msg); olsr_syslog(OLSR_LOG_ERR, "olsrd: out of memory!: %s\n", err_msg); olsr_exit(ci->ci_name, EXIT_FAILURE); } } else { /* * There is a memory block on the free list. * Carve it out of the list, and clean. */ free_list_node = ci->ci_free_list.next; list_remove(free_list_node); ptr = (void *)free_list_node; memset(ptr, 0, ci->ci_size); ci->ci_free_list_usage--; #ifdef OLSR_COOKIE_DEBUG reuse = true; #endif } /* * Now brand mark the end of the memory block with a short signature * indicating presence of a cookie. This will be checked against * When the block is freed to detect corruption. */ branding = (struct olsr_cookie_mem_brand *)ARM_NOWARN_ALIGN(((unsigned char *)ptr + ci->ci_size)); memcpy(&branding->cmb_sig, "cookie", 6); branding->cmb_id = ci->ci_id; /* Stats keeping */ olsr_cookie_usage_incr(ci->ci_id); #ifdef OLSR_COOKIE_DEBUG OLSR_PRINTF(1, "MEMORY: alloc %s, %p, %u bytes%s\n", ci->ci_name, ptr, ci->ci_size, reuse ? ", reuse" : ""); #endif return ptr; }
static void olsr_shutdown(int signo __attribute__ ((unused))) #endif { struct interface *ifn; int exit_value; OLSR_PRINTF(1, "Received signal %d - shutting down\n", (int)signo); #ifdef WIN32 OLSR_PRINTF(1, "Waiting for the scheduler to stop.\n"); olsr_win32_end_request = TRUE; while (!olsr_win32_end_flag) Sleep(100); OLSR_PRINTF(1, "Scheduler stopped.\n"); #endif /* clear all links and send empty hellos/tcs */ olsr_reset_all_links(); /* deactivate fisheye and immediate TCs */ olsr_cnf->lq_fish = 0; for (ifn = ifnet; ifn; ifn = ifn->int_next) { ifn->immediate_send_tc = false; } increase_local_ansn(); /* send first shutdown message burst */ olsr_shutdown_messages(); /* delete all routes */ olsr_delete_all_kernel_routes(); /* send second shutdown message burst */ olsr_shutdown_messages(); /* now try to cleanup the rest of the mess */ olsr_delete_all_tc_entries(); olsr_delete_all_mid_entries(); #ifdef LINUX_NETLINK_ROUTING /* trigger gateway selection */ if (olsr_cnf->smart_gw_active) { olsr_cleanup_gateways(); } /* trigger niit static route cleanup */ if (olsr_cnf->use_niit) { olsr_cleanup_niit_routes(); } /* cleanup lo:olsr interface */ if (olsr_cnf->use_src_ip_routes) { olsr_os_localhost_if(&olsr_cnf->main_addr, false); } #endif olsr_destroy_parser(); OLSR_PRINTF(1, "Closing sockets...\n"); /* front-end IPC socket */ if (olsr_cnf->ipc_connections > 0) { shutdown_ipc(); } /* OLSR sockets */ for (ifn = ifnet; ifn; ifn = ifn->int_next) { close(ifn->olsr_socket); close(ifn->send_socket); #ifdef LINUX_NETLINK_ROUTING if (DEF_RT_NONE != olsr_cnf->rt_table_defaultolsr_pri) { olsr_os_policy_rule(olsr_cnf->ip_version, olsr_cnf->rt_table_default, olsr_cnf->rt_table_defaultolsr_pri, ifn->int_name, false); } #endif } /* Closing plug-ins */ olsr_close_plugins(); /* Reset network settings */ net_os_restore_ifoptions(); /* ioctl socket */ close(olsr_cnf->ioctl_s); #ifdef LINUX_NETLINK_ROUTING if (DEF_RT_NONE != olsr_cnf->rt_table_pri) { olsr_os_policy_rule(olsr_cnf->ip_version, olsr_cnf->rt_table, olsr_cnf->rt_table_pri, NULL, false); } if (DEF_RT_NONE != olsr_cnf->rt_table_tunnel_pri) { olsr_os_policy_rule(olsr_cnf->ip_version, olsr_cnf->rt_table_tunnel, olsr_cnf->rt_table_tunnel_pri, NULL, false); } if (DEF_RT_NONE != olsr_cnf->rt_table_default_pri) { olsr_os_policy_rule(olsr_cnf->ip_version, olsr_cnf->rt_table_default, olsr_cnf->rt_table_default_pri, NULL, false); } close(olsr_cnf->rtnl_s); close (olsr_cnf->rt_monitor_socket); #endif #if defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__ /* routing socket */ close(olsr_cnf->rts); #endif /* Free cookies and memory pools attached. */ OLSR_PRINTF(0, "Free all memory...\n"); olsr_delete_all_cookies(); olsr_syslog(OLSR_LOG_INFO, "%s stopped", olsrd_version); OLSR_PRINTF(1, "\n <<<< %s - terminating >>>>\n http://www.olsr.org\n", olsrd_version); exit_value = olsr_cnf->exit_value; olsrd_free_cnf(olsr_cnf); exit(exit_value); }
/** *Check if a message is to be forwarded and forward *it if necessary. * *@param m the OLSR message to be forwarded *@param neighbour we received message from * *@returns positive if forwarded */ int olsr_forward_message(union olsr_message *m, struct interface *in_if, union olsr_ip_addr *from_addr) { union olsr_ip_addr *src; struct neighbor_entry *neighbor; int msgsize; struct interface *ifn; bool is_ttl_1 = false; /* * Sven-Ola: We should not flood the mesh with overdue messages. Because * of a bug in parser.c:parse_packet, we have a lot of messages because * all older olsrd's have lq_fish enabled. */ if (AF_INET == olsr_cnf->ip_version) { if (m->v4.ttl < 2 || 255 < (int)m->v4.hopcnt + (int)m->v4.ttl) is_ttl_1 = true; } else { if (m->v6.ttl < 2 || 255 < (int)m->v6.hopcnt + (int)m->v6.ttl) is_ttl_1 = true; } /* Lookup sender address */ src = mid_lookup_main_addr(from_addr); if (!src) src = from_addr; neighbor = olsr_lookup_neighbor_table(src); if (!neighbor) return 0; if (neighbor->status != SYM) return 0; /* Check MPR */ if (olsr_lookup_mprs_set(src) == NULL) { #ifdef DEBUG struct ipaddr_str buf; OLSR_PRINTF(5, "Forward - sender %s not MPR selector\n", olsr_ip_to_string(&buf, src)); #endif return 0; } if (olsr_message_is_duplicate(m)) { return 0; } /* Treat TTL hopcnt except for ethernet link */ if (!is_ttl_1) { if (olsr_cnf->ip_version == AF_INET) { /* IPv4 */ m->v4.hopcnt++; m->v4.ttl--; } else { /* IPv6 */ m->v6.hopcnt++; m->v6.ttl--; } } /* Update packet data */ msgsize = ntohs(m->v4.olsr_msgsize); /* looping trough interfaces */ for (ifn = ifnet; ifn; ifn = ifn->int_next) { /* do not retransmit out through the same interface if it has mode == ether */ if (ifn == in_if && ifn->mode == IF_MODE_ETHER) continue; /* do not forward TTL 1 messages to non-ether interfaces */ if (is_ttl_1 && ifn->mode != IF_MODE_ETHER) continue; if (net_output_pending(ifn)) { /* * Check if message is to big to be piggybacked */ if (net_outbuffer_push(ifn, m, msgsize) != msgsize) { /* Send */ net_output(ifn); /* Buffer message */ set_buffer_timer(ifn); if (net_outbuffer_push(ifn, m, msgsize) != msgsize) { OLSR_PRINTF(1, "Received message to big to be forwarded in %s(%d bytes)!", ifn->int_name, msgsize); olsr_syslog(OLSR_LOG_ERR, "Received message to big to be forwarded on %s(%d bytes)!", ifn->int_name, msgsize); } } } else { /* No forwarding pending */ set_buffer_timer(ifn); if (net_outbuffer_push(ifn, m, msgsize) != msgsize) { OLSR_PRINTF(1, "Received message to big to be forwarded in %s(%d bytes)!", ifn->int_name, msgsize); olsr_syslog(OLSR_LOG_ERR, "Received message to big to be forwarded on %s(%d bytes)!", ifn->int_name, msgsize); } } } return 1; }
int main(int argc, char *argv[]) { struct if_config_options *default_ifcnf; char conf_file_name[FILENAME_MAX]; struct ipaddr_str buf; bool loadedConfig = false; int i; #ifdef LINUX_NETLINK_ROUTING struct interface *ifn; #endif #ifdef WIN32 WSADATA WsaData; size_t len; #endif /* paranoia checks */ assert(sizeof(uint8_t) == 1); assert(sizeof(uint16_t) == 2); assert(sizeof(uint32_t) == 4); assert(sizeof(int8_t) == 1); assert(sizeof(int16_t) == 2); assert(sizeof(int32_t) == 4); printf("\n *** %s ***\n Build date: %s on %s\n http://www.olsr.org\n\n", olsrd_version, build_date, build_host); if (argc == 2) { if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "/?") == 0) { print_usage(false); exit(0); } if (strcmp(argv[1], "-v") == 0) { exit(0); } } debug_handle = stdout; #ifndef WIN32 olsr_argv = argv; #endif setbuf(stdout, NULL); setbuf(stderr, NULL); #ifndef WIN32 /* Check if user is root */ if (geteuid()) { fprintf(stderr, "You must be root(uid = 0) to run olsrd!\nExiting\n\n"); exit(EXIT_FAILURE); } #else DisableIcmpRedirects(); if (WSAStartup(0x0202, &WsaData)) { fprintf(stderr, "Could not initialize WinSock.\n"); olsr_exit(__func__, EXIT_FAILURE); } #endif /* Open syslog */ olsr_openlog("olsrd"); /* Using PID as random seed */ srandom(getpid()); /* Init widely used statics */ memset(&all_zero, 0, sizeof(union olsr_ip_addr)); /* * Set configfile name and * check if a configfile name was given as parameter */ #ifdef WIN32 #ifndef WINCE GetWindowsDirectory(conf_file_name, FILENAME_MAX - 11); #else conf_file_name[0] = 0; #endif len = strlen(conf_file_name); if (len == 0 || conf_file_name[len - 1] != '\\') conf_file_name[len++] = '\\'; strscpy(conf_file_name + len, "olsrd.conf", sizeof(conf_file_name) - len); #else strscpy(conf_file_name, OLSRD_GLOBAL_CONF_FILE, sizeof(conf_file_name)); #endif olsr_cnf = olsrd_get_default_cnf(); for (i=1; i < argc-1;) { if (strcmp(argv[i], "-f") == 0) { loadedConfig = true; if (olsrmain_load_config(argv[i+1]) < 0) { exit(EXIT_FAILURE); } if (i+2 < argc) { memmove(&argv[i], &argv[i+2], sizeof(*argv) * (argc-i-1)); } argc -= 2; } else { i++; } } /* * set up configuration prior to processing commandline options */ if (!loadedConfig && olsrmain_load_config(conf_file_name) == 0) { loadedConfig = true; } if (!loadedConfig) { olsrd_free_cnf(olsr_cnf); olsr_cnf = olsrd_get_default_cnf(); } default_ifcnf = get_default_if_config(); if (default_ifcnf == NULL) { fprintf(stderr, "No default ifconfig found!\n"); exit(EXIT_FAILURE); } /* Initialize timers */ olsr_init_timers(); /* * Process olsrd options. */ if (olsr_process_arguments(argc, argv, olsr_cnf, default_ifcnf) < 0) { print_usage(true); olsr_exit(__func__, EXIT_FAILURE); } /* * Set configuration for command-line specified interfaces */ set_default_ifcnfs(olsr_cnf->interfaces, default_ifcnf); /* free the default ifcnf */ free(default_ifcnf); /* Sanity check configuration */ if (olsrd_sanity_check_cnf(olsr_cnf) < 0) { fprintf(stderr, "Bad configuration!\n"); olsr_exit(__func__, EXIT_FAILURE); } /* * Establish file lock to prevent multiple instances */ if (olsr_cnf->lock_file) { strscpy(lock_file_name, olsr_cnf->lock_file, sizeof(lock_file_name)); } else { size_t l; #ifdef DEFAULT_LOCKFILE_PREFIX strscpy(lock_file_name, DEFAULT_LOCKFILE_PREFIX, sizeof(lock_file_name)); #else strscpy(lock_file_name, conf_file_name, sizeof(lock_file_name)); #endif l = strlen(lock_file_name); snprintf(&lock_file_name[l], sizeof(lock_file_name) - l, "-ipv%d.lock", olsr_cnf->ip_version == AF_INET ? 4 : 6); } /* * Print configuration */ if (olsr_cnf->debug_level > 1) { olsrd_print_cnf(olsr_cnf); } def_timer_ci = olsr_alloc_cookie("Default Timer Cookie", OLSR_COOKIE_TYPE_TIMER); /* * socket for ioctl calls */ olsr_cnf->ioctl_s = socket(olsr_cnf->ip_version, SOCK_DGRAM, 0); if (olsr_cnf->ioctl_s < 0) { #ifndef WIN32 olsr_syslog(OLSR_LOG_ERR, "ioctl socket: %m"); #endif olsr_exit(__func__, 0); } #ifdef LINUX_NETLINK_ROUTING olsr_cnf->rtnl_s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); if (olsr_cnf->rtnl_s < 0) { olsr_syslog(OLSR_LOG_ERR, "rtnetlink socket: %m"); olsr_exit(__func__, 0); } fcntl(olsr_cnf->rtnl_s, F_SETFL, O_NONBLOCK); if ((olsr_cnf->rt_monitor_socket = rtnetlink_register_socket(RTMGRP_LINK)) < 0) { olsr_syslog(OLSR_LOG_ERR, "rtmonitor socket: %m"); olsr_exit(__func__, 0); } #endif /* * create routing socket */ #if defined __FreeBSD__ || __FreeBSD_kernel__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__ olsr_cnf->rts = socket(PF_ROUTE, SOCK_RAW, 0); if (olsr_cnf->rts < 0) { olsr_syslog(OLSR_LOG_ERR, "routing socket: %m"); olsr_exit(__func__, 0); } #endif #ifdef LINUX_NETLINK_ROUTING /* initialize gateway system */ if (olsr_cnf->smart_gw_active) { if (olsr_init_gateways()) { olsr_exit("Cannot initialize gateway tunnels", 1); } } /* initialize niit if index */ if (olsr_cnf->use_niit) { olsr_init_niit(); } #endif /* Init empty TC timer */ set_empty_tc_timer(GET_TIMESTAMP(0)); /* enable ip forwarding on host */ /* Disable redirects globally */ #ifndef WIN32 net_os_set_global_ifoptions(); #endif /* Initialize parser */ olsr_init_parser(); /* Initialize route-exporter */ olsr_init_export_route(); /* Initialize message sequencnumber */ init_msg_seqno(); /* Initialize dynamic willingness calculation */ olsr_init_willingness(); /* *Set up willingness/APM */ if (olsr_cnf->willingness_auto) { if (apm_init() < 0) { OLSR_PRINTF(1, "Could not read APM info - setting default willingness(%d)\n", WILL_DEFAULT); olsr_syslog(OLSR_LOG_ERR, "Could not read APM info - setting default willingness(%d)\n", WILL_DEFAULT); olsr_cnf->willingness_auto = 0; olsr_cnf->willingness = WILL_DEFAULT; } else { olsr_cnf->willingness = olsr_calculate_willingness(); OLSR_PRINTF(1, "Willingness set to %d - next update in %.1f secs\n", olsr_cnf->willingness, olsr_cnf->will_int); } } /* Initialize net */ init_net(); /* Initializing networkinterfaces */ if (!olsr_init_interfacedb()) { if (olsr_cnf->allow_no_interfaces) { fprintf( stderr, "No interfaces detected! This might be intentional, but it also might mean that your configuration is fubar.\nI will continue after 5 seconds...\n"); olsr_startup_sleep(5); } else { fprintf(stderr, "No interfaces detected!\nBailing out!\n"); olsr_exit(__func__, EXIT_FAILURE); } } olsr_do_startup_sleep(); /* Print heartbeat to stdout */ #if !defined WINCE if (olsr_cnf->debug_level > 0 && isatty(STDOUT_FILENO)) { olsr_start_timer(STDOUT_PULSE_INT, 0, OLSR_TIMER_PERIODIC, &generate_stdout_pulse, NULL, 0); } #endif /* Initialize the IPC socket */ if (olsr_cnf->ipc_connections > 0) { ipc_init(); } /* Initialisation of different tables to be used. */ olsr_init_tables(); /* daemon mode */ #ifndef WIN32 if (olsr_cnf->debug_level == 0 && !olsr_cnf->no_fork) { printf("%s detaching from the current process...\n", olsrd_version); if (daemon(0, 0) < 0) { printf("daemon(3) failed: %s\n", strerror(errno)); exit(EXIT_FAILURE); } } #endif /* * Create locking file for olsrd, will be cleared after olsrd exits */ for (i=5; i>=0; i--) { OLSR_PRINTF(3, "Trying to get olsrd lock...\n"); if (olsr_create_lock_file(i > 0) == 0) { /* lock sucessfully created */ break; } sleep (1); } /* Load plugins */ olsr_load_plugins(); OLSR_PRINTF(1, "Main address: %s\n\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr)); #ifdef LINUX_NETLINK_ROUTING /* create policy routing priorities if necessary */ if (DEF_RT_NONE != olsr_cnf->rt_table_pri) { olsr_os_policy_rule(olsr_cnf->ip_version, olsr_cnf->rt_table, olsr_cnf->rt_table_pri, NULL, true); } if (DEF_RT_NONE != olsr_cnf->rt_table_tunnel_pri) { olsr_os_policy_rule(olsr_cnf->ip_version, olsr_cnf->rt_table_tunnel, olsr_cnf->rt_table_tunnel_pri, NULL, true); } if (DEF_RT_NONE != olsr_cnf->rt_table_default_pri) { olsr_os_policy_rule(olsr_cnf->ip_version, olsr_cnf->rt_table_default, olsr_cnf->rt_table_default_pri, NULL, true); } /* OLSR sockets */ if (DEF_RT_NONE != olsr_cnf->rt_table_defaultolsr_pri) { for (ifn = ifnet; ifn; ifn = ifn->int_next) { olsr_os_policy_rule(olsr_cnf->ip_version, olsr_cnf->rt_table_default, olsr_cnf->rt_table_defaultolsr_pri, ifn->int_name, true); } } /* trigger gateway selection */ if (olsr_cnf->smart_gw_active) { olsr_trigger_inetgw_startup(); } /* trigger niit static route setup */ if (olsr_cnf->use_niit) { olsr_setup_niit_routes(); } /* create lo:olsr interface */ if (olsr_cnf->use_src_ip_routes) { olsr_os_localhost_if(&olsr_cnf->main_addr, true); } #endif /* Start syslog entry */ olsr_syslog(OLSR_LOG_INFO, "%s successfully started", olsrd_version); /* *signal-handlers */ /* ctrl-C and friends */ #ifdef WIN32 #ifndef WINCE SetConsoleCtrlHandler(SignalHandler, true); #endif #else signal(SIGHUP, olsr_reconfigure); signal(SIGINT, olsr_shutdown); signal(SIGQUIT, olsr_shutdown); signal(SIGILL, olsr_shutdown); signal(SIGABRT, olsr_shutdown); // signal(SIGSEGV, olsr_shutdown); signal(SIGTERM, olsr_shutdown); signal(SIGPIPE, SIG_IGN); // Ignoring SIGUSR1 and SIGUSR1 by default to be able to use them in plugins signal(SIGUSR1, SIG_IGN); signal(SIGUSR2, SIG_IGN); #endif link_changes = false; /* Starting scheduler */ olsr_scheduler(); /* Like we're ever going to reach this ;-) */ return 1; } /* main */
void olsr_remove_interface(struct olsr_if * iface) { struct interface *ifp, *tmp_ifp; ifp = iface->interf; OLSR_PRINTF(1, "Removing interface %s (%d)\n", iface->name, ifp->if_index); olsr_syslog(OLSR_LOG_INFO, "Removing interface %s\n", iface->name); olsr_delete_link_entry_by_ip(&ifp->ip_addr); /* *Call possible ifchange functions registered by plugins */ olsr_trigger_ifchange(ifp->if_index, ifp, IFCHG_IF_REMOVE); /* cleanup routes over this interface */ olsr_delete_interface_routes(ifp->if_index); /* Dequeue */ if (ifp == ifnet) { ifnet = ifp->int_next; } else { tmp_ifp = ifnet; while (tmp_ifp->int_next != ifp) { tmp_ifp = tmp_ifp->int_next; } tmp_ifp->int_next = ifp->int_next; } /* Remove output buffer */ net_remove_buffer(ifp); /* Check main addr */ /* deactivated to prevent change of originator IP */ #if 0 if (ipequal(&olsr_cnf->main_addr, &ifp->ip_addr)) { if (ifnet == NULL) { /* No more interfaces */ memset(&olsr_cnf->main_addr, 0, olsr_cnf->ipsize); OLSR_PRINTF(1, "No more interfaces...\n"); } else { struct ipaddr_str buf; olsr_cnf->main_addr = ifnet->ip_addr; OLSR_PRINTF(1, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr)); olsr_syslog(OLSR_LOG_INFO, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr)); } } #endif /* 0 */ /* * Deregister functions for periodic message generation */ olsr_stop_timer(ifp->hello_gen_timer); olsr_stop_timer(ifp->tc_gen_timer); olsr_stop_timer(ifp->mid_gen_timer); olsr_stop_timer(ifp->hna_gen_timer); iface->configured = 0; iface->interf = NULL; /* Close olsr socket */ remove_olsr_socket(ifp->olsr_socket, &olsr_input, NULL); close(ifp->olsr_socket); remove_olsr_socket(ifp->send_socket, &olsr_input, NULL); close(ifp->send_socket); /* Free memory */ free(ifp->int_name); free(ifp); if ((ifnet == NULL) && (!olsr_cnf->allow_no_interfaces)) { olsr_syslog(OLSR_LOG_INFO, "No more active interfaces - exiting.\n"); olsr_exit("No more active interfaces - exiting.\n", EXIT_FAILURE); } }