//Create the name of the node //If the id contains a ',' marking the start of the domain //the domain is ommitted void nodes_setNameFromID(struct node *n) { //n->name is of size n->id ub_assert(sizeof(n->name) >= sizeof(n->id)); strcpy(n->name,n->id); char *s = strchr(n->name,','); if( s != NULL){ *s = 0; ub_assert(sizeof(n->domain) >= sizeof(n->id)); strcpy(n->domain,++s); }else{ //there was no domain in the id syslog(LOG_WARNING,"ill formated id for this node: %s\n",n->id); n->domain[0] = 0; } if( n->avahiname[0] == 0 ){ //TODO: check buffer strcpy(n->avahiname, n->name); } if( n->hostname[0] == 0 ){ //TODO: check buffer strcpy(n->hostname, n->name); strcat(n->hostname, ".local"); } }
void nodes_deactivateNode(struct node *node) { ub_assert(node->free == FALSE); // syslog(LOG_WARNING,"nodes.c: warning: trying to"); // syslog(LOG_WARNING,"deactivate a free node!\n"); node->active = FALSE; }
void address6_createAddress(struct node *n) { syslog(LOG_INFO,"adding address for %s\n",n->id); if( n->netadr == NULL ){ n->netadr = address6db_getFreeAddr(n->id); ub_assert(n->netadr); } avahi_removeNode(n); interface_removeAddress(n); avahi_registerNode(n); interface_createAddress(n); }
static gboolean net_createUDPSocket(struct node *n, guint classid) { GError * err = NULL; GInetAddress *addr = n->netadr; guint port = 2300+n->classes[classid]; syslog(LOG_DEBUG,"net_createSockets: Creating udp socket on port %u\n", port); GSocketAddress * sa = g_inet_socket_address_new(addr,port); n->udpsockets[classid].n = n; GSocket *socket = g_socket_new(G_SOCKET_FAMILY_IPV6, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, NULL); ub_assert(socket != NULL); if( g_socket_bind(socket, sa, TRUE, &err) == FALSE ){ syslog(LOG_WARNING, "net_createSockets: Error while binding udp socket: %s\n", err->message); g_error_free(err); return FALSE; } GSource *source = g_socket_create_source(socket, G_IO_IN, NULL); ub_assert(source != NULL); g_source_set_callback(source, (GSourceFunc)udp_read, &(n->udpsockets[classid]) , NULL); g_source_attach(source, g_main_context_default()); n->udpsockets[classid].socket = socket; n->udpsockets[classid].source = source; n->udpsockets[classid].socketaddress = sa; n->udpsockets[classid].classid = classid; //broadcast_addService(n->classes[classid]); return TRUE; }
void dirserver_init(gchar* baseaddress) { syslog(LOG_DEBUG,"dirserver_init: starting directory server"); services = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); dirserversocket = multicast_createSocket("directoryserver", 2323, &sa); if( socket != NULL){ syslog(LOG_DEBUG,"dirserver_init: socket open"); GSource *source = g_socket_create_source(dirserversocket, G_IO_IN, NULL); ub_assert(source != NULL); g_source_set_callback(source, (GSourceFunc)dirserver_read, NULL, NULL); g_source_attach(source, g_main_context_default()); }else{ syslog(LOG_WARNING, "directory-server.c: warning: could not create socket"); } GError * e = NULL; GInetAddress *net_base = g_inet_address_new_from_string(baseaddress); if( net_base == NULL ){ syslog(LOG_ERR, "dirserver_init: Could not parse base address"); return; } //set up http tcp listener GSocketAddress *httpsa = g_inet_socket_address_new(net_base,8080); syslog(LOG_DEBUG,"dirserver_init: Creating tcp socket on port 8080\n"); GSocketService *gss = g_socket_service_new(); //TODO: save a reference to the gss somewhere if( g_socket_listener_add_address(G_SOCKET_LISTENER(gss), httpsa, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP, NULL, NULL, &e) == FALSE ){ syslog(LOG_WARNING, "dirserver_init: error while creating socket listener: %s\n",e->message); g_error_free(e); } g_signal_connect(gss, "incoming", G_CALLBACK(dirserver_tcp_listener),NULL); g_socket_service_start(gss); g_timeout_add_seconds(1,dirserver_tick,NULL); }
GSocket *multicast_createSocket(gchar *interface, gchar *groupaddress, guint port, GSocketAddress **sa) { GError *err = NULL; GInetAddress *addr = g_inet_address_new_from_string(groupaddress); *sa = g_inet_socket_address_new(addr,port); GSocket *socket = g_socket_new(G_SOCKET_FAMILY_IPV6, G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, NULL); ub_assert(socket != NULL); int on = 1; setsockopt(g_socket_get_fd(socket), SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if( g_socket_bind(socket, *sa, TRUE, &err) == FALSE ){ syslog(LOG_ERR, "net_createSockets: Error while binding udp socket: %s\n", err->message); g_error_free(err); g_object_unref(*sa); g_object_unref(socket); return NULL; } struct addrinfo *resmulti; struct ipv6_mreq mreq; mreq.ipv6mr_interface = if_nametoindex(interface); gchar *tmp = g_inet_address_to_string(addr); syslog(LOG_DEBUG,"using address: %s\n",tmp); int ret = getaddrinfo(tmp, NULL, NULL, &resmulti); g_free(tmp); if( ret ){ syslog(LOG_ERR,"net_multicast.c: %s", gai_strerror(ret)); g_object_unref(*sa); g_object_unref(socket); return NULL; } mreq.ipv6mr_multiaddr = ((struct sockaddr_in6 *)resmulti->ai_addr)->sin6_addr; setsockopt(g_socket_get_fd(socket), IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq)); return socket; }
//Make sure data is sanatized static void dirserver_newMCData(const char *data, GSocketAddress *src) { struct json_object *json_tmp; struct json_object *json = json_tokener_parse(data); ub_assert(json != NULL); if( is_error(json) ){ syslog(LOG_DEBUG,"dirserver_newMCData: invalid json"); return; } json_tmp = json_object_object_get(json, "cmd"); if( json_tmp == NULL || is_error(json_tmp) ){ syslog(LOG_DEBUG,"dirserver_newMCData: no cmd field in json"); return; } if( json_object_get_type(json_tmp) != json_type_string ){ syslog(LOG_DEBUG,"dirserver_newMCData: no cmd field is not a string"); return; } enum commandlist cmd = dirserver_parseCommand( json_object_get_string(json_tmp)); json_object_object_del(json, "cmd"); switch( cmd ){ case DISCOVER_DIRECTORY: dirserver_announce(dirserver_getJsonString(json, "service-type",NULL), dirserver_getJsonString(json, "protocol",NULL), dirserver_getJsonBool(json, "local-only",FALSE), src); break; case UPDATE_SERVICE: dirserver_updateServiceCmd(json); break; case DELETE_SERVICE: dirserver_deleteServiceCmd(json); case NO_COMMAND: break; }; json_object_put(json); }
void busmgt_inpacket(struct ubpacket* p) { //TODO: check len of id buffer gchar id[100]; guchar classes[4]; struct node * n; uint16_t interval; switch(p->data[0]){ //A new node tries to get an address case 'D': interval = (p->data[1]<<8) + p->data[2]; if( p->len > sizeof(id) ) return; memcpy(classes, p->data+3, 4); memcpy(id, p->data+7, p->len-7); id[p->len-7] = 0; syslog(LOG_INFO,"busmgt: got discover from %s\n", id); //n = nodes_getNodeById(id); //if( n == NULL ){ syslog(LOG_DEBUG,"busmgt: creating new node\n"); n = mgt_createNode(TYPE_NODE, id); if( n == NULL){ syslog(LOG_WARNING,"busmgt: no free nodes available. please wait.\n"); return; } ub_assert(n->busadr != 0); syslog(LOG_DEBUG,"busmgt: new bus address: %u\n",n->busadr); //}else{ // syslog(LOG_DEBUG,"busmgt: old bus address: %u\n",n->busadr); //} //TODO: check if it is possible for the bus to query //the node at this interval busmgt_setClasses(n, classes, sizeof(classes)); busmgt_setQueryInterval(n->busadr, interval); busmgt_setAddress(n->busadr, id); n->state = NODE_IDENTIFY; n->timeout = config.nodetimeout; break; //The node confirms an address case 'I': //TODO:log error if( sizeof(id) < p->len ) return; memcpy(id, p->data+1, p->len-1); id[p->len-1] = 0; syslog(LOG_INFO,"busmgt: got identify from %s\n", id); n = nodes_getNodeById(id); if( n == NULL ){ syslog(LOG_WARNING,"busmgt: unkown node\n"); busmgt_sendReset(p->src); return; } if( n->state != NODE_IDENTIFY ){ syslog(LOG_WARNING,"busmgt: node in wrong state"); busmgt_sendReset(p->src); return; } //send the OK if we have our interface ready if( n->netup == TRUE){ syslog(LOG_DEBUG,"busmgt: node known\n"); busmgt_sendMulticastGroups(n); busmgt_sendOK(p->src); //n->state = NODE_IDENTIFY; n->state = NODE_NORMAL; n->timeout = config.nodetimeout; n->busup = TRUE; nodes_activateNode(n); }else{ syslog(LOG_INFO,"IPv6 interface not up yet\n"); } break; case 'V': n = nodes_getNodeByBusAdr(p->src); //TODO: check len of p->data memcpy(n->version, p->data+2, p->len-2); break; //a keep alive packet case 'A': n = nodes_getNodeByBusAdr(p->src); if( n == NULL ){ busmgt_sendReset(p->src); return; } //reset the timeout n->timeout = config.nodetimeout; break; //the bridge id case 'B': //TODO: check len of p->data memcpy(classes, p->data+1, 4); memcpy(id, p->data+5, p->len-5); id[p->len-5] = 0; syslog(LOG_INFO,"busmgt: bridge id %s\n", id); mgt_createBridge(id); n = nodes_getNodeByBusAdr(p->src); syslog(LOG_DEBUG,"bus addr of new node is %d\n",n->busadr); busmgt_setClasses(n, classes, sizeof(classes)); busmgt_sendMulticastGroups(n); busmgt_sendOK(p->src); n->state = NODE_NORMAL; n->timeout = config.nodetimeout; n->busup = TRUE; syslog(LOG_INFO,"bus is up\n"); break; }; }