void handle_message(cjdnsadmin_t *adm, char *buffer, ssize_t len) { // TODO: fix memory leak struct bencode *b = ben_decode(buffer, len); if (!b) { fprintf(stderr, "bencode error: %lu\n",len); printf("message from cjdns: \"%*s\"\n", (int)len, buffer); return; } // Get IPs struct bencode *table = ben_dict_get_by_str(b, "routingTable"); size_t i, num_items = ben_list_len(table); for (i = 0; i < num_items; i++) { struct bencode *item = ben_list_get(table, i); struct bencode *ip = ben_dict_get_by_str(item, "ip"); if (ben_is_str(ip)) { const char *ip_str = ben_str_val(ip); if (adm->on_found_ip) { (*adm->on_found_ip)(adm->on_found_ip_obj, ip_str); } } } // check if there is more struct bencode *more = ben_dict_get_by_str(b, "more"); int more_int = more && ben_is_int(more) && ben_int_val(more); if (more_int == 1) { // get the next page of the routing table adm->fetch_peers_page++; cjdnsadmin_fetch_peers(adm); } else { // start from the first page next time adm->fetch_peers_page = 0; } ben_free(b); }
void p2p_decode(UCHAR * bencode, size_t bensize, IP * from) { BEN *packet = NULL; BEN *y = NULL; /* Parse request */ packet = ben_dec(bencode, bensize); if (packet == NULL) { info(_log, from, "Decoding UDP packet failed:"); return; } else if (packet->t != BEN_DICT) { info(_log, from, "UDP packet is not a dictionary:"); ben_free(packet); return; } /* Type of message */ y = ben_dict_search_str(packet, "y"); if (!ben_is_str(y) || ben_str_i(y) != 1) { info(_log, from, "Message type missing or broken:"); ben_free(packet); return; } mutex_block(_main->work->mutex); switch (*y->v.s->s) { case 'q': p2p_request(packet, from); break; case 'r': p2p_reply(packet, from); break; case 'e': p2p_error(packet, from); break; default: info(_log, from, "Drop invalid message type '%c' from", *y->v.s->s); } mutex_unblock(_main->work->mutex); ben_free(packet); }
BEN *ben_dict_search_str(BEN * node, const char *buffer) { BEN *result = NULL; BEN *key = ben_init(BEN_STR); ben_str(key, (UCHAR *) buffer, strlen(buffer)); result = ben_dict_search_key(node, key); ben_free(key); return result; }
void tuple_free(TUPLE * tuple) { ben_free(tuple->key); ben_free(tuple->val); myfree(tuple); }
void p2p_decrypt(UCHAR * bencode, size_t bensize, IP * from) { BEN *packet = NULL; BEN *salt = NULL; BEN *aes = NULL; struct obj_str *plain = NULL; /* Parse request */ packet = ben_dec(bencode, bensize); if (!ben_is_dict(packet)) { info(_log, from, "Decoding AES packet failed:"); ben_free(packet); return; } /* Salt */ salt = ben_dict_search_str(packet, "s"); if (!ben_is_str(salt) || ben_str_i(salt) != AES_IV_SIZE) { info(_log, from, "Salt missing or broken:"); ben_free(packet); return; } /* Encrypted AES message */ aes = ben_dict_search_str(packet, "a"); if (!ben_is_str(aes) || ben_str_i(aes) <= 2) { info(_log, from, "AES message missing or broken:"); ben_free(packet); return; } /* Decrypt message */ plain = aes_decrypt(ben_str_s(aes), ben_str_i(aes), ben_str_s(salt), _main->conf->key, strlen(_main->conf->key)); if (plain == NULL) { info(_log, from, "Decoding AES message failed:"); ben_free(packet); return; } /* AES packet too small */ if (plain->i < SHA1_SIZE) { ben_free(packet); str_free(plain); info(_log, from, "AES packet contains less than 20 bytes:"); return; } /* Validate bencode */ if (!ben_validate(plain->s, plain->i)) { ben_free(packet); str_free(plain); info(_log, from, "AES packet contains broken bencode:"); return; } /* Parse message */ p2p_decode(plain->s, plain->i, from); /* Free */ ben_free(packet); str_free(plain); }
static void on_written(uv_udp_send_t* req, int status) { CHECK(status); struct bencode* b = req->data; ben_free(b); }