void NS_CLASS local_repair_timeout(void *arg) { rt_table_t *rt; struct in_addr rerr_dest; RERR *rerr = NULL; rt = (rt_table_t *) arg; if (!rt) return; rerr_dest.s_addr = AODV_BROADCAST; /* Default destination */ /* Unset the REPAIR flag */ rt->flags &= ~RT_REPAIR; #ifndef NS_PORT nl_send_del_route_msg(rt->dest_addr, rt->next_hop, rt->hcnt); #endif /* Route should already be invalidated. */ if (rt->nprec) { rerr = rerr_create(0, rt->dest_addr, rt->dest_seqno); if (rt->nprec == 1) { rerr_dest = FIRST_PREC(rt->precursors)->neighbor; aodv_socket_send((AODV_msg *) rerr, rerr_dest, RERR_CALC_SIZE(rerr), 1, &DEV_IFINDEX(rt->ifindex)); } else { int i; for (i = 0; i < MAX_NR_INTERFACES; i++) { if (!DEV_NR(i).enabled) continue; aodv_socket_send((AODV_msg *) rerr, rerr_dest, RERR_CALC_SIZE(rerr), 1, &DEV_NR(i)); } } DEBUG(LOG_DEBUG, 0, "Sending RERR about %s to %s", ip_to_str(rt->dest_addr), ip_to_str(rerr_dest)); } precursor_list_destroy(rt); /* Purge any packets that may be queued */ /* packet_queue_set_verdict(rt->dest_addr, PQ_DROP); */ rt->rt_timer.handler = &NS_CLASS route_delete_timeout; timer_set_timeout(&rt->rt_timer, DELETE_PERIOD); DEBUG(LOG_DEBUG, 0, "%s removed in %u msecs", ip_to_str(rt->dest_addr), DELETE_PERIOD); }
int NS_CLASS locality(struct in_addr dest, unsigned int ifindex) { #ifndef NS_PORT if (gw_prefix) { if ((dest.s_addr & DEV_IFINDEX(ifindex).netmask.s_addr) == (DEV_IFINDEX(ifindex).ipaddr.s_addr & DEV_IFINDEX(ifindex). netmask.s_addr)) return HOST_ADHOC; else return HOST_INET; } else { struct hostent *hent; hent = gethostbyaddr(&dest, sizeof(struct in_addr), AF_INET); if (!hent) { switch (h_errno) { case HOST_NOT_FOUND: DEBUG(LOG_DEBUG, 0, "RREQ for Non-Internet dest %s", ip_to_str(dest)); return HOST_UNKNOWN; default: DEBUG(LOG_DEBUG, 0, "Unknown DNS error"); break; } } else return HOST_INET; } #else char *dstnet = Address::instance().get_subnetaddr(dest.s_addr); char *subnet = Address::instance().get_subnetaddr(DEV_NR(NS_DEV_NR).ipaddr.s_addr); DEBUG(LOG_DEBUG, 0, "myaddr=%d, dest=%d dstnet=%s subnet=%s", DEV_NR(NS_DEV_NR).ipaddr.s_addr, dest.s_addr, dstnet, subnet); if (subnet != NULL) { if (dstnet != NULL) { if (strcmp(dstnet, subnet) != 0) { delete[]dstnet; return HOST_INET; } delete[]dstnet; } delete[]subnet; } assert(dstnet == NULL); return HOST_UNKNOWN; #endif return HOST_UNKNOWN; }
void aodv_socket_cleanup(void) { #ifndef NS_PORT int i; for (i = 0; i < MAX_NR_INTERFACES; i++) { if (!DEV_NR(i).enabled) continue; close(DEV_NR(i).sock); } #endif /* NS_PORT */ }
char *devs_ip_to_str() { static char buf[MAX_NR_INTERFACES*IFNAMSIZ]; char *str; int i, index = 0; for (i = 0; i < MAX_NR_INTERFACES; i++) { if (!DEV_NR(i).enabled) continue; index += sprintf(buf+index,"%s,", ip_to_str(DEV_NR(i).ipaddr)); } str = buf; return str; }
void NS_CLASS local_repair_timeout(void *arg) { rt_table_t *rt; u_int32_t rerr_dest = AODV_BROADCAST; RERR *rerr = NULL; rt = (rt_table_t *) arg; if (!rt) return; /* Unset the REPAIR flag */ rt->flags &= ~RT_REPAIR; rt->rt_timer.handler = &NS_CLASS route_delete_timeout; timer_set_timeout(&rt->rt_timer, DELETE_PERIOD); DEBUG(LOG_DEBUG, 0, "%s removed in %u msecs", ip_to_str(rt->dest_addr), DELETE_PERIOD); /* Route should already be invalidated. */ if (rt->nprec) { rerr = rerr_create(0, rt->dest_addr, rt->dest_seqno); if (rt->nprec == 1) { rerr_dest = FIRST_PREC(rt->precursors)->neighbor; aodv_socket_send((AODV_msg *) rerr, rerr_dest, RERR_CALC_SIZE(rerr), 1, &DEV_IFINDEX(rt->ifindex)); } else { int i; for (i = 0; i < MAX_NR_INTERFACES; i++) { if (!DEV_NR(i).enabled) continue; aodv_socket_send((AODV_msg *) rerr, rerr_dest, RERR_CALC_SIZE(rerr), 1, &DEV_NR(i)); } } DEBUG(LOG_DEBUG, 0, "Sending RERR about %s to %s", ip_to_str(rt->dest_addr), ip_to_str(rerr_dest)); } precursor_list_destroy(rt); }
void NS_CLASS log_init() { /* NS_PORT: Log filename is prefix + IP address + suffix */ #ifdef NS_PORT const char *ipaddr_str = ip_to_str(DEV_NR(NS_DEV_NR).ipaddr); const int ipaddr_len = strlen(ipaddr_str); const int log_filename_len = strlen(AODV_LOG_PATH_PREFIX) + ipaddr_len + strlen(AODV_LOG_PATH_SUFFIX); const int rt_log_filename_len = strlen(AODV_RT_LOG_PATH_PREFIX) + ipaddr_len + strlen(AODV_RT_LOG_PATH_SUFFIX); char AODV_LOG_PATH[log_filename_len + 1]; char AODV_RT_LOG_PATH[rt_log_filename_len + 1]; AODV_LOG_PATH[0] = '\0'; AODV_RT_LOG_PATH[0] = '\0'; strcat(AODV_LOG_PATH, AODV_LOG_PATH_PREFIX); strcat(AODV_LOG_PATH, ipaddr_str); strcat(AODV_LOG_PATH, AODV_LOG_PATH_SUFFIX); strcat(AODV_RT_LOG_PATH, AODV_RT_LOG_PATH_PREFIX); strcat(AODV_RT_LOG_PATH, ipaddr_str); strcat(AODV_RT_LOG_PATH, AODV_RT_LOG_PATH_SUFFIX); #endif /* NS_PORT */ if (log_to_file) { if ((log_file_fd = open(AODV_LOG_PATH, O_RDWR | O_CREAT | O_TRUNC, S_IROTH | S_IWUSR | S_IRUSR | S_IRGRP)) < 0) { perror("open log file failed!"); exit(-1); } } if (rt_log_interval) { if ((log_rt_fd = open(AODV_RT_LOG_PATH, O_RDWR | O_CREAT | O_TRUNC, S_IROTH | S_IWUSR | S_IRUSR | S_IRGRP)) < 0) { perror("open rt log file failed!"); exit(-1); } } openlog(progname, 0, LOG_DAEMON); }
void send_rt_sock_init(void) { struct sockaddr_in addr; struct ifreq ifr; int i, retval = 0; int on = 1; int tos = IPTOS_LOWDELAY; int bufsize = SO_RECVBUF_SIZE; socklen_t optlen = sizeof(bufsize); if (this_host.nif == 0) { fprintf(stderr, "CPC: No interfaces configured\n"); exit(-1); } for (i = 0; i < MAX_NR_INTERFACES; i++) { if (!DEV_NR(i).enabled) continue; DEV_NR(i).sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); if (DEV_NR(i).sock < 0) { perror("CPC: create udp socket failed"); exit(-1); } memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(ROUTING_PORT); addr.sin_addr.s_addr = htonl(INADDR_ANY); retval = bind(DEV_NR(i).sock, (struct sockaddr *)&addr, sizeof(struct sockaddr)); if (retval < 0) { perror("CPC: Bind faild"); exit(-1); } if (setsockopt(DEV_NR(i).sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof(int)) < 0) { perror("CPC: SO_BROADCAST failed"); exit(-1); } memset(&ifr, 0, sizeof(struct ifreq)); strcpy(ifr.ifr_name, DEV_NR(i).ifname); if (setsockopt(DEV_NR(i).sock, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0) { fprintf(stderr, "CPC: SO_BINDTODEVICE failed for %s", DEV_NR(i).ifname); exit(-1); } if (setsockopt(DEV_NR(i).sock, SOL_SOCKET, SO_PRIORITY, &tos, sizeof(int)) < 0) { perror("CPC: SO_PRIORITY failed"); exit(-1); } if (setsockopt(DEV_NR(i).sock, SOL_IP, IP_RECVTTL, &on, sizeof(int)) < 0) { perror("CPC: IP_RECVTTL failed"); exit(-1); } if (setsockopt(DEV_NR(i).sock, SOL_IP, IP_PKTINFO, &on, sizeof(int)) < 0) { perror("CPC: IP_PKTINFO failed"); exit(-1); } for ( ; ; bufsize -= 1024) { if (setsockopt(DEV_NR(i).sock, SOL_SOCKET, SO_RCVBUF, (char *) &bufsize, optlen) == 0) { fprintf(stderr, "Receive buffer size set to %d", bufsize); break; } if (bufsize < RECV_BUF_SIZE) { fprintf(stderr, "Could not set receive buffer size"); exit(-1); } } register_callback_func(DEV_NR(i).sock, routing_packet_read); } }
int set_kernel_options() { int i, fd = -1; char on = '1'; char off = '0'; char command[64]; if ((fd = open("/proc/sys/net/ipv4/ip_forward", O_WRONLY)) < 0) return -1; if (write(fd, &on, sizeof(char)) < 0) return -1; close(fd); /* Disabled for kernel 2.6.28. if ((fd = open("/proc/sys/net/ipv4/route/max_delay", O_WRONLY)) < 0) return -1; if (write(fd, &off, sizeof(char)) < 0) return -1; close(fd); if ((fd = open("/proc/sys/net/ipv4/route/min_delay", O_WRONLY)) < 0) return -1; if (write(fd, &off, sizeof(char)) < 0) return -1; close(fd); */ /* Disable ICMP redirects on all interfaces: */ for (i = 0; i < MAX_NR_INTERFACES; i++) { if (!DEV_NR(i).enabled) continue; memset(command, '\0', 64); sprintf(command, "/proc/sys/net/ipv4/conf/%s/send_redirects", DEV_NR(i).ifname); if ((fd = open(command, O_WRONLY)) < 0) return -1; if (write(fd, &off, sizeof(char)) < 0) return -1; close(fd); memset(command, '\0', 64); sprintf(command, "/proc/sys/net/ipv4/conf/%s/accept_redirects", DEV_NR(i).ifname); if ((fd = open(command, O_WRONLY)) < 0) return -1; if (write(fd, &off, sizeof(char)) < 0) return -1; close(fd); } memset(command, '\0', 64); sprintf(command, "/proc/sys/net/ipv4/conf/all/send_redirects"); if ((fd = open(command, O_WRONLY)) < 0) return -1; if (write(fd, &off, sizeof(char)) < 0) return -1; close(fd); memset(command, '\0', 64); sprintf(command, "/proc/sys/net/ipv4/conf/all/accept_redirects"); if ((fd = open(command, O_WRONLY)) < 0) return -1; if (write(fd, &off, sizeof(char)) < 0) return -1; close(fd); return 0; }
void NS_CLASS aodv_socket_init() { #ifndef NS_PORT struct sockaddr_in aodv_addr; struct ifreq ifr; int i, retval = 0; int on = 1; int tos = IPTOS_LOWDELAY; int bufsize = SO_RECVBUF_SIZE; /* Create a UDP socket */ if (this_host.nif == 0) { fprintf(stderr, "No interfaces configured\n"); exit(-1); } /* Open a socket for every AODV enabled interface */ for (i = 0; i < MAX_NR_INTERFACES; i++) { if (!DEV_NR(i).enabled) continue; #ifdef RAW_SOCKET DEV_NR(i).sock = socket(PF_INET, SOCK_RAW, IPPROTO_UDP); #else DEV_NR(i).sock = socket(PF_INET, SOCK_DGRAM, 0); #endif if (DEV_NR(i).sock < 0) { perror(""); exit(-1); } /* Bind the socket to the AODV port number */ memset(&aodv_addr, 0, sizeof(aodv_addr)); aodv_addr.sin_family = AF_INET; aodv_addr.sin_port = htons(AODV_PORT); aodv_addr.sin_addr.s_addr = htonl(INADDR_ANY); retval = bind(DEV_NR(i).sock, (struct sockaddr *) &aodv_addr, sizeof(struct sockaddr)); if (retval < 0) { perror("Bind failed "); exit(-1); } if (setsockopt(DEV_NR(i).sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof(int)) < 0) { perror("SO_BROADCAST failed "); exit(-1); } memset(&ifr, 0, sizeof(struct ifreq)); strcpy(ifr.ifr_name, DEV_NR(i).ifname); if (setsockopt(DEV_NR(i).sock, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0) { fprintf(stderr, "SO_BINDTODEVICE failed for %s", DEV_NR(i).ifname); perror(" "); exit(-1); } if (setsockopt(DEV_NR(i).sock, SOL_SOCKET, SO_PRIORITY, &tos, sizeof(int)) < 0) { perror("Setsockopt SO_PRIORITY failed "); exit(-1); } #ifdef RAW_SOCKET /* We provide our own IP header... */ if (setsockopt(DEV_NR(i).sock, SOL_IP, IP_HDRINCL, &on, sizeof(int)) < 0) { perror("Setsockopt IP_HDRINCL failed "); exit(-1); } #else if (setsockopt(DEV_NR(i).sock, SOL_IP, IP_PKTINFO, &on, sizeof(int)) < 0) { perror("Setsockopt IP_PKTINFO failed "); exit(-1); } if (setsockopt(DEV_NR(i).sock, SOL_IP, IP_RECVTTL, &on, sizeof(int)) < 0) { perror("Setsockopt IP_TTL failed "); exit(-1); } #endif /* Set max allowable receive buffer size... */ for (;; bufsize -= 1024) { if (setsockopt(DEV_NR(i).sock, SOL_SOCKET, SO_RCVBUF, (char *) &bufsize, sizeof(bufsize)) == 0) { log(LOG_NOTICE, 0, __FUNCTION__, "Receive buffer size set to %d", bufsize); break; } if (bufsize < RECV_BUF_SIZE) { log(LOG_ERR, 0, __FUNCTION__, "Could not set receive buffer size"); exit(-1); } } retval = attach_callback_func(DEV_NR(i).sock, aodv_socket_read); if (retval < 0) { perror("register input handler failed "); exit(-1); } } #endif /* NS_PORT */ time_last_rreq.tv_sec = 0; time_last_rreq.tv_usec = 0; time_last_rerr.tv_sec = 0; time_last_rerr.tv_usec = 0; /* gettimeofday(&time_last_rerr, NULL); */ num_rreq = 0; num_rerr = 0; }
void rerr_process(RERR * rerr, int rerrlen, u_int32_t ip_src, u_int32_t ip_dst) { RERR *new_rerr = NULL; rt_table_t *entry; u_int32_t rerr_dest, rerr_dest_seqno; int i; RERR_udest *udest; #ifdef DEBUG log(LOG_DEBUG, 0, "rerr_process: ip_src=%s", ip_to_str(ip_src)); log_pkt_fields((AODV_msg *) rerr); #endif if (rerrlen < RERR_CALC_SIZE(rerr)) { log(LOG_WARNING, 0, "rerr_process: IP data too short (%u bytes) from %s to %s. Should be %d bytes.", rerrlen, ip_to_str(ip_src), ip_to_str(ip_dst), RERR_CALC_SIZE(rerr)); return; } /* Check which destinations that are unreachable. */ udest = RERR_UDEST_FIRST(rerr); while (rerr->dest_count) { rerr_dest = ntohl(udest->dest_addr); rerr_dest_seqno = ntohl(udest->dest_seqno); #ifdef DEBUG log(LOG_DEBUG, 0, "rerr_process: unreachable dest=%s seqno=%ld", ip_to_str(rerr_dest), rerr_dest_seqno); #endif if ((entry = rt_table_find_active(rerr_dest)) != NULL && memcmp(&entry->next_hop, &ip_src, sizeof(u_int32_t)) == 0) { /* (a) updates the corresponding destination sequence number with the Destination Sequence Number in the packet, and */ /* UGLY HACK: we decrement the seqno by one here, since it will be incremented upon calling rt_table_invalidate() below... */ entry->dest_seqno = rerr_dest_seqno - 1; /* (d) check precursor list for emptiness. If not empty, include the destination as an unreachable destination in the RERR... */ if (entry->precursors != NULL) { if (new_rerr == NULL) new_rerr = rerr_create(0, entry->dest_addr, entry->dest_seqno); else rerr_add_udest(new_rerr, entry->dest_addr, entry->dest_seqno); } #ifdef DEBUG log(LOG_DEBUG, 0, "rerr_process: removing rte %s - WAS IN RERR!!", ip_to_str(rerr_dest)); #endif /* Invalidate route: Hop count -> INFTY */ rt_table_invalidate(entry); } udest = RERR_UDEST_NEXT(udest); rerr->dest_count--; } /* End while() */ /* If a RERR was created, then send it now... */ /* FIXME: Unicast if possible... And send on only those interfaces where it is necessary. */ if (new_rerr) { for (i = 0; i < MAX_NR_INTERFACES; i++) { if (!DEV_NR(i).enabled) continue; aodv_socket_send((AODV_msg *) new_rerr, AODV_BROADCAST, RERR_CALC_SIZE(rerr), 1, &DEV_NR(i)); } } }
void NS_CLASS log(int type, int errnum, const char *function, char *format, ...) { va_list ap; static char buffer[256] = ""; static char log_buf[1024]; char *msg; struct timeval now; struct tm *time; int len = 0; /* NS_PORT: Include IP address in log */ #ifdef NS_PORT if (DEV_NR(NS_DEV_NR).enabled == 1) { len += sprintf(log_buf + len, "%s: ", ip_to_str(DEV_NR(NS_DEV_NR).ipaddr)); } #endif /* NS_PORT */ va_start(ap, format); if (type == LOG_WARNING) msg = &buffer[9]; else msg = buffer; vsprintf(msg, format, ap); va_end(ap); if (!debug && !log_to_file) goto syslog; gettimeofday(&now, NULL); #ifdef NS_PORT time = gmtime(&now.tv_sec); #else time = localtime(&now.tv_sec); #endif /* if (type <= LOG_NOTICE) */ /* len += sprintf(log_buf + len, "%s: ", progname); */ len += sprintf(log_buf + len, "%02d:%02d:%02d.%03ld %s: %s", time->tm_hour, time->tm_min, time->tm_sec, now.tv_usec / 1000, function, msg); if (errnum == 0) len += sprintf(log_buf + len, "\n"); else len += sprintf(log_buf + len, ": %s\n", strerror(errnum)); if (len > 1024) { fprintf(stderr, "log(): buffer to small! len = %d\n", len); goto syslog; } /* OK, we are clear to write the buffer to the aodv log file... */ if (log_to_file) write_to_log_file(log_buf, len); /* If we have the debug option set, also write to stdout */ if (debug) printf(log_buf); /* Syslog all messages that are of severity LOG_NOTICE or worse */ syslog: if (type <= LOG_NOTICE) { if (errnum != 0) { errno = errnum; syslog(type, "%s: %s: %m", function, msg); } else syslog(type, "%s: %s", function, msg); } /* Exit on error */ if (type <= LOG_ERR) exit(-1); }