/* packet-srvloc.c * Routines for SRVLOC (Service Location Protocol) packet dissection * Copyright 1999, James Coe * Copyright 2002, Brad Hards * Updated for TCP segments by Greg Morris * Copyright 2003, Greg Morris * * NOTE: This is Alpha software not all features have been verified yet. * In particular I have not had an opportunity to see how it * responds to SRVLOC over TCP. * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * Service Location Protocol is RFC 2165 * Service Location Protocol Version 2 is RFC 2608 * - partial support by Brad Hards * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "config.h" #include /* for strtoul() */ #include #include #include "packet-tcp.h" #include void proto_register_srvloc(void); void proto_reg_handoff_srvloc(void); static dissector_handle_t srvloc_handle; static dissector_handle_t srvloc_tcp_handle; static bool srvloc_desegment = true; static int proto_srvloc; static int hf_srvloc_version; static int hf_srvloc_function; static int hf_srvloc_pktlen; static int hf_srvloc_xid; static int hf_srvloc_langtaglen; static int hf_srvloc_langtag; static int hf_srvloc_nextextoff; static int hf_srvloc_flags_v1; static int hf_srvloc_flags_v1_overflow; static int hf_srvloc_flags_v1_monolingual; static int hf_srvloc_flags_v1_url_auth; static int hf_srvloc_flags_v1_attribute_auth; static int hf_srvloc_flags_v1_fresh; static int hf_srvloc_error; static int hf_srvloc_flags_v2; static int hf_srvloc_flags_v2_overflow; static int hf_srvloc_flags_v2_fresh; static int hf_srvloc_flags_v2_reqmulti; static int hf_srvloc_error_v2; static int hf_srvloc_daadvert_timestamp; static int hf_srvloc_daadvert_urllen; static int hf_srvloc_daadvert_url; static int hf_srvloc_daadvert_scopelistlen; static int hf_srvloc_daadvert_scopelist; static int hf_srvloc_daadvert_attrlistlen; static int hf_srvloc_daadvert_attrlist; static int hf_srvloc_daadvert_slpspilen; static int hf_srvloc_daadvert_slpspi; static int hf_srvloc_daadvert_authcount; static int hf_srvloc_srvreq_prlistlen; static int hf_srvloc_srvreq_prlist; static int hf_srvloc_srvreq_srvtypelen; static int hf_srvloc_srvreq_srvtypelist; static int hf_srvloc_srvreq_scopelistlen; static int hf_srvloc_srvreq_scopelist; static int hf_srvloc_srvreq_predicatelen; static int hf_srvloc_srvreq_predicate; static int hf_srvloc_srvreq_slpspilen; static int hf_srvloc_srvreq_slpspi; static int hf_srvloc_srvrply_urlcount; static int hf_srvloc_srvreg_attrlistlen; static int hf_srvloc_srvreg_attrlist; static int hf_srvloc_srvreg_attrauthcount; static int hf_srvloc_srvreg_srvtypelen; static int hf_srvloc_srvreg_srvtype; static int hf_srvloc_srvreg_scopelistlen; static int hf_srvloc_srvreg_scopelist; static int hf_srvloc_srvdereg_scopelistlen; static int hf_srvloc_srvdereg_scopelist; static int hf_srvloc_srvdereg_taglistlen; static int hf_srvloc_srvdereg_taglist; static int hf_srvloc_attrreq_prlistlen; static int hf_srvloc_attrreq_prlist; static int hf_srvloc_attrreq_urllen; static int hf_srvloc_attrreq_url; static int hf_srvloc_attrreq_scopelistlen; static int hf_srvloc_attrreq_scopelist; static int hf_srvloc_attrreq_attrlistlen; static int hf_srvloc_attrreq_attrlist; static int hf_srvloc_attrreq_taglistlen; static int hf_srvloc_attrreq_taglist; static int hf_srvloc_attrreq_slpspilen; static int hf_srvloc_attrreq_slpspi; static int hf_srvloc_attrrply_attrlistlen; static int hf_srvloc_attrrply_attrlist; static int hf_srvloc_attrrply_attrauthcount; static int hf_srvloc_srvtypereq_prlistlen; static int hf_srvloc_srvtypereq_prlist; static int hf_srvloc_srvtypereq_nameauthlistlen; static int hf_srvloc_srvtypereq_nameauthlistlenall; static int hf_srvloc_srvtypereq_nameauthlist; static int hf_srvloc_srvtypereq_scopelistlen; static int hf_srvloc_srvtypereq_scopelist; static int hf_srvloc_srvtyperply_srvtypelen; static int hf_srvloc_srvtyperply_srvtype; static int hf_srvloc_srvtyperply_srvtypelistlen; static int hf_srvloc_srvtyperply_srvtypelist; static int hf_srvloc_saadvert_urllen; static int hf_srvloc_saadvert_url; static int hf_srvloc_saadvert_scopelistlen; static int hf_srvloc_saadvert_scopelist; static int hf_srvloc_saadvert_attrlistlen; static int hf_srvloc_saadvert_attrlist; static int hf_srvloc_saadvert_authcount; static int hf_srvloc_authblkv2_bsd; static int hf_srvloc_authblkv2_len; static int hf_srvloc_authblkv2_timestamp; static int hf_srvloc_authblkv2_slpspilen; static int hf_srvloc_authblkv2_slpspi; static int hf_srvloc_url_reserved; static int hf_srvloc_url_lifetime; static int hf_srvloc_url_urllen; static int hf_srvloc_url_url; static int hf_srvloc_url_numauths; static int hf_srvloc_add_ref_ip; static int hf_srvloc_srvrply_svcname; /* Generated from convert_proto_tree_add_text.pl */ static int hf_srvloc_timestamp; static int hf_srvloc_authentication_block; static int hf_srvloc_transaction_id; static int hf_srvloc_block_structure_descriptor; static int hf_srvloc_communication_type; static int hf_srvloc_language; static int hf_srvloc_socket; static int hf_srvloc_encoding; static int hf_srvloc_node; static int hf_srvloc_item; static int hf_srvloc_service_type; static int hf_srvloc_network; static int hf_srvloc_service_type_count; static int hf_srvloc_dialect; static int hf_srvloc_authenticator_length; static int hf_srvloc_protocol; static int hf_srvloc_port; static int ett_srvloc; static int ett_srvloc_attr; static int ett_srvloc_flags; static expert_field ei_srvloc_error; static expert_field ei_srvloc_error_v2; static expert_field ei_srvloc_function_unknown; static expert_field ei_srvloc_malformed; static const true_false_string tfs_srvloc_flags_overflow = { "Message will not fit in datagram", "Message will fit in a datagram" }; static const true_false_string tfs_srvloc_flags_v1_monolingual = { "Only responses in specified language will be accepted", "Responses in any language will be accepted" }; static const true_false_string tfs_srvloc_flags_v1_url_auth = { "URL Authentication Block is present", "URL Authentication Block is absent" }; static const true_false_string tfs_srvloc_flags_v1_attribute_auth = { "Attribute Authentication Block is present", "Attribute Authentication Block is absent" }; static const true_false_string tfs_srvloc_flags_fresh = { "New Service Registration", "Not a new Service Registration" }; static const true_false_string tfs_srvloc_flags_v2_reqmulti = { "Multicast (or broadcast) request", "Not multicast or broadcast" }; #define TCP_PORT_SRVLOC 427 #define UDP_PORT_SRVLOC 427 /* Define function types */ #define SRVREQ 1 #define SRVRPLY 2 #define SRVREG 3 #define SRVDEREG 4 #define SRVACK 5 #define ATTRRQST 6 #define ATTRRPLY 7 #define DAADVERT 8 #define SRVTYPERQST 9 #define SRVTYPERPLY 10 #define SAADVERT 11 /* SLPv2, section 8 */ /* Create protocol header structure */ /* bradh: looks like never used. */ /* bradh: comment it out for now since it doesn't work for v2 struct srvloc_hdr { uint8_t version; uint8_t function; uint16_t length; uint8_t flags; uint8_t dialect; unsigned char language[2]; uint16_t encoding; uint16_t xid; }; */ /* List to resolve function numbers to names */ static const value_string srvloc_functions[] = { { SRVREQ, "Service Request" }, { SRVRPLY, "Service Reply" }, { SRVREG, "Service Registration" }, { SRVDEREG, "Service Deregister" }, { SRVACK, "Service Acknowledge" }, { ATTRRQST, "Attribute Request" }, { ATTRRPLY, "Attribute Reply" }, { DAADVERT, "DA Advertisement" }, { SRVTYPERQST, "Service Type Request" }, { SRVTYPERPLY, "Service Type Reply" }, { SAADVERT, "SA Advertisement" }, /* v2 only */ { 0, NULL } }; /* List to resolve flag values to names */ /* Define flag masks */ #define FLAG_O 0x80 #define FLAG_M 0x40 #define FLAG_U 0x20 #define FLAG_A 0x10 #define FLAG_F 0x08 /* it all changes for Version 2 */ #define FLAG_O_V2 0x8000 #define FLAG_F_V2 0x4000 #define FLAG_R_V2 0x2000 /* Define Error Codes - Version 1*/ #define SUCCESS 0 #define LANG_NOT_SPTD 1 #define PROT_PARSE_ERR 2 #define INVLD_REG 3 #define SCOPE_NOT_SPTD 4 #define CHRSET_NOT_UND 5 #define AUTH_ABSENT 6 #define AUTH_FAILED 7 /* List to resolve error codes to names */ static const value_string srvloc_errs[] = { { SUCCESS, "No Error" }, { LANG_NOT_SPTD, "Language not supported" }, { PROT_PARSE_ERR, "Protocol parse error" }, { INVLD_REG, "Invalid registration" }, { SCOPE_NOT_SPTD, "Scope not supported" }, { CHRSET_NOT_UND, "Character set not understood" }, { AUTH_ABSENT, "Authentication absent" }, { AUTH_FAILED, "Authentication failed" }, { 0, NULL } }; /* Define Error Codes for Version 2 */ #define LANGUAGE_NOT_SUPPORTED 1 #define PARSE_ERROR 2 #define INVALID_REGISTRATION 3 #define SCOPE_NOT_SUPPORTED 4 #define AUTHENTICATION_UNKNOWN 5 #define AUTHENTICATION_ABSENT 6 #define AUTHENTICATION_FAILED 7 #define VER_NOT_SUPPORTED 9 #define INTERNAL_ERROR 10 #define DA_BUSY_NOW 11 #define OPTION_NOT_UNDERSTOOD 12 #define INVALID_UPDATE 13 #define MSG_NOT_SUPPORTED 14 #define REFRESH_REJECTED 15 static const value_string srvloc_errs_v2[] = { { SUCCESS, "No Error" }, { LANGUAGE_NOT_SUPPORTED, "No data in the requested language" }, { PARSE_ERROR, "The message fails to obey SLP syntax." }, { INVALID_REGISTRATION, "The SrvReg has problems" }, { SCOPE_NOT_SUPPORTED, "Scope list not supported" }, { AUTHENTICATION_UNKNOWN, "Unsupported SLP SPI." }, { AUTHENTICATION_ABSENT, "URL and ATTR authentication not provided"}, { AUTHENTICATION_FAILED, "Authentication error"}, { VER_NOT_SUPPORTED, "Unsupported version number in message header" }, { INTERNAL_ERROR, "The DA (or SA) is too sick to respond" }, { DA_BUSY_NOW, "UA or SA SHOULD retry" }, { OPTION_NOT_UNDERSTOOD, "Unknown option from the mandatory range"}, { INVALID_UPDATE, "Invalid SrvReg" }, { MSG_NOT_SUPPORTED, "No support for AttrRqst or SrvTypeRqst" }, { REFRESH_REJECTED, "SrvReg sent too soon"}, { 0, NULL } }; /* * Character encodings. * This is a small subset of what's in * * http://www.iana.org/assignments/character-sets * * XXX - we should do something useful with this, i.e. properly * handle strings based on the character set they're in. * * XXX - what does "properly handle strings" mean? How do we know * what character set the terminal can handle (for tty-based code) * or the GUI can handle (for GUI code)? * * XXX - the Wireshark core really should be what does all the * character set handling for strings, and it should be stuck with * the task of figuring out how to properly handle them. */ #define CHARSET_ASCII 3 #define CHARSET_ISO_10646_UTF_1 27 #define CHARSET_ISO_646_BASIC 28 #define CHARSET_ISO_646_IRV 30 #define CHARSET_ISO_8859_1 4 #define CHARSET_ISO_10646_UCS_2 1000 /* a/k/a Unicode */ #define CHARSET_UTF_7 1012 #define CHARSET_UTF_8 106 static const value_string charsets[] = { { CHARSET_ASCII, "US-ASCII" }, { CHARSET_ISO_10646_UTF_1, "ISO 10646 UTF-1" }, { CHARSET_ISO_646_BASIC, "ISO 646 basic:1983" }, { CHARSET_ISO_646_IRV, "ISO 646 IRV:1983" }, { CHARSET_ISO_8859_1, "ISO 8859-1" }, { CHARSET_ISO_10646_UCS_2, "Unicode" }, { CHARSET_UTF_7, "UTF-7" }, { CHARSET_UTF_8, "UTF-8" }, { 0, NULL } }; static int dissect_authblk(tvbuff_t *tvb, int offset, proto_tree *tree) { uint16_t length; proto_tree_add_item(tree, hf_srvloc_timestamp, tvb, offset, 8, ENC_TIME_NTP|ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_srvloc_block_structure_descriptor, tvb, offset + 8, 2, ENC_BIG_ENDIAN); length = tvb_get_ntohs(tvb, offset + 10); proto_tree_add_item(tree, hf_srvloc_authenticator_length, tvb, offset + 10, 2, ENC_BIG_ENDIAN); offset += 12; proto_tree_add_item(tree, hf_srvloc_authentication_block, tvb, offset, length, ENC_NA|ENC_ASCII); offset += length; return offset; } /* SLPv2 version - Needs to be fixed to match RFC2608 sect 9.2*/ static int dissect_authblk_v2(tvbuff_t *tvb, int offset, proto_tree *tree) { uint16_t length; proto_tree_add_item(tree, hf_srvloc_authblkv2_bsd, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_srvloc_authblkv2_len, tvb, offset+2, 2, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_srvloc_authblkv2_timestamp, tvb, offset+4, 4, ENC_TIME_SECS|ENC_BIG_ENDIAN); length = tvb_get_ntohs(tvb, offset + 8); proto_tree_add_uint(tree, hf_srvloc_authblkv2_slpspilen, tvb, offset + 8, 2, length); offset += 10; proto_tree_add_item(tree, hf_srvloc_authblkv2_slpspi, tvb, offset, length, ENC_ASCII); offset += length; /* add code in here to handle Structured Authentication Block */ return offset; } static int dissect_attrauthblk_v2(tvbuff_t *tvb _U_, int offset, proto_tree *tree _U_) { /* add code in here to handle attribute authentication */ return offset; } static void add_v1_string(proto_tree *tree, int hf, tvbuff_t *tvb, int offset, int length, uint16_t encoding) { switch (encoding) { case CHARSET_ISO_10646_UCS_2: proto_tree_add_item(tree, hf, tvb, offset, length, ENC_UCS_2|ENC_BIG_ENDIAN); break; default: /* XXX - need to support all the CHARSET_ values */ proto_tree_add_item(tree, hf, tvb, offset, length, ENC_ASCII|ENC_NA); break; } } /* * XXX - is this trying to guess the byte order? * * http://www.iana.org/assignments/character-sets * * says of ISO-10646-UCS-2, which has the code 1000 (this routine is used * with CHARSET_ISO_10646_UCS_2, which is #defined to be 1000): * * this needs to specify network byte order: the standard * does not specify (it is a 16-bit integer space) * * Does that mean that in SRVLOC, ISO-10646-UCS-2 is always big-endian? * If so, can we just use "tvb_get_string_enc()" and be * done with it? * * XXX - this is also used with CHARSET_UTF_8. Is that a cut-and-pasteo? */ static const uint8_t* unicode_to_bytes(tvbuff_t *tvb, int offset, int length, bool endianness) { const uint8_t *ascii_text = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, length, ENC_ASCII); int i, j = 0; uint8_t c_char, c_char1; uint8_t *byte_array; /* XXX - Is this the correct behavior? */ if (length < 1) return ""; if (endianness) { byte_array = (uint8_t *)wmem_alloc(wmem_packet_scope(), length*2 + 1); for (i = length; i > 0; i--) { c_char = ascii_text[i]; if (c_char != 0) { if (i == 0) break; i--; c_char1 = ascii_text[i]; if (c_char1 == 0) { if (i == 0) break; i--; c_char1 = ascii_text[i]; } byte_array[j] = c_char1; j++; byte_array[j] = c_char; j++; } } } else { byte_array = (uint8_t *)wmem_alloc(wmem_packet_scope(), length + 1); for (i = 0; i < length; i++) { c_char = ascii_text[i]; if (c_char != 0) { byte_array[j] = c_char; j++; } } } byte_array[j]=0; return byte_array; } /* * Format of x-x-x-xxxxxxxx. Each of these entries represents the service binding to UDP, TCP, or IPX. * The first digit is the protocol family: 2 for TCP/UPD, 6 for IPX. * The second digit is the socket type: 1 for socket stream (TCP), 2 for datagram (UDP and IPX). * The third is the protocol: 6 for TCP, 17 for UDP, and 1000 for IPX. * Last is the IP address, in hex, of the interface that is registered (or, in the case of IPX, an IPX network number). * * OpenSLP supports multiple attribute replies so we need to parse the attribute name and then decode accordingly. * We currently only parse the (non-utf8) attributes: * svcname * svcaddr */ static const value_string srvloc_svc[] = { { 50, "TCP/UDP" }, { 54, "IPX" }, { 0, NULL } }; static const value_string srvloc_ss[] = { { 49, "Socket" }, { 50, "Datagram" }, { 0, NULL } }; static const value_string srvloc_prot[] = { { 54, "TCP" }, { 17, "UDP" }, { 1000, "IPX" }, { 0, NULL } }; static void attr_list(proto_tree *tree, packet_info* pinfo, int hf, tvbuff_t *tvb, int offset, int length, uint16_t encoding) { const char *attr_type; int i, svc, type_len, foffset=offset; uint32_t prot; const uint8_t *byte_value; proto_tree *srvloc_tree; proto_item *ti; char *tmp; switch (encoding) { case CHARSET_ISO_10646_UCS_2: while (offset+2~ and 0x00-1F, 0x7f are reserved and must be escaped in the form \HH */ /* create a sub tree for attributes */ /* XXX - is this always ASCII, or what? */ ti = proto_tree_add_item(tree, hf, tvb, offset, length, ENC_ASCII|ENC_NA); attr_tree = proto_item_add_subtree(ti, ett_srvloc_attr); /* this will ensure there is a terminating null */ start = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, length, ENC_ASCII); cnt = 0; x = 0; c = start[x]; while (c) { if (c == ',') { cnt++; /* Attribute count */ start[x] = 0; proto_tree_add_string_format(attr_tree, hf_srvloc_item, tvb, offset, x, start, "Item %d: %s", cnt, start); offset += x+1; start += x+1; /* reset string length */ x = 0; c = start[x]; } else { /* increment and get next */ x++; c = start[x]; } } /* display anything remaining */ if (x) { cnt++; proto_tree_add_string_format(attr_tree, hf_srvloc_item, tvb, offset, x, start, "Item %d: %s", cnt, start); } } static int dissect_url_entry_v1(tvbuff_t *tvb, int offset, proto_tree *tree, uint16_t encoding, uint16_t flags) { uint16_t url_len; proto_tree_add_item(tree, hf_srvloc_url_lifetime, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; url_len = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(tree, hf_srvloc_url_urllen, tvb, offset, 2, url_len); offset += 2; add_v1_string(tree, hf_srvloc_url_url, tvb, offset, url_len, encoding); offset += url_len; if ( (flags & FLAG_U) == FLAG_U ) offset = dissect_authblk(tvb, offset, tree); return offset; } static int dissect_url_entry_v2(tvbuff_t *tvb, int offset, proto_tree *tree) { uint8_t reserved; uint16_t url_len; uint8_t num_auths; reserved = tvb_get_uint8(tvb, offset); proto_tree_add_uint(tree, hf_srvloc_url_reserved, tvb, offset, 1, reserved); offset += 1; proto_tree_add_item(tree, hf_srvloc_url_lifetime, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; url_len = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(tree, hf_srvloc_url_urllen, tvb, offset, 2, url_len); offset += 2; proto_tree_add_item(tree, hf_srvloc_url_url, tvb, offset, url_len, ENC_ASCII); offset += url_len; num_auths = tvb_get_uint8(tvb, offset); proto_tree_add_uint(tree, hf_srvloc_url_numauths, tvb, offset, 1, num_auths); offset += 1; while (num_auths > 0) { offset = dissect_authblk_v2(tvb, offset, tree); num_auths--; } return offset; } /* Packet dissection routine called by tcp & udp when port 427 detected */ static int dissect_srvloc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { int offset = 0; proto_item *ti; proto_tree *srvloc_tree; uint8_t version; uint8_t function; uint16_t encoding; uint32_t length; /* three bytes needed for v2 */ uint16_t flags; /* two byes needed for v2 */ uint32_t count; uint32_t next_ext_off; /* three bytes, v2 only */ uint16_t lang_tag_len; proto_item *expert_item; uint16_t expert_status; col_set_str(pinfo->cinfo, COL_PROTOCOL, "SRVLOC"); col_clear(pinfo->cinfo, COL_INFO); version = tvb_get_uint8(tvb, offset); function = tvb_get_uint8(tvb, offset + 1); col_add_str(pinfo->cinfo, COL_INFO, val_to_str(function, srvloc_functions, "Unknown Function (%u)")); ti = proto_tree_add_item(tree, proto_srvloc, tvb, offset, -1, ENC_NA); srvloc_tree = proto_item_add_subtree(ti, ett_srvloc); proto_tree_add_uint(srvloc_tree, hf_srvloc_version, tvb, offset, 1, version); proto_tree_add_uint(srvloc_tree, hf_srvloc_function, tvb, offset + 1, 1, function); if (version < 2) { static int * const v1_flags[] = { &hf_srvloc_flags_v1_overflow, &hf_srvloc_flags_v1_monolingual, &hf_srvloc_flags_v1_url_auth, &hf_srvloc_flags_v1_attribute_auth, &hf_srvloc_flags_v1_fresh, NULL }; length = tvb_get_ntohs(tvb, offset + 2); proto_tree_add_uint(srvloc_tree, hf_srvloc_pktlen, tvb, offset + 2, 2, length); flags = tvb_get_uint8(tvb, offset + 4); proto_tree_add_bitmask(srvloc_tree, tvb, offset + 4, hf_srvloc_flags_v1, ett_srvloc_flags, v1_flags, ENC_NA); proto_tree_add_item(srvloc_tree, hf_srvloc_dialect, tvb, offset + 5, 1, ENC_NA); proto_tree_add_item(srvloc_tree, hf_srvloc_language, tvb, offset + 6, 2, ENC_NA|ENC_ASCII); encoding = tvb_get_ntohs(tvb, offset + 8); proto_tree_add_item(srvloc_tree, hf_srvloc_encoding, tvb, offset + 8, 2, ENC_BIG_ENDIAN); proto_tree_add_item(srvloc_tree, hf_srvloc_transaction_id, tvb, offset + 10, 2, ENC_BIG_ENDIAN); /* added echo of XID to info column by Greg Morris 0ct 14, 2005 */ col_append_fstr(pinfo->cinfo, COL_INFO, ", V1 Transaction ID - %u", tvb_get_ntohs(tvb, offset + 10)); offset += 12; switch (function) { case SRVREQ: length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreq_prlistlen, tvb, offset, 2, length); offset += 2; add_v1_string(srvloc_tree, hf_srvloc_srvreq_prlist, tvb, offset, length, encoding); offset += length; length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreq_predicatelen, tvb, offset, 2, length); offset += 2; add_v1_string(srvloc_tree, hf_srvloc_srvreq_predicate, tvb, offset, length, encoding); offset += length; break; case SRVRPLY: expert_item = proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, ENC_BIG_ENDIAN); expert_status = tvb_get_ntohs(tvb, offset); if (expert_status!=0) { expert_add_info_format(pinfo, expert_item, &ei_srvloc_error, "Error: %s", val_to_str(expert_status, srvloc_errs, "Unknown SRVLOC Error (0x%02x)")); } offset += 2; count = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_srvrply_urlcount, tvb, offset, 2, count); offset += 2; while (count > 0) { offset = dissect_url_entry_v1(tvb, offset, srvloc_tree, encoding, flags); count--; } break; case SRVREG: offset = dissect_url_entry_v1(tvb, offset, srvloc_tree, encoding, flags); length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreg_attrlistlen, tvb, offset, 2, length); offset += 2; add_v1_string(srvloc_tree, hf_srvloc_srvreg_attrlist, tvb, offset, length, encoding); offset += length; if ( (flags & FLAG_A) == FLAG_A ) offset = dissect_authblk(tvb, offset, srvloc_tree); break; case SRVDEREG: length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(tree, hf_srvloc_url_urllen, tvb, offset, 2, length); offset += 2; add_v1_string(tree, hf_srvloc_url_url, tvb, offset, length, encoding); offset += length; if ( (flags & FLAG_U) == FLAG_U ) offset = dissect_authblk(tvb, offset, srvloc_tree); length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_srvdereg_taglistlen, tvb, offset, 2, length); offset += 2; add_v1_string(srvloc_tree, hf_srvloc_srvdereg_taglist, tvb, offset, length, encoding); offset += length; /* * XXX - this was there before, but RFC 2165 doesn't speak * of there being an attribute authentication block in * a Service Deregister message. Is that a post-RFC-2165 * addition? */ if ( (flags & FLAG_A) == FLAG_A ) offset = dissect_authblk(tvb, offset, srvloc_tree); break; case SRVACK: expert_item = proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, ENC_BIG_ENDIAN); expert_status = tvb_get_ntohs(tvb, offset); if (expert_status!=0) { expert_add_info_format(pinfo, expert_item, &ei_srvloc_error, "Error: %s", val_to_str(expert_status, srvloc_errs, "Unknown SRVLOC Error (0x%02x)")); } offset += 2; break; case ATTRRQST: length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_prlistlen, tvb, offset, 2, length); offset += 2; add_v1_string(srvloc_tree, hf_srvloc_attrreq_prlist, tvb, offset, length, encoding); offset += length; length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_urllen, tvb, offset, 2, length); offset += 2; add_v1_string(srvloc_tree, hf_srvloc_attrreq_url, tvb, offset, length, encoding); offset += length; length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_scopelistlen, tvb, offset, 2, length); offset += 2; add_v1_string(srvloc_tree, hf_srvloc_attrreq_scopelist, tvb, offset, length, encoding); offset += length; length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_attrlistlen, tvb, offset, 2, length); offset += 2; add_v1_string(srvloc_tree, hf_srvloc_attrreq_attrlist, tvb, offset, length, encoding); offset += length; break; case ATTRRPLY: expert_item = proto_tree_add_item(srvloc_tree, hf_srvloc_error_v2, tvb, offset, 2, ENC_BIG_ENDIAN); expert_status = tvb_get_ntohs(tvb, offset); if (expert_status!=0) { expert_add_info_format(pinfo, expert_item, &ei_srvloc_error, "Error: %s", val_to_str(expert_status, srvloc_errs_v2, "Unknown SRVLOC Error (0x%02x)")); } offset += 2; length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_attrrply_attrlistlen, tvb, offset, 2, length); if (length > 0) { offset += 2; attr_list(srvloc_tree, pinfo, hf_srvloc_attrrply_attrlist, tvb, offset, length, encoding); offset += length; if ( (flags & FLAG_A) == FLAG_A ) offset = dissect_authblk(tvb, offset, srvloc_tree); } break; case DAADVERT: expert_item = proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, ENC_BIG_ENDIAN); expert_status = tvb_get_ntohs(tvb, offset); if (expert_status!=0) { expert_add_info_format(pinfo, expert_item, &ei_srvloc_error, "Error: %s", val_to_str(expert_status, srvloc_errs, "Unknown SRVLOC Error (0x%02x)")); } offset += 2; length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_daadvert_urllen, tvb, offset, 2, length); offset += 2; add_v1_string(srvloc_tree, hf_srvloc_daadvert_url, tvb, offset, length, encoding); offset += length; length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_daadvert_scopelistlen, tvb, offset, 2, length); offset += 2; add_v1_string(srvloc_tree, hf_srvloc_daadvert_scopelist, tvb, offset, length, encoding); offset += length; break; case SRVTYPERQST: length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtypereq_prlistlen, tvb, offset, 2, length); offset += 2; add_v1_string(srvloc_tree, hf_srvloc_srvtypereq_prlist, tvb, offset, length, encoding); offset += length; length = tvb_get_ntohs(tvb, offset); /* Updated by Greg Morris on 1-30-04 */ if (0xFFFF == length) { proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtypereq_nameauthlistlenall, tvb, offset, 2, length); offset += 2; } else { proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtypereq_nameauthlistlen, tvb, offset, 2, length); offset += 2; add_v1_string(srvloc_tree, hf_srvloc_srvtypereq_nameauthlist, tvb, offset, length, encoding); offset += length; } length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtypereq_scopelistlen, tvb, offset, 2, length); offset += 2; add_v1_string(srvloc_tree, hf_srvloc_srvtypereq_scopelist, tvb, offset, length, encoding); offset += length; break; case SRVTYPERPLY: expert_item = proto_tree_add_item(srvloc_tree, hf_srvloc_error, tvb, offset, 2, ENC_BIG_ENDIAN); expert_status = tvb_get_ntohs(tvb, offset); if (expert_status!=0) { expert_add_info_format(pinfo, expert_item, &ei_srvloc_error, "Error: %s", val_to_str(expert_status, srvloc_errs, "Unknown SRVLOC Error (0x%02x)")); } offset += 2; count = tvb_get_ntohs(tvb, offset); proto_tree_add_item(srvloc_tree, hf_srvloc_service_type_count, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; while (count > 0) { length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtyperply_srvtypelen, tvb, offset, 2, length); offset += 2; add_v1_string(srvloc_tree, hf_srvloc_srvtyperply_srvtype, tvb, offset, length, encoding); offset += length; count--; } break; default: proto_tree_add_expert_format(srvloc_tree, pinfo, &ei_srvloc_function_unknown, tvb, offset, -1, "Unknown Function Type: %d", function); } } else { /* Version 2 */ static int * const v2_flags[] = { &hf_srvloc_flags_v2_overflow, &hf_srvloc_flags_v2_fresh, &hf_srvloc_flags_v2_reqmulti, NULL }; proto_tree_add_item_ret_uint(srvloc_tree, hf_srvloc_pktlen, tvb, offset + 2, 3, ENC_BIG_ENDIAN, &length); proto_tree_add_bitmask(srvloc_tree, tvb, offset + 5, hf_srvloc_flags_v2, ett_srvloc_flags, v2_flags, ENC_BIG_ENDIAN); proto_tree_add_item_ret_uint(srvloc_tree, hf_srvloc_nextextoff, tvb, offset + 7, 3, ENC_BIG_ENDIAN, &next_ext_off); proto_tree_add_item(srvloc_tree, hf_srvloc_xid, tvb, offset + 10, 2, ENC_BIG_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, ", V2 XID - %u", tvb_get_ntohs(tvb, offset + 10)); lang_tag_len = tvb_get_ntohs(tvb, offset + 12); proto_tree_add_uint(srvloc_tree, hf_srvloc_langtaglen, tvb, offset + 12, 2, lang_tag_len); proto_tree_add_item(srvloc_tree, hf_srvloc_langtag, tvb, offset + 14, lang_tag_len, ENC_ASCII); offset += 14+lang_tag_len; switch (function) { case SRVREQ: /* RFC2608 8.1 */ length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreq_prlistlen, tvb, offset, 2, length); offset += 2; if (length) { proto_tree_add_item(srvloc_tree, hf_srvloc_srvreq_prlist, tvb, offset, length, ENC_ASCII); offset += length; } length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreq_srvtypelen, tvb, offset, 2, length); offset += 2; if (length) { proto_tree_add_item(srvloc_tree, hf_srvloc_srvreq_srvtypelist, tvb, offset, length, ENC_ASCII); offset += length; } length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreq_scopelistlen, tvb, offset, 2, length); offset += 2; if (length) { proto_tree_add_item(srvloc_tree, hf_srvloc_srvreq_scopelist, tvb, offset, length, ENC_ASCII); offset += length; } length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreq_predicatelen, tvb, offset, 2, length); offset += 2; if (length) { proto_tree_add_item(srvloc_tree, hf_srvloc_srvreq_predicate, tvb, offset, length, ENC_ASCII); offset += length; } length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreq_slpspilen, tvb, offset, 2, length); offset += 2; if (length) { proto_tree_add_item(srvloc_tree, hf_srvloc_srvreq_slpspi, tvb, offset, length, ENC_ASCII); offset += length; } break; case SRVRPLY: /* RFC2608 8.2 */ expert_item = proto_tree_add_item(srvloc_tree, hf_srvloc_error_v2, tvb, offset, 2, ENC_BIG_ENDIAN); expert_status = tvb_get_ntohs(tvb, offset); if (expert_status!=0) { expert_add_info_format(pinfo, expert_item, &ei_srvloc_error_v2, "Error: %s", val_to_str(expert_status, srvloc_errs_v2, "Unknown SRVLOC Error (0x%02x)")); } offset += 2; count = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_srvrply_urlcount, tvb, offset, 2, count); offset += 2; while (count > 0) { offset = dissect_url_entry_v2(tvb, offset, srvloc_tree); count--; } break; case SRVREG: /* RFC2608 8.3 */ offset = dissect_url_entry_v2(tvb, offset, srvloc_tree); length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreg_srvtypelen, tvb, offset, 2, length); offset += 2; if (length) { proto_tree_add_item(srvloc_tree, hf_srvloc_srvreg_srvtype, tvb, offset, length, ENC_ASCII); offset += length; } length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreg_scopelistlen, tvb, offset, 2, length); offset += 2; if (length) { proto_tree_add_item(srvloc_tree, hf_srvloc_srvreg_scopelist, tvb, offset, length, ENC_ASCII); offset += length; } length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreg_attrlistlen, tvb, offset, 2, length); offset += 2; if (length) { attr_list2(srvloc_tree, hf_srvloc_srvreg_attrlist, tvb, offset, length, CHARSET_UTF_8); offset += length; } count = tvb_get_uint8(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_srvreg_attrauthcount, tvb, offset, 1, count); offset += 1; while (count > 0) { offset = dissect_attrauthblk_v2(tvb, offset, srvloc_tree); count--; } break; case SRVDEREG: /* RFC2608 10.6 */ length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_srvdereg_scopelistlen, tvb, offset, 2, length); offset += 2; if (length) { proto_tree_add_item(srvloc_tree, hf_srvloc_srvdereg_scopelist, tvb, offset, length, ENC_ASCII); offset += length; } offset = dissect_url_entry_v2(tvb, offset, srvloc_tree); length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_srvdereg_taglistlen, tvb, offset, 2, length); offset += 2; if (length) { proto_tree_add_item(srvloc_tree, hf_srvloc_srvdereg_taglist, tvb, offset, length, ENC_ASCII); offset += length; } break; case SRVACK: /* RFC2608 8.4 */ expert_item = proto_tree_add_item(srvloc_tree, hf_srvloc_error_v2, tvb, offset, 2, ENC_BIG_ENDIAN); expert_status = tvb_get_ntohs(tvb, offset); if (expert_status!=0) { expert_add_info_format(pinfo, expert_item, &ei_srvloc_error_v2, "Error: %s", val_to_str(expert_status, srvloc_errs_v2, "Unknown SRVLOC Error (0x%02x)")); } offset += 2; break; case ATTRRQST: /* RFC2608 10.3*/ length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_prlistlen, tvb, offset, 2, length); offset += 2; if (length) { proto_tree_add_item(srvloc_tree, hf_srvloc_attrreq_prlist, tvb, offset, length, ENC_ASCII); offset += length; } length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_urllen, tvb, offset, 2, length); offset += 2; if (length) { proto_tree_add_item(srvloc_tree, hf_srvloc_attrreq_url, tvb, offset, length, ENC_ASCII); offset += length; } length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_scopelistlen, tvb, offset, 2, length); offset += 2; if (length) { proto_tree_add_item(srvloc_tree, hf_srvloc_attrreq_scopelist, tvb, offset, length, ENC_ASCII); offset += length; } length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_taglistlen, tvb, offset, 2, length); offset += 2; if (length) { proto_tree_add_item(srvloc_tree, hf_srvloc_attrreq_taglist, tvb, offset, length, ENC_ASCII); offset += length; } length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_attrreq_slpspilen, tvb, offset, 2, length); offset += 2; if (length) { proto_tree_add_item(srvloc_tree, hf_srvloc_attrreq_slpspi, tvb, offset, length, ENC_ASCII); offset += length; } break; case ATTRRPLY: /* RFC2608 10.4 */ expert_item = proto_tree_add_item(srvloc_tree, hf_srvloc_error_v2, tvb, offset, 2, ENC_BIG_ENDIAN); expert_status = tvb_get_ntohs(tvb, offset); if (expert_status!=0) { expert_add_info_format(pinfo, expert_item, &ei_srvloc_error_v2, "Error: %s", val_to_str(expert_status, srvloc_errs_v2, "Unknown SRVLOC Error (0x%02x)")); } offset += 2; length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_attrrply_attrlistlen, tvb, offset, 2, length); offset += 2; if (length) { attr_list2(srvloc_tree, hf_srvloc_attrrply_attrlist, tvb, offset, length, CHARSET_UTF_8); offset += length; } count = tvb_get_uint8(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_attrrply_attrauthcount, tvb, offset, 1, count); offset += 1; while (count > 0) { offset = dissect_attrauthblk_v2(tvb, offset, srvloc_tree); count--; } break; case DAADVERT: /* RCC 2608 8.5 */ expert_item = proto_tree_add_item(srvloc_tree, hf_srvloc_error_v2, tvb, offset, 2, ENC_BIG_ENDIAN); expert_status = tvb_get_ntohs(tvb, offset); if (expert_status!=0) { expert_add_info_format(pinfo, expert_item, &ei_srvloc_error_v2, "Error: %s", val_to_str(expert_status, srvloc_errs_v2, "Unknown SRVLOC Error (0x%02x)")); } offset += 2; proto_tree_add_item(srvloc_tree, hf_srvloc_daadvert_timestamp, tvb, offset, 4, ENC_TIME_SECS|ENC_BIG_ENDIAN); offset += 4; length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_daadvert_urllen, tvb, offset, 2, length); offset += 2; if (length) { proto_tree_add_item(srvloc_tree, hf_srvloc_daadvert_url, tvb, offset, length, ENC_ASCII); offset += length; } length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_daadvert_scopelistlen, tvb, offset, 2, length); offset += 2; if (length) { proto_tree_add_item(srvloc_tree, hf_srvloc_daadvert_scopelist, tvb, offset, length, ENC_ASCII); offset += length; } length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_daadvert_attrlistlen, tvb, offset, 2, length); offset += 2; if (length) { proto_tree_add_item(srvloc_tree, hf_srvloc_daadvert_attrlist, tvb, offset, length, ENC_ASCII); offset += length; } length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_daadvert_slpspilen, tvb, offset, 2, length); offset += 2; if (length) { proto_tree_add_item(srvloc_tree, hf_srvloc_daadvert_slpspi, tvb, offset, length, ENC_ASCII); offset += length; } count = tvb_get_uint8(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_daadvert_authcount, tvb, offset, 1, count); offset += 1; while (count > 0) { offset = dissect_authblk_v2(tvb, offset, srvloc_tree); count--; } break; case SRVTYPERQST: /* RFC2608 10.1 */ length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtypereq_prlistlen, tvb, offset, 2, length); offset += 2; if (length) { proto_tree_add_item(srvloc_tree, hf_srvloc_srvtypereq_prlist, tvb, offset, length, ENC_ASCII); offset += length; } length = tvb_get_ntohs(tvb, offset); if (0xFFFF == length) { proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtypereq_nameauthlistlenall, tvb, offset, 2, length); offset += 2; } else { proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtypereq_nameauthlistlen, tvb, offset, 2, length); offset += 2; if (length) { proto_tree_add_item(srvloc_tree, hf_srvloc_srvtypereq_nameauthlist, tvb, offset, length, ENC_ASCII); offset += length; } } length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtypereq_scopelistlen, tvb, offset, 2, length); offset += 2; if (length) { proto_tree_add_item(srvloc_tree, hf_srvloc_srvtypereq_scopelist, tvb, offset, length, ENC_ASCII); offset += length; } break; case SRVTYPERPLY: /* rfc2608 10.2 */ expert_item = proto_tree_add_item(srvloc_tree, hf_srvloc_error_v2, tvb, offset, 2, ENC_BIG_ENDIAN); expert_status = tvb_get_ntohs(tvb, offset); if (expert_status!=0) { expert_add_info_format(pinfo, expert_item, &ei_srvloc_error_v2, "Error: %s", val_to_str(expert_status, srvloc_errs_v2, "Unknown SRVLOC Error (0x%02x)")); } offset += 2; length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_srvtyperply_srvtypelistlen, tvb, offset, 2, length); offset += 2; if (length) { proto_tree_add_item(srvloc_tree, hf_srvloc_srvtyperply_srvtypelist, tvb, offset, length, ENC_ASCII); offset += length; } break; case SAADVERT: /* rfc2608 10.2 */ length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_saadvert_urllen, tvb, offset, 2, length); offset += 2; if (length) { proto_tree_add_item(srvloc_tree, hf_srvloc_saadvert_url, tvb, offset, length, ENC_ASCII); offset += length; } length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_saadvert_scopelistlen, tvb, offset, 2, length); offset += 2; if (length) { proto_tree_add_item(srvloc_tree, hf_srvloc_saadvert_scopelist, tvb, offset, length, ENC_ASCII); offset += length; } length = tvb_get_ntohs(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_saadvert_attrlistlen, tvb, offset, 2, length); offset += 2; if (length) { proto_tree_add_item(srvloc_tree, hf_srvloc_saadvert_attrlist, tvb, offset, length, ENC_ASCII); offset += length; } count = tvb_get_uint8(tvb, offset); proto_tree_add_uint(srvloc_tree, hf_srvloc_saadvert_authcount, tvb, offset, 1, length); offset += 1; while (count > 0) { offset = dissect_authblk_v2(tvb, offset, srvloc_tree); count--; } break; default: proto_tree_add_expert_format(srvloc_tree, pinfo, &ei_srvloc_function_unknown, tvb, offset, -1, "Unknown Function Type: %d", function); } } return offset; } static unsigned get_srvloc_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_) { /* * Get the length of the SRVLOC packet. * It starts at offset+2, but it's 2 bytes in SLPv1 and 3 bytes * in SLPv2. */ if (tvb_get_uint8(tvb, offset) == 2) return tvb_get_ntoh24(tvb, offset + 2); else return tvb_get_ntohs(tvb, offset + 2); } static int dissect_srvloc_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { /* * XXX - in SLPv1, the fixed length need only be 4, as the length * is 2 bytes long; however, it must be 5 for SLPv2, as the length * is 3 bytes long, and there's probably no harm in asking for 5 * bytes, as even SLPv1 packets start with a 12-byte header, * and if the packet has a length that's 4 or less, it's bogus, * and we can't handle a length < 4 anyway. */ tcp_dissect_pdus(tvb, pinfo, tree, srvloc_desegment, 5, get_srvloc_pdu_len, dissect_srvloc, data); return tvb_captured_length(tvb); } /* Register protocol with Wireshark. */ void proto_register_srvloc(void) { static hf_register_info hf[] = { /* Helper functions for the Version 1 Header*/ {&hf_srvloc_error, {"Error Code", "srvloc.err", FT_UINT16, BASE_DEC, VALS(srvloc_errs), 0x0, NULL, HFILL } }, /* Helper function for the Version 2 Header */ {&hf_srvloc_error_v2, {"Error Code", "srvloc.errv2", FT_UINT16, BASE_DEC, VALS(srvloc_errs_v2), 0x0, NULL, HFILL } }, {&hf_srvloc_xid, {"XID", "srvloc.xid", FT_UINT24, BASE_DEC, NULL, 0x0, "Transaction ID", HFILL } }, {&hf_srvloc_langtag, {"Lang Tag", "srvloc.langtag", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, {&hf_srvloc_langtaglen, {"Lang Tag Len", "srvloc.langtaglen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, {&hf_srvloc_nextextoff, {"Next Extension Offset", "srvloc.nextextoff", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL } }, /* Helper functions for URL and URL Entry parsing - both versions */ {&hf_srvloc_url_reserved, {"Reserved", "srvloc.url.reserved", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, {&hf_srvloc_url_lifetime, {"URL lifetime", "srvloc.url.lifetime", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, {&hf_srvloc_url_urllen, {"URL Length", "srvloc.url.urllen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, {&hf_srvloc_url_url, {"URL", "srvloc.url.url", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, {&hf_srvloc_url_numauths, {"Num Auths", "srvloc.url.numauths", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, /* Helper functions for the common header fields */ {&hf_srvloc_function, {"Function", "srvloc.function", FT_UINT8, BASE_DEC, VALS(srvloc_functions), 0x0, NULL, HFILL } }, {&hf_srvloc_pktlen, {"Packet Length", "srvloc.pktlen", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_srvloc_version, { "Version", "srvloc.version", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, {&hf_srvloc_flags_v1, {"Flags", "srvloc.flags_v1", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_srvloc_flags_v1_overflow, { "Overflow", "srvloc.flags_v1.overflow", FT_BOOLEAN, 8, TFS(&tfs_srvloc_flags_overflow), FLAG_O, "Can whole packet fit into a datagram?", HFILL }}, { &hf_srvloc_flags_v1_monolingual, { "Monolingual", "srvloc.flags_v1.monolingual", FT_BOOLEAN, 8, TFS(&tfs_srvloc_flags_v1_monolingual), FLAG_M, "Can whole packet fit into a datagram?", HFILL }}, { &hf_srvloc_flags_v1_url_auth, { "URL Authentication", "srvloc.flags_v1.url_auth", FT_BOOLEAN, 8, TFS(&tfs_srvloc_flags_v1_url_auth), FLAG_U, "Can whole packet fit into a datagram?", HFILL }}, { &hf_srvloc_flags_v1_attribute_auth, { "Attribute Authentication", "srvloc.flags_v1.attribute_auth", FT_BOOLEAN, 8, TFS(&tfs_srvloc_flags_v1_attribute_auth), FLAG_A, "Can whole packet fit into a datagram?", HFILL }}, { &hf_srvloc_flags_v1_fresh, { "Fresh Registration", "srvloc.flags_v1.fresh", FT_BOOLEAN, 8, TFS(&tfs_srvloc_flags_fresh), FLAG_F, "Is this a new registration?", HFILL }}, {&hf_srvloc_flags_v2, {"Flags", "srvloc.flags_v2", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } }, { &hf_srvloc_flags_v2_overflow, { "Overflow", "srvloc.flags_v2.overflow", FT_BOOLEAN, 16, TFS(&tfs_srvloc_flags_overflow), FLAG_O_V2, "Can whole packet fit into a datagram?", HFILL }}, { &hf_srvloc_flags_v2_fresh, { "Fresh Registration", "srvloc.flags_v2.fresh", FT_BOOLEAN, 16, TFS(&tfs_srvloc_flags_fresh), FLAG_F_V2, "Is this a new registration?", HFILL }}, { &hf_srvloc_flags_v2_reqmulti, { "Multicast requested", "srvloc.flags_v2.reqmulti", FT_BOOLEAN, 16, TFS(&tfs_srvloc_flags_v2_reqmulti), FLAG_R_V2, "Do we want multicast?", HFILL }}, /* collection of helper functions for dissect_authblk_v2 */ { &hf_srvloc_authblkv2_bsd, { "BSD", "srvloc.authblkv2_bsd", FT_UINT16, BASE_HEX, NULL, 0x0, "Block Structure Descriptor", HFILL} }, { &hf_srvloc_authblkv2_len, { "Length", "srvloc.authblkv2_len", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of Authentication Block", HFILL} }, { &hf_srvloc_authblkv2_timestamp, { "Timestamp", "srvloc.authblkv2.timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0, "Timestamp on Authentication Block", HFILL } }, { &hf_srvloc_authblkv2_slpspilen, { "SLP SPI Length", "srvloc.authblkv2.slpspilen", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of the SLP SPI", HFILL} }, { &hf_srvloc_authblkv2_slpspi, { "SLP SPI", "srvloc.authblkv2.slpspi", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, /* collection of helper functions for Service Request */ { &hf_srvloc_srvreq_prlistlen, { "Previous Response List Length", "srvloc.srvreq.prlistlen", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of Previous Response List", HFILL} }, { &hf_srvloc_srvreq_prlist, { "Previous Response List", "srvloc.srvreq.prlist", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_srvreq_srvtypelen, { "Service Type Length", "srvloc.srvreq.srvtypelen", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of Service Type List", HFILL} }, { &hf_srvloc_srvreq_srvtypelist, { "Service Type List", "srvloc.srvreq.srvtypelist", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_srvreq_scopelistlen, { "Scope List Length", "srvloc.srvreq.scopelistlen", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of the Scope List", HFILL} }, { &hf_srvloc_srvreq_scopelist, { "Scope List", "srvloc.srvreq.scopelist", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_srvreq_predicatelen, { "Predicate Length", "srvloc.srvreq.predicatelen", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of the Predicate", HFILL} }, { &hf_srvloc_srvreq_predicate, { "Predicate", "srvloc.srvreq.predicate", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_srvreq_slpspilen, { "SLP SPI Length", "srvloc.srvreq.slpspilen", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of the SLP SPI", HFILL} }, { &hf_srvloc_srvreq_slpspi, { "SLP SPI", "srvloc.srvreq.slpspi", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, /* Helper function for Service Request */ { &hf_srvloc_srvrply_urlcount, { "Number of URLs", "srvloc.srvreq.urlcount", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} }, /* Helper functions for Service Registration */ { &hf_srvloc_srvreg_srvtypelen, { "Service Type Length", "srvloc.srvreq.srvtypelen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_srvreg_srvtype, { "Service Type", "srvloc.srvreq.srvtype", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_srvreg_scopelistlen, { "Scope List Length", "srvloc.srvreq.scopelistlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_srvreg_scopelist, { "Scope List", "srvloc.srvreq.scopelist", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_srvreg_attrlistlen, { "Attribute List Length", "srvloc.srvreq.attrlistlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_srvreg_attrlist, { "Attribute List", "srvloc.srvreq.attrlist", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_srvreg_attrauthcount, { "Attr Auths", "srvloc.srvreq.attrauthcount", FT_UINT8, BASE_DEC, NULL, 0x0, "Number of Attribute Authentication Blocks", HFILL} }, /* Helper functions for Service Deregistration */ { &hf_srvloc_srvdereg_scopelistlen, { "Scope List Length", "srvloc.srvdereq.scopelistlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_srvdereg_scopelist, { "Scope List", "srvloc.srvdereq.scopelist", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_srvdereg_taglistlen, { "Tag List Length", "srvloc.srvdereq.taglistlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_srvdereg_taglist, { "Tag List", "srvloc.srvdereq.taglist", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, /* collection of helper functions for Attribute Request */ { &hf_srvloc_attrreq_prlistlen, { "Previous Response List Length", "srvloc.attrreq.prlistlen", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of Previous Response List", HFILL} }, { &hf_srvloc_attrreq_prlist, { "Previous Response List", "srvloc.attrreq.prlist", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_attrreq_urllen, { "URL Length", "srvloc.attrreq.urllen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_attrreq_url, { "Service URL", "srvloc.attrreq.url", FT_STRING, BASE_NONE, NULL, 0x0, "URL of service", HFILL} }, { &hf_srvloc_attrreq_scopelistlen, { "Scope List Length", "srvloc.attrreq.scopelistlen", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of the Scope List", HFILL} }, { &hf_srvloc_attrreq_scopelist, { "Scope List", "srvloc.attrreq.scopelist", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_attrreq_attrlistlen, { "Attribute List Length", "srvloc.attrreq.attrlistlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_attrreq_attrlist, { "Attribute List", "srvloc.attrreq.attrlist", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_attrreq_taglistlen, { "Tag List Length", "srvloc.attrreq.taglistlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_attrreq_taglist, { "Tag List", "srvloc.attrreq.taglist", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_attrreq_slpspilen, { "SLP SPI Length", "srvloc.attrreq.slpspilen", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of the SLP SPI", HFILL} }, { &hf_srvloc_attrreq_slpspi, { "SLP SPI", "srvloc.attrreq.slpspi", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, /* collection of helper functions for Attribute Reply */ { &hf_srvloc_attrrply_attrlistlen, { "Attribute List Length", "srvloc.attrrply.attrlistlen", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of Attribute List", HFILL} }, { &hf_srvloc_attrrply_attrlist, { "Attribute List", "srvloc.attrrply.attrlist", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_attrrply_attrauthcount, { "Attr Auths", "srvloc.srvreq.attrauthcount", FT_UINT8, BASE_DEC, NULL, 0x0, "Number of Attribute Authentication Blocks", HFILL} }, /* collection of helper functions for DA Advertisement */ { &hf_srvloc_daadvert_timestamp, { "DAADVERT Timestamp", "srvloc.daadvert.timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0, "Timestamp on DA Advert", HFILL } }, { &hf_srvloc_daadvert_urllen, { "URL Length", "srvloc.daadvert.urllen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_daadvert_url, { "URL", "srvloc.daadvert.url", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_daadvert_scopelistlen, { "Scope List Length", "srvloc.daadvert.scopelistlen", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of the Scope List", HFILL} }, { &hf_srvloc_daadvert_scopelist, { "Scope List", "srvloc.daadvert.scopelist", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_daadvert_attrlistlen, { "Attribute List Length", "srvloc.daadvert.attrlistlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_daadvert_attrlist, { "Attribute List", "srvloc.daadvert.attrlist", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_daadvert_slpspilen, { "SLP SPI Length", "srvloc.daadvert.slpspilen", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of the SLP SPI", HFILL} }, { &hf_srvloc_daadvert_slpspi, { "SLP SPI", "srvloc.daadvert.slpspi", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_daadvert_authcount, { "Auths", "srvloc.daadvert.authcount", FT_UINT8, BASE_DEC, NULL, 0x0, "Number of Authentication Blocks", HFILL} }, /* collection of helper functions for Service Type Request */ { &hf_srvloc_srvtypereq_prlistlen, { "Previous Response List Length", "srvloc.srvtypereq.prlistlen", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of Previous Response List", HFILL} }, { &hf_srvloc_srvtypereq_prlist, { "Previous Response List", "srvloc.srvtypereq.prlist", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_srvtypereq_nameauthlistlen, { "Naming Authority List Length", "srvloc.srvtypereq.nameauthlistlen", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of the Naming Authority List", HFILL} }, { &hf_srvloc_srvtypereq_nameauthlistlenall, { "Naming Authority List Length (All Naming Authorities)", "srvloc.srvtypereq.nameauthlistlen", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of the Naming Authority List", HFILL} }, { &hf_srvloc_srvtypereq_nameauthlist, { "Naming Authority List", "srvloc.srvtypereq.nameauthlist", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_srvtypereq_scopelistlen, { "Scope List Length", "srvloc.srvtypereq.scopelistlen", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of the Scope List", HFILL} }, { &hf_srvloc_srvtypereq_scopelist, { "Scope List", "srvloc.srvtypereq.scopelist", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, /* collection of helper functions for Service Type Replies */ { &hf_srvloc_srvtyperply_srvtypelen, { "Service Type Length", "srvloc.srvtypereq.srvtypelen", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of the Service Type", HFILL} }, { &hf_srvloc_srvtyperply_srvtype, { "Service Type", "srvloc.srvtyperply.srvtype", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_srvtyperply_srvtypelistlen, { "Service Type List Length", "srvloc.srvtypereq.srvtypelistlen", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of the Service Type List", HFILL} }, { &hf_srvloc_srvtyperply_srvtypelist, { "Service Type List", "srvloc.srvtyperply.srvtypelist", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, /* collection of helper functions for SA Advertisement */ { &hf_srvloc_saadvert_urllen, { "URL Length", "srvloc.saadvert.urllen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_saadvert_url, { "URL", "srvloc.saadvert.url", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_saadvert_scopelistlen, { "Scope List Length", "srvloc.saadvert.scopelistlen", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of the Scope List", HFILL} }, { &hf_srvloc_saadvert_scopelist, { "Scope List", "srvloc.saadvert.scopelist", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_saadvert_attrlistlen, { "Attribute List Length", "srvloc.saadvert.attrlistlen", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_saadvert_attrlist, { "Attribute List", "srvloc.saadvert.attrlist", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, { &hf_srvloc_saadvert_authcount, { "Auths", "srvloc.saadvert.authcount", FT_UINT8, BASE_DEC, NULL, 0x0, "Number of Authentication Blocks", HFILL} }, { &hf_srvloc_add_ref_ip, { "IP Address", "srvloc.list.ipaddr", FT_IPv4, BASE_NONE, NULL, 0x0, "IP Address of SLP server", HFILL} }, { &hf_srvloc_srvrply_svcname, { "Service Name Value", "srvloc.srvrply.svcname", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} }, /* Generated from convert_proto_tree_add_text.pl */ { &hf_srvloc_timestamp, { "Timestamp", "srvloc.timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0x0, NULL, HFILL }}, { &hf_srvloc_block_structure_descriptor, { "Block Structure Descriptor", "srvloc.block_structure_descriptor", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_srvloc_authenticator_length, { "Authenticator length", "srvloc.authenticator_length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_srvloc_authentication_block, { "Authentication block", "srvloc.authentication_block", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_srvloc_service_type, { "Service Type", "srvloc.service_type", FT_UINT8, BASE_DEC, VALS(srvloc_svc), 0x0, NULL, HFILL }}, { &hf_srvloc_communication_type, { "Communication Type", "srvloc.communication_type", FT_UINT8, BASE_DEC, VALS(srvloc_ss), 0x0, NULL, HFILL }}, { &hf_srvloc_protocol, { "Protocol", "srvloc.protocol", FT_UINT32, BASE_DEC, VALS(srvloc_prot), 0x0, NULL, HFILL }}, { &hf_srvloc_port, { "Port", "srvloc.port", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_srvloc_network, { "Network", "srvloc.network", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_srvloc_node, { "Node", "srvloc.node", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_srvloc_socket, { "Socket", "srvloc.socket", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_srvloc_item, { "Item", "srvloc.item", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_srvloc_dialect, { "Dialect", "srvloc.dialect", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_srvloc_language, { "Language", "srvloc.language", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_srvloc_encoding, { "Encoding", "srvloc.encoding", FT_UINT16, BASE_DEC, VALS(charsets), 0x0, NULL, HFILL }}, { &hf_srvloc_transaction_id, { "Transaction ID", "srvloc.transaction_id", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_srvloc_service_type_count, { "Service Type Count", "srvloc.service_type_count", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, }; static int *ett[] = { &ett_srvloc, &ett_srvloc_attr, &ett_srvloc_flags, }; static ei_register_info ei[] = { { &ei_srvloc_error, { "srvloc.err.expert", PI_RESPONSE_CODE, PI_ERROR, "Error", EXPFILL }}, { &ei_srvloc_error_v2, { "srvloc.errv2.expert", PI_RESPONSE_CODE, PI_ERROR, "Error", EXPFILL }}, { &ei_srvloc_function_unknown, { "srvloc.function.unknown", PI_RESPONSE_CODE, PI_ERROR, "Unknown Function Type", EXPFILL }}, { &ei_srvloc_malformed, { "srvloc.malformed", PI_MALFORMED, PI_ERROR, "Too much data to pass inside this protocol. Resubmit request using a streaming protocol like TCP. " "Protocol dissection is aborted due to packet overflow. See overflow flag.", EXPFILL }}, }; module_t *srvloc_module; expert_module_t* expert_srvloc; proto_srvloc = proto_register_protocol("Service Location Protocol", "SRVLOC", "srvloc"); proto_register_field_array(proto_srvloc, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); srvloc_handle = register_dissector("srvloc", dissect_srvloc, proto_srvloc); srvloc_tcp_handle = register_dissector("srvloc.tcp", dissect_srvloc_tcp, proto_srvloc); expert_srvloc = expert_register_protocol(proto_srvloc); expert_register_field_array(expert_srvloc, ei, array_length(ei)); srvloc_module = prefs_register_protocol(proto_srvloc, NULL); prefs_register_bool_preference(srvloc_module, "desegment_tcp", "Reassemble SRVLOC messages spanning multiple TCP segments", "Whether the SRVLOC dissector should reassemble messages spanning multiple TCP segments. " "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.", &srvloc_desegment); } void proto_reg_handoff_srvloc(void) { dissector_add_uint_with_preference("udp.port", UDP_PORT_SRVLOC, srvloc_handle); dissector_add_uint_with_preference("tcp.port", TCP_PORT_SRVLOC, srvloc_tcp_handle); } /* * Editor modelines - https://www.wireshark.org/tools/modelines.html * * Local variables: * c-basic-offset: 4 * tab-width: 8 * indent-tabs-mode: nil * End: * * vi: set shiftwidth=4 tabstop=8 expandtab: * :indentSize=4:tabSize=8:noTabs=true: */