diff options
author | Jérôme LAFORGE <jerome.laforge@gmail.com> | 2014-09-01 11:15:47 +0200 |
---|---|---|
committer | Evan Huus <eapache@gmail.com> | 2014-09-03 11:18:31 +0000 |
commit | c1325e8378001c616e323e01ff90e5f53e208117 (patch) | |
tree | 522b670193190e53426ec3ffdd7d8c258474ff96 | |
parent | 798b1e173d752bf620780eaf97ef7f350e603ea5 (diff) |
Check whether the hop-count of most inner message is equal to 0
Extract RFC3315 about relay message and hop-count :
20.1.1. Relaying a Message from a Client
If the relay agent received the message to be relayed from a client,
the relay agent places a global or site-scoped address with a prefix
assigned to the link on which the client should be assigned an
address in the link-address field. This address will be used by the
server to determine the link from which the client should be assigned
an address and other configuration information. The hop-count in the
Relay-forward message is set to 0.
20.3. Construction of Relay-reply Messages
A server uses a Relay-reply message to return a response to a client
if the original message from the client was relayed to the server in
a Relay-forward message or to send a Reconfigure message to a client
if the server does not have an address it can use to send the message
directly to the client.
A response to the client MUST be relayed through the same relay
agents as the original client message. The server causes this to
happen by creating a Relay-reply message that includes a Relay
Message option containing the message for the next relay agent in the
return path to the client. The contained Relay-reply message
contains another Relay Message option to be sent to the next relay
agent, and so on. The server must record the contents of the
peer-address fields in the received message so it can construct the
appropriate Relay-reply message carrying the response from the
server.
For example, if client C sent a message that was relayed by relay
agent A to relay agent B and then to the server, the server would
send the following Relay-Reply message to relay agent B:
msg-type: RELAY-REPLY
hop-count: 1
link-address: 0
peer-address: A
Relay Message option, containing:
msg-type: RELAY-REPLY
hop-count: 0
link-address: address from link to which C is attached
peer-address: C
Relay Message option: <response from server>
Change-Id: I774cc22c9c090af1a5d3732115c7cd3478343288
Bug:10437
Reviewed-on: https://code.wireshark.org/review/3936
Petri-Dish: Evan Huus <eapache@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Evan Huus <eapache@gmail.com>
-rw-r--r-- | epan/dissectors/packet-dhcpv6.c | 57 |
1 files changed, 37 insertions, 20 deletions
diff --git a/epan/dissectors/packet-dhcpv6.c b/epan/dissectors/packet-dhcpv6.c index ba8a06bab9..787caf76db 100644 --- a/epan/dissectors/packet-dhcpv6.c +++ b/epan/dissectors/packet-dhcpv6.c @@ -722,9 +722,14 @@ static const value_string eue_capabilities_encoding [] = { }; static value_string_ext eue_capabilities_encoding_ext = VALUE_STRING_EXT_INIT(eue_capabilities_encoding); +typedef struct hopcount_info_t { + guint8 hopcount; + proto_item *pi; +} hopcount_info; + static void dissect_dhcpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, - gboolean downstream, int off, int eoff); + gboolean downstream, int off, int eoff, hopcount_info hpi); static int dissect_packetcable_ccc_option(proto_tree *v_tree, proto_item *v_item, packet_info *pinfo, tvbuff_t *tvb, int optoff, @@ -1262,7 +1267,7 @@ dissect_cablelabs_specific_opts(proto_tree *v_tree, proto_item *v_item, packet_i /* Returns the number of bytes consumed by this option. */ static int dhcpv6_option(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bp_tree, - gboolean downstream, int off, int eoff, gboolean *at_end, int protocol) + gboolean downstream, int off, int eoff, gboolean *at_end, int protocol, hopcount_info hpi) { guint16 opttype, hwtype, subopt_type; int temp_optlen, optlen, subopt_len; /* 16-bit values that need 16-bit rollover protection */ @@ -1421,7 +1426,7 @@ dhcpv6_option(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bp_tree, temp_optlen = 12; while ((optlen - temp_optlen) > 0) { temp_optlen += dhcpv6_option(tvb, pinfo, subtree, downstream, - off+temp_optlen, off + optlen, at_end, protocol); + off+temp_optlen, off + optlen, at_end, protocol, hpi); if (*at_end) { /* Bad option - just skip to the end */ temp_optlen = optlen; @@ -1438,7 +1443,7 @@ dhcpv6_option(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bp_tree, temp_optlen = 4; while ((optlen - temp_optlen) > 0) { temp_optlen += dhcpv6_option(tvb, pinfo, subtree, downstream, - off+temp_optlen, off + optlen, at_end, protocol); + off+temp_optlen, off + optlen, at_end, protocol, hpi); if (*at_end) { /* Bad option - just skip to the end */ temp_optlen = optlen; @@ -1478,7 +1483,7 @@ dhcpv6_option(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bp_tree, temp_optlen = 24; while ((optlen - temp_optlen) > 0) { temp_optlen += dhcpv6_option(tvb, pinfo, subtree, downstream, - off+temp_optlen, off + optlen, at_end, protocol); + off+temp_optlen, off + optlen, at_end, protocol, hpi); if (*at_end) { /* Bad option - just skip to the end */ temp_optlen = optlen; @@ -1515,7 +1520,7 @@ dhcpv6_option(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bp_tree, expert_add_info_format(pinfo, option_item, &ei_dhcpv6_malformed_option, "RELAY-MSG: malformed option"); } else { /* here, we should dissect a full DHCP message */ - dissect_dhcpv6(tvb, pinfo, subtree, downstream, off, off + optlen); + dissect_dhcpv6(tvb, pinfo, subtree, downstream, off, off + optlen, hpi); } break; case OPTION_AUTH: @@ -1768,7 +1773,7 @@ dhcpv6_option(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bp_tree, while ((optlen - temp_optlen) > 0) { temp_optlen += dhcpv6_option(tvb, pinfo, subtree, downstream, off + temp_optlen, - off + optlen, at_end, protocol); + off + optlen, at_end, protocol, hpi); if (*at_end) { /* Bad option - just skip to the end */ temp_optlen = optlen; @@ -1781,7 +1786,7 @@ dhcpv6_option(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bp_tree, while ((optlen - temp_optlen) > 0) { temp_optlen += dhcpv6_option(tvb, pinfo, subtree, downstream, off + temp_optlen, - off + optlen, at_end, protocol); + off + optlen, at_end, protocol, hpi); if (*at_end) { /* Bad option - just skip to the end */ temp_optlen = optlen; @@ -1857,7 +1862,7 @@ dhcpv6_option(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bp_tree, temp_optlen = 25; while ((optlen - temp_optlen) > 0) { temp_optlen += dhcpv6_option(tvb, pinfo, subtree, downstream, - off+temp_optlen, off + optlen, at_end, protocol); + off+temp_optlen, off + optlen, at_end, protocol, hpi); if (*at_end) { /* Bad option - just skip to the end */ temp_optlen = optlen; @@ -1903,10 +1908,10 @@ dhcpv6_option(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bp_tree, /* May be called recursively */ static void dissect_dhcpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, - gboolean downstream, int off, int eoff) + gboolean downstream, int off, int eoff, hopcount_info hpi) { proto_tree *bp_tree = NULL; - proto_item *ti, *subti = NULL; + proto_item *ti; guint8 msgtype; gboolean at_end; struct e_in6_addr in6; @@ -1922,23 +1927,26 @@ dissect_dhcpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, if ((msgtype == RELAY_FORW) || (msgtype == RELAY_REPLY)) { - guint8 byte; if (tree) { proto_tree_add_item(bp_tree, hf_dhcpv6_msgtype, tvb, off, 1, ENC_BIG_ENDIAN); - subti = proto_tree_add_item(bp_tree, hf_dhcpv6_hopcount, tvb, off + 1, 1, ENC_BIG_ENDIAN); + hpi.pi = proto_tree_add_item(bp_tree, hf_dhcpv6_hopcount, tvb, off + 1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(bp_tree, hf_dhcpv6_linkaddr, tvb, off + 2, 16, ENC_NA); proto_tree_add_item(bp_tree, hf_dhcpv6_peeraddr, tvb, off + 18, 16, ENC_NA); } /* Check the hopcount not exceed the HOP_COUNT_LIMIT */ - byte = tvb_get_guint8(tvb, off + 1); - if (byte > HOP_COUNT_LIMIT) { - expert_add_info_format(pinfo, subti, &ei_dhcpv6_error_hopcount, "Hopcount (%d) exceeds the maximum limit HOP_COUNT_LIMIT (%d)", byte, HOP_COUNT_LIMIT); + hpi.hopcount = tvb_get_guint8(tvb, off + 1); + if (hpi.hopcount > HOP_COUNT_LIMIT) { + expert_add_info_format(pinfo, hpi.pi, &ei_dhcpv6_error_hopcount, "Hopcount (%d) exceeds the maximum limit HOP_COUNT_LIMIT (%d)", hpi.hopcount, HOP_COUNT_LIMIT); } tvb_get_ipv6(tvb, off + 2, &in6); col_append_fstr(pinfo->cinfo, COL_INFO, "L: %s ", ip6_to_str(&in6)); off += 34; } else { + /* Check the inner hopcount equals 0 */ + if (hpi.hopcount) { + expert_add_info_format(pinfo, hpi.pi, &ei_dhcpv6_error_hopcount, "Hopcount of most inner message has to equal 0 instead of %d", hpi.hopcount); + } if (tree) { proto_tree_add_item(bp_tree, hf_dhcpv6_msgtype, tvb, off, 1, ENC_BIG_ENDIAN); proto_tree_add_item(bp_tree, hf_dhcpv6_xid, tvb, off + 1, 3, ENC_BIG_ENDIAN); @@ -1949,23 +1957,29 @@ dissect_dhcpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, at_end = FALSE; while ((off < eoff) && !at_end) - off += dhcpv6_option(tvb, pinfo, bp_tree, downstream, off, eoff, &at_end, proto_dhcpv6); + off += dhcpv6_option(tvb, pinfo, bp_tree, downstream, off, eoff, &at_end, proto_dhcpv6, hpi); } static void dissect_dhcpv6_downstream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { + hopcount_info hpi; + hpi.hopcount = 0; + hpi.pi = NULL; col_set_str(pinfo->cinfo, COL_PROTOCOL, "DHCPv6"); col_clear(pinfo->cinfo, COL_INFO); - dissect_dhcpv6(tvb, pinfo, tree, TRUE, 0, tvb_reported_length(tvb)); + dissect_dhcpv6(tvb, pinfo, tree, TRUE, 0, tvb_reported_length(tvb), hpi); } static void dissect_dhcpv6_upstream(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { + hopcount_info hpi; + hpi.hopcount = 0; + hpi.pi = NULL; col_set_str(pinfo->cinfo, COL_PROTOCOL, "DHCPv6"); col_clear(pinfo->cinfo, COL_INFO); - dissect_dhcpv6(tvb, pinfo, tree, FALSE, 0, tvb_reported_length(tvb)); + dissect_dhcpv6(tvb, pinfo, tree, FALSE, 0, tvb_reported_length(tvb), hpi); } @@ -1984,6 +1998,9 @@ dissect_dhcpv6_bulk_leasequery_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree guint16 size, trans_id; guint8 msg_type; gboolean at_end = FALSE; + hopcount_info hpi; + hpi.hopcount = 0; + hpi.pi = NULL; col_set_str(pinfo->cinfo, COL_PROTOCOL, "DHCPv6 BulkLease"); col_clear(pinfo->cinfo, COL_INFO); @@ -2019,7 +2036,7 @@ dissect_dhcpv6_bulk_leasequery_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree end = size + 2; while ((offset < end) && !at_end) offset += dhcpv6_option(tvb, pinfo, option_tree, FALSE, offset, - end, &at_end, proto_dhcpv6_bulk_leasequery); + end, &at_end, proto_dhcpv6_bulk_leasequery, hpi); return tvb_length(tvb); } |