int jx_pair_is_constant( struct jx_pair *p ) { if(!p) return 1; return jx_is_constant(p->key) && jx_is_constant(p->value) && jx_pair_is_constant(p->next); }
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); }
int jx_item_is_constant( struct jx_item *i ) { if(!i) return 1; return jx_is_constant(i->value) && jx_item_is_constant(i->next); }