static void handle_vmsg_dummy(const struct gnutella_header *header, const char *data, size_t size) { (void) header; handle_extension(&data[8], size - 8); }
static void handle_vmsg_time_sync_reply(const struct gnutella_header *header, const char *data, size_t size) { if (size < 17) { printf("Too short: %s\n", escape_buffer(data, size)); } else { bool used_ntp = data[8] & 0x1; char buf[32], *p; printf("NTP: %s\n", used_ntp ? "yes" : "no"); p = print_iso8601_date(buf, sizeof buf, peek_be32(&header->guid.data[0])); *p = '\0'; printf("T1: %s (%lu us)\n", buf, (unsigned long) peek_be32(&header->guid.data[4])); p = print_iso8601_date(buf, sizeof buf, peek_be32(&data[9])); *p = '\0'; printf("T2: %s (%lu us)\n", buf, (unsigned long) peek_be32(&data[13])); p = print_iso8601_date(buf, sizeof buf, peek_be32(&header->guid.data[8])); *p = '\0'; printf("T3: %s (%lu us)\n", buf, (unsigned long) peek_be32(&header->guid.data[12])); if (size > 17) { handle_extension(&data[17], size - 17); } } }
static void handle_vmsg_port(const struct gnutella_header *header, const char *data, size_t size) { const char *base = &data[8]; const size_t len = size - 8; (void) header; if (len == 2) { printf("Port: %u\n", peek_le16(base)); } else { handle_extension(base, len); } }
static void handle_vmsg_addr_port(const struct gnutella_header *header, const char *data, size_t size) { const char *base = &data[8]; const size_t len = size - 8; (void) header; if (len == 6) { printf("Address: %s\n", net_addr_port_to_string( net_addr_peek_ipv4(&base[0]), peek_le16(&base[4]))); } else { handle_extension(base, len); } }
static void handle_vmsg_oob_reply(const struct gnutella_header *header, const char *data, size_t size) { (void) header; if (size < 9) { printf("Too short: %s\n", escape_buffer(data, size)); } else { printf("Hits: %u\n", (uint8_t) data[8]); if (size > 9) { handle_extension(&data[9], size - 9); } } }
static void handle_pong(const char * const data, const size_t size) { if (size < 14) { printf("Too short: %s\n", escape_buffer(data, size)); } else { printf("Source: %s\n", net_addr_port_to_string(net_addr_peek_ipv4(&data[2]), peek_le16(data))); printf("Files: %lu\n", (unsigned long) peek_le32(&data[6])); printf("Volume: %lu KiB\n", (unsigned long) peek_le32(&data[10])); if (size > 14) { handle_extension(&data[14], size - 14); } } }
static void handle_vmsg_time_sync_request(const struct gnutella_header *header, const char *data, size_t size) { (void) header; if (size < 9) { printf("Too short: %s\n", escape_buffer(data, size)); } else { bool used_ntp = data[8] & 0x1; printf("NTP: %s\n", used_ntp ? "yes" : "no"); if (size > 9) { handle_extension(&data[9], size - 9); } } }
static void handle_push(const char *data, size_t size) { if (size < 26) { fprintf(stderr, "handle_push(): Too small\n"); return; } printf("ServentID: %08lx-%08lx-%08lx-%08lx\n", (unsigned long) peek_be32(&data[0]), (unsigned long) peek_be32(&data[4]), (unsigned long) peek_be32(&data[8]), (unsigned long) peek_be32(&data[12])); printf("Index: %lu\n", (unsigned long) peek_le32(&data[16])); printf("Target: %s\n", net_addr_port_to_string(net_addr_peek_ipv4(&data[20]), peek_le16(&data[24]))); handle_extension(&data[26], size - 26); }
static void handle_vmsg_priv(const struct gnutella_header *header, const char *data, size_t size) { if (size < 8) { printf("Too short: %s\n", escape_buffer(data, size)); } else { char vendor[32], *p; size_t vendor_size = sizeof vendor; struct vmsg_head vh; unsigned i; p = append_escaped_chars(vendor, &vendor_size, data, 4); *p = '\0'; vh.vendor = peek_be32(&data[0]); vh.selector = peek_le16(&data[4]); vh.version = peek_le16(&data[6]); printf("%s/%uv%u", vendor, vh.selector, vh.version); for (i = 0; i < ARRAY_LEN(vmsg_table); i++) { if ( vmsg_table[i].vendor == vh.vendor && vmsg_table[i].selector == vh.selector && vmsg_table[i].version == vh.version ) { printf(" %s\n", vmsg_table[i].name); vmsg_table[i].handler(header, data, size); break; } } if (ARRAY_LEN(vmsg_table) == i) { printf("\n"); handle_extension(&data[8], size - 8); } } }
static void handle_options(int argc, char *argv[], Font *fnt) { register int lastext; register int i; size_t l; int arginc; char *temp; char c; char *vpl_name = NULL; Boolean have_capheight = 0; Boolean have_sfd = 0; int sfd_begin, postfix_begin; int base_name; stringlist* sl; /* scan first whether the -q switch is set */ for (i = 1; i < argc; i++) if (argv[i][0] == '-' && argv[i][1] == 'q') quiet = True; if (!quiet) printf("This is %s\n", ident); /* Make VPL file identical to that created under Unix */ fnt->titlebuf = (char *)mymalloc(strlen(progname) + strlen(argv[1]) + 1 + 1); sprintf(fnt->titlebuf, "%s %s", progname, argv[1]); /* * TrueType font name. */ fnt->ttfname = newstring(argv[1]); /* * The other arguments. We delay the final processing of some switches * until the tfm font name has been scanned -- if it contains two `@'s, * many switches are ignored. */ while (argc > 2 && *argv[2] == '-') { arginc = 2; i = argv[2][1]; switch (i) { case 'v': makevpl = 1; if (argc <= 3) oops("Missing parameter for -v option."); if (vpl_name) free(vpl_name); vpl_name = newstring(argv[3]); handle_extension(&vpl_name, ".vpl"); break; case 'V': makevpl = 2; if (argc <= 3) oops("Missing parameter for -V option."); if (vpl_name) free(vpl_name); vpl_name = newstring(argv[3]); handle_extension(&vpl_name, ".vpl"); break; case 'f': if (argc <= 3) oops("Missing parameter for -f option."); if (sscanf(argv[3], "%lu", &(fnt->fontindex)) == 0) oops("Invalid font index."); fnt->fontindexparam = argv[3]; break; case 'E': if (argc <= 3) oops("Missing parameter for -E option."); if (sscanf(argv[3], "%hu", &(fnt->eid)) == 0) oops("Invalid encoding ID."); fnt->eidparam = argv[3]; break; case 'P': if (argc <= 3) oops("Missing parameter for -P option."); if (sscanf(argv[3], "%hu", &(fnt->pid)) == 0) oops("Invalid platform ID."); fnt->pidparam = argv[3]; break; case 'e': if (argc <= 3) oops("Missing parameter for -e option."); if (sscanf(argv[3], "%f", &(fnt->efactor)) == 0 || fnt->efactor < 0.01) oops("Bad extension factor."); fnt->efactorparam = argv[3]; break; case 'c': if (argc <= 3) oops("Missing parameter for -c option."); have_capheight = True; if (sscanf(argv[3], "%f", &(fnt->capheight)) == 0) fnt->capheight = 0; break; case 's': if (argc <= 3) oops("Missing parameter for -s option."); if (sscanf(argv[3], "%f", &(fnt->slant)) == 0) oops("Bad slant parameter."); fnt->slantparam = argv[3]; break; case 'p': if (argc <= 3) oops("Missing parameter for -p option."); if (fnt->inencname) free(fnt->inencname); fnt->inencname = newstring(argv[3]); break; case 'T': if (argc <= 3) oops("Missing parameter for -T option."); if (fnt->inencname) free(fnt->inencname); if (fnt->outencname) free(fnt->outencname); fnt->inencname = newstring(argv[3]); fnt->outencname = newstring(argv[3]); break; case 't': if (argc <= 3) oops("Missing parameter for -T option."); if (fnt->outencname) free(fnt->outencname); fnt->outencname = newstring(argv[3]); break; case 'r': if (argc <= 4) oops("Not enough parameters for -r option."); sl = newstringlist(); sl->old_name = newstring(argv[3]); sl->new_name = newstring(argv[4]); sl->single_replacement = True; sl->next = fnt->replacements; fnt->replacements = sl; arginc = 3; break; case 'R': if (argc <= 3) oops("Missing parameter for -R option."); if (fnt->replacementname) free(fnt->replacementname); fnt->replacementname = newstring(argv[3]); break; case 'y': if (argc <= 3) oops("Missing parameter for -y option."); if (sscanf(argv[3], "%f", &(fnt->y_offset)) == 0) oops("Invalid y-offset."); fnt->y_offsetparam = argv[3]; break; case 'O': forceoctal = True; arginc = 1; break; case 'n': fnt->PSnames = Yes; arginc = 1; break; case 'N': fnt->PSnames = Only; arginc = 1; break; case 'u': pedantic = True; arginc = 1; break; case 'q': quiet = True; arginc = 1; break; case 'L': if (argc <= 3) oops("Missing parameter for -L option."); if (fnt->ligname) free(fnt->ligname); fnt->ligname = newstring(argv[3]); fnt->subfont_ligs = True; break; case 'l': fnt->subfont_ligs = True; arginc = 1; break; case 'w': fnt->write_enc = True; arginc = 1; break; case 'x': fnt->rotate = True; arginc = 1; break; case 'o': if (argc <= 3) oops("Missing parameter for -o option."); if (vpl_name) free(vpl_name); vpl_name = newstring(argv[3]); handle_extension(&vpl_name, ".ovp"); break; default: if (argc <= 3 || argv[3][0] == '-') { warning("Unknown option `%s' will be ignored.\n", argv[2]); arginc = 1; } else warning("Unknown option `%s %s' will be ignored.\n", argv[2], argv[3]); } for (i = 0; i < arginc; i++) { l = strlen(fnt->titlebuf); fnt->titlebuf = (char *)myrealloc((void *)fnt->titlebuf, l + strlen(argv[2]) + 1 + 1); sprintf(fnt->titlebuf + strlen(fnt->titlebuf), " %s", argv[2]); argv++; argc--; } } /* Read replacement glyph name file */ get_replacements(fnt); if (argc > 3 || (argc == 3 && *argv[2] == '-')) oops("Need at most two non-option arguments."); /* * The tfm file name. */ if (argc == 2) temp = newstring(fnt->ttfname); else { temp = newstring(argv[2]); l = strlen(fnt->titlebuf); fnt->titlebuf = (char *)myrealloc((void *)fnt->titlebuf, l + strlen(argv[2]) + 1 + 1); sprintf(fnt->titlebuf + strlen(fnt->titlebuf), " %s", argv[2]); } handle_sfd(temp, &sfd_begin, &postfix_begin); if (sfd_begin > -1) { have_sfd = True; i = sfd_begin - 2; } else i = strlen(temp) - 1; /* * Now we search the beginning of the name without directory. */ for (; i >= 0; i--) if (temp[i] == '/' || temp[i] == ':' || temp[i] == '\\') break; base_name = i + 1; /* * We store the path (with the final directory separator). */ if (base_name > 0) { c = temp[base_name]; temp[base_name] = '\0'; fnt->tfm_path = newstring(temp); temp[base_name] = c; } if (have_sfd) { /* the prefix and the sfd file name */ if (temp[base_name]) fnt->outname = newstring(temp + base_name); fnt->sfdname = newstring(temp + sfd_begin); } else postfix_begin = base_name; /* * Get the extension. */ lastext = -1; for (i = postfix_begin; temp[i]; i++) if (temp[i] == '.') lastext = i; if (argc == 2 && lastext >= 0) { temp[lastext] = '\0'; /* remove TTF file extension */ lastext = -1; } if (lastext == -1) fnt->tfm_ext = newstring(".tfm"); else { fnt->tfm_ext = newstring(temp + lastext); temp[lastext] = '\0'; } if (have_sfd) { if (temp[postfix_begin]) fnt->outname_postfix = newstring(temp + postfix_begin); } else { if (temp[base_name]) fnt->outname = newstring(temp + base_name); else oops("Invalid tfm file name."); } /* * Now we can process the remaining parameters. */ if (have_sfd) { if (makevpl) { warning("Ignoring `-v' and `-V' switches for subfonts."); makevpl = 0; } if (vpl_name) if ((fnt->vplout = fopen(vpl_name, "wb")) == NULL) oops("Cannot open ovp output file."); if (have_capheight) warning("Ignoring `-c' switch for subfonts."); if (fnt->inencname || fnt->outencname) { warning("Ignoring `-p', `-t', and `-T' switches for subfonts."); fnt->inencname = NULL; fnt->outencname = NULL; } if (fnt->y_offsetparam && !fnt->rotate) warning("Ignoring `-y' switch for non-rotated subfonts."); if (fnt->PSnames) { warning("Ignoring `-n' or '-N' switch for subfonts."); fnt->PSnames = No; } init_sfd(fnt, True); } else { if (have_capheight && fnt->capheight < 0.01) oops("Bad small caps height."); if (vpl_name) if ((fnt->vplout = fopen(vpl_name, "wb")) == NULL) oops("Cannot open vpl output file."); if (fnt->subfont_ligs) { warning("Ignoring `-l' switch for non-subfont."); fnt->subfont_ligs = False; } if (fnt->rotate) { warning("Ignoring `-x' switch for non-subfont."); fnt->rotate = False; } if (fnt->write_enc) { warning("Ignoring `-w' switch for non-subfont."); fnt->write_enc = False; } if (fnt->y_offsetparam) warning("Ignoring `-y' switch for non-subfont."); } if (fnt->PSnames == Only) { if (fnt->pidparam || fnt->eidparam) { warning("Ignoring `-P' and `-E' options if `-N' switch is selected."); fnt->pidparam = NULL; fnt->eidparam = NULL; } } if (vpl_name) free(vpl_name); free(temp); }
static void handle_ping(const char * const data, const size_t size) { handle_extension(data, size); }
static void handle_query(const struct gnutella_header *header, const char * const data, const size_t size) { const char *end; if (size < 2) { printf("Too short: %s\n", escape_buffer(data, size)); } else { uint16_t flags; int swapped = 0; flags = peek_be16(data); if (!(flags & QUERY_F_MARK)) { uint16_t mask = QUERY_F_MARK | QUERY_F_GGEP_H | QUERY_F_LEAF_GUIDED; uint16_t reversed; /* Try to decode endian swapped flags as emitted by RAZA */ reversed = peek_le16(data); if ((reversed & mask) == mask) { swapped = 1; flags = reversed; } } if (flags & QUERY_F_MARK) { int is_firewalled = flags & QUERY_F_FIREWALLED; int want_xml = flags & QUERY_F_WANT_XML; int leaf_guided = flags & QUERY_F_LEAF_GUIDED; int ggep_h = flags & QUERY_F_GGEP_H; int is_oob = flags & QUERY_F_OOB; int rudp_supp = flags & QUERY_F_RUDP; int bit8 = flags & QUERY_F_BIT8; printf("Flags: %s%s%s%s%s%s%s%s\n" , is_firewalled ? "firewalled " : "" , want_xml ? "XML " : "" , leaf_guided ? "leaf-guided " : "" , ggep_h ? "GGEP/H " : "" , is_oob ? "OOB " : "" , rudp_supp ? "RUDP " : "" , bit8 ? "bit8 " : "" , swapped ? "[SWAPPED]" : "" ); if (is_oob) { printf("OOB address: %s\n", net_addr_port_to_string(net_addr_peek_ipv4(&header->guid.data[0]), peek_le16(&header->guid.data[13])) ); } } else { printf("Flags: 0x%04X\n", flags); } end = memchr(&data[2], '\0', size - 2); if (end) { end++; } else { end = &data[size]; } printf("Query: \"%s\"\n", escape_buffer(&data[2], (end - &data[2]) - 1)); if (&data[size] != end) { size_t ext_len; ext_len = &data[size] - end; if ('\0' == data[size - 1]) { ext_len--; } handle_extension(end, ext_len); } } }
static void handle_qhit(const char *data, size_t size) { const struct gnutella_qhit_header *header; const struct gnutella_guid *guid; const struct gnutella_qhit_item *item; size_t guid_offset = size - sizeof *guid; unsigned hits; size_t pos; RUNTIME_ASSERT(size <= GNUTELLA_MAX_PAYLOAD); if (size < sizeof *header) { fprintf(stderr, "handle_qhit(): Too little payload for header.\n"); return; } header = cast_to_const_void_ptr(data); hits = (unsigned char) header->hits; printf("Hits: %u\n", hits); printf("Address: %s\n", net_addr_port_to_string(net_addr_peek_ipv4(cast_to_const_char_ptr(header->addr)), peek_le16(header->port))); printf("Speed: %lu\n", (unsigned long) peek_le32(header->speed)); if (size < sizeof *header + sizeof *guid) { fprintf(stderr, "handle_qhit(): Insufficient payload for query hit.\n"); return; } if (size >= sizeof *header + sizeof *guid) { guid = cast_to_const_void_ptr(&data[guid_offset]); printf("Servent ID: %08lx-%08lx-%08lx-%08lx\n", (unsigned long) peek_be32(&guid->data[0]), (unsigned long) peek_be32(&guid->data[4]), (unsigned long) peek_be32(&guid->data[8]), (unsigned long) peek_be32(&guid->data[12])); } printf("----\n"); pos = sizeof *header; for (/* NOTHING */; hits > 0; hits--) { const char *nul_ptr; if (pos >= guid_offset || guid_offset - pos < sizeof *item + 2) break; item = cast_to_const_void_ptr(&data[pos]); printf("Index: %lu\n", (unsigned long) peek_le32(item->index)); printf("Size: %lu\n", (unsigned long) peek_le32(item->size)); pos += sizeof *item; nul_ptr = memchr(&data[pos], 0, guid_offset - pos); if (!nul_ptr) { fprintf(stderr, "handle_qhit(): Non-terminated filename.\n"); return; } else { size_t len; len = (nul_ptr - &data[pos]); if (len > (((size_t) -1) / 4 - 1)) { fprintf(stderr, "handle_qhit(): Filename is too long.\n"); /* Ignore */ } else { const char *p; size_t avail; printf("Filename: "); avail = len; p = &data[pos]; while (avail > 0) { uint32_t cp; cp = utf8_decode(p, avail); if ((uint32_t) -1 != cp) { uint8_t u_len, i; u_len = utf8_first_byte_length_hint((unsigned char) *p); RUNTIME_ASSERT(u_len > 0); RUNTIME_ASSERT(avail >= u_len); avail -= u_len; if (cp >= 0x20 && cp != 0x7f) { for (i = 0; i < u_len; i++) { putchar((unsigned char) p[i]); } } else { char ch = cp & 0xff; printf("%s", escape_buffer(&ch, 1)); } p += u_len; } else { if (verbosity > 0) { fprintf(stderr, "handle_qhit(): Invalid UTF-8.\n"); } break; } } } printf("\n"); pos += len; } RUNTIME_ASSERT(nul_ptr); RUNTIME_ASSERT(&data[pos] == nul_ptr); RUNTIME_ASSERT('\0' == *nul_ptr); pos++; RUNTIME_ASSERT(pos <= guid_offset); nul_ptr = memchr(&data[pos], 0, guid_offset - pos); if (!nul_ptr) { fprintf(stderr, "handle_qhit(): Non-terminated extension block.\n"); return; } else if (nul_ptr != &data[pos]) { size_t len = nul_ptr - &data[pos]; printf("Extension size: %lu\n", (unsigned long) len); handle_extension(&data[pos], len); pos += len; } RUNTIME_ASSERT(nul_ptr); RUNTIME_ASSERT(&data[pos] == nul_ptr); RUNTIME_ASSERT('\0' == *nul_ptr); pos++; RUNTIME_ASSERT(pos <= guid_offset); printf("------\n"); } if (hits > 0) { fprintf(stderr, "handle_qhit(): Expected %u more hits.\n", hits); } if (pos < guid_offset) { static const unsigned vendor_id_len = 4; printf("Extended QHD size: %lu\n", (unsigned long) guid_offset - pos); if (guid_offset - pos >= vendor_id_len) { printf("Vendor ID: %s\n", escape_buffer(&data[pos], vendor_id_len)); pos += vendor_id_len; if (pos < guid_offset) { uint8_t open_data_size = data[pos]; bool has_ggep = false; printf("Open data size: %u\n", open_data_size); pos++; if (open_data_size > guid_offset - pos) { printf("Open data size is too large.\n"); return; } if (open_data_size >= 2) { uint8_t mask = data[pos]; uint8_t value = data[pos + 1]; printf("mask: 0x%02x\n", mask); printf("value: 0x%02x\n", value); if (0x20 & mask) { has_ggep = 0x20 & value; printf("Has GGEP: %s\n", has_ggep ? "yes" : "no"); } if (0x10 & mask) { printf("Has speed: %s\n", (0x10 & value) ? "yes" : "no"); } if (0x08 & mask) { printf("Has uploaded: %s\n", (0x08 & value) ? "yes" : "no"); } if (0x04 & mask) { printf("Busy: %s\n", (0x04 & value) ? "yes" : "no"); } /* mask and value are swapped */ if (0x01 & value) { printf("Must push: %s\n", (0x01 & mask) ? "yes" : "no"); } } pos += open_data_size; if (pos < guid_offset) { size_t priv_data_size = guid_offset - pos; static const char id_deflate[] = "{deflate}"; const char *priv_data, *x; priv_data = &data[pos]; priv_data_size = guid_offset - pos; printf("Private data area size: %lu\n", (unsigned long) priv_data_size); handle_extension(priv_data, priv_data_size); x = compat_memmem(priv_data, priv_data_size, id_deflate, STATIC_STRLEN(id_deflate)); if (x) { char buf[64 * 1024]; const char *src; size_t n, src_len; src = &x[STATIC_STRLEN(id_deflate)]; src_len = priv_data_size - STATIC_STRLEN(id_deflate); n = buffer_inflate(buf, sizeof buf, src, src_len); if ((size_t) -1 != n) { printf("Inflated: %s\n", escape_buffer(buf, n)); } } pos += priv_data_size; } RUNTIME_ASSERT(pos == guid_offset); } } } printf("----\n"); }