/* * udp_exec_pkt: passes the received udp packet to pkt_exec(). * `passed_argv' is a pointer to a udp_exec_pkt_argv struct */ void * udp_exec_pkt(void *passed_argv) { struct udp_exec_pkt_argv argv; PACKET rpkt; const char *ntop; memcpy(&argv, passed_argv, sizeof(struct udp_exec_pkt_argv)); memcpy(&rpkt, argv.recv_pkt, sizeof(PACKET)); if (argv.flags & UDP_THREAD_FOR_EACH_PKT) pthread_mutex_unlock(&udp_exec_lock); /* Drop any packet we sent in broadcast */ if (!memcmp(rpkt.from.data, me.cur_ip.data, MAX_IP_SZ)) { pkt_free(&rpkt, 0); return 0; } if (add_accept(rpkt.from, 1)) { ntop = inet_to_str(rpkt.from); debug(DBG_NORMAL, "ACPT: dropped UDP pkt from %s: " "Accept table full.", ntop); return 0; } pkt_exec(rpkt, argv.acpt_idx); pkt_free(&rpkt, 0); return 0; }
const char * inet_ntop(int af, const void *addr, char *buff, socklen_t buff_sz) { int ret; switch (af) { default: ret = -EAFNOSUPPORT; break; case AF_INET: ret = inet_to_str((const struct in_addr *)addr, buff, buff_sz); break; case AF_INET6: ret = inet6_to_str((const struct in6_addr *)addr, buff, buff_sz); break; } if (ret != 0) { SET_ERRNO(-ret); return NULL; } return buff; }
const char * rnode_to_ipstr(u_int mapstart, u_int maprnode, inet_prefix ipstart) { inet_prefix ip; rnodetoip(mapstart, maprnode, ipstart, &ip); return inet_to_str(ip); }
/* * internet_hosts_to_ip: replace the hostnames present in * `server_opt.inet_hosts' with IP strings. The IPs are obtained * with a normal DNS resolution. The hosts which cannot be resolved are * deleted from the `inet_hosts' array. */ void internet_hosts_to_ip(void) { int i; for (i = 0; i < server_opt.inet_hosts_counter; i++) { inet_prefix ip; if (andns_gethostbyname(server_opt.inet_hosts[i], &ip)) { error("Cannot resolve \"%s\". Check your netsukuku.conf", server_opt.inet_hosts[i]); /* remove the hname from `inet_hosts' */ xfree(server_opt.inet_hosts[i]); server_opt.inet_hosts[i] = server_opt.inet_hosts[server_opt.inet_hosts_counter - 1]; server_opt.inet_hosts_counter--; } else { xfree(server_opt.inet_hosts[i]); server_opt.inet_hosts[i] = xstrdup(inet_to_str(ip)); } } }
void * tcp_daemon(void *door) { pthread_t thread; pthread_attr_t t_attr; PACKET rpkt; struct sockaddr_storage addr; socklen_t addrlen = sizeof addr; inet_prefix ip; fd_set fdset; int fd, ret, err, i; interface *ifs; int max_sk_idx, dev_sk[me.cur_ifs_n]; u_short tcp_port = *(u_short *) door; const char *ntop; pthread_attr_init(&t_attr); pthread_attr_setdetachstate(&t_attr, PTHREAD_CREATE_DETACHED); debug(DBG_SOFT, "Preparing the tcp listening socket on port %d", tcp_port); err = sockets_all_ifs(my_family, SOCK_STREAM, tcp_port, me.cur_ifs, me.cur_ifs_n, dev_sk, &max_sk_idx); if (!err) return NULL; else if (err < 0) fatal("Creation of the %s daemon aborted. " "Is there another ntkd running?", "tcp"); pthread_mutex_init(&tcp_exec_lock, 0); for (i = 0; i < me.cur_ifs_n; i++) { if (!dev_sk[i]) continue; /* * While we are accepting the connections we keep the socket non * blocking. */ if (set_nonblock_sk(dev_sk[i])) { pthread_mutex_unlock(&tcp_daemon_lock); return NULL; } /* Shhh, it's listening... */ if (listen(dev_sk[i], 5) == -1) { inet_close(&dev_sk[i]); pthread_mutex_unlock(&tcp_daemon_lock); return NULL; } } debug(DBG_NORMAL, "Tcp daemon on port %d up & running", tcp_port); pthread_mutex_unlock(&tcp_daemon_lock); for (;;) { FD_ZERO(&fdset); if (!me.cur_ifs_n) { /* All the devices have been removed while ntkd was * running, sleep well */ sleep(1); continue; } for (i = 0; i < me.cur_ifs_n; i++) if (dev_sk[i]) FD_SET(dev_sk[i], &fdset); ret = select(dev_sk[max_sk_idx] + 1, &fdset, NULL, NULL, NULL); if (sigterm_timestamp) /* NetsukukuD has been closed */ break; if (ret < 0 && errno != EINTR) error("daemon_tcp: select error: %s", strerror(errno)); if (ret < 0) continue; for (i = 0; i < me.cur_ifs_n; i++) { ifs = &me.cur_ifs[i]; if (!dev_sk[i]) continue; if (!FD_ISSET(dev_sk[i], &fdset)) continue; fd = accept(dev_sk[i], (struct sockaddr *) &addr, &addrlen); if (fd == -1) { if (errno != EINTR && errno != EWOULDBLOCK) error("daemon_tcp: accept(): %s", strerror(errno)); continue; } setzero(&rpkt, sizeof(PACKET)); pkt_addsk(&rpkt, my_family, fd, SKT_TCP); pkt_add_dev(&rpkt, ifs, 0); rpkt.flags = MSG_WAITALL; pkt_addport(&rpkt, tcp_port); ntop = 0; sockaddr_to_inet((struct sockaddr *) &addr, &ip, 0); pkt_addfrom(&rpkt, &ip); if (server_opt.dbg_lvl) ntop = inet_to_str(ip); if ((ret = add_accept(ip, 0))) { debug(DBG_NORMAL, "ACPT: drop connection with %s: " "Accept table full.", ntop); /* Omg, we cannot take it anymore, go away: ACK_NEGATIVE */ pkt_err(rpkt, ret, 1); inet_close(&fd); continue; } else { /* * Ok, the connection is good, send back the * ACK_AFFERMATIVE. */ pkt_addto(&rpkt, &rpkt.from); send_rq(&rpkt, 0, ACK_AFFERMATIVE, 0, 0, 0, 0); } if (unset_nonblock_sk(fd)) continue; pthread_mutex_lock(&tcp_exec_lock); err = pthread_create(&thread, &t_attr, tcp_recv_loop, (void *) &rpkt); pthread_detach(thread); pthread_mutex_lock(&tcp_exec_lock); pthread_mutex_unlock(&tcp_exec_lock); } } return NULL; }
/* * init_internet_gateway_search: * Initialization of the igs.c code. */ void init_internet_gateway_search(void) { inet_prefix new_gw; char new_gw_dev[IFNAMSIZ]; pthread_t ping_thread; pthread_attr_t t_attr; int i, ret, res, e; active_gws = 0; igw_multi_gw_disabled = 0; setzero(multigw_nh, sizeof(igw_nexthop) * MAX_MULTIPATH_ROUTES); /* * Just return if we aren't in restricted mode or if the user doesn't * want to use shared internet connections */ if (!restricted_mode || (!server_opt.use_shared_inet && !server_opt.share_internet)) return; loginfo("Activating the Internet Gateway Search engine"); init_igws(&me.igws, &me.igws_counter, GET_LEVELS(my_family)); init_tunnels_ifs(); /* delete all the old tunnels */ del_all_tunnel_ifs(0, 0, 0, NTK_TUNL_PREFIX); /* * Bring tunl0 up (just to test if the ipip module is loaded) */ loginfo("Checking if \"" DEFAULT_TUNL_IF "\" exists"); if (tunnel_change(0, 0, 0, DEFAULT_TUNL_PREFIX, DEFAULT_TUNL_NUMBER) < 0) { printf("Cannot read \"" DEFAULT_TUNL_IF "\". " "Is the \"ipip\" kernel module loaded?\n" " If you don't care about using the shared internet " "connections of the ntk nodes\n" " around you, disable the \"use_shared_inet\" option " "in netsukuku.conf"); del_resolv_conf("nameserver 127.0.0.1", "/etc/resolv.conf"); exit(1); } ifs_del_all_name(me.cur_ifs, &me.cur_ifs_n, NTK_TUNL_PREFIX); ifs_del_all_name(me.cur_ifs, &me.cur_ifs_n, DEFAULT_TUNL_PREFIX); /* * Delete old routing rules */ reset_igw_rules(); /* * Init netfilter */ res = mark_init(server_opt.share_internet); if (res) { error(err_str); error("Cannot set the netfilter rules needed for the multi-igw. " "This feature will be disabled"); igw_multi_gw_disabled = 1; } /* * Check anomalies: from this point we initialize stuff only if we * have an Inet connection */ if (!server_opt.inet_connection) return; if (!server_opt.inet_hosts) fatal("You didn't specified any Internet hosts in the " "configuration file. What hosts should I ping?"); /* * If we are sharing our internet connection, activate the * masquerading. */ if (server_opt.share_internet) { igw_exec_masquerade_sh(server_opt.ip_masq_script, 0); if (!server_opt.ip_masq_script) fatal("No masquerading script was configured!"); }; /* * Get the default gateway route currently set in the kernel routing * table */ setzero(&new_gw, sizeof(inet_prefix)); ret = rt_get_default_gw(&new_gw, new_gw_dev); /* * If there is no IP set in the route, fetch it at least from the * device included in it. */ if (!new_gw.family && *new_gw_dev) { if (get_dev_ip(&new_gw, my_family, new_gw_dev) < 0) (*new_gw_dev) = 0; } if (ret < 0 || (!*new_gw_dev && !new_gw.family)) { /* Nothing useful has been found */ loginfo("The retrieval of the default gw from the kernel failed."); if (!server_opt.inet_gw.data[0]) fatal("The default gw isn't set in the kernel and you " "didn't specified it in netsukuku.conf. " "Cannot continue!"); } else if (!server_opt.inet_gw_dev || strncmp(new_gw_dev, server_opt.inet_gw_dev, IFNAMSIZ) || memcmp(new_gw.data, server_opt.inet_gw.data, MAX_IP_SZ)) { if (server_opt.inet_gw.data[0]) loginfo("Your specified Internet gateway doesn't match with " "the one currently stored in the kernel routing table." "I'm going to use the kernel gateway: %s dev %s", inet_to_str(new_gw), new_gw_dev); if (!server_opt.inet_gw_dev) server_opt.inet_gw_dev = xstrdup(new_gw_dev); else strncpy(server_opt.inet_gw_dev, new_gw_dev, IFNAMSIZ); memcpy(&server_opt.inet_gw, &new_gw, sizeof(inet_prefix)); /* Delete the default gw, we are replacing it */ rt_delete_def_gw(0); } loginfo("Using \"%s dev %s\" as your first Internet gateway.", inet_to_str(server_opt.inet_gw), server_opt.inet_gw_dev); if (rt_replace_def_gw(server_opt.inet_gw_dev, server_opt.inet_gw, 0)) fatal("Cannot set the default gw to %s %s", inet_to_str(server_opt.inet_gw), server_opt.inet_gw_dev); active_gws++; /* * Activate the anti-loop multi-igw shield */ if (server_opt.share_internet) { rule_add(0, 0, 0, 0, FWMARK_ALISHIELD, RTTABLE_ALISHIELD); if (rt_replace_def_gw(server_opt.inet_gw_dev, server_opt.inet_gw, RTTABLE_ALISHIELD)) { error("Cannot set the default route in the ALISHIELD table. " "Disabling the multi-inet_gw feature"); igw_multi_gw_disabled = 1; } } /* * Activate the traffic shaping for the `server_opt.inet_gw_dev' * device */ if (server_opt.shape_internet) igw_exec_tcshaper_sh(server_opt.tc_shaper_script, 0, server_opt.inet_gw_dev, server_opt.my_upload_bw, server_opt.my_dnload_bw); for (i = 0; i < me.cur_ifs_n; i++) if (!strcmp(me.cur_ifs[i].dev_name, server_opt.inet_gw_dev)) { for (e = 0; e < server_opt.ifs_n; e++) if (!strcmp(server_opt.ifs[i], server_opt.inet_gw_dev)) fatal("You specified the \"%s\" interface" " in the options, but this device is also" " part of the primary Internet gw route." " Don't include \"%s\" in the list of " "interfaces utilised by the daemon", server_opt.inet_gw_dev, server_opt.inet_gw_dev); loginfo("Deleting the \"%s\" interface from the device " "list since it is part of the primary Internet" " gw route.", me.cur_ifs[i].dev_name); ifs_del(me.cur_ifs, &me.cur_ifs_n, i); if (me.cur_ifs_n <= 0) fatal ("The deleted interface cannot be used by NetsukukuD because it is part\n" " of your primary Internet gw route. You have to specify another\n" " interface with the -i option or you won't be able share your" " Internet connection"); } loginfo("Launching the first ping to the Internet hosts"); if (!server_opt.disable_andna) internet_hosts_to_ip(); me.inet_connected = igw_check_inet_conn(); if (me.inet_connected) loginfo("The Internet connection is up & running"); else loginfo("The Internet connection appears to be down"); if (!me.inet_connected && server_opt.share_internet) fatal("We are not connected to the Internet, but you want to " "share your connection. Please check your options"); debug(DBG_SOFT, "Evoking the Internet ping daemon."); pthread_attr_init(&t_attr); pthread_attr_setdetachstate(&t_attr, PTHREAD_CREATE_DETACHED); pthread_create(&ping_thread, &t_attr, igw_check_inet_conn_t, 0); }
/* * radar_update_map * * it updates the int_map and the ext_map if any bnodes are found. * Note that the rnodes in the map are held in a different way. First of all the qspn * is not applied to them (we already know how to reach them ;) and they have only * one rnode... ME. So me.cur_node->r_node[x].r_node->r_node[0] == me.cur_node. * Gotcha? */ void radar_update_map(void) { struct qspn_buffer *qb; struct radar_queue *rq; ext_rnode_cache *erc; map_gnode *gnode = 0; map_node *node, *root_node; map_rnode rnn, *new_root_rnode; ext_rnode *e_rnode; int i, diff, rnode_pos; u_char rnode_added[MAX_LEVELS / 8], rnode_deleted[MAX_LEVELS / 8]; int level, external_node, total_levels, root_node_pos, node_update; void *void_map; const char *ntop; char updated_rnodes, routes_update, devs_update; updated_rnodes = routes_update = devs_update = 0; setzero(rnode_added, sizeof(rnode_added)); setzero(rnode_deleted, sizeof(rnode_deleted)); /** * Let's consider all our rnodes void, in this way we'll know what * rnodes will remain void after the update. */ for (i = 0; i < me.cur_node->links; i++) { node = (map_node *) me.cur_node->r_node[i].r_node; node->flags |= MAP_VOID | MAP_UPDATE; } /**/ rq = radar_q; list_for(rq) { if (!rq->node) continue; if (!(me.cur_node->flags & MAP_HNODE) && (rq->flags & MAP_HNODE)) continue; /* * We need to know if it is a node which is not in the gnode * where we are (external_rnode). */ if ((int) rq->node == RADQ_EXT_RNODE) { external_node = 1; total_levels = rq->quadg.levels; } else { external_node = 0; total_levels = 1; } for (level = total_levels - 1; level >= 0; level--) { qspn_set_map_vars(level, 0, &root_node, &root_node_pos, 0); node_update = devs_update = 0; if (!level) { void_map = me.int_map; node = rq->node; } else { /* Skip the levels where the ext_rnode belongs * to our same gids */ if (!quadg_gids_cmp(rq->quadg, me.cur_quadg, level)) continue; /* Update only the gnodes which belongs to * our same gid of the upper level, because * we don't keep the internal info of the * extern gnodes. */ if ((level < rq->quadg.levels - 1) && quadg_gids_cmp(rq->quadg, me.cur_quadg, level + 1)) { rq->quadg.gnode[_EL(level)] = 0; continue; } /* Ehi, we are a bnode */ root_node->flags |= MAP_BNODE; me.cur_node->flags |= MAP_BNODE; void_map = me.ext_map; gnode = rq->quadg.gnode[_EL(level)]; node = &gnode->g; } if (external_node && !level && me.cur_erc_counter) { erc = e_rnode_find(me.cur_erc, &rq->quadg, 0); if (!erc) rnode_pos = -1; else { rnode_pos = erc->rnode_pos; node = (map_node *) erc->e; } } else rnode_pos = rnode_find(root_node, node); if (rnode_pos == -1) { /* W00t, we've found a new rnode! */ node_update = 1; rnode_pos = root_node->links; ntop = inet_to_str(rq->quadg.ipstart[level]); if (server_opt.dbg_lvl || !level) loginfo ("Radar: New node found: %s, ext: %d, level: %d", ntop, external_node, level); if (external_node && !level) { /* * If this node we are processing is external, at level 0, * in the root_node's rnodes we add a rnode which point * to a ext_rnode struct. */ setzero(&rnn, sizeof(map_rnode)); e_rnode = xzalloc(sizeof(ext_rnode)); memcpy(&e_rnode->quadg, &rq->quadg, sizeof(quadro_group)); e_rnode->node.flags = MAP_BNODE | MAP_GNODE | MAP_RNODE | MAP_ERNODE; rnn.r_node = (int *) e_rnode; node = rq->node = &e_rnode->node; new_root_rnode = &rnn; /* Update the external_rnode_cache list */ e_rnode_add(&me.cur_erc, e_rnode, rnode_pos, &me.cur_erc_counter); } else { /*We purge all the node's rnodes. */ rnode_destroy(node); /* * This node has only one rnode, * and that is the root_node. */ setzero(&rnn, sizeof(map_rnode)); rnn.r_node = (int *) root_node; rnode_add(node, &rnn); /* It is a border node */ if (level) node->flags |= MAP_BNODE | MAP_GNODE; node->flags |= MAP_RNODE; /* * Fill the rnode to be added in the * root_node. */ setzero(&rnn, sizeof(map_rnode)); rnn.r_node = (int *) node; new_root_rnode = &rnn; } /* * The new node is added in the root_node's * rnodes. */ rnode_add(root_node, new_root_rnode); /* Update the qspn_buffer */ if (!external_node || level) { qb = xzalloc(sizeof(struct qspn_buffer)); qb->rnode = node; qspn_b[level] = list_add(qspn_b[level], qb); send_qspn_now[level] = 1; } /* If the new rnode wasn't present in the map, * then it is also a new node in the map, so * update the seeds counter too */ if (!level && !external_node && (node->flags & MAP_VOID)) { gnode_inc_seeds(&me.cur_quadg, level); qspn_inc_gcount(qspn_gnode_count, level + 1, 1); } SET_BIT(rnode_added, level); } else { /* * Nah, We have the node in the map. Let's see if * its rtt is changed */ if (!send_qspn_now[level] && node->links) { diff = abs(root_node->r_node[rnode_pos].trtt - MILLISEC(rq->final_rtt)); if (diff >= RTT_DELTA) { node_update = 1; send_qspn_now[level] = 1; debug(DBG_NOISE, "node %s rtt changed, diff: %d", inet_to_str(rq->ip), diff); } } } /* Restore the flags */ if (level) gnode->flags &= ~GMAP_VOID; node->flags &= ~MAP_VOID & ~MAP_UPDATE & ~QSPN_OLD; /* * Update the devices list of the rnode */ if (!level) { devs_update = rnl_update_devs(&rlist, &rlist_counter, node, rq->dev, rq->dev_n); if (devs_update) routes_update++; } /* Nothing is really changed */ if (!node_update) continue; /* Update the rtt */ root_node->r_node[rnode_pos].trtt = MILLISEC(rq->final_rtt); /* Bnode map stuff */ if (external_node && level) { /* * All the root_node bnodes which are in the * bmaps of level smaller than `level' points to * the same gnode which is rq->quadg.gnode[_EL(level-1+1)]. * This is because the inferior levels cannot * have knowledge about the bordering gnode * which is in an upper level, but it's necessary that * they know which who the root_node borders on, * so the get_route algorithm can descend to * the inferior levels and it will still know * what is the border node which is linked * to the target gnode. */ for (i = 0; i < level; i++) radar_update_bmap(rq, i, level - 1); send_qspn_now[level - 1] = 1; } if (node_update || devs_update) node->flags |= MAP_UPDATE; } /*for(level=0, ...) */ updated_rnodes++; } /*list_for(rq) */ /* Burn the deads */ if (updated_rnodes < me.cur_node->links) radar_remove_old_rnodes((char *) rnode_deleted); /* <<keep your room tidy... order, ORDER>> */ if (!is_bufzero(rnode_added, sizeof(rnode_added)) || !is_bufzero(rnode_deleted, sizeof(rnode_deleted))) { /*** * qsort the rnodes of me.cur_node and me.cur_quadg comparing * their trtt */ rnode_trtt_order(me.cur_node); for (i = 1; i < me.cur_quadg.levels; i++) if (TEST_BIT(rnode_added, i) || TEST_BIT(rnode_deleted, i)) rnode_trtt_order(&me.cur_quadg.gnode[_EL(i)]->g); /**/ /* adjust the rnode_pos variables in the ext_rnode_cache list */ erc_reorder_rnodepos(&me.cur_erc, &me.cur_erc_counter, me.cur_node); } /* Give a refresh to the kernel */ if ((!is_bufzero(rnode_added, sizeof(rnode_added)) || routes_update) && !(me.cur_node->flags & MAP_HNODE)) rt_rnodes_update(1); }
/* * radard * * It sends back to rpkt.from the ECHO_REPLY pkt in reply to the ECHO_ME * pkt received. */ int radard(PACKET rpkt) { PACKET pkt; struct radar_queue *rq; ssize_t err; const char *ntop = 0; int dev_pos; u_char echo_scans_count; if (alwd_rnodes_counter && !is_rnode_allowed(rpkt.from, alwd_rnodes)) { debug(DBG_INSANE, "Filtering 0x%x ECHO_ME", rpkt.hdr.id); return -1; } if ((rpkt.hdr.flags & RESTRICTED_PKT && !restricted_mode) || (!(rpkt.hdr.flags & RESTRICTED_PKT) && restricted_mode)) return -1; dev_pos = ifs_get_pos(me.cur_ifs, me.cur_ifs_n, rpkt.dev); if (dev_pos < 0) debug(DBG_NORMAL, "The 0x%x ECHO_ME pkt was received by a non " "existent interface", rpkt.hdr.id); /* If we are hooking we reply only to others hooking nodes */ if (me.cur_node->flags & MAP_HNODE) { if (rpkt.hdr.flags & HOOK_PKT) { memcpy(&echo_scans_count, rpkt.msg, sizeof(u_char)); /* * So, we are hooking, but we haven't yet started the * first scan or we have done less scans than rpkt.from, * this means that this node, who is hooking * too and sent us this rpkt, has started the hook * before us. If we are in a black zone, this flag * will be used to decide which of the hooking nodes * have to create the new gnode: if it is set we'll wait, * the other hooking node will create the gnode, then we * restart the hook. Clear? */ if (!radar_scan_mutex || echo_scans_count >= radar_scans[dev_pos]) hook_retry = 1; } else { /*debug(DBG_NOISE, "ECHO_ME pkt dropped: We are hooking"); */ return 0; } } /* We create the ECHO_REPLY pkt */ setzero(&pkt, sizeof(PACKET)); pkt_addto(&pkt, &rpkt.from); pkt_addsk(&pkt, rpkt.from.family, rpkt.sk, SKT_UDP); if (me.cur_node->flags & MAP_HNODE) { /* * We attach in the ECHO_REPLY a flag that indicates if we have * finished our radar_scan or not. This is usefull if we already * sent all the ECHO_ME pkts of our radar scan and while we are * waiting the MAX_RADAR_WAIT another node start the hooking: * with this flag it can know if we came before him. */ u_char scanning = 1; pkt.hdr.sz = sizeof(u_char); pkt.hdr.flags |= HOOK_PKT; pkt.msg = xmalloc(pkt.hdr.sz); if (radar_scans[dev_pos] == MAX_RADAR_SCANS) scanning = 0; memcpy(pkt.msg, &scanning, sizeof(u_char)); /* * W Poetry Palazzolo, the enlightening holy garden. * Sat Mar 12 20:41:36 CET 2005 */ } if (restricted_mode) pkt.hdr.flags |= RESTRICTED_PKT; /* We send it */ err = send_rq(&pkt, 0, ECHO_REPLY, rpkt.hdr.id, 0, 0, 0); pkt_free(&pkt, 0); if (err < 0) { error("radard(): Cannot send back the ECHO_REPLY to %s.", ntop); return -1; } /* * Ok, we have sent the reply, now we can update the radar_queue with * calm. */ if (radar_q) { rq = add_radar_q(rpkt); rq->pings++; #ifdef DEBUG if (server_opt.dbg_lvl && rq->pings == 1 && me.cur_node->flags & MAP_HNODE) { ntop = inet_to_str(pkt.to); debug(DBG_INSANE, "%s(0x%x) to %s", rq_to_str(ECHO_REPLY), rpkt.hdr.id, ntop); } #endif } return 0; }
char * inet_ntoa(struct in_addr in) { static char buff[INET_ADDRSTRLEN]; return 0 == inet_to_str(&in, &buff[0], ARRAY_SIZE(buff)) ? &buff[0] : NULL; }