static void handle_updates(struct datagram *update_port) { char data[DATAGRAM_PAYLOAD_MAX * 2]; char addr[DATAGRAM_ADDRESS_MAX]; char key[LINE_MAX]; int port; int result; struct nvpair *nv; while(1) { result = datagram_recv(update_port, data, DATAGRAM_PAYLOAD_MAX, addr, &port, 0); if(result <= 0) return; data[result] = 0; nv = nvpair_create(); nvpair_parse(nv, data); nvpair_insert_string(nv, "address", addr); nvpair_insert_integer(nv, "lastheardfrom", time(0)); /* If the server reports unbelievable numbers, simply reset them */ if(max_server_size > 0) { INT64_T total = nvpair_lookup_integer(nv, "total"); INT64_T avail = nvpair_lookup_integer(nv, "avail"); if(total > max_server_size || avail > max_server_size) { nvpair_insert_integer(nv, "total", max_server_size); nvpair_insert_integer(nv, "avail", max_server_size); } } /* Do not believe the server's reported name, just resolve it backwards. */ char name[DOMAIN_NAME_MAX]; if(domain_name_cache_lookup_reverse(addr, name)) { nvpair_insert_string(nv, "name", name); } else if (nvpair_lookup_string(nv, "name") == NULL) { /* If rDNS is unsuccessful, then we use the name reported if given. * This allows for hostnames that are only valid in the subnet of * the reporting server. Here we set the "name" field to the IP * Address, addr, because it was not set by the reporting server. */ nvpair_insert_string(nv, "name", addr); } make_hash_key(nv, key); if(logfile) { if(!nvpair_database_lookup(table,key)) { nvpair_print_text(nv,logfile); fflush(logfile); } } nvpair_database_insert(table, key, nv); debug(D_DEBUG, "received udp update from %s", key); } }
static void handle_update( const char *addr, int port, const char *raw_data, int raw_data_length, const char *protocol ) { char key[LINE_MAX]; unsigned long data_length; struct jx *j; // If the packet starts with Control-Z (0x1A), it is compressed, // so uncompress it to data[]. Otherwise just copy to data[];. if(raw_data[0]==0x1A) { data_length = sizeof(data); int success = uncompress((Bytef*)data,&data_length,(const Bytef*)&raw_data[1],raw_data_length-1); if(success!=Z_OK) { debug(D_DEBUG,"warning: %s:%d sent invalid compressed data (ignoring it)\n",addr,port); return; } } else { memcpy(data,raw_data,raw_data_length); data_length = raw_data_length; } // Make sure the string data is null terminated. data[data_length] = 0; // Once uncompressed, if it starts with a bracket, // then it is JX/JSON, otherwise it is the legacy nvpair format. if(data[0]=='{') { j = jx_parse_string(data); if(!j) { debug(D_DEBUG,"warning: %s:%d sent invalid JSON data (ignoring it)\n%s\n",addr,port,data); return; } if(!jx_is_constant(j)) { debug(D_DEBUG,"warning: %s:%d sent non-constant JX data (ignoring it)\n%s\n",addr,port,data); jx_delete(j); return; } } else { struct nvpair *nv = nvpair_create(); if(!nv) return; nvpair_parse(nv, data); j = nvpair_to_jx(nv); nvpair_delete(nv); } jx_insert_string(j, "address", addr); jx_insert_integer(j, "lastheardfrom", time(0)); /* If the server reports unbelievable numbers, simply reset them */ if(max_server_size > 0) { INT64_T total = jx_lookup_integer(j, "total"); INT64_T avail = jx_lookup_integer(j, "avail"); if(total > max_server_size || avail > max_server_size) { jx_insert_integer(j, "total", max_server_size); jx_insert_integer(j, "avail", max_server_size); } } /* Do not believe the server's reported name, just resolve it backwards. */ char name[DOMAIN_NAME_MAX]; if(domain_name_cache_lookup_reverse(addr, name)) { /* Special case: Prior bug resulted in multiple name entries in logged data. When removing the name property, keep looking until all items are removed. */ struct jx *jname = jx_string("name"); struct jx *n; while((n=jx_remove(j,jname))) { jx_delete(n); } jx_delete(jname); jx_insert_string(j,"name",name); } else if (jx_lookup_string(j, "name") == NULL) { /* If rDNS is unsuccessful, then we use the name reported if given. * This allows for hostnames that are only valid in the subnet of * the reporting server. Here we set the "name" field to the IP * Address, addr, because it was not set by the reporting server. */ jx_insert_string(j, "name", addr); } make_hash_key(j, key); if(logfile) { if(!jx_database_lookup(table,key)) { jx_print_stream(j,logfile); fprintf(logfile,"\n"); fflush(logfile); } } jx_database_insert(table, key, j); debug(D_DEBUG, "received %s update from %s",protocol,key); }