void* map_put(Map *map, const void *key, void *value, uint8_t freewhat) { void* oldvalue; map->root = node_add(map->root, key, value, map->cmp, freewhat, &oldvalue); map->root->color = BLACK; map->size += (oldvalue == NULL); return oldvalue; }
inline void page_addSchedule() { static schedule s; //Schedule to be added static int value = 0; if(pre_page != ADD_SCHEDULE) { PTLS("Page Add Schedule"); pre_page = ADD_SCHEDULE; lcd.cursor(); //Need to reintialize everytime we enter the page but not every refresh s.day = weekday(); s.hour = hour(); s.minute = minute(); s.temperature = temperature_sensor; value = 0; } String t = getTimeString(s); lcd.print(F("Add: ")); lcd.print(t); lcd.setCursor(0,1); lcd.print(F("Temp: ")); lcd.print(s.temperature); if (button_input == PLUS_UP || button_input == PLUS_HOLD) { if (value == 0) { s.day++; if (s.day >= 8) s.day = 1; } else if (value == 1) { s.hour++; if (s.hour >= 24) s.hour = 0; } else if (value == 2) { s.minute++; if (s.minute >= 60) s.minute = 0; } else if (value == 3) { s.temperature++; if (s.temperature >= 99) s.temperature = 99; } } else if (button_input == MINUS_UP || button_input == MINUS_HOLD) { if (value == 0) { s.day--; if (s.day <= 0) s.day = 7; } else if (value == 1) { s.hour--; if (s.hour >= 24) s.hour = 23; } else if (value == 2) { s.minute--; if (s.minute >= 60) s.minute = 59; } else if (value == 3) { s.temperature--; if (s.temperature <= 32 || s.temperature >= 99) s.temperature = 32; } } else if (button_input == MODE_UP) { value += 1; value = value % 4; } else if (button_input == SET_UP) { node_add(s); switchPage(LIST_MODE); } }
void node_discovered( xbee_dev_t *xbee, const xbee_node_id_t *rec) { if (rec != NULL) { node_add( rec); xbee_disc_node_id_dump( rec); } }
/* Read Subnets from all host config files */ void load_all_subnets(void) { DIR *dir; struct dirent *ent; char *dname; char *fname; avl_tree_t *config_tree; config_t *cfg; subnet_t *s, *s2; node_t *n; bool result; xasprintf(&dname, "%s/hosts", confbase); dir = opendir(dname); if(!dir) { logger(LOG_ERR, "Could not open %s: %s", dname, strerror(errno)); free(dname); return; } while((ent = readdir(dir))) { if(!check_id(ent->d_name)) continue; n = lookup_node(ent->d_name); #ifdef _DIRENT_HAVE_D_TYPE //if(ent->d_type != DT_REG) // continue; #endif xasprintf(&fname, "%s/hosts/%s", confbase, ent->d_name); init_configuration(&config_tree); result = read_config_file(config_tree, fname); free(fname); if(!result) continue; if(!n) { n = new_node(); n->name = xstrdup(ent->d_name); node_add(n); } for(cfg = lookup_config(config_tree, "Subnet"); cfg; cfg = lookup_config_next(config_tree, cfg)) { if(!get_config_subnet(cfg, &s)) continue; if((s2 = lookup_subnet(n, s))) { s2->expires = -1; } else { subnet_add(n, s); } } exit_configuration(&config_tree); } closedir(dir); }
/* Modify is slightly trickier. The basic idea is we simply delete the * object and create it with the new parameters. Then we need to mark the * objects that depend on this one */ int output_pgsql_t::node_modify(osmium::Node const &node) { if (!m_options.slim) { fprintf(stderr, "Cannot apply diffs unless in slim mode\n"); util::exit_nicely(); } node_delete(node.id()); node_add(node); return 0; }
/* Modify is slightly trickier. The basic idea is we simply delete the * object and create it with the new parameters. Then we need to mark the * objects that depend on this one */ int output_pgsql_t::node_modify(osmid_t osm_id, double lat, double lon, const taglist_t &tags) { if( !m_options.slim ) { fprintf( stderr, "Cannot apply diffs unless in slim mode\n" ); util::exit_nicely(); } node_delete(osm_id); node_add(osm_id, lat, lon, tags); return 0; }
int main() { struct node* head = head_init(); int i; for(i=0; i<5; i++) { node_add(head, i); } printf_list(head); node_del(head, 3); printf_list(head); node_insert_after(head,2,6); printf_list(head); node_insert_before(&head,0,5); printf_list(head); node_insert_before(&head,6,8); printf_list(head); node_reverse(&head); printf_list(head); node_reverse_by_test(&head); printf_list(head); struct node* p = search_mid_node(head); printf("mid=%d\n", p->data); /* delete head emlement */ Remove_head(&head); printf_list(head); for(i=7; i<10; i++) { node_add(head, i); } printf_list(head); p = search_mid_node(head); printf("mid=%d\n", p->data); return 0; }
void addnode(t_tree **tree, void *data, int pos) { t_tree *tmptree; t_tree *elem; tmptree = *tree; elem = NULL; elem = createnode(elem, data); if (!tmptree) *tree = elem; else node_add(tmptree, elem, pos); }
static void xmlrpc_config_ready(void *vptr) { /* Note: handle_xmlrpc.path may point to freed memory between * reading the config and here. */ handle_xmlrpc.path = xmlrpc_config.path; if (handle_xmlrpc.handler != NULL) { if (node_find(&handle_xmlrpc, httpd_path_handlers)) return; node_add(&handle_xmlrpc, node_create(), httpd_path_handlers); } else slog(LG_ERROR, "xmlrpc_config_ready(): xmlrpc {} block missing or invalid"); }
elem* heap_add(heap** H, node* newNode){ assert(H); assert(newNode); node* oldNode = *H; newNode->parent = NULL; newNode->hasLostKid = 0; if (oldNode){ //nonempty heap node_add(oldNode, newNode); if (oldNode->key > newNode->key){ //new smallest *H = newNode; } }else{ //previously empty heap newNode->left = newNode; newNode->right = newNode; *H = newNode; } return newNode; }
/* adds a node to a list before another node, or to the end */ void node_add_before(void *data, node_t *n, list_t *l, node_t *before) { return_if_fail(n != NULL); return_if_fail(l != NULL); if (before == NULL) node_add(data, n, l); else if (before == l->head) node_add_head(data, n, l); else { n->data = data; n->prev = before->prev; n->next = before; before->prev = n; l->count++; } }
main() { struct node *root; int line; char word[MAXWORD]; root = NULL; line = 1; for (;;) { line += getword(word, MAXWORD); if (word[0] == '\0') break; if (binsearch(word, noise, sizeof(noise) / sizeof(*noise)) == NULL) root = node_add(root, word, line); } treeprint(root); return 0; }
ret_t chula_avl_generic_add (chula_avl_generic_t *avl, chula_avl_generic_node_t *key, void *value) { ret_t ret; if (unlikely (avl->node_is_empty (key))) return ret_error; /* Store the node value */ key->value = value; /* Add th node to the tree */ ret = node_add (avl, key); if (unlikely (ret != ret_ok)) { return ret; } return ret_ok; }
void skill_add_tool(struct skill *skill, void *objtype) { struct node *node = node_new(objtype); node_add(&skill->tools, node); }
void node_add_node_and_text(Node * node, const char * tag, const char * text) { Node * x = node_add_new(node, tag); node_add(x, Text(text)); }
/* Configure node_t mesh->self and set up the local sockets (listen only) */ bool setup_myself(meshlink_handle_t *mesh) { char *name; char *address = NULL; if(!(name = get_name(mesh))) { logger(mesh, MESHLINK_ERROR, "Name for MeshLink instance required!"); return false; } mesh->self = new_node(); mesh->self->connection = new_connection(); mesh->self->name = name; mesh->self->devclass = mesh->devclass; mesh->self->connection->name = xstrdup(name); read_host_config(mesh, mesh->config, name); if(!get_config_string(lookup_config(mesh->config, "Port"), &mesh->myport)) { logger(mesh, MESHLINK_ERROR, "Port for MeshLink instance required!"); return false; } mesh->self->connection->options = 0; mesh->self->connection->protocol_major = PROT_MAJOR; mesh->self->connection->protocol_minor = PROT_MINOR; mesh->self->options |= PROT_MINOR << 24; if(!read_ecdsa_private_key(mesh)) return false; /* Ensure mesh->myport is numeric */ if(!atoi(mesh->myport)) { struct addrinfo *ai = str2addrinfo("localhost", mesh->myport, SOCK_DGRAM); sockaddr_t sa; if(!ai || !ai->ai_addr) return false; free(mesh->myport); memcpy(&sa, ai->ai_addr, ai->ai_addrlen); sockaddr2str(&sa, NULL, &mesh->myport); } /* Check some options */ if(!setup_myself_reloadable(mesh)) return false; /* Compression */ // TODO: drop compression in the packet layer? mesh->self->incompression = 0; mesh->self->connection->outcompression = 0; /* Done */ mesh->self->nexthop = mesh->self; mesh->self->via = mesh->self; mesh->self->status.reachable = true; mesh->self->last_state_change = mesh->loop.now.tv_sec; node_write_devclass(mesh, mesh->self); node_add(mesh, mesh->self); graph(mesh); load_all_nodes(mesh); /* Open sockets */ mesh->listen_sockets = 0; if(!add_listen_address(mesh, address, NULL)) return false; if(!mesh->listen_sockets) { logger(mesh, MESHLINK_ERROR, "Unable to create any listening socket!"); return false; } xasprintf(&mesh->self->hostname, "MYSELF port %s", mesh->myport); mesh->self->connection->hostname = xstrdup(mesh->self->hostname); /* Done. */ mesh->last_config_check = mesh->loop.now.tv_sec; return true; }
const struct sensors_input_cache_entry_t *sensors_input_cache_get( const char *name) { int rc; int fd; DIR *dir; struct dirent * item; struct list_node *member; struct input_dev_list *temp; pthread_t id[MAX_EVENT_DRIVERS]; unsigned int i = 0; unsigned int threads = 0; const struct sensors_input_cache_entry_t *found = NULL; pthread_mutex_lock(&util_mutex); if (!list_initialized) { node_init(&head); list_initialized = 1; } temp = lookup(name, NULL); if (temp) { found = &temp->entry; goto exit; } dir = opendir(INPUT_EVENT_DIR); if (!dir) { ALOGE("%s: error opening '%s'\n", __func__, INPUT_EVENT_DIR); goto exit; } while ((item = readdir(dir)) != NULL) { if (strncmp(item->d_name, INPUT_EVENT_BASENAME, sizeof(INPUT_EVENT_BASENAME) - 1) != 0) { continue; } temp = (temp ? temp : malloc(sizeof(*temp))); if (temp == NULL) { ALOGE("%s: malloc error!\n", __func__); break; } /* skip already cached entries */ snprintf(temp->entry.event_path, sizeof(temp->entry.event_path), "%s%s", INPUT_EVENT_DIR, item->d_name); if (lookup(NULL, temp->entry.event_path)) continue; /* make sure we have access */ fd = open(temp->entry.event_path, O_RDONLY); if (fd < 0) { ALOGE("%s: cant open %s", __func__, item->d_name); continue; } rc = ioctl(fd, EVIOCGNAME(sizeof(temp->entry.dev_name)), temp->entry.dev_name); /* close in parallell to optimize boot time */ pthread_create(&id[threads++], NULL, close_input_dev_fd, (void*) fd); if (rc < 0) { ALOGE("%s: cant get name from %s", __func__, item->d_name); continue; } temp->entry.nr = atoi(item->d_name + sizeof(INPUT_EVENT_BASENAME) - 1); node_add(&head, &temp->node); if (!found && !strncmp(temp->entry.dev_name, name, sizeof(temp->entry.dev_name) - 1)) found = &temp->entry; temp = NULL; } closedir(dir); for(i = 0; i < threads; ++i) pthread_join(id[i], NULL); exit: pthread_mutex_unlock(&util_mutex); return found; }
void list_add(struct list *l, int value) { l->head = node_add(l->head, value); }
void cgraphics_toolbar_new_icon( widget_t *widget, list_item_t *item ) { widget_t *parent = (widget_t *)OBJECT(widget)->parent; HWND rebar = parent->ndata; REBARBANDINFO ri; TBADDBITMAP tbb; TBBUTTON tbut; DWORD dwBtnSize; node_t *n; image_t *img = item->data[0]; const char *txt = item->data[1]; if ( img == 0 && txt == 0 ) { /* regardless of style, this is a separator :) */ tbut.iBitmap = 10; tbut.fsStyle = BTNS_SEP; tbut.iString = 0; /* JIC */ } else { /* it has SOMETHING filled in, so let's tell Windows */ tbut.fsStyle = BTNS_BUTTON; tbb.hInst = NULL; tbb.nID = 0; if ( widget->flags & cToolbarAutoSizeButtons ) tbut.fsStyle |= BTNS_AUTOSIZE; if ( LIST_LENGTH( &item->children ) > 0 ) tbut.fsStyle |= BTNS_DROPDOWN; if ( widget->flags & cToolbarShowImages ) { tbb.hInst = NULL; #ifdef IMAGES_USE_LIBPNG tbb.nID = 0; tbut.iBitmap = 0; #else tbb.nID = (UINT_PTR)img->native2; // BMP a = SendMessage( widget->native, TB_ADDBITMAP, 1, (LPARAM)&tbb ); tbut.iBitmap = a; #endif } if ( widget->flags & cToolbarShowText ) { tbut.iString = (size_t)txt; tbut.fsStyle |= BTNS_SHOWTEXT; } else tbut.iString = 0; } /* if none so far, just for safely clean the list :) */ if ( tblist_cmdid == 0 ) { tblist_cmdid++; list_create( &tblist ); } /* that's our cmdid! prepare the next one, too.. */ item->nativeid = tblist_cmdid; tblist_cmdid++; /* save into cmdid mapping list */ n = node_create( ); node_add( item, n, &tblist ); tbut.idCommand = item->nativeid; tbut.fsState = TBSTATE_ENABLED; tbut.dwData = 0; SendMessage( widget->native, TB_INSERTBUTTON, item->row, (LPARAM)&tbut ); /* Fix the rebar :) */ SendMessage( widget->native, TB_AUTOSIZE, 0, 0 ); dwBtnSize = SendMessage( widget->native, TB_GETBUTTONSIZE, 0, 0 ); ZeroMemory( &ri, sizeof(ri) ); ri.cbSize = sizeof(REBARBANDINFO); ri.fMask = RBBIM_CHILDSIZE; ri.cxMinChild = 0; ri.cyMinChild = HIWORD(dwBtnSize); ri.cx = 10; SendMessage( rebar, RB_SETBANDINFO, (WPARAM)0, (LPARAM)&ri ); }
/* Configure node_t myself and set up the local sockets (listen only) */ bool setup_myself(void) { config_t *cfg; subnet_t *subnet; char *name, *hostname, *mode, *afname, *cipher, *digest; char *fname = NULL; char *address = NULL; char *envp[5]; struct addrinfo *ai, *aip, hint = {0}; bool choice; int i, err; int replaywin_int; myself = new_node(); myself->connection = new_connection(); myself->hostname = xstrdup("MYSELF"); myself->connection->hostname = xstrdup("MYSELF"); myself->connection->options = 0; myself->connection->protocol_version = PROT_CURRENT; if(!get_config_string(lookup_config(config_tree, "Name"), &name)) { /* Not acceptable */ logger(LOG_ERR, "Name for tinc daemon required!"); return false; } if(!check_id(name)) { logger(LOG_ERR, "Invalid name for myself!"); free(name); return false; } myself->name = name; myself->connection->name = xstrdup(name); xasprintf(&fname, "%s/hosts/%s", confbase, name); read_config_options(config_tree, name); read_config_file(config_tree, fname); free(fname); if(!read_rsa_private_key()) return false; if(!get_config_string(lookup_config(config_tree, "Port"), &myport)) myport = xstrdup("655"); if(!atoi(myport)) { struct addrinfo *ai = str2addrinfo("localhost", myport, SOCK_DGRAM); sockaddr_t sa; if(!ai || !ai->ai_addr) return false; free(myport); memcpy(&sa, ai->ai_addr, ai->ai_addrlen); sockaddr2str(&sa, NULL, &myport); } /* Read in all the subnets specified in the host configuration file */ cfg = lookup_config(config_tree, "Subnet"); while(cfg) { if(!get_config_subnet(cfg, &subnet)) return false; subnet_add(myself, subnet); cfg = lookup_config_next(config_tree, cfg); } /* Check some options */ if(get_config_bool(lookup_config(config_tree, "IndirectData"), &choice) && choice) myself->options |= OPTION_INDIRECT; if(get_config_bool(lookup_config(config_tree, "TCPOnly"), &choice) && choice) myself->options |= OPTION_TCPONLY; if(myself->options & OPTION_TCPONLY) myself->options |= OPTION_INDIRECT; get_config_bool(lookup_config(config_tree, "DirectOnly"), &directonly); get_config_bool(lookup_config(config_tree, "StrictSubnets"), &strictsubnets); get_config_bool(lookup_config(config_tree, "TunnelServer"), &tunnelserver); strictsubnets |= tunnelserver; if(get_config_string(lookup_config(config_tree, "Mode"), &mode)) { if(!strcasecmp(mode, "router")) routing_mode = RMODE_ROUTER; else if(!strcasecmp(mode, "switch")) routing_mode = RMODE_SWITCH; else if(!strcasecmp(mode, "hub")) routing_mode = RMODE_HUB; else { logger(LOG_ERR, "Invalid routing mode!"); return false; } free(mode); } if(get_config_string(lookup_config(config_tree, "Forwarding"), &mode)) { if(!strcasecmp(mode, "off")) forwarding_mode = FMODE_OFF; else if(!strcasecmp(mode, "internal")) forwarding_mode = FMODE_INTERNAL; else if(!strcasecmp(mode, "kernel")) forwarding_mode = FMODE_KERNEL; else { logger(LOG_ERR, "Invalid forwarding mode!"); return false; } free(mode); } choice = true; get_config_bool(lookup_config(config_tree, "PMTUDiscovery"), &choice); if(choice) myself->options |= OPTION_PMTU_DISCOVERY; choice = true; get_config_bool(lookup_config(config_tree, "ClampMSS"), &choice); if(choice) myself->options |= OPTION_CLAMP_MSS; get_config_bool(lookup_config(config_tree, "PriorityInheritance"), &priorityinheritance); #if !defined(SOL_IP) || !defined(IP_TOS) if(priorityinheritance) logger(LOG_WARNING, "%s not supported on this platform", "PriorityInheritance"); #endif if(!get_config_int(lookup_config(config_tree, "MACExpire"), &macexpire)) macexpire = 600; if(get_config_int(lookup_config(config_tree, "MaxTimeout"), &maxtimeout)) { if(maxtimeout <= 0) { logger(LOG_ERR, "Bogus maximum timeout!"); return false; } } else maxtimeout = 900; if(get_config_int(lookup_config(config_tree, "UDPRcvBuf"), &udp_rcvbuf)) { if(udp_rcvbuf <= 0) { logger(LOG_ERR, "UDPRcvBuf cannot be negative!"); return false; } } if(get_config_int(lookup_config(config_tree, "UDPSndBuf"), &udp_sndbuf)) { if(udp_sndbuf <= 0) { logger(LOG_ERR, "UDPSndBuf cannot be negative!"); return false; } } if(get_config_int(lookup_config(config_tree, "ReplayWindow"), &replaywin_int)) { if(replaywin_int < 0) { logger(LOG_ERR, "ReplayWindow cannot be negative!"); return false; } replaywin = (unsigned)replaywin_int; } if(get_config_string(lookup_config(config_tree, "AddressFamily"), &afname)) { if(!strcasecmp(afname, "IPv4")) addressfamily = AF_INET; else if(!strcasecmp(afname, "IPv6")) addressfamily = AF_INET6; else if(!strcasecmp(afname, "any")) addressfamily = AF_UNSPEC; else { logger(LOG_ERR, "Invalid address family!"); return false; } free(afname); } get_config_bool(lookup_config(config_tree, "Hostnames"), &hostnames); /* Generate packet encryption key */ if(get_config_string (lookup_config(config_tree, "Cipher"), &cipher)) { if(!strcasecmp(cipher, "none")) { myself->incipher = NULL; } else { myself->incipher = EVP_get_cipherbyname(cipher); if(!myself->incipher) { logger(LOG_ERR, "Unrecognized cipher type!"); return false; } } } else myself->incipher = EVP_bf_cbc(); if(myself->incipher) myself->inkeylength = myself->incipher->key_len + myself->incipher->iv_len; else myself->inkeylength = 1; myself->connection->outcipher = EVP_bf_ofb(); if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime)) keylifetime = 3600; keyexpires = now + keylifetime; /* Check if we want to use message authentication codes... */ if(get_config_string(lookup_config(config_tree, "Digest"), &digest)) { if(!strcasecmp(digest, "none")) { myself->indigest = NULL; } else { myself->indigest = EVP_get_digestbyname(digest); if(!myself->indigest) { logger(LOG_ERR, "Unrecognized digest type!"); return false; } } } else myself->indigest = EVP_sha1(); myself->connection->outdigest = EVP_sha1(); if(get_config_int(lookup_config(config_tree, "MACLength"), &myself->inmaclength)) { if(myself->indigest) { if(myself->inmaclength > myself->indigest->md_size) { logger(LOG_ERR, "MAC length exceeds size of digest!"); return false; } else if(myself->inmaclength < 0) { logger(LOG_ERR, "Bogus MAC length!"); return false; } } } else myself->inmaclength = 4; myself->connection->outmaclength = 0; /* Compression */ if(get_config_int(lookup_config(config_tree, "Compression"), &myself->incompression)) { if(myself->incompression < 0 || myself->incompression > 11) { logger(LOG_ERR, "Bogus compression level!"); return false; } } else myself->incompression = 0; myself->connection->outcompression = 0; /* Done */ myself->nexthop = myself; myself->via = myself; myself->status.reachable = true; node_add(myself); graph(); if(strictsubnets) load_all_subnets(); /* Open device */ if(!setup_device()) return false; /* Run tinc-up script to further initialize the tap interface */ xasprintf(&envp[0], "NETNAME=%s", netname ? : ""); xasprintf(&envp[1], "DEVICE=%s", device ? : ""); xasprintf(&envp[2], "INTERFACE=%s", iface ? : ""); xasprintf(&envp[3], "NAME=%s", myself->name); envp[4] = NULL; execute_script("tinc-up", envp); for(i = 0; i < 5; i++) free(envp[i]); /* Run subnet-up scripts for our own subnets */ subnet_update(myself, NULL, true); /* Open sockets */ get_config_string(lookup_config(config_tree, "BindToAddress"), &address); hint.ai_family = addressfamily; hint.ai_socktype = SOCK_STREAM; hint.ai_protocol = IPPROTO_TCP; hint.ai_flags = AI_PASSIVE; err = getaddrinfo(address, myport, &hint, &ai); if(err || !ai) { logger(LOG_ERR, "System call `%s' failed: %s", "getaddrinfo", gai_strerror(err)); return false; } listen_sockets = 0; for(aip = ai; aip; aip = aip->ai_next) { listen_socket[listen_sockets].tcp = setup_listen_socket((sockaddr_t *) aip->ai_addr); if(listen_socket[listen_sockets].tcp < 0) continue; listen_socket[listen_sockets].udp = setup_vpn_in_socket((sockaddr_t *) aip->ai_addr); if(listen_socket[listen_sockets].udp < 0) continue; ifdebug(CONNECTIONS) { hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr); logger(LOG_NOTICE, "Listening on %s", hostname); free(hostname); } memcpy(&listen_socket[listen_sockets].sa, aip->ai_addr, aip->ai_addrlen); listen_sockets++; } freeaddrinfo(ai); if(listen_sockets) logger(LOG_NOTICE, "Ready"); else { logger(LOG_ERR, "Unable to create any listening socket!"); return false; } return true; }
bool ack_h(connection_t *c, const char *request) { if(c->protocol_minor == 1) return upgrade_h(c, request); char hisport[MAX_STRING_SIZE]; char *hisaddress; int weight, mtu; uint32_t options; node_t *n; bool choice; if(sscanf(request, "%*d " MAX_STRING " %d %x", hisport, &weight, &options) != 3) { logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "ACK", c->name, c->hostname); return false; } /* Check if we already have a node_t for him */ n = lookup_node(c->name); if(!n) { n = new_node(); n->name = xstrdup(c->name); node_add(n); } else { if(n->connection) { /* Oh dear, we already have a connection to this node. */ logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Established a second connection with %s (%s), closing old connection", n->connection->name, n->connection->hostname); if(n->connection->outgoing) { if(c->outgoing) logger(DEBUG_ALWAYS, LOG_WARNING, "Two outgoing connections to the same node!"); else c->outgoing = n->connection->outgoing; n->connection->outgoing = NULL; } terminate_connection(n->connection, false); /* Run graph algorithm to purge key and make sure up/down scripts are rerun with new IP addresses and stuff */ graph(); } } n->connection = c; c->node = n; if(!(c->options & options & OPTION_PMTU_DISCOVERY)) { c->options &= ~OPTION_PMTU_DISCOVERY; options &= ~OPTION_PMTU_DISCOVERY; } c->options |= options; if(get_config_int(lookup_config(c->config_tree, "PMTU"), &mtu) && mtu < n->mtu) n->mtu = mtu; if(get_config_int(lookup_config(config_tree, "PMTU"), &mtu) && mtu < n->mtu) n->mtu = mtu; if(get_config_bool(lookup_config(c->config_tree, "ClampMSS"), &choice)) { if(choice) c->options |= OPTION_CLAMP_MSS; else c->options &= ~OPTION_CLAMP_MSS; } /* Activate this connection */ c->allow_request = ALL; logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Connection with %s (%s) activated", c->name, c->hostname); /* Send him everything we know */ send_everything(c); /* Create an edge_t for this connection */ c->edge = new_edge(); c->edge->from = myself; c->edge->to = n; sockaddr2str(&c->address, &hisaddress, NULL); c->edge->address = str2sockaddr(hisaddress, hisport); free(hisaddress); sockaddr_t local_sa; socklen_t local_salen = sizeof local_sa; if (getsockname(c->socket, &local_sa.sa, &local_salen) < 0) logger(DEBUG_ALWAYS, LOG_WARNING, "Could not get local socket address for connection with %s", c->name); else { char *local_address; sockaddr2str(&local_sa, &local_address, NULL); c->edge->local_address = str2sockaddr(local_address, myport); free(local_address); } c->edge->weight = (weight + c->estimated_weight) / 2; c->edge->connection = c; c->edge->options = c->options; edge_add(c->edge); /* Notify everyone of the new edge */ if(tunnelserver) send_add_edge(c, c->edge); else send_add_edge(everyone, c->edge); /* Run MST and SSSP algorithms */ graph(); return true; }
/* Configure node_t myself and set up the local sockets (listen only) */ static bool setup_myself(void) { config_t *cfg; subnet_t *subnet; char *name, *hostname, *mode, *afname, *cipher, *digest, *type; char *fname = NULL; char *address = NULL; char *proxy = NULL; char *space; char *envp[5] = {NULL}; struct addrinfo *ai, *aip, hint = {0}; bool choice; int i, err; int replaywin_int; bool port_specified = false; myself = new_node(); myself->connection = new_connection(); myself->hostname = xstrdup("MYSELF"); myself->connection->hostname = xstrdup("MYSELF"); myself->connection->options = 0; myself->connection->protocol_version = PROT_CURRENT; if(!(name = get_name())) { logger(LOG_ERR, "Name for tinc daemon required!"); return false; } /* Read tinc.conf and our own host config file */ myself->name = name; myself->connection->name = xstrdup(name); xasprintf(&fname, "%s/hosts/%s", confbase, name); read_config_options(config_tree, name); read_config_file(config_tree, fname); free(fname); if(!read_rsa_private_key()) return false; if(!get_config_string(lookup_config(config_tree, "Port"), &myport)) myport = xstrdup("655"); else port_specified = true; /* Ensure myport is numeric */ if(!atoi(myport)) { struct addrinfo *ai = str2addrinfo("localhost", myport, SOCK_DGRAM); sockaddr_t sa; if(!ai || !ai->ai_addr) return false; free(myport); memcpy(&sa, ai->ai_addr, ai->ai_addrlen); sockaddr2str(&sa, NULL, &myport); } get_config_string(lookup_config(config_tree, "Proxy"), &proxy); if(proxy) { if((space = strchr(proxy, ' '))) *space++ = 0; if(!strcasecmp(proxy, "none")) { proxytype = PROXY_NONE; } else if(!strcasecmp(proxy, "socks4")) { proxytype = PROXY_SOCKS4; } else if(!strcasecmp(proxy, "socks4a")) { proxytype = PROXY_SOCKS4A; } else if(!strcasecmp(proxy, "socks5")) { proxytype = PROXY_SOCKS5; } else if(!strcasecmp(proxy, "http")) { proxytype = PROXY_HTTP; } else if(!strcasecmp(proxy, "exec")) { proxytype = PROXY_EXEC; } else { logger(LOG_ERR, "Unknown proxy type %s!", proxy); return false; } switch(proxytype) { case PROXY_NONE: default: break; case PROXY_EXEC: if(!space || !*space) { logger(LOG_ERR, "Argument expected for proxy type exec!"); return false; } proxyhost = xstrdup(space); break; case PROXY_SOCKS4: case PROXY_SOCKS4A: case PROXY_SOCKS5: case PROXY_HTTP: proxyhost = space; if(space && (space = strchr(space, ' '))) *space++ = 0, proxyport = space; if(space && (space = strchr(space, ' '))) *space++ = 0, proxyuser = space; if(space && (space = strchr(space, ' '))) *space++ = 0, proxypass = space; if(!proxyhost || !*proxyhost || !proxyport || !*proxyport) { logger(LOG_ERR, "Host and port argument expected for proxy!"); return false; } proxyhost = xstrdup(proxyhost); proxyport = xstrdup(proxyport); if(proxyuser && *proxyuser) proxyuser = xstrdup(proxyuser); if(proxypass && *proxypass) proxypass = xstrdup(proxypass); break; } free(proxy); } /* Read in all the subnets specified in the host configuration file */ cfg = lookup_config(config_tree, "Subnet"); while(cfg) { if(!get_config_subnet(cfg, &subnet)) return false; subnet_add(myself, subnet); cfg = lookup_config_next(config_tree, cfg); } /* Check some options */ if(get_config_bool(lookup_config(config_tree, "IndirectData"), &choice) && choice) myself->options |= OPTION_INDIRECT; if(get_config_bool(lookup_config(config_tree, "TCPOnly"), &choice) && choice) myself->options |= OPTION_TCPONLY; if(myself->options & OPTION_TCPONLY) myself->options |= OPTION_INDIRECT; get_config_bool(lookup_config(config_tree, "DirectOnly"), &directonly); get_config_bool(lookup_config(config_tree, "StrictSubnets"), &strictsubnets); get_config_bool(lookup_config(config_tree, "TunnelServer"), &tunnelserver); get_config_bool(lookup_config(config_tree, "LocalDiscovery"), &localdiscovery); strictsubnets |= tunnelserver; if(get_config_string(lookup_config(config_tree, "Mode"), &mode)) { if(!strcasecmp(mode, "router")) routing_mode = RMODE_ROUTER; else if(!strcasecmp(mode, "switch")) routing_mode = RMODE_SWITCH; else if(!strcasecmp(mode, "hub")) routing_mode = RMODE_HUB; else { logger(LOG_ERR, "Invalid routing mode!"); return false; } free(mode); } if(get_config_string(lookup_config(config_tree, "Forwarding"), &mode)) { if(!strcasecmp(mode, "off")) forwarding_mode = FMODE_OFF; else if(!strcasecmp(mode, "internal")) forwarding_mode = FMODE_INTERNAL; else if(!strcasecmp(mode, "kernel")) forwarding_mode = FMODE_KERNEL; else { logger(LOG_ERR, "Invalid forwarding mode!"); return false; } free(mode); } choice = true; get_config_bool(lookup_config(config_tree, "PMTUDiscovery"), &choice); if(choice) myself->options |= OPTION_PMTU_DISCOVERY; choice = true; get_config_bool(lookup_config(config_tree, "ClampMSS"), &choice); if(choice) myself->options |= OPTION_CLAMP_MSS; get_config_bool(lookup_config(config_tree, "PriorityInheritance"), &priorityinheritance); get_config_bool(lookup_config(config_tree, "DecrementTTL"), &decrement_ttl); if(get_config_string(lookup_config(config_tree, "Broadcast"), &mode)) { if(!strcasecmp(mode, "no")) broadcast_mode = BMODE_NONE; else if(!strcasecmp(mode, "yes") || !strcasecmp(mode, "mst")) broadcast_mode = BMODE_MST; else if(!strcasecmp(mode, "direct")) broadcast_mode = BMODE_DIRECT; else { logger(LOG_ERR, "Invalid broadcast mode!"); return false; } free(mode); } #if !defined(SOL_IP) || !defined(IP_TOS) if(priorityinheritance) logger(LOG_WARNING, "%s not supported on this platform", "PriorityInheritance"); #endif if(!get_config_int(lookup_config(config_tree, "MACExpire"), &macexpire)) macexpire = 600; if(get_config_int(lookup_config(config_tree, "MaxTimeout"), &maxtimeout)) { if(maxtimeout <= 0) { logger(LOG_ERR, "Bogus maximum timeout!"); return false; } } else maxtimeout = 900; if(get_config_int(lookup_config(config_tree, "UDPRcvBuf"), &udp_rcvbuf)) { if(udp_rcvbuf <= 0) { logger(LOG_ERR, "UDPRcvBuf cannot be negative!"); return false; } } if(get_config_int(lookup_config(config_tree, "UDPSndBuf"), &udp_sndbuf)) { if(udp_sndbuf <= 0) { logger(LOG_ERR, "UDPSndBuf cannot be negative!"); return false; } } if(get_config_int(lookup_config(config_tree, "ReplayWindow"), &replaywin_int)) { if(replaywin_int < 0) { logger(LOG_ERR, "ReplayWindow cannot be negative!"); return false; } replaywin = (unsigned)replaywin_int; } if(get_config_string(lookup_config(config_tree, "AddressFamily"), &afname)) { if(!strcasecmp(afname, "IPv4")) addressfamily = AF_INET; else if(!strcasecmp(afname, "IPv6")) addressfamily = AF_INET6; else if(!strcasecmp(afname, "any")) addressfamily = AF_UNSPEC; else { logger(LOG_ERR, "Invalid address family!"); return false; } free(afname); } get_config_bool(lookup_config(config_tree, "Hostnames"), &hostnames); /* Generate packet encryption key */ if(get_config_string (lookup_config(config_tree, "Cipher"), &cipher)) { if(!strcasecmp(cipher, "none")) { myself->incipher = NULL; } else { myself->incipher = EVP_get_cipherbyname(cipher); if(!myself->incipher) { logger(LOG_ERR, "Unrecognized cipher type!"); return false; } } } else myself->incipher = EVP_bf_cbc(); if(myself->incipher) myself->inkeylength = myself->incipher->key_len + myself->incipher->iv_len; else myself->inkeylength = 1; myself->connection->outcipher = EVP_bf_ofb(); if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime)) keylifetime = 3600; keyexpires = now + keylifetime; /* Check if we want to use message authentication codes... */ if(get_config_string(lookup_config(config_tree, "Digest"), &digest)) { if(!strcasecmp(digest, "none")) { myself->indigest = NULL; } else { myself->indigest = EVP_get_digestbyname(digest); if(!myself->indigest) { logger(LOG_ERR, "Unrecognized digest type!"); return false; } } } else myself->indigest = EVP_sha1(); myself->connection->outdigest = EVP_sha1(); if(get_config_int(lookup_config(config_tree, "MACLength"), &myself->inmaclength)) { if(myself->indigest) { if(myself->inmaclength > myself->indigest->md_size) { logger(LOG_ERR, "MAC length exceeds size of digest!"); return false; } else if(myself->inmaclength < 0) { logger(LOG_ERR, "Bogus MAC length!"); return false; } } } else myself->inmaclength = 4; myself->connection->outmaclength = 0; /* Compression */ if(get_config_int(lookup_config(config_tree, "Compression"), &myself->incompression)) { if(myself->incompression < 0 || myself->incompression > 11) { logger(LOG_ERR, "Bogus compression level!"); return false; } } else myself->incompression = 0; myself->connection->outcompression = 0; /* Done */ myself->nexthop = myself; myself->via = myself; myself->status.reachable = true; node_add(myself); graph(); if(strictsubnets) load_all_subnets(); /* Open device */ devops = os_devops; if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) { if(!strcasecmp(type, "dummy")) devops = dummy_devops; else if(!strcasecmp(type, "raw_socket")) devops = raw_socket_devops; else if(!strcasecmp(type, "multicast")) devops = multicast_devops; #ifdef ENABLE_UML else if(!strcasecmp(type, "uml")) devops = uml_devops; #endif #ifdef ENABLE_VDE else if(!strcasecmp(type, "vde")) devops = vde_devops; #endif } if(!devops.setup()) return false; /* Run tinc-up script to further initialize the tap interface */ xasprintf(&envp[0], "NETNAME=%s", netname ? : ""); xasprintf(&envp[1], "DEVICE=%s", device ? : ""); xasprintf(&envp[2], "INTERFACE=%s", iface ? : ""); xasprintf(&envp[3], "NAME=%s", myself->name); execute_script("tinc-up", envp); for(i = 0; i < 4; i++) free(envp[i]); /* Run subnet-up scripts for our own subnets */ subnet_update(myself, NULL, true); /* Open sockets */ if(!do_detach && getenv("LISTEN_FDS")) { sockaddr_t sa; socklen_t salen; listen_sockets = atoi(getenv("LISTEN_FDS")); #ifdef HAVE_UNSETENV unsetenv("LISTEN_FDS"); #endif if(listen_sockets > MAXSOCKETS) { logger(LOG_ERR, "Too many listening sockets"); return false; } for(i = 0; i < listen_sockets; i++) { salen = sizeof sa; if(getsockname(i + 3, &sa.sa, &salen) < 0) { logger(LOG_ERR, "Could not get address of listen fd %d: %s", i + 3, sockstrerror(errno)); return false; } listen_socket[i].tcp = i + 3; #ifdef FD_CLOEXEC fcntl(i + 3, F_SETFD, FD_CLOEXEC); #endif listen_socket[i].udp = setup_vpn_in_socket(&sa); if(listen_socket[i].udp < 0) return false; ifdebug(CONNECTIONS) { hostname = sockaddr2hostname(&sa); logger(LOG_NOTICE, "Listening on %s", hostname); free(hostname); } memcpy(&listen_socket[i].sa, &sa, salen); } } else {
/** * Periodic host heartbeat timer. */ void host_timer(void) { guint count; int missing; host_addr_t addr; guint16 port; host_type_t htype; guint max_nodes; gboolean empty_cache = FALSE; if (in_shutdown || !GNET_PROPERTY(online_mode)) return; max_nodes = settings_is_leaf() ? GNET_PROPERTY(max_ultrapeers) : GNET_PROPERTY(max_connections); count = node_count(); /* Established + connecting */ missing = node_keep_missing(); if (GNET_PROPERTY(host_debug) > 1) g_debug("host_timer - count %u, missing %u", count, missing); /* * If we are not connected to the Internet, apparently, make sure to * connect to at most one host, to avoid using all our hostcache. * Also, we don't connect each time we are called. */ if (!GNET_PROPERTY(is_inet_connected)) { static time_t last_try; if (last_try && delta_time(tm_time(), last_try) < 20) return; last_try = tm_time(); if (GNET_PROPERTY(host_debug)) g_debug("host_timer - not connected, trying to connect"); } /* * Allow more outgoing connections than the maximum amount of * established Gnet connection we can maintain, but not more * than quick_connect_pool_size This is the "greedy mode". */ if (count >= GNET_PROPERTY(quick_connect_pool_size)) { if (GNET_PROPERTY(host_debug) > 1) g_debug("host_timer - count %u >= pool size %u", count, GNET_PROPERTY(quick_connect_pool_size)); return; } if (count < max_nodes) missing -= whitelist_connect(); /* * If we are under the number of connections wanted, we add hosts * to the connection list */ htype = HOST_ULTRA; if ( settings_is_ultra() && GNET_PROPERTY(node_normal_count) < GNET_PROPERTY(normal_connections) && GNET_PROPERTY(node_ultra_count) >= (GNET_PROPERTY(up_connections) - GNET_PROPERTY(normal_connections)) ) { htype = HOST_ANY; } if (hcache_size(htype) == 0) htype = HOST_ANY; if (hcache_size(htype) == 0) empty_cache = TRUE; if (GNET_PROPERTY(host_debug) && missing > 0) g_debug("host_timer - missing %d host%s%s", missing, missing == 1 ? "" : "s", empty_cache ? " [empty caches]" : ""); if (!GNET_PROPERTY(stop_host_get)) { if (missing > 0) { static time_t last_try; unsigned fan, max_pool, to_add; max_pool = MAX(GNET_PROPERTY(quick_connect_pool_size), max_nodes); fan = (missing * GNET_PROPERTY(quick_connect_pool_size))/ max_pool; fan = MAX(1, fan); to_add = GNET_PROPERTY(is_inet_connected) ? fan : (guint) missing; /* * Every so many calls, attempt to ping all our neighbours to * get fresh pongs, in case our host cache is not containing * sufficiently fresh hosts and we keep getting connection failures. */ if ( 0 == last_try || delta_time(tm_time(), last_try) >= HOST_PINGING_PERIOD ) { ping_all_neighbours(); last_try = tm_time(); } /* * Make sure that we never use more connections then the * quick pool or the maximum number of hosts allow. */ if (to_add + count > max_pool) to_add = max_pool - count; if (GNET_PROPERTY(host_debug) > 2) { g_debug("host_timer - connecting - " "add: %d fan:%d miss:%d max_hosts:%d count:%d extra:%d", to_add, fan, missing, max_nodes, count, GNET_PROPERTY(quick_connect_pool_size)); } missing = to_add; if (missing > 0 && (0 == connected_nodes() || host_low_on_pongs)) { gnet_host_t host[HOST_DHT_MAX]; int hcount; int i; hcount = dht_fill_random(host, MIN(UNSIGNED(missing), G_N_ELEMENTS(host))); missing -= hcount; for (i = 0; i < hcount; i++) { addr = gnet_host_get_addr(&host[i]); port = gnet_host_get_port(&host[i]); if (!hcache_node_is_bad(addr)) { if (GNET_PROPERTY(host_debug) > 3) { g_debug("host_timer - UHC pinging and connecting " "to DHT node at %s", host_addr_port_to_string(addr, port)); } /* Try to use the host as an UHC before connecting */ udp_send_ping(NULL, addr, port, TRUE); if (!host_gnutella_connect(addr, port)) { missing++; /* Did not use entry */ } } else { missing++; /* Did not use entry */ } } } while (hcache_size(htype) && missing-- > 0) { if (hcache_get_caught(htype, &addr, &port)) { if (!(hostiles_check(addr) || hcache_node_is_bad(addr))) { if (!host_gnutella_connect(addr, port)) { missing++; /* Did not use entry */ } } else { missing++; /* Did not use entry */ } } } if (missing > 0 && (empty_cache || host_cache_allow_bypass())) { if (!uhc_is_waiting()) { if (GNET_PROPERTY(host_debug)) g_debug("host_timer - querying UDP host cache"); uhc_get_hosts(); /* Get new hosts from UHCs */ } } } } else if (GNET_PROPERTY(use_netmasks)) { /* Try to find better hosts */ if (hcache_find_nearby(htype, &addr, &port)) { if (node_remove_worst(TRUE)) node_add(addr, port, 0); else hcache_add_caught(htype, addr, port, "nearby host"); } } }
void guc_node_add(const host_addr_t addr, guint16 port, guint32 flags) { node_add(addr, port, flags); }
bool add_edge_h(connection_t *c) { edge_t *e; node_t *from, *to; char from_name[MAX_STRING_SIZE]; char to_name[MAX_STRING_SIZE]; char to_address[MAX_STRING_SIZE]; char to_port[MAX_STRING_SIZE]; sockaddr_t address; uint32_t options; int weight; if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" %x %d", from_name, to_name, to_address, to_port, &options, &weight) != 6) { logger(LOG_ERR, "Got bad %s from %s (%s)", "ADD_EDGE", c->name, c->hostname); return false; } /* Check if names are valid */ if(!check_id(from_name) || !check_id(to_name)) { logger(LOG_ERR, "Got bad %s from %s (%s): %s", "ADD_EDGE", c->name, c->hostname, "invalid name"); return false; } if(seen_request(c->buffer)) return true; /* Lookup nodes */ from = lookup_node(from_name); to = lookup_node(to_name); if(tunnelserver && from != myself && from != c->node && to != myself && to != c->node) { /* ignore indirect edge registrations for tunnelserver */ ifdebug(PROTOCOL) logger(LOG_WARNING, "Ignoring indirect %s from %s (%s)", "ADD_EDGE", c->name, c->hostname); return true; } if(!from) { from = new_node(); from->name = xstrdup(from_name); node_add(from); } if(!to) { to = new_node(); to->name = xstrdup(to_name); node_add(to); } /* Convert addresses */ address = str2sockaddr(to_address, to_port); /* Check if edge already exists */ e = lookup_edge(from, to); if(e) { if(e->weight != weight || e->options != options || sockaddrcmp(&e->address, &address)) { if(from == myself) { ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) for ourself which does not match existing entry", "ADD_EDGE", c->name, c->hostname); send_add_edge(c, e); return true; } else { ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) which does not match existing entry", "ADD_EDGE", c->name, c->hostname); edge_del(e); graph(); } } else return true; } else if(from == myself) { ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) for ourself which does not exist", "ADD_EDGE", c->name, c->hostname); contradicting_add_edge++; e = new_edge(); e->from = from; e->to = to; send_del_edge(c, e); free_edge(e); return true; } e = new_edge(); e->from = from; e->to = to; e->address = address; e->options = options; e->weight = weight; edge_add(e); /* Tell the rest about the new edge */ if(!tunnelserver) forward_request(c); /* Run MST before or after we tell the rest? */ graph(); return true; }
bool add_edge_h(meshlink_handle_t *mesh, connection_t *c, const char *request) { edge_t *e; node_t *from, *to; char from_name[MAX_STRING_SIZE]; int from_devclass; char to_name[MAX_STRING_SIZE]; char to_address[MAX_STRING_SIZE]; char to_port[MAX_STRING_SIZE]; int to_devclass; sockaddr_t address; uint32_t options; int weight; if(sscanf(request, "%*d %*x "MAX_STRING" %d "MAX_STRING" "MAX_STRING" "MAX_STRING" %d %x %d", from_name, &from_devclass, to_name, to_address, to_port, &to_devclass, &options, &weight) != 8) { logger(mesh, MESHLINK_ERROR, "Got bad %s from %s (%s)", "ADD_EDGE", c->name, c->hostname); return false; } /* Check if names are valid */ if(!check_id(from_name) || !check_id(to_name)) { logger(mesh, MESHLINK_ERROR, "Got bad %s from %s (%s): %s", "ADD_EDGE", c->name, c->hostname, "invalid name"); return false; } // Check if devclasses are valid if(from_devclass < 0 || from_devclass > _DEV_CLASS_MAX) { logger(mesh, MESHLINK_ERROR, "Got bad %s from %s (%s): %s", "ADD_EDGE", c->name, c->hostname, "from devclass invalid"); return false; } if(to_devclass < 0 || to_devclass > _DEV_CLASS_MAX) { logger(mesh, MESHLINK_ERROR, "Got bad %s from %s (%s): %s", "ADD_EDGE", c->name, c->hostname, "to devclass invalid"); return false; } if(seen_request(mesh, request)) return true; /* Lookup nodes */ from = lookup_node(mesh, from_name); to = lookup_node(mesh, to_name); if(!from) { from = new_node(); from->status.blacklisted = mesh->default_blacklist; from->name = xstrdup(from_name); node_add(mesh, from); } from->devclass = from_devclass; node_write_devclass(mesh, from); if(!to) { to = new_node(); to->status.blacklisted = mesh->default_blacklist; to->name = xstrdup(to_name); node_add(mesh, to); } to->devclass = to_devclass; node_write_devclass(mesh, to); /* Convert addresses */ address = str2sockaddr(to_address, to_port); /* Check if edge already exists */ e = lookup_edge(from, to); if(e) { if(e->weight != weight || e->options != options || sockaddrcmp(&e->address, &address)) { if(from == mesh->self) { logger(mesh, MESHLINK_WARNING, "Got %s from %s (%s) for ourself which does not match existing entry", "ADD_EDGE", c->name, c->hostname); send_add_edge(mesh, c, e); return true; } else { logger(mesh, MESHLINK_WARNING, "Got %s from %s (%s) which does not match existing entry", "ADD_EDGE", c->name, c->hostname); edge_del(mesh, e); graph(mesh); } } else return true; } else if(from == mesh->self) { logger(mesh, MESHLINK_WARNING, "Got %s from %s (%s) for ourself which does not exist", "ADD_EDGE", c->name, c->hostname); mesh->contradicting_add_edge++; e = new_edge(); e->from = from; e->to = to; send_del_edge(mesh, c, e); free_edge(e); return true; } e = new_edge(); e->from = from; e->to = to; e->address = address; e->options = options; e->weight = weight; edge_add(mesh, e); /* Tell the rest about the new edge */ forward_request(mesh, c, request); /* Run MST before or after we tell the rest? */ graph(mesh); return true; }