2 * Routines for DIAMETER packet disassembly
4 * $Id: packet-diameter.c,v 1.23 2001/06/18 02:17:45 guy Exp $
6 * Copyright (c) 2001 by David Frascone <dave@frascone.com>
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@ethereal.com>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #ifdef HAVE_SYS_TYPES_H
32 # include <sys/types.h>
35 #ifdef HAVE_NETINET_IN_H
36 #include <netinet/in.h>
49 /* This must be defined before we include packet-diameter-defs.h s*/
50 typedef struct _value_value_pair {
55 /* Valid data types */
71 #include "packet-diameter-defs.h"
73 #define NTP_TIME_DIFF (2208988800UL)
75 #define TCP_PORT_DIAMETER 1812
76 #define SCTP_PORT_DIAMETER 1812
78 static int proto_diameter = -1;
79 static int hf_diameter_length = -1;
80 static int hf_diameter_code = -1;
81 static int hf_diameter_hopbyhopid =-1;
82 static int hf_diameter_endtoendid =-1;
83 static int hf_diameter_reserved = -1;
84 static int hf_diameter_flags = -1;
85 static int hf_diameter_version = -1;
86 static int hf_diameter_vendor_id = -1;
88 static int hf_diameter_avp_code = -1;
89 static int hf_diameter_avp_length = -1;
90 static int hf_diameter_avp_reserved = -1;
91 static int hf_diameter_avp_flags = -1;
92 static int hf_diameter_avp_vendor_id = -1;
95 static int hf_diameter_avp_data_uint32 = -1;
96 static int hf_diameter_avp_data_int32 = -1;
98 static int hf_diameter_avp_data_uint64 = -1;
99 static int hf_diameter_avp_data_int64 = -1;
101 static int hf_diameter_avp_data_bytes = -1;
102 static int hf_diameter_avp_data_string = -1;
103 static int hf_diameter_avp_data_v4addr = -1;
104 static int hf_diameter_avp_data_v6addr = -1;
105 static int hf_diameter_avp_data_time = -1;
107 static gint ett_diameter = -1;
108 static gint ett_diameter_avp = -1;
109 static gint ett_diameter_avpinfo = -1;
111 static char gbl_diameterString[200];
112 static int gbl_diameterTcpPort=TCP_PORT_DIAMETER;
113 static int gbl_diameterSctpPort=SCTP_PORT_DIAMETER;
115 typedef struct _e_diameterhdr {
125 typedef struct _e_avphdr {
130 guint32 avp_vendorId; /* optional */
133 #define AUTHENTICATOR_LENGTH 12
135 /* Diameter Header Flags */
136 #define DIAM_FLAGS_E 0x20
137 #define DIAM_FLAGS_I 0x10
138 #define DIAM_FLAGS_R 0x08
139 #define DIAM_FLAGS_RESERVED 0xc0 /* 11000000 -- X X E I R V V V */
141 /* Diameter AVP Flags */
142 #define AVP_FLAGS_P 0x0020
143 #define AVP_FLAGS_V 0x0004
144 #define AVP_FLAGS_M 0x0001
145 #define AVP_FLAGS_RESERVED 0xea /* 11101010 -- X X X P X V X M */
147 #define MIN_AVP_SIZE (sizeof(e_avphdr) - sizeof(guint32))
148 #define MIN_DIAMETER_SIZE (sizeof(e_diameterhdr) + MIN_AVP_SIZE)
150 static gchar *rd_value_to_str(e_avphdr *avph,const u_char *input, int length);
151 static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
152 static guint32 match_numval(guint32 val, const value_value_pair *vs);
153 static gchar *DetermineMessageType(char flagsVer);
155 /* Code to actually dissect the packets */
160 static void dissect_diameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
163 /* Set up structures needed to add the protocol subtree and manage it */
166 proto_tree *diameter_tree;
171 proto_tree *avp_tree;
173 int BadPacket = FALSE;
175 /* Make entries in Protocol column and Info column on summary display */
176 if (check_col(pinfo->fd, COL_PROTOCOL))
177 col_add_str(pinfo->fd, COL_PROTOCOL, "Diameter");
178 if (check_col(pinfo->fd, COL_INFO))
179 col_clear(pinfo->fd, COL_INFO);
181 /* Copy our header */
182 tvb_memcpy(tvb, (guint8*) &dh, offset, sizeof(dh));
184 /* Fix byte ordering in our static structure */
185 dh.pktLength = ntohs(dh.pktLength);
186 dh.hopByHopId = ntohl(dh.hopByHopId);
187 dh.endToEndId = ntohl(dh.endToEndId);
189 dh.commandCode = ntohl(dh.commandCode);
190 dh.vendorId = ntohl(dh.vendorId);
192 codestrval= match_strval(dh.commandCode,diameter_command_code_vals);
193 if (codestrval==NULL) {
194 codestrval="Unknown Command Code";
197 /* Short packet. Should have at LEAST one avp */
198 if (dh.pktLength < MIN_DIAMETER_SIZE) {
199 g_warning("DIAMETER: Packet too short: %d bytes less than min size (%d bytes))",
200 dh.pktLength, MIN_DIAMETER_SIZE);
204 /* And, check our reserved flags/version */
205 if (dh.reserved || (dh.flagsVer & DIAM_FLAGS_RESERVED) ||
206 ((dh.flagsVer & 0x7) != 1)) {
207 g_warning("DIAMETER: Bad packet: Bad Flags or Version");
211 if (check_col(pinfo->fd, COL_INFO)) {
212 col_add_fstr(pinfo->fd, COL_INFO,
213 "%s%s: %s(%d) vendor=%d (hop-id=%d) (end-id=%d) EIR=%d%d%d",
214 (BadPacket)?"***** Bad Packet!: ":"",
215 DetermineMessageType(dh.flagsVer),
216 codestrval, dh.commandCode, dh.vendorId,
217 dh.hopByHopId, dh.endToEndId,
218 (dh.flagsVer & DIAM_FLAGS_E)?1:0,
219 (dh.flagsVer & DIAM_FLAGS_I)?1:0,
220 (dh.flagsVer & DIAM_FLAGS_R)?1:0);
224 /* In the interest of speed, if "tree" is NULL, don't do any work not
225 necessary to generate protocol tree items. */
228 /* create display subtree for the protocol */
229 ti = proto_tree_add_item(tree, proto_diameter, tvb, offset, tvb_length(tvb), FALSE);
230 diameter_tree = proto_item_add_subtree(ti, ett_diameter);
233 proto_tree_add_uint(diameter_tree, hf_diameter_reserved, tvb, offset, 1, dh.reserved);
237 proto_tree_add_uint_format(diameter_tree,
241 "Packet flags: 0x%02x E:%d I:%d R:%d (%s)",
242 (dh.flagsVer&0xf8)>>3,
243 (dh.flagsVer & DIAM_FLAGS_E)?1:0,
244 (dh.flagsVer & DIAM_FLAGS_I)?1:0,
245 (dh.flagsVer & DIAM_FLAGS_R)?1:0,
246 DetermineMessageType(dh.flagsVer));
249 proto_tree_add_uint(diameter_tree,
258 proto_tree_add_uint(diameter_tree,
259 hf_diameter_length, tvb,
260 offset, 2, dh.pktLength);
263 /* Hop-by-hop Identifier */
264 proto_tree_add_uint(diameter_tree, hf_diameter_hopbyhopid,
265 tvb, offset, 4, dh.hopByHopId);
268 /* End-to-end Identifier */
269 proto_tree_add_uint(diameter_tree, hf_diameter_endtoendid,
270 tvb, offset, 4, dh.endToEndId);
274 proto_tree_add_uint(diameter_tree, hf_diameter_code,
275 tvb, offset, 4, dh.commandCode);
279 proto_tree_add_uint(diameter_tree,hf_diameter_vendor_id,
284 /* If we have a bad packet, don't bother trying to parse the AVPs */
289 /* Start looking at the AVPS */
290 /* Make the next tvbuff */
292 /* Update the lengths */
293 avplength= dh.pktLength - sizeof(e_diameterhdr);
295 avp_tvb = tvb_new_subset(tvb, offset, -1, avplength);
296 avptf = proto_tree_add_text(diameter_tree,
297 tvb, offset, tvb_length(tvb),
298 "Attribute Value Pairs");
300 avp_tree = proto_item_add_subtree(avptf,
302 if (avp_tree != NULL) {
303 dissect_avps( avp_tvb, pinfo, avp_tree);
306 } /* dissect_diameter */
309 * This function will dissect the AVPs in a diameter packet. It handles
310 * all normal types, and even recursively calls itself for grouped AVPs
312 static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree)
314 /* adds the attribute value pairs to the tree */
321 proto_tree *avpi_tree;
324 char dataBuffer[4096];
326 proto_tree *group_tree;
330 int BadPacket = FALSE;
333 size_t avpDataLength;
336 packetLength = tvb_length(tvb);
338 /* Check for invalid packet lengths */
339 if (packetLength <= 0) {
340 proto_tree_add_text(avp_tree, tvb, offset, tvb_length(tvb),
341 "No Attribute Value Pairs Found");
346 /* Spin around until we run out of packet */
347 while (packetLength > 0 ) {
350 /* Check for short packet */
351 if (packetLength < MIN_AVP_SIZE) {
352 g_warning("DIAMETER: AVP Payload too short: %d bytes less than min size (%d bytes))",
353 packetLength, MIN_AVP_SIZE);
355 /* Don't even bother trying to parse a short packet. */
359 /* Copy our header */
360 tvb_memcpy(tvb, (guint8*) &avph, offset, sizeof(avph));
362 /* Fix the byte ordering */
363 avph.avp_code = ntohl(avph.avp_code);
364 avph.avp_length = ntohs(avph.avp_length);
366 /* Dissect our vendor id if it exists and set hdr length*/
367 if (avph.avp_flags & AVP_FLAGS_V) {
368 vendorId = ntohl(avph.avp_vendorId);
370 hdrLength = sizeof(e_avphdr);
373 hdrLength = sizeof(e_avphdr) -
377 /* Check for bad length */
378 if (avph.avp_length < MIN_AVP_SIZE ||
379 (avph.avp_length > packetLength)) {
380 g_warning("DIAMETER: AVP payload size invalid: avp_length: %d bytes, min: %d bytes, packetLen: %d",
381 avph.avp_length, MIN_AVP_SIZE, packetLength);
385 /* Check for bad flags */
386 if (avph.avp_reserved ||
387 (avph.avp_flags & AVP_FLAGS_RESERVED)) {
388 g_warning("DIAMETER: Invalid AVP: avph.avp_reserved = 0x%x, avph.avp_flags = 0x%x, resFl=0x%x",
389 avph.avp_reserved, avph.avp_flags, AVP_FLAGS_RESERVED);
394 * Fix byte-alignment (Diameter AVPs are sent on 4 byte
397 fixAmt = 4 - (avph.avp_length % 4);
398 if (fixAmt == 4) fixAmt = 0;
400 packetLength = packetLength - (avph.avp_length + fixAmt);
402 /* Check for out of bounds */
403 if (packetLength < 0) {
404 g_warning("DIAMETER: Bad AVP: Bad new length (%d bytes)",
409 avptpstrval = match_strval(avph.avp_code, diameter_attrib_type_vals);
410 if (avptpstrval == NULL) avptpstrval="Unknown Type";
412 avptf = proto_tree_add_text(avp_tree, tvb,
413 offset, avph.avp_length,
414 "%s(%d) l:0x%x (%d bytes)",
415 avptpstrval, avph.avp_code, avph.avp_length,
417 avpi_tree = proto_item_add_subtree(avptf,
418 ett_diameter_avpinfo);
420 if (avpi_tree !=NULL) {
422 proto_tree_add_uint(avpi_tree, hf_diameter_avp_code,
423 tvb, offset, 4, avph.avp_code);
426 proto_tree_add_uint(avpi_tree, hf_diameter_avp_length,
427 tvb, offset, 2, avph.avp_length);
430 proto_tree_add_uint(avpi_tree, hf_diameter_avp_reserved,
431 tvb, offset, 1, avph.avp_reserved);
434 proto_tree_add_uint_format(avpi_tree,
435 hf_diameter_avp_flags, tvb,
436 offset, 1, avph.avp_flags,
437 "Flags: P:%d V:%d M:%d",
438 (avph.avp_flags & AVP_FLAGS_P)?1:0,
439 (avph.avp_flags & AVP_FLAGS_V)?1:0,
440 (avph.avp_flags & AVP_FLAGS_M)?1:0);
443 if (avph.avp_flags & AVP_FLAGS_V) {
444 proto_tree_add_uint(avpi_tree, hf_diameter_avp_vendor_id,
445 tvb, offset, 4, avph.avp_vendorId);
449 avpDataLength = avph.avp_length - hdrLength;
452 * If we've got a bad packet, just highlight the data. Don't try
453 * to parse it, and, don't move to next AVP.
457 proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
458 tvb, offset, tvb_length(tvb) - offset, dataBuffer,
459 "Bad AVP (Suspect Data Not Dissected)");
463 avpType=match_numval(avph.avp_code, diameter_printinfo);
464 tvb_memcpy(tvb, (guint8*) dataBuffer, offset, MIN(4095,
465 avph.avp_length - hdrLength));
468 case DIAMETER_GROUPED:
469 sprintf(buffer, "%s Grouped AVPs", avptpstrval);
470 /* Recursively call ourselves */
471 grouptf = proto_tree_add_text(avpi_tree,
472 tvb, offset, tvb_length(tvb),
475 group_tree = proto_item_add_subtree(grouptf,
478 group_tvb = tvb_new_subset(tvb, offset,
479 MIN(avpDataLength, tvb_length(tvb)-offset), avpDataLength);
480 if (group_tree != NULL) {
481 dissect_avps( group_tvb, pinfo, group_tree);
485 case DIAMETER_STRING:
486 proto_tree_add_string_format(avpi_tree, hf_diameter_avp_data_string,
487 tvb, offset, avpDataLength, dataBuffer,
488 "String: %*.*s", (int)avpDataLength, (int)avpDataLength,
491 case DIAMETER_ADDRESS:
492 if (avpDataLength == 4) {
493 guint32 ipv4Address = ntohl((*(guint32*)dataBuffer));
494 proto_tree_add_ipv4_format(avpi_tree, hf_diameter_avp_data_v4addr,
495 tvb, offset, avpDataLength, ipv4Address,
496 "IPv4 Address: %u.%u.%u.%u",
497 (ipv4Address&0xff000000)>>24,
498 (ipv4Address&0xff0000)>>16,
499 (ipv4Address&0xff00)>>8,
501 } else if (avpDataLength == 16) {
502 proto_tree_add_ipv6_format(avpi_tree, hf_diameter_avp_data_v6addr,
503 tvb, offset, avpDataLength, dataBuffer,
504 "IPv6 Address: %04x:%04x:%04x:%04x",
505 *((guint32*)dataBuffer),
506 *((guint32*)&dataBuffer[4]),
507 *((guint32*)&dataBuffer[8]),
508 *((guint32*)&dataBuffer[12]));
510 proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
511 tvb, offset, avpDataLength, dataBuffer,
512 "Error! Bad Address Length");
516 case DIAMETER_INTEGER32:
517 case DIAMETER_UNSIGNED32:
518 case DIAMETER_INTEGER64:
519 case DIAMETER_UNSIGNED64:
520 valstr=rd_value_to_str(&avph, dataBuffer, offset);
522 proto_tree_add_int_format(avpi_tree, hf_diameter_avp_data_int32,
523 tvb, offset, avpDataLength, (*(guint32*)dataBuffer),
524 "Value: %s", valstr);
529 valstr=rd_value_to_str(&avph, dataBuffer, offset);
531 proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
532 tvb, offset, avpDataLength, dataBuffer, "Time: %s", valstr);
537 proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
538 tvb, offset, avpDataLength, dataBuffer,
543 offset += avph.avp_length - hdrLength;
545 offset += fixAmt; /* fix byte alignment */
549 /* Generic routine to work with value value pairs */
550 static guint32 match_numval(guint32 val, const value_value_pair *vs)
555 if (vs[i].val1 == val)
563 static gchar *rd_match_strval(guint32 val, const value_string *vs) {
565 result=match_strval(val,vs);
566 if (result == NULL ) {
571 static char *customValCheck(int code, int value)
574 case DIAMETER_ATT_QOS_SERVICE_TYPE:
575 return rd_match_strval(value, diameter_qos_service_type_vals);
577 case DIAMETER_ATT_SERVICE_TYPE:
578 return rd_match_strval(value, diameter_service_type_vals);
580 case DIAMETER_ATT_PROHIBIT:
581 return rd_match_strval(value, diameter_prohibit_vals);
583 case DIAMETER_ATT_PROMPT:
584 return rd_match_strval(value, diameter_prompt_vals);
586 case DIAMETER_ATT_SOURCE_PORT:
587 return rd_match_strval(value, diameter_source_port_vals);
589 case DIAMETER_ATT_NAS_PORT_TYPE:
590 return rd_match_strval(value, diameter_nas_port_type_vals);
592 case DIAMETER_ATT_INTERFACE_ADDRESS:
593 return rd_match_strval(value, diameter_interface_address_vals);
595 case DIAMETER_ATT_FRAMED_ROUTING:
596 return rd_match_strval(value, diameter_framed_routing_vals);
598 case DIAMETER_ATT_ARAP_ZONE_ACCESS:
599 return rd_match_strval(value, diameter_arap_zone_access_vals);
601 case DIAMETER_ATT_ACCT_AUTHENTIC:
602 return rd_match_strval(value, diameter_acct_authentic_vals);
604 case DIAMETER_ATT_FRAMED_PROTOCOL:
605 return rd_match_strval(value, diameter_framed_protocol_vals);
607 case DIAMETER_ATT_FRAMED_COMPRESSION:
608 return rd_match_strval(value, diameter_framed_compression_vals);
610 case DIAMETER_ATT_AUTHENTICATION_TYPE:
611 return rd_match_strval(value, diameter_authentication_type_vals);
613 case DIAMETER_ATT_ACCT_TERMINATE_CAUSE:
614 return rd_match_strval(value, diameter_acct_terminate_cause_vals);
616 case DIAMETER_ATT_PROTOCOL:
617 return rd_match_strval(value, diameter_protocol_vals);
619 case DIAMETER_ATT_DESTINATION_PORT:
620 return rd_match_strval(value, diameter_destination_port_vals);
622 case DIAMETER_ATT_TERMINATION_ACTION:
623 return rd_match_strval(value, diameter_termination_action_vals);
625 case DIAMETER_ATT_EXTENSION_ID:
626 return rd_match_strval(value, diameter_extension_id_vals);
628 case DIAMETER_ATT_MERIT_LAS_CODE:
629 return rd_match_strval(value, diameter_merit_las_code_vals);
631 case DIAMETER_ATT_LOGIN_SERVICE:
632 return rd_match_strval(value, diameter_login_service_vals);
634 case DIAMETER_ATT_RSVP_SERVICE_TYPE:
635 return rd_match_strval(value, diameter_rsvp_service_type_vals);
637 case DIAMETER_ATT_ACCT_STATUS_TYPE:
638 return rd_match_strval(value, diameter_acct_status_type_vals);
645 static gchar *rd_value_to_str(e_avphdr *avph, const u_char *input, int length)
650 static char buffer[1024];
652 /* prints the values of the attribute value pairs into a text buffer */
654 print_type=match_numval(avph->avp_code,diameter_printinfo);
656 /* Set the Default */
657 strcpy(buffer, "Unknown Value");
662 case DIAMETER_INTEGER32:
663 /* Check for custom values */
664 intval=pntohl(input);
665 valstr=customValCheck(avph->avp_code, intval);
667 sprintf(buffer,"%s (%u)", valstr, intval);
669 sprintf(buffer,"%d", intval);
672 case DIAMETER_UNSIGNED32:
673 /* Check for custom values */
674 intval=pntohl(input);
675 valstr=customValCheck(avph->avp_code, intval);
677 sprintf(buffer,"%s (%u)", valstr, intval);
679 sprintf(buffer,"%u", intval);
683 /* XXX - have to handle platforms without 64-bit integral
685 Have to handle platforms where "%lld" and "%llu"
686 aren't the right formats to use to print 64-bit integral
688 case DIAMETER_INTEGER64:
691 llval = pntohll(input);
692 sprintf(buffer,"%lld", llval);
695 case DIAMETER_UNSIGNED64:
698 llval = pntohll(input);
699 sprintf(buffer,"%llu", llval);
706 intval=pntohl(input);
707 intval -= NTP_TIME_DIFF;
708 lt=*localtime((time_t *)&intval);
709 strftime(buffer, 1024,
710 "%a, %d %b %Y %H:%M:%S %z",<);
717 } /* rd value to str */
720 DetermineMessageType(char flagsVer)
722 /* Get rid of version */
723 flagsVer = flagsVer >> 3;
725 /* Mask out reserved bits */
726 flagsVer = flagsVer & 0x7;
729 case 0x0: /* Indication */
731 case 0x4: /* Request */
733 case 0x1: /* Answer */
735 case 0x6: /* Query */
737 case 0x3: /* Reply */
740 return "Illegal Command Type";
742 } /* DetermineMessageType */
746 proto_reg_handoff_diameter(void)
748 static int Initialized=FALSE;
749 static int TcpPort=0;
750 static int SctpPort=0;
753 dissector_delete("tcp.port", TcpPort, dissect_diameter);
754 dissector_delete("sctp.port", SctpPort, dissect_diameter);
759 /* set port for future deletes */
760 TcpPort=gbl_diameterTcpPort;
761 SctpPort=gbl_diameterSctpPort;
763 strcpy(gbl_diameterString, "Diameter Protocol");
765 /* g_warning ("Diameter: Adding tcp dissector to port %d",
766 gbl_diameterTcpPort); */
767 dissector_add("tcp.port", gbl_diameterTcpPort, dissect_diameter,
769 dissector_add("sctp.port", gbl_diameterSctpPort,
770 dissect_diameter, proto_diameter);
773 /* registration with the filtering engine */
775 proto_register_diameter(void)
778 static hf_register_info hf[] = {
779 { &hf_diameter_reserved,
780 { "Reserved", "diameter.reserved", FT_UINT8, BASE_HEX, NULL, 0x0,
781 "Should be zero", HFILL }},
782 { &hf_diameter_flags,
783 { "Flags", "diameter.flags", FT_UINT8, BASE_HEX, NULL, 0xf8,
785 { &hf_diameter_version,
786 { "Version", "diameter.version", FT_UINT8, BASE_HEX, NULL, 0x07,
788 { &hf_diameter_length,
789 { "Length","diameter.length", FT_UINT16, BASE_DEC, NULL, 0x0,
791 { &hf_diameter_hopbyhopid,
792 { "Hop-by-Hop Identifier", "diameter.hopbyhopid", FT_UINT32,
793 BASE_HEX, NULL, 0x0, "", HFILL }},
794 { &hf_diameter_endtoendid,
795 { "End-to-End Identifier", "diameter.endtoendid", FT_UINT32,
796 BASE_HEX, NULL, 0x0, "", HFILL }},
798 { "Command Code","diameter.code", FT_UINT32, BASE_DEC,
799 VALS(diameter_command_code_vals), 0x0, "", HFILL }},
800 { &hf_diameter_vendor_id,
801 { "VendorId", "diameter.vendorId", FT_UINT32, BASE_DEC, NULL, 0x0,
804 { &hf_diameter_avp_code,
805 { "AVP Code","diameter.avp.code", FT_UINT32, BASE_DEC,
806 VALS(diameter_attrib_type_vals), 0x0, "", HFILL }},
807 { &hf_diameter_avp_length,
808 { "AVP length","diameter.avp.length", FT_UINT16, BASE_DEC,
809 NULL, 0x0, "", HFILL }},
810 { &hf_diameter_avp_reserved,
811 { "AVP Reserved","diameter.avp.reserved", FT_UINT8, BASE_HEX,
812 NULL, 0x0, "Should be Zero", HFILL }},
813 { &hf_diameter_avp_flags,
814 { "AVP Flags","diameter.avp.flags", FT_UINT8, BASE_HEX,
815 NULL, 0x1f, "", HFILL }},
816 { &hf_diameter_avp_vendor_id,
817 { "AVP Vendor Id","diameter.avp.vendorId", FT_UINT32, BASE_DEC,
818 NULL, 0x0, "", HFILL }},
819 { &hf_diameter_avp_data_uint32,
820 { "AVP Data","diameter.avp.data.uint32", FT_UINT32, BASE_DEC,
821 NULL, 0x0, "", HFILL }},
823 { &hf_diameter_avp_data_uint64,
824 { "AVP Data","diameter.avp.data.uint64", FT_UINT64, BASE_DEC,
825 NULL, 0x0, "", HFILL }},
827 { &hf_diameter_avp_data_int32,
828 { "AVP Data","diameter.avp.data.int32", FT_INT32, BASE_DEC,
829 NULL, 0x0, "", HFILL }},
831 { &hf_diameter_avp_data_int64,
832 { "AVP Data","diameter.avp.data.int64", FT_INT_64, BASE_DEC,
833 NULL, 0x0, "", HFILL }},
835 { &hf_diameter_avp_data_bytes,
836 { "AVP Data","diameter.avp.data.bytes", FT_BYTES, BASE_NONE,
837 NULL, 0x0, "", HFILL }},
839 { &hf_diameter_avp_data_string,
840 { "AVP Data","diameter.avp.data.string", FT_STRING, BASE_NONE,
841 NULL, 0x0, "", HFILL }},
842 { &hf_diameter_avp_data_v4addr,
843 { "AVP Data","diameter.avp.data.v4addr", FT_IPv4, BASE_NONE,
844 NULL, 0x0, "", HFILL }},
845 { &hf_diameter_avp_data_v6addr,
846 { "AVP Data","diameter.avp.data.v6addr", FT_IPv6, BASE_NONE,
847 NULL, 0x0, "", HFILL }},
848 { &hf_diameter_avp_data_time,
849 { "AVP Data","diameter.avp.data.time", FT_ABSOLUTE_TIME, BASE_NONE,
850 NULL, 0x0, "", HFILL }},
853 static gint *ett[] = {
856 &ett_diameter_avpinfo
858 module_t *diameter_module;
860 proto_diameter = proto_register_protocol (gbl_diameterString,
861 "DIAMETER", "diameter");
862 proto_register_field_array(proto_diameter, hf, array_length(hf));
863 proto_register_subtree_array(ett, array_length(ett));
865 /* Register a configuration option for port */
866 diameter_module = prefs_register_protocol(proto_diameter,
867 proto_reg_handoff_diameter);
868 prefs_register_uint_preference(diameter_module, "tcp.port",
870 "Set the TCP port for DIAMETER messages",
872 &gbl_diameterTcpPort);
873 prefs_register_uint_preference(diameter_module, "sctp.port",
874 "DIAMETER SCTP Port",
875 "Set the SCTP port for DIAMETER messages",
877 &gbl_diameterSctpPort);