Ethereal-dev: [ethereal-dev] Code for ISAKMP, GRE, and PPTP
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Brad Robel-Forrest <bradr@xxxxxxxxxxxxxx>
Date: Tue, 8 Jun 1999 17:15:54 -0700 (PDT)
Here is the diff and code to enable the parsed display of ISAKMP, GRE, and PPTP packets. I've stubbed out the call that could be made from the GRE dissection code to dump possible PPP encapsulated packets until the dissect code for PPP can accept offsets (which I think Jeff Jahr <jjahr@xxxxxxxxxxxxxx> has recently mailed a patch for). Please let me know of any problems or anything else I can provide to have this added to the CVS tree. The diff is based on an update I did today, so everything should be current. -brad
Attachment:
ethereal.diff
Description: ethereal.diff
/* packet-gre.c * Routines for the Internet Security Association and Key Management Protocol (ISAKMP) * Brad Robel-Forrest <brad.robel-forrest@xxxxxxxxxxxxxx> * * $Id$ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@xxxxxxxxxx> * Copyright 1998 Gerald Combs * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #ifdef HAVE_SYS_TYPES_H # include <sys/types.h> #endif #include <stdio.h> #include <netinet/in.h> #include <glib.h> #include "packet.h" #define NUM_PROTO_TYPES 5 #define proto2str(t) \ ((t < NUM_PROTO_TYPES) ? prototypestr[t] : "UNKNOWN-PROTO-TYPE") static const char *prototypestr[NUM_PROTO_TYPES] = { "RESERVED", "ISAKMP", "IPSEC_AH", "IPSEC_ESP", "IPCOMP" }; #define NUM_ATT_TYPES 13 #define atttype2str(t) \ ((t < NUM_ATT_TYPES) ? atttypestr[t] : "UNKNOWN-ATTRIBUTE-TYPE") static const char *atttypestr[NUM_ATT_TYPES] = { "UNKNOWN-ATTRIBUTE-TYPE", "SA-Life-Type", "SA-Life-Duration", "Group-Description", "Encapsulation-Mode", "Authentication-Algorithm", "Key-Length", "Key-Rounds", "Compress-Dictinary-Size", "Compress-Private-Algorithm" "UNKNOWN-ATTRIBUTE-TYPE", "Oakley-Life", "Oakley-Value", "Oakley-Life-Duration" }; #define NUM_TRANS_TYPES 2 #define trans2str(t) \ ((t < NUM_TRANS_TYPES) ? transtypestr[t] : "UNKNOWN-TRANS-TYPE") static const char *transtypestr[NUM_TRANS_TYPES] = { "RESERVED", "KEY_IKE" }; #define NUM_ID_TYPES 12 #define id2str(t) \ ((t < NUM_ID_TYPES) ? idtypestr[t] : "UNKNOWN-ID-TYPE") static const char *idtypestr[NUM_ID_TYPES] = { "RESERVED", "IPV4_ADDR", "FQDN", "USER_FQDN", "IPV4_ADDR_SUBNET", "IPV6_ADDR", "IPV6_ADDR_SUBNET", "IPV4_ADDR_RANGE", "IPV6_ADDR_RANGE", "DER_ASN1_DN", "DER_ASN1_GN", "KEY_ID" }; struct isakmp_hdr { guint8 icookie[8]; guint8 rcookie[8]; guint8 next_payload; guint8 version; guint8 exch_type; guint8 flags; #define E_FLAG 0x01 #define C_FLAG 0x02 #define A_FLAG 0x04 guint32 message_id; guint32 length; }; struct sa_hdr { guint8 next_payload; guint8 reserved; guint16 length; guint32 doi; guint32 situation; }; struct proposal_hdr { guint8 next_payload; guint8 reserved; guint16 length; guint8 proposal_num; guint8 protocol_id; guint8 spi_size; guint8 num_transforms; }; struct trans_hdr { guint8 next_payload; guint8 reserved; guint16 length; guint8 transform_num; guint8 transform_id; guint16 reserved2; }; #define TRANS_LEN(p) (ntohs(((struct trans_hdr *)(p))->length)) struct ke_hdr { guint8 next_payload; guint8 reserved; guint16 length; }; struct id_hdr { guint8 next_payload; guint8 reserved; guint16 length; guint8 id_type; guint8 protocol_id; guint16 port; }; struct cert_hdr { guint8 next_payload; guint8 reserved; guint16 length; guint8 cert_enc; }; struct certreq_hdr { guint8 next_payload; guint8 reserved; guint16 length; guint8 cert_type; }; struct hash_hdr { guint8 next_payload; guint8 reserved; guint16 length; }; struct sig_hdr { guint8 next_payload; guint8 reserved; guint16 length; }; struct nonce_hdr { guint8 next_payload; guint8 reserved; guint16 length; }; struct notif_hdr { guint8 next_payload; guint8 reserved; guint16 length; guint32 doi; guint8 protocol_id; guint8 spi_size; guint16 msgtype; }; struct delete_hdr { guint8 next_payload; guint8 reserved; guint16 length; guint32 doi; guint8 protocol_id; guint8 spi_size; guint16 num_spis; }; struct vid_hdr { guint8 next_payload; guint8 reserved; guint16 length; }; static void dissect_none(const u_char *, int, frame_data *, proto_tree *); static void dissect_sa(const u_char *, int, frame_data *, proto_tree *); static void dissect_proposal(const u_char *, int, frame_data *, proto_tree *); static void dissect_transform(const u_char *, int, frame_data *, proto_tree *); static void dissect_key_exch(const u_char *, int, frame_data *, proto_tree *); static void dissect_id(const u_char *, int, frame_data *, proto_tree *); static void dissect_cert(const u_char *, int, frame_data *, proto_tree *); static void dissect_certreq(const u_char *, int, frame_data *, proto_tree *); static void dissect_hash(const u_char *, int, frame_data *, proto_tree *); static void dissect_sig(const u_char *, int, frame_data *, proto_tree *); static void dissect_nonce(const u_char *, int, frame_data *, proto_tree *); static void dissect_notif(const u_char *, int, frame_data *, proto_tree *); static void dissect_delete(const u_char *, int, frame_data *, proto_tree *); static void dissect_vid(const u_char *, int, frame_data *, proto_tree *); static const char *payloadtype2str(guint8); static const char *exchtype2str(guint8); static const char *doitype2str(guint32); static const char *msgtype2str(guint16); static const char *situation2str(guint32); static const char *value2str(guint16, guint16); static const char *num2str(const guint8 *, guint16); #define NUM_LOAD_TYPES 14 #define loadtype2str(t) \ ((t < NUM_LOAD_TYPES) ? strfuncs[t].str : "Unknown payload type") static struct strfunc { const char * str; void (*func)(const u_char *, int, frame_data *, proto_tree *); } strfuncs[NUM_LOAD_TYPES] = { {"NONE", dissect_none }, {"Security Association", dissect_sa }, {"Proposal", dissect_proposal }, {"Transform", dissect_transform }, {"Key Exchange", dissect_key_exch }, {"Identification", dissect_id }, {"Certificate", dissect_cert }, {"Certificate Request", dissect_certreq }, {"Hash", dissect_hash }, {"Signature", dissect_sig }, {"Nonce", dissect_nonce }, {"Notification", dissect_notif }, {"Delete", dissect_delete }, {"Vendor ID", dissect_vid } }; void dissect_isakmp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct isakmp_hdr * hdr = (struct isakmp_hdr *)(pd + offset); guint32 len; if (check_col(fd, COL_PROTOCOL)) col_add_str(fd, COL_PROTOCOL, "ISAKMP"); len = ntohl(hdr->length); if (check_col(fd, COL_INFO)) col_add_fstr(fd, COL_INFO, "%s", exchtype2str(hdr->exch_type)); if (fd->cap_len > offset && tree) { proto_item * ti; proto_tree * isakmp_tree; ti = proto_tree_add_item(tree, offset, len, "Internet Security Association and Key Management Protocol"); isakmp_tree = proto_tree_new(); proto_item_add_subtree(ti, isakmp_tree, ETT_ISAKMP); proto_tree_add_item(isakmp_tree, offset, sizeof(hdr->icookie), "Initiator cookie"); offset += sizeof(hdr->icookie); proto_tree_add_item(isakmp_tree, offset, sizeof(hdr->rcookie), "Responder cookie"); offset += sizeof(hdr->rcookie); proto_tree_add_item(isakmp_tree, offset, sizeof(hdr->next_payload), "Next payload: %s (%u)", payloadtype2str(hdr->next_payload), hdr->next_payload); offset += sizeof(hdr->next_payload); proto_tree_add_item(isakmp_tree, offset, sizeof(hdr->version), "Version: %u.%u", hi_nibble(hdr->version), lo_nibble(hdr->version)); offset += sizeof(hdr->version); proto_tree_add_item(isakmp_tree, offset, sizeof(hdr->exch_type), "Exchange type: %s (%u)", exchtype2str(hdr->exch_type), hdr->exch_type); offset += sizeof(hdr->exch_type); { proto_item * fti; proto_tree * ftree; fti = proto_tree_add_item(isakmp_tree, offset, sizeof(hdr->flags), "Flags"); ftree = proto_tree_new(); proto_item_add_subtree(fti, ftree, ETT_ISAKMP_FLAGS); proto_tree_add_item(ftree, offset, 1, "%s", decode_boolean_bitfield(hdr->flags, E_FLAG, sizeof(hdr->flags)*8, "Encryption", "No encryption")); proto_tree_add_item(ftree, offset, 1, "%s", decode_boolean_bitfield(hdr->flags, C_FLAG, sizeof(hdr->flags)*8, "Commit", "No commit")); proto_tree_add_item(ftree, offset, 1, "%s", decode_boolean_bitfield(hdr->flags, A_FLAG, sizeof(hdr->flags)*8, "Authentication", "No authentication")); offset += sizeof(hdr->flags); } proto_tree_add_item(isakmp_tree, offset, sizeof(hdr->message_id), "Message ID"); offset += sizeof(hdr->message_id); proto_tree_add_item(isakmp_tree, offset, sizeof(hdr->length), "Length: %u", len); offset += sizeof(hdr->length); if (hdr->next_payload < NUM_LOAD_TYPES) (*strfuncs[hdr->next_payload].func)(pd, offset, fd, isakmp_tree); else dissect_data(pd, offset, fd, isakmp_tree); } } static void dissect_none(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { } static void dissect_sa(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct sa_hdr * hdr = (struct sa_hdr *)(pd + offset); guint16 length = ntohs(hdr->length); guint32 doi = ntohl(hdr->doi); guint32 situation = ntohl(hdr->situation); proto_item * ti = proto_tree_add_item(tree, offset, length, "Security Association payload"); proto_tree * ntree = proto_tree_new(); proto_item_add_subtree(ti, ntree, ETT_ISAKMP_PAYLOAD); proto_tree_add_item(ntree, offset, sizeof(hdr->next_payload), "Next payload: %s (%u)", payloadtype2str(hdr->next_payload), hdr->next_payload); offset += sizeof(hdr->next_payload) * 2; proto_tree_add_item(ntree, offset, sizeof(length), "Length: %u", length); offset += sizeof(length); proto_tree_add_item(ntree, offset, sizeof(doi), "Domain of interpretation: %s (%u)", doitype2str(doi), doi); offset += sizeof(doi); proto_tree_add_item(ntree, offset, sizeof(situation), "Situation: %s (%u)", situation2str(situation), situation); offset += sizeof(situation); dissect_proposal(pd, offset, fd, ntree); offset += (length - sizeof(*hdr)); if (hdr->next_payload < NUM_LOAD_TYPES) (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree); else dissect_data(pd, offset, fd, tree); } static void dissect_proposal(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct proposal_hdr * hdr = (struct proposal_hdr *)(pd + offset); guint16 length = ntohs(hdr->length); proto_item * ti = proto_tree_add_item(tree, offset, length, "Proposal payload"); proto_tree * ntree = proto_tree_new(); guint8 i; proto_item_add_subtree(ti, ntree, ETT_ISAKMP_PAYLOAD); proto_tree_add_item(ntree, offset, sizeof(hdr->next_payload), "Next payload: %s (%u)", payloadtype2str(hdr->next_payload), hdr->next_payload); offset += sizeof(hdr->next_payload) * 2; proto_tree_add_item(ntree, offset, sizeof(length), "Length: %u", length); offset += sizeof(length); proto_tree_add_item(ntree, offset, sizeof(hdr->proposal_num), "Proposal number: %u", hdr->proposal_num); offset += sizeof(hdr->proposal_num); proto_tree_add_item(ntree, offset, sizeof(hdr->protocol_id), "Protocol ID: %s (%u)", proto2str(hdr->protocol_id), hdr->protocol_id); offset += sizeof(hdr->protocol_id); proto_tree_add_item(ntree, offset, sizeof(hdr->spi_size), "SPI size: %u", hdr->spi_size); offset += sizeof(hdr->spi_size); if (hdr->spi_size) { proto_tree_add_item(ntree, offset, hdr->spi_size, "SPI"); offset += hdr->spi_size; } proto_tree_add_item(ntree, offset, sizeof(hdr->num_transforms), "Number of transforms: %u", hdr->num_transforms); offset += sizeof(hdr->num_transforms); for (i = 0; i < hdr->num_transforms; ++i) { dissect_transform(pd, offset, fd, ntree); offset += TRANS_LEN(pd+offset); } if (hdr->next_payload < NUM_LOAD_TYPES) (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree); else dissect_data(pd, offset, fd, tree); } static void dissect_transform(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct trans_hdr * hdr = (struct trans_hdr *)(pd + offset); guint16 length = ntohs(hdr->length); proto_item * ti = proto_tree_add_item(tree, offset, length, "Transform payload"); proto_tree * ntree = proto_tree_new(); proto_item_add_subtree(ti, ntree, ETT_ISAKMP_PAYLOAD); proto_tree_add_item(ntree, offset, sizeof(hdr->next_payload), "Next payload: %s (%u)", payloadtype2str(hdr->next_payload), hdr->next_payload); offset += sizeof(hdr->next_payload) * 2; proto_tree_add_item(ntree, offset, sizeof(length), "Length: %u", length); offset += sizeof(length); proto_tree_add_item(ntree, offset, sizeof(hdr->transform_num), "Transform number: %u", hdr->transform_num); offset += sizeof(hdr->transform_num); proto_tree_add_item(ntree, offset, sizeof(hdr->transform_id), "Transform ID: %s (%u)", trans2str(hdr->transform_id), hdr->transform_id); offset += sizeof(hdr->transform_id) + sizeof(hdr->reserved2); length -= sizeof(*hdr); while (length) { guint16 type = ntohs(*(guint16 *)(pd + offset)) & 0x7fff; guint16 val_len = ntohs(*(guint16 *)(pd + offset + 2)); if (pd[offset] & 0xf0) { proto_tree_add_item(ntree, offset, 4, "%s (%u): %s (%u)", atttype2str(type), type, value2str(type, val_len), val_len); offset += 4; length -= 4; } else { guint16 pack_len = 4 + val_len; proto_tree_add_item(ntree, offset, pack_len, "%s (%u): %s", atttype2str(type), type, num2str(pd + offset + 4, val_len)); offset += pack_len; length -= pack_len; } } if (hdr->next_payload < NUM_LOAD_TYPES) (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree); else dissect_data(pd, offset, fd, tree); } static void dissect_key_exch(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct ke_hdr * hdr = (struct ke_hdr *)(pd + offset); guint16 length = ntohs(hdr->length); proto_item * ti = proto_tree_add_item(tree, offset, length, "Key Exchange payload"); proto_tree * ntree = proto_tree_new(); proto_item_add_subtree(ti, ntree, ETT_ISAKMP_PAYLOAD); proto_tree_add_item(ntree, offset, sizeof(hdr->next_payload), "Next payload: %s (%u)", payloadtype2str(hdr->next_payload), hdr->next_payload); offset += sizeof(hdr->next_payload) * 2; proto_tree_add_item(ntree, offset, sizeof(length), "Length: %u", length); offset += sizeof(length); proto_tree_add_item(ntree, offset, length - sizeof(*hdr), "Key Exchange Data"); offset += (length - sizeof(*hdr)); if (hdr->next_payload < NUM_LOAD_TYPES) (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree); else dissect_data(pd, offset, fd, tree); } static void dissect_id(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct id_hdr * hdr = (struct id_hdr *)(pd + offset); guint16 length = ntohs(hdr->length); proto_item * ti = proto_tree_add_item(tree, offset, length, "Identification payload"); proto_tree * ntree = proto_tree_new(); proto_item_add_subtree(ti, ntree, ETT_ISAKMP_PAYLOAD); proto_tree_add_item(ntree, offset, sizeof(hdr->next_payload), "Next payload: %s (%u)", payloadtype2str(hdr->next_payload), hdr->next_payload); offset += sizeof(hdr->next_payload) * 2; proto_tree_add_item(ntree, offset, sizeof(length), "Length: %u", length); offset += sizeof(length); proto_tree_add_item(ntree, offset, sizeof(hdr->id_type), "ID type: %s (%u)", id2str(hdr->id_type), hdr->id_type); offset += sizeof(hdr->id_type); proto_tree_add_item(ntree, offset, sizeof(hdr->protocol_id), "Protocol ID: %u", hdr->protocol_id); offset += sizeof(hdr->protocol_id); proto_tree_add_item(ntree, offset, sizeof(hdr->port), "Port: %u", ntohs(hdr->port)); offset += sizeof(hdr->port); switch (hdr->id_type) { case 1: case 4: proto_tree_add_item(ntree, offset, length-sizeof(*hdr), "Identification data: %s", ip_to_str(pd+offset)); break; case 2: case 3: proto_tree_add_item(ntree, offset, length-sizeof(*hdr), "Identification data: %s", (char *)(pd+offset)); break; default: proto_tree_add_item(ntree, offset, length - sizeof(*hdr), "Identification Data"); } offset += (length - sizeof(*hdr)); if (hdr->next_payload < NUM_LOAD_TYPES) (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree); else dissect_data(pd, offset, fd, tree); } static void dissect_cert(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct cert_hdr * hdr = (struct cert_hdr *)(pd + offset); guint16 length = ntohs(hdr->length); proto_item * ti = proto_tree_add_item(tree, offset, length, "Certificate payload"); proto_tree * ntree = proto_tree_new(); proto_item_add_subtree(ti, ntree, ETT_ISAKMP_PAYLOAD); proto_tree_add_item(ntree, offset, sizeof(hdr->next_payload), "Next payload: %s (%u)", payloadtype2str(hdr->next_payload), hdr->next_payload); offset += sizeof(hdr->next_payload) * 2; proto_tree_add_item(ntree, offset, sizeof(length), "Length: %u", length); offset += sizeof(length); proto_tree_add_item(ntree, offset, sizeof(hdr->cert_enc), "Certificate encoding: %u", hdr->cert_enc); offset += sizeof(hdr->cert_enc); proto_tree_add_item(ntree, offset, length - sizeof(*hdr), "Certificate Data"); offset += (length - sizeof(*hdr)); if (hdr->next_payload < NUM_LOAD_TYPES) (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree); else dissect_data(pd, offset, fd, tree); } static void dissect_certreq(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct certreq_hdr * hdr = (struct certreq_hdr *)(pd + offset); guint16 length = ntohs(hdr->length); proto_item * ti = proto_tree_add_item(tree, offset, length, "Certificate Request payload"); proto_tree * ntree = proto_tree_new(); proto_item_add_subtree(ti, ntree, ETT_ISAKMP_PAYLOAD); proto_tree_add_item(ntree, offset, sizeof(hdr->next_payload), "Next payload: %s (%u)", payloadtype2str(hdr->next_payload), hdr->next_payload); offset += sizeof(hdr->next_payload) * 2; proto_tree_add_item(ntree, offset, sizeof(length), "Length: %u", length); offset += sizeof(length); proto_tree_add_item(ntree, offset, sizeof(hdr->cert_type), "Certificate type: %u", hdr->cert_type); offset += sizeof(hdr->cert_type); proto_tree_add_item(ntree, offset, length - sizeof(*hdr), "Certificate Authority"); offset += (length - sizeof(*hdr)); if (hdr->next_payload < NUM_LOAD_TYPES) (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree); else dissect_data(pd, offset, fd, tree); } static void dissect_hash(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct hash_hdr * hdr = (struct hash_hdr *)(pd + offset); guint16 length = ntohs(hdr->length); proto_item * ti = proto_tree_add_item(tree, offset, length, "Hash payload"); proto_tree * ntree = proto_tree_new(); proto_item_add_subtree(ti, ntree, ETT_ISAKMP_PAYLOAD); proto_tree_add_item(ntree, offset, sizeof(hdr->next_payload), "Next payload: %s (%u)", payloadtype2str(hdr->next_payload), hdr->next_payload); offset += sizeof(hdr->next_payload) * 2; proto_tree_add_item(ntree, offset, sizeof(length), "Length: %u", length); offset += sizeof(length); proto_tree_add_item(ntree, offset, length - sizeof(*hdr), "Hash Data"); offset += (length - sizeof(*hdr)); if (hdr->next_payload < NUM_LOAD_TYPES) (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree); else dissect_data(pd, offset, fd, tree); } static void dissect_sig(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct sig_hdr * hdr = (struct sig_hdr *)(pd + offset); guint16 length = ntohs(hdr->length); proto_item * ti = proto_tree_add_item(tree, offset, length, "Signature payload"); proto_tree * ntree = proto_tree_new(); proto_item_add_subtree(ti, ntree, ETT_ISAKMP_PAYLOAD); proto_tree_add_item(ntree, offset, sizeof(hdr->next_payload), "Next payload: %s (%u)", payloadtype2str(hdr->next_payload), hdr->next_payload); offset += sizeof(hdr->next_payload) * 2; proto_tree_add_item(ntree, offset, sizeof(length), "Length: %u", length); offset += sizeof(length); proto_tree_add_item(ntree, offset, length - sizeof(*hdr), "Signature Data"); offset += (length - sizeof(*hdr)); if (hdr->next_payload < NUM_LOAD_TYPES) (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree); else dissect_data(pd, offset, fd, tree); } static void dissect_nonce(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct nonce_hdr * hdr = (struct nonce_hdr *)(pd + offset); guint16 length = ntohs(hdr->length); proto_item * ti = proto_tree_add_item(tree, offset, length, "Nonce payload"); proto_tree * ntree = proto_tree_new(); proto_item_add_subtree(ti, ntree, ETT_ISAKMP_PAYLOAD); proto_tree_add_item(ntree, offset, sizeof(hdr->next_payload), "Next payload: %s (%u)", payloadtype2str(hdr->next_payload), hdr->next_payload); offset += sizeof(hdr->next_payload) * 2; proto_tree_add_item(ntree, offset, sizeof(length), "Length: %u", length); offset += sizeof(length); proto_tree_add_item(ntree, offset, length - sizeof(*hdr), "Nonce Data"); offset += (length - sizeof(*hdr)); if (hdr->next_payload < NUM_LOAD_TYPES) (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree); else dissect_data(pd, offset, fd, tree); } static void dissect_notif(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct notif_hdr * hdr = (struct notif_hdr *)(pd + offset); guint16 length = ntohs(hdr->length); guint32 doi = ntohl(hdr->doi); guint16 msgtype = ntohs(hdr->msgtype); proto_item * ti = proto_tree_add_item(tree, offset, length, "Notification payload"); proto_tree * ntree = proto_tree_new(); proto_item_add_subtree(ti, ntree, ETT_ISAKMP_PAYLOAD); proto_tree_add_item(ntree, offset, sizeof(hdr->next_payload), "Next payload: %s (%u)", payloadtype2str(hdr->next_payload), hdr->next_payload); offset += sizeof(hdr->next_payload) * 2; proto_tree_add_item(ntree, offset, sizeof(length), "Length: %u", length); offset += sizeof(length); proto_tree_add_item(ntree, offset, sizeof(doi), "Domain of Interpretation: %s (%u)", doitype2str(doi), doi); offset += sizeof(doi); proto_tree_add_item(ntree, offset, sizeof(hdr->protocol_id), "Protocol ID: %s (%u)", proto2str(hdr->protocol_id), hdr->protocol_id); offset += sizeof(hdr->protocol_id); proto_tree_add_item(ntree, offset, sizeof(hdr->spi_size), "SPI size: %u", hdr->spi_size); offset += sizeof(hdr->spi_size); proto_tree_add_item(ntree, offset, sizeof(msgtype), "Message type: %s (%u)", msgtype2str(msgtype), msgtype); offset += sizeof(msgtype); if (hdr->spi_size) { proto_tree_add_item(ntree, offset, hdr->spi_size, "Security Parameter Index"); offset += hdr->spi_size; } if (length - sizeof(*hdr)) { proto_tree_add_item(ntree, offset, length - sizeof(*hdr) - hdr->spi_size, "Notification Data"); offset += (length - sizeof(*hdr) - hdr->spi_size); } if (hdr->next_payload < NUM_LOAD_TYPES) (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree); else dissect_data(pd, offset, fd, tree); } static void dissect_delete(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct delete_hdr * hdr = (struct delete_hdr *)(pd + offset); guint16 length = ntohs(hdr->length); guint32 doi = ntohl(hdr->doi); guint16 num_spis = ntohs(hdr->num_spis); proto_item * ti = proto_tree_add_item(tree, offset, length, "Delete payload"); proto_tree * ntree = proto_tree_new(); guint16 i; proto_item_add_subtree(ti, ntree, ETT_ISAKMP_PAYLOAD); proto_tree_add_item(ntree, offset, sizeof(hdr->next_payload), "Next payload: %s (%u)", payloadtype2str(hdr->next_payload), hdr->next_payload); offset += sizeof(hdr->next_payload) * 2; proto_tree_add_item(ntree, offset, sizeof(length), "Length: %u", length); offset += sizeof(length); proto_tree_add_item(ntree, offset, sizeof(doi), "Domain of Interpretation: %s (%u)", doitype2str(doi), doi); offset += sizeof(doi); proto_tree_add_item(ntree, offset, sizeof(hdr->protocol_id), "Protocol ID: %s (%u)", proto2str(hdr->protocol_id), hdr->protocol_id); offset += sizeof(hdr->protocol_id); proto_tree_add_item(ntree, offset, sizeof(hdr->spi_size), "SPI size: %u", hdr->spi_size); offset += sizeof(hdr->spi_size); proto_tree_add_item(ntree, offset, num_spis, "Number of SPIs: %u", num_spis); offset += sizeof(hdr->num_spis); for (i = 0; i < num_spis; ++i) { proto_tree_add_item(ntree, offset, hdr->spi_size, "SPI (%d)", i); offset += hdr->spi_size; } if (hdr->next_payload < NUM_LOAD_TYPES) (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree); else dissect_data(pd, offset, fd, tree); } static void dissect_vid(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct vid_hdr * hdr = (struct vid_hdr *)(pd + offset); guint16 length = ntohs(hdr->length); proto_item * ti = proto_tree_add_item(tree, offset, length, "Vendor ID payload"); proto_tree * ntree = proto_tree_new(); proto_item_add_subtree(ti, ntree, ETT_ISAKMP_PAYLOAD); proto_tree_add_item(ntree, offset, sizeof(hdr->next_payload), "Next payload: %s (%u)", payloadtype2str(hdr->next_payload), hdr->next_payload); offset += sizeof(hdr->next_payload) * 2; proto_tree_add_item(ntree, offset, sizeof(length), "Length: %u", length); offset += sizeof(length); proto_tree_add_item(ntree, offset, length - sizeof(*hdr), "Vendor ID"); offset += (length - sizeof(*hdr)); if (hdr->next_payload < NUM_LOAD_TYPES) (*strfuncs[hdr->next_payload].func)(pd, offset, fd, tree); else dissect_data(pd, offset, fd, tree); } static const char * payloadtype2str(guint8 type) { if (type < NUM_LOAD_TYPES) return strfuncs[type].str; if (type < 128) return "RESERVED"; if (type < 256) return "Private USE"; return "Huh? You should never see this! Shame on you!"; } static const char * exchtype2str(guint8 type) { #define NUM_EXCHSTRS 6 static const char * exchstrs[NUM_EXCHSTRS] = { "NONE", "Base", "Identity Protection", "Authentication Only", "Aggressive", "Informational" }; if (type < NUM_EXCHSTRS) return exchstrs[type]; if (type < 32) return "ISAKMP Future Use"; if (type < 240) return "DOI Specific Use"; if (type < 256) return "Private Use"; return "Huh? You should never see this! Shame on you!"; } static const char * doitype2str(guint32 type) { if (type == 1) return "IPSEC"; return "Unknown DOI Type"; } static const char * msgtype2str(guint16 type) { #define NUM_PREDEFINED 31 static const char *msgs[NUM_PREDEFINED] = { "<UNKNOWN>", "INVALID-PAYLOAD-TYPE", "DOI-NOT-SUPPORTED", "SITUATION-NOT-SUPPORTED", "INVALID-COOKIE", "INVALID-MAJOR-VERSION", "INVALID-MINOR-VERSION", "INVALID-EXCHANGE-TYPE", "INVALID-FLAGS", "INVALID-MESSAGE-ID", "INVALID-PROTOCOL-ID", "INVALID-SPI", "INVALID-TRANSFORM-ID", "ATTRIBUTES-NOT-SUPPORTED", "NO-PROPOSAL-CHOSEN", "BAD-PROPOSAL-SYNTAX", "PAYLOAD-MALFORMED", "INVALID-KEY-INFORMATION", "INVALID-ID-INFORMATION", "INVALID-CERT-ENCODING", "INVALID-CERTIFICATE", "CERT-TYPE-UNSUPPORTED", "INVALID-CERT-AUTHORITY", "INVALID-HASH-INFORMATION", "AUTHENTICATION-FAILED", "INVALID-SIGNATURE", "ADDRESS-NOTIFICATION", "NOTIFY-SA-LIFETIME", "CERTIFICATE-UNAVAILABLE", "UNSUPPORTED-EXCHANGE-TYPE", "UNEQUAL-PAYLOAD-LENGTHS" }; if (type < NUM_PREDEFINED) return msgs[type]; if (type < 8192) return "RESERVED (Future Use)"; if (type < 16384) return "Private Use"; if (type < 16385) return "CONNECTED"; if (type < 24576) return "RESERVED (Future Use) - status"; if (type < 24577) return "RESPONDER-LIFETIME"; if (type < 24578) return "REPLAY-STATUS"; if (type < 24579) return "INITIAL-CONTACT"; if (type < 32768) return "DOI-specific codes"; if (type < 40960) return "Private Use - status"; if (type < 65535) return "RESERVED (Future Use) - status (2)"; return "Huh? You should never see this! Shame on you!"; } static const char * situation2str(guint32 type) { #define SIT_MSG_NUM 1024 #define SIT_IDENTITY 0x01 #define SIT_SECRECY 0x02 #define SIT_INTEGRITY 0x04 static char msg[SIT_MSG_NUM]; int n = 0; char * sep = ""; if (type & SIT_IDENTITY) { n += snprintf(msg, SIT_MSG_NUM-n, "%sIDENTITY", sep); sep = " & "; } if (type & SIT_SECRECY) { n += snprintf(msg, SIT_MSG_NUM-n, "%sSECRECY", sep); sep = " & "; } if (type & SIT_INTEGRITY) { n += snprintf(msg, SIT_MSG_NUM-n, "%sINTEGRITY", sep); sep = " & "; } return msg; } static const char * value2str(guint16 att_type, guint16 value) { if (value == 0) return "RESERVED"; switch (att_type) { case 1: case 2: switch (value) { case 1: return "Seconds"; case 2: return "Kilobytes"; default: return "UNKNOWN-SA-VALUE"; } case 3: return "Group-Value"; case 4: switch (value) { case 1: return "Tunnel"; case 2: return "Transport"; default: return "UNKNOWN-ENCAPSULATION-VALUE"; } case 5: switch (value) { case 1: return "HMAC-MD5"; case 2: return "HMAC-SHA"; case 3: return "DES-MAC"; case 4: return "KPDK"; default: return "UNKNOWN-AUTHENTICATION-VALUE"; } case 11: return "Life-Type"; default: return "UNKNOWN-ATTRIBUTE-TYPE"; } } static const char * num2str(const guint8 *pd, guint16 len) { #define NUMSTR_LEN 1024 static char numstr[NUMSTR_LEN]; switch (len) { case 1: snprintf(numstr, NUMSTR_LEN, "%u", *pd); break; case 2: snprintf(numstr, NUMSTR_LEN, "%u", ntohs(*((guint16 *)pd))); break; case 3: snprintf(numstr, NUMSTR_LEN, "%lu", ntohl(*((guint32 *)pd) & 0x0fff)); break; case 4: snprintf(numstr, NUMSTR_LEN, "%lu", ntohl(*((guint32 *)pd))); break; default: snprintf(numstr, NUMSTR_LEN, "<too big>"); } return numstr; }
/* packet-gre.c * Routines for the Generic Routing Encapsulation (GRE) protocol * Brad Robel-Forrest <brad.robel-forrest@xxxxxxxxxxxxxx> * * $Id$ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@xxxxxxxxxx> * Copyright 1998 Gerald Combs * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #ifdef HAVE_SYS_TYPES_H # include <sys/types.h> #endif #include <netinet/in.h> #include <glib.h> #include "packet.h" /* bit positions for flags in header */ #define GH_B_C 0x8000 #define GH_B_R 0x4000 #define GH_B_K 0x2000 #define GH_B_S 0x1000 #define GH_B_s 0x0800 #define GH_B_RECUR 0x0700 #define GH_P_A 0x0080 /* only in special PPTPized GRE header */ #define GH_P_FLAGS 0x0078 /* only in special PPTPized GRE header */ #define GH_R_FLAGS 0x00F8 #define GH_B_VER 0x0007 #define GRE_PPP 0x880B static int calc_len(guint16, int); static void add_flags_and_ver(proto_tree *, guint16, int, int); void dissect_gre(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { guint16 flags_and_ver = ntohs(*((guint16 *)(pd + offset))); guint16 type = ntohs(*((guint16 *)(pd + offset + sizeof(flags_and_ver)))); static const value_string typevals[] = { { GRE_PPP, "PPP" }, { 0, NULL } }; if (check_col(fd, COL_PROTOCOL)) col_add_str(fd, COL_PROTOCOL, "GRE"); if (check_col(fd, COL_INFO)) { if (type == GRE_PPP) col_add_str(fd, COL_INFO, "Encapsulated PPP"); else col_add_str(fd, COL_INFO, "Encapsulated unknown"); } if (fd->cap_len > offset && tree) { int is_ppp; proto_item * ti; proto_tree * gre_tree; if (type == GRE_PPP) { is_ppp = 1; ti = proto_tree_add_item(tree, offset, calc_len(flags_and_ver, 1), "GRE (PPP)"); gre_tree = proto_tree_new(); proto_item_add_subtree(ti, gre_tree, ETT_GRE); add_flags_and_ver(gre_tree, flags_and_ver, offset, 1); } else { is_ppp = 0; ti = proto_tree_add_item(tree, offset, calc_len(flags_and_ver, 1), "GRE"); gre_tree = proto_tree_new(); proto_item_add_subtree(ti, gre_tree, ETT_GRE); add_flags_and_ver(gre_tree, flags_and_ver, offset, 0); } offset += sizeof(flags_and_ver); proto_tree_add_item(gre_tree, offset, sizeof(type), "Protocol Type: %s (%#04x)", val_to_str(type, typevals, "Unknown"), type); offset += sizeof(type); if (flags_and_ver & GH_B_C || flags_and_ver & GH_B_R) { guint16 checksum = ntohs(*((guint16 *)(pd + offset))); proto_tree_add_item(gre_tree, offset, sizeof(checksum), "Checksum: %u", checksum); offset += sizeof(checksum); } if (flags_and_ver & GH_B_C || flags_and_ver & GH_B_R) { guint16 rtoffset = ntohs(*((guint16 *)(pd + offset))); proto_tree_add_item(gre_tree, offset, sizeof(rtoffset), "Offset: %u", rtoffset); offset += sizeof(rtoffset); } if (flags_and_ver & GH_B_K) { if (is_ppp) { guint16 paylen; guint16 callid; paylen = ntohs(*((guint16 *)(pd + offset))); proto_tree_add_item(gre_tree, offset, sizeof(paylen), "Payload length: %u", paylen); offset += sizeof(paylen); callid = ntohs(*((guint16 *)(pd + offset))); proto_tree_add_item(gre_tree, offset, sizeof(callid), "Call ID: %u", callid); offset += sizeof(callid); } else { guint32 key = ntohl(*((guint32 *)(pd + offset))); proto_tree_add_item(gre_tree, offset, sizeof(key), "Key: %u", key); offset += sizeof(key); } } if (flags_and_ver & GH_B_S) { guint32 seqnum = ntohl(*((guint32 *)(pd + offset))); proto_tree_add_item(gre_tree, offset, sizeof(seqnum), "Sequence number: %u", seqnum); offset += sizeof(seqnum); } if (is_ppp && flags_and_ver & GH_P_A) { guint32 acknum = ntohl(*((guint32 *)(pd + offset))); proto_tree_add_item(gre_tree, offset, sizeof(acknum), "Acknowledgement number: %u", acknum); offset += sizeof(acknum); } if (flags_and_ver & GH_B_R) { proto_tree_add_item(gre_tree, offset, sizeof(guint16), "Address family: %u", ntohs(*((guint16 *)(pd + offset)))); offset += sizeof(guint16); proto_tree_add_item(gre_tree, offset, 1, "SRE offset: %u", pd[offset++]); proto_tree_add_item(gre_tree, offset, 1, "SRE length: %u", pd[offset++]); } switch (type) { /* case GRE_PPP: */ /* dissect_ppp(pd, offset, fd, tree); */ /* break; */ default: dissect_data(pd, offset, fd, gre_tree); } } } static int calc_len(guint16 flags_and_ver, int is_ppp) { int len = 4; if (flags_and_ver & GH_B_C || flags_and_ver & GH_B_R) len += 4; if (flags_and_ver & GH_B_K) len += 4; if (flags_and_ver & GH_B_S) len += 4; if (is_ppp && flags_and_ver & GH_P_A) len += 4; return len; } static void add_flags_and_ver(proto_tree *tree, guint16 flags_and_ver, int offset, int is_ppp) { proto_item * ti; proto_tree * fv_tree; int nbits = sizeof(flags_and_ver) * 8; ti = proto_tree_add_item(tree, offset, 2, "Flags and version: %#08x", flags_and_ver); fv_tree = proto_tree_new(); proto_item_add_subtree(ti, fv_tree, ETT_GRE_FLAGS); proto_tree_add_item(fv_tree, offset, sizeof(flags_and_ver), "%s", decode_boolean_bitfield(flags_and_ver, GH_B_C, nbits, "Checksum", "No checksum")); proto_tree_add_item(fv_tree, offset, sizeof(flags_and_ver), "%s", decode_boolean_bitfield(flags_and_ver, GH_B_R, nbits, "Routing", "No routing")); proto_tree_add_item(fv_tree, offset, sizeof(flags_and_ver), "%s", decode_boolean_bitfield(flags_and_ver, GH_B_K, nbits, "Key", "No key")); proto_tree_add_item(fv_tree, offset, sizeof(flags_and_ver), "%s", decode_boolean_bitfield(flags_and_ver, GH_B_S, nbits, "Sequence number", "No sequence number")); proto_tree_add_item(fv_tree, offset, sizeof(flags_and_ver), "%s", decode_boolean_bitfield(flags_and_ver, GH_B_s, nbits, "Strict source route", "No strict source route")); proto_tree_add_item(fv_tree, offset, sizeof(flags_and_ver), "%s", decode_numeric_bitfield(flags_and_ver, GH_B_RECUR, nbits, "Recursion control: %u")); if (is_ppp) { proto_tree_add_item(fv_tree, offset, sizeof(flags_and_ver), "%s", decode_boolean_bitfield(flags_and_ver, GH_P_A, nbits, "Acknowledgment number", "No acknowledgment number")); proto_tree_add_item(fv_tree, offset, sizeof(flags_and_ver), "%s", decode_numeric_bitfield(flags_and_ver, GH_P_FLAGS, nbits, "Flags: %u")); } else { proto_tree_add_item(fv_tree, offset, sizeof(flags_and_ver), "%s", decode_numeric_bitfield(flags_and_ver, GH_R_FLAGS, nbits, "Flags: %u")); } proto_tree_add_item(fv_tree, offset, sizeof(flags_and_ver), "%s", decode_numeric_bitfield(flags_and_ver, GH_B_VER, nbits, "Version: %u")); }
/* packet-pptp.c * Routines for the Point-to-Point Tunnelling Protocol (PPTP) * Brad Robel-Forrest <brad.robel-forrest@xxxxxxxxxxxxxx> * * $Id$ * * Ethereal - Network traffic analyzer * By Gerald Combs <gerald@xxxxxxxxxx> * Copyright 1998 Gerald Combs * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #ifdef HAVE_SYS_TYPES_H # include <sys/types.h> #endif #include <stdio.h> #include <netinet/in.h> #include <glib.h> #include "packet.h" #define NUM_MSG_TYPES 3 #define msgtype2str(t) \ ((t < NUM_MSG_TYPES) ? msgtypestr[t] : "UNKNOWN-MESSAGES-TYPE") static const char *msgtypestr[NUM_MSG_TYPES] = { "UNKNOWN-MESSAGE-TYPE", "CONTROL-MESSAGE", "MANAGEMENT-MESSAGE" }; #define NUM_FRAME_TYPES 4 #define frametype2str(t) \ ((t < NUM_FRAME_TYPES) ? frametypestr[t] : "UNKNOWN-FRAMING-TYPE") static const char *frametypestr[NUM_FRAME_TYPES] = { "UNKNOWN-FRAMING-TYPE", "ASYNCHRONOUS", "SYNCHRONOUS", "EITHER" }; #define NUM_BEARER_TYPES 4 #define bearertype2str(t) \ ((t < NUM_BEARER_TYPES) ? bearertypestr[t] : "UNKNOWN-BEARER-TYPE") static const char *bearertypestr[NUM_BEARER_TYPES] = { "UNKNOWN-BEARER-TYPE", "ANALOG", "DIGITAL", "EITHER" }; #define NUM_CNTRLRESULT_TYPES 6 #define cntrlresulttype2str(t) \ ((t < NUM_CNTRLRESULT_TYPES) ? cntrlresulttypestr[t] : "UNKNOWN-CNTRLRESULT-TYPE") static const char *cntrlresulttypestr[NUM_CNTRLRESULT_TYPES] = { "UNKNOWN-CNTRLRESULT-TYPE", "SUCCESS", "GENERAL-ERROR", "COMMAND-CHANNEL-EXISTS", "NOT-AUTHORIZED", "VERSION-NOT-SUPPORTED" }; #define NUM_ERROR_TYPES 7 #define errortype2str(t) \ ((t < NUM_ERROR_TYPES) ? errortypestr[t] : "UNKNOWN-ERROR-TYPE") static const char *errortypestr[NUM_ERROR_TYPES] = { "NONE", "NOT-CONNECTED", "BAD-FORMAT", "BAD-VALUE", "NO-RESOURCE", "BAD-CALL-ID", "PAC-ERROR" }; #define NUM_REASON_TYPES 4 #define reasontype2str(t) \ ((t < NUM_REASON_TYPES) ? reasontypestr[t] : "UNKNOWN-REASON-TYPE") static const char *reasontypestr[NUM_REASON_TYPES] = { "UNKNOWN-REASON-TYPE", "NONE", "STOP-PROTOCOL", "STOP-LOCAL-SHUTDOWN" }; #define NUM_STOPRESULT_TYPES 3 #define stopresulttype2str(t) \ ((t < NUM_STOPRESULT_TYPES) ? stopresulttypestr[t] : "UNKNOWN-STOPRESULT-TYPE") static const char *stopresulttypestr[NUM_STOPRESULT_TYPES] = { "UNKNOWN-STOPRESULT-TYPE", "SUCCESS", "GENERAL-ERROR" }; #define NUM_ECHORESULT_TYPES 3 #define echoresulttype2str(t) \ ((t < NUM_ECHORESULT_TYPES) ? echoresulttypestr[t] : "UNKNOWN-ECHORESULT-TYPE") static const char *echoresulttypestr[NUM_ECHORESULT_TYPES] = { "UNKNOWN-ECHORESULT-TYPE", "SUCCESS", "GENERAL-ERROR" }; #define NUM_OUTRESULT_TYPES 8 #define outresulttype2str(t) \ ((t < NUM_OUTRESULT_TYPES) ? outresulttypestr[t] : "UNKNOWN-OUTRESULT-TYPE") static const char *outresulttypestr[NUM_OUTRESULT_TYPES] = { "UNKNOWN-OUTRESULT-TYPE", "CONNECTED", "GENERAL-ERROR", "NO-CARRIER", "BUSY", "NO-DIAL-TONE", "TIME-OUT", "DO-NOT-ACCEPT" }; #define NUM_INRESULT_TYPES 4 #define inresulttype2str(t) \ ((t < NUM_INRESULT_TYPES) ? inresulttypestr[t] : "UNKNOWN-INRESULT-TYPE") static const char *inresulttypestr[NUM_INRESULT_TYPES] = { "UNKNOWN-INRESULT-TYPE", "CONNECT", "GENERAL-ERROR", "DO-NOT-ACCEPT" }; #define NUM_DISCRESULT_TYPES 5 #define discresulttype2str(t) \ ((t < NUM_DISCRESULT_TYPES) ? discresulttypestr[t] : "UNKNOWN-DISCRESULT-TYPE") static const char *discresulttypestr[NUM_DISCRESULT_TYPES] = { "UNKNOWN-DISCRESULT-TYPE", "LOST-CARRIER", "GENERAL-ERROR", "ADMIN-SHUTDOWN", "REQUEST" }; static void dissect_unknown(const u_char *, int, frame_data *, proto_tree *); static void dissect_cntrl_req(const u_char *, int, frame_data *, proto_tree *); static void dissect_cntrl_reply(const u_char *, int, frame_data *, proto_tree *); static void dissect_stop_req(const u_char *, int, frame_data *, proto_tree *); static void dissect_stop_reply(const u_char *, int, frame_data *, proto_tree *); static void dissect_echo_req(const u_char *, int, frame_data *, proto_tree *); static void dissect_echo_reply(const u_char *, int, frame_data *, proto_tree *); static void dissect_out_req(const u_char *, int, frame_data *, proto_tree *); static void dissect_out_reply(const u_char *, int, frame_data *, proto_tree *); static void dissect_in_req(const u_char *, int, frame_data *, proto_tree *); static void dissect_in_reply(const u_char *, int, frame_data *, proto_tree *); static void dissect_in_connected(const u_char *, int, frame_data *, proto_tree *); static void dissect_clear_req(const u_char *, int, frame_data *, proto_tree *); static void dissect_disc_notify(const u_char *, int, frame_data *, proto_tree *); static void dissect_error_notify(const u_char *, int, frame_data *, proto_tree *); static void dissect_set_link(const u_char *, int, frame_data *, proto_tree *); #define NUM_CNTRL_TYPES 16 #define cntrltype2str(t) \ ((t < NUM_CNTRL_TYPES) ? strfuncs[t].str : "UNKNOWN-CONTROL-TYPE") static struct strfunc { const char * str; void (*func)(const u_char *, int, frame_data *, proto_tree *); } strfuncs[NUM_CNTRL_TYPES] = { {"UNKNOWN-CONTROL-TYPE", dissect_unknown }, {"START-CONTROL-REQUEST", dissect_cntrl_req }, {"START-CONTROL-REPLY", dissect_cntrl_reply }, {"STOP-CONTROL-REQUEST", dissect_stop_req }, {"STOP-CONTROL-REPLY", dissect_stop_reply }, {"ECHO-REQUEST", dissect_echo_req }, {"ECHO-REPLY", dissect_echo_reply }, {"OUTGOING-CALL-REQUEST", dissect_out_req }, {"OUTGOING-CALL-REPLY", dissect_out_reply }, {"INCOMING-CALL-REQUEST", dissect_in_req }, {"INCOMING-CALL-REPLY", dissect_in_reply }, {"INCOMING-CALL-CONNECTED", dissect_in_connected }, {"CLEAR-CALL-REQUEST", dissect_clear_req }, {"DISCONNECT-NOTIFY", dissect_disc_notify }, {"ERROR-NOTIFY", dissect_error_notify }, {"SET-LINK", dissect_set_link } }; struct pptp_hdr { guint16 len; guint16 type; guint32 cookie; guint16 cntrl_type; guint16 resv; }; struct cntrl_req { guint8 major_ver; guint8 minor_ver; guint16 resv; guint32 frame; guint32 bearer; guint16 max_chan; guint16 firm_rev; guint8 host[64]; guint8 vendor[64]; }; struct cntrl_reply { guint8 major_ver; guint8 minor_ver; guint8 result; guint8 error; guint32 frame; guint32 bearer; guint16 max_chan; guint16 firm_rev; guint8 host[64]; guint8 vendor[64]; }; struct stop_req { guint8 reason; guint8 resv0; guint16 resv1; }; struct stop_reply { guint8 result; guint8 error; guint16 resv; }; struct echo_req { guint32 ident; }; struct echo_reply { guint32 ident; guint8 result; guint8 error; guint16 resv; }; struct out_req { guint16 call_id; guint16 call_serial; guint32 min_bps; guint32 max_bps; guint32 bearer; guint32 frame; guint16 win_size; guint16 delay; guint16 phone_len; guint16 resv; guint8 phone[64]; guint8 subaddr[64]; }; struct out_reply { guint16 call_id; guint16 peer_id; guint8 result; guint8 error; guint16 cause; guint32 speed; guint16 win_size; guint16 delay; guint32 channel_id; }; struct in_req { guint16 call_id; guint16 call_serial; guint32 bearer; guint32 channel_id; guint16 dialed_len; guint16 dialing_len; guint8 dialed[64]; guint8 dialing[64]; guint8 subaddr[64]; }; struct in_reply { guint16 call_id; guint16 peer_id; guint8 result; guint8 error; guint16 win_size; guint16 delay; guint16 resv; }; struct in_connected { guint16 peer_id; guint16 resv; guint32 speed; guint16 win_size; guint16 delay; guint32 frame; }; struct clear_req { guint16 call_id; guint16 resv; }; struct disc_notify { guint16 call_id; guint8 result; guint8 error; guint16 cause; guint16 resv; guint8 stats[128]; }; struct error_notify { guint16 peer_id; guint16 resv; guint32 crc; guint32 frame; guint32 hardware; guint32 buffer; guint32 timeout; guint32 alignment; }; struct set_link { guint16 peer_id; guint16 resv; guint32 send_acm; guint32 recv_acm; }; void dissect_pptp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct pptp_hdr * hdr = (struct pptp_hdr *)(pd + offset); guint16 len; guint16 cntrl_type; if (check_col(fd, COL_PROTOCOL)) col_add_str(fd, COL_PROTOCOL, "PPTP"); len = ntohs(hdr->len); cntrl_type = ntohs(hdr->cntrl_type); if (check_col(fd, COL_INFO)) col_add_fstr(fd, COL_INFO, "%s", cntrltype2str(cntrl_type)); if (fd->cap_len > offset && tree) { guint16 msg_type; proto_item * ti; proto_tree * pptp_tree; ti = proto_tree_add_item(tree, offset, len, "PPTP Control Channel"); pptp_tree = proto_tree_new(); proto_item_add_subtree(ti, pptp_tree, ETT_PPTP); proto_tree_add_item(pptp_tree, offset, sizeof(hdr->len), "Length: %u", len); offset += sizeof(hdr->len); msg_type = ntohs(hdr->type); proto_tree_add_item(pptp_tree, offset, sizeof(hdr->type), "Message type: %s (%u)", msgtype2str(msg_type), msg_type); offset += sizeof(hdr->type); proto_tree_add_item(pptp_tree, offset, sizeof(hdr->cookie), "Cookie: %#08x", ntohl(hdr->cookie)); offset += sizeof(hdr->cookie); proto_tree_add_item(pptp_tree, offset, sizeof(hdr->cntrl_type), "Control type: %s (%u)", cntrltype2str(cntrl_type), cntrl_type); offset += sizeof(hdr->cntrl_type); proto_tree_add_item(pptp_tree, offset, sizeof(hdr->resv), "Reserved: %u", ntohs(hdr->resv)); offset += sizeof(hdr->resv); if (cntrl_type < NUM_CNTRL_TYPES) ( *(strfuncs[cntrl_type].func))(pd, offset, fd, pptp_tree); else dissect_data(pd, offset, fd, pptp_tree); } } static void dissect_unknown(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { dissect_data(pd, offset, fd, tree); } static void dissect_cntrl_req(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct cntrl_req * hdr = (struct cntrl_req *)(pd + offset); guint32 frame; guint32 bearer; proto_tree_add_item(tree, offset, sizeof(hdr->major_ver) + sizeof(hdr->minor_ver), "Protocol version: %u.%u", hdr->major_ver, hdr->minor_ver ); offset += sizeof(hdr->major_ver) + sizeof(hdr->minor_ver); proto_tree_add_item(tree, offset, sizeof(hdr->resv), "Reserved: %u", hdr->resv); offset += sizeof(hdr->resv); frame = ntohl(hdr->frame); proto_tree_add_item(tree, offset, sizeof(hdr->frame), "Framing capabilities: %s (%u)", frametype2str(frame), frame); offset += sizeof(hdr->frame); bearer = ntohl(hdr->bearer); proto_tree_add_item(tree, offset, sizeof(hdr->bearer), "Bearer capabilities: %s (%u)", bearertype2str(bearer), bearer); offset += sizeof(hdr->bearer); proto_tree_add_item(tree, offset, sizeof(hdr->max_chan), "Maximum channels: %u", hdr->max_chan); offset += sizeof(hdr->max_chan); proto_tree_add_item(tree, offset, sizeof(hdr->firm_rev), "Firmware revision: %u", hdr->firm_rev); offset += sizeof(hdr->firm_rev); proto_tree_add_item(tree, offset, sizeof(hdr->host), "Hostname: %s", hdr->host); offset += sizeof(hdr->host); proto_tree_add_item(tree, offset, sizeof(hdr->vendor), "Vendor: %s", hdr->vendor); } static void dissect_cntrl_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct cntrl_reply * hdr = (struct cntrl_reply *)(pd + offset); guint32 frame; guint32 bearer; proto_tree_add_item(tree, offset, sizeof(hdr->major_ver) + sizeof(hdr->minor_ver), "Protocol version: %u.%u", hdr->major_ver, hdr->minor_ver ); offset += sizeof(hdr->major_ver) + sizeof(hdr->minor_ver); proto_tree_add_item(tree, offset, sizeof(hdr->result), "Result: %s (%u)", cntrlresulttype2str(hdr->result), hdr->result); offset += sizeof(hdr->result); proto_tree_add_item(tree, offset, sizeof(hdr->error), "Error: %s (%u)", errortype2str(hdr->error), hdr->error); offset += sizeof(hdr->error); frame = ntohl(hdr->frame); proto_tree_add_item(tree, offset, sizeof(hdr->frame), "Framing capabilities: %s (%u)", frametype2str(frame), frame); offset += sizeof(hdr->frame); bearer = ntohl(hdr->bearer); proto_tree_add_item(tree, offset, sizeof(hdr->bearer), "Bearer capabilities: %s (%u)", bearertype2str(bearer), bearer); offset += sizeof(hdr->bearer); proto_tree_add_item(tree, offset, sizeof(hdr->max_chan), "Maximum channels: %u", hdr->max_chan); offset += sizeof(hdr->max_chan); proto_tree_add_item(tree, offset, sizeof(hdr->firm_rev), "Firmware revision: %u", hdr->firm_rev); offset += sizeof(hdr->firm_rev); proto_tree_add_item(tree, offset, sizeof(hdr->host), "Hostname: %s", hdr->host); offset += sizeof(hdr->host); proto_tree_add_item(tree, offset, sizeof(hdr->vendor), "Vendor: %s", hdr->vendor); } static void dissect_stop_req(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct stop_req * hdr = (struct stop_req *)(pd + offset); proto_tree_add_item(tree, offset, sizeof(hdr->reason), "Reason: %s (%u)", reasontype2str(hdr->reason), hdr->reason); offset += sizeof(hdr->reason); proto_tree_add_item(tree, offset, sizeof(hdr->resv0), "Reserved: %u", hdr->resv0); offset += sizeof(hdr->resv0); proto_tree_add_item(tree, offset, sizeof(hdr->resv1), "Reserved: %u", hdr->resv1); offset += sizeof(hdr->resv1); } static void dissect_stop_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct stop_reply * hdr = (struct stop_reply *)(pd + offset); proto_tree_add_item(tree, offset, sizeof(hdr->result), "Result: %s (%u)", stopresulttype2str(hdr->result), hdr->result); offset += sizeof(hdr->result); proto_tree_add_item(tree, offset, sizeof(hdr->error), "Error: %s (%u)", errortype2str(hdr->error), hdr->error); offset += sizeof(hdr->error); proto_tree_add_item(tree, offset, sizeof(hdr->resv), "Reserved: %u", hdr->resv); offset += sizeof(hdr->resv); } static void dissect_echo_req(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct echo_req * hdr = (struct echo_req *)(pd + offset); proto_tree_add_item(tree, offset, sizeof(hdr->ident), "Identifier: %u", hdr->ident); offset += sizeof(hdr->ident); } static void dissect_echo_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct echo_reply * hdr = (struct echo_reply *)(pd + offset); proto_tree_add_item(tree, offset, sizeof(hdr->ident), "Identifier: %u", hdr->ident); offset += sizeof(hdr->ident); proto_tree_add_item(tree, offset, sizeof(hdr->result), "Result: %s (%u)", echoresulttype2str(hdr->result), hdr->result); offset += sizeof(hdr->result); proto_tree_add_item(tree, offset, sizeof(hdr->error), "Error: %s (%u)", errortype2str(hdr->error), hdr->error); offset += sizeof(hdr->error); proto_tree_add_item(tree, offset, sizeof(hdr->resv), "Reserved: %u", hdr->resv); offset += sizeof(hdr->resv); } static void dissect_out_req(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct out_req * hdr = (struct out_req *)(pd + offset); guint32 bearer; guint32 frame; proto_tree_add_item(tree, offset, sizeof(hdr->call_id), "Call ID: %u", hdr->call_id); offset += sizeof(hdr->call_id); proto_tree_add_item(tree, offset, sizeof(hdr->call_serial), "Call Serial Number: %u", hdr->call_serial); offset += sizeof(hdr->call_serial); proto_tree_add_item(tree, offset, sizeof(hdr->min_bps), "Minimum BPS: %u", hdr->min_bps); offset += sizeof(hdr->min_bps); proto_tree_add_item(tree, offset, sizeof(hdr->max_bps), "Maximum BPS: %u", hdr->max_bps); offset += sizeof(hdr->max_bps); bearer = ntohl(hdr->bearer); proto_tree_add_item(tree, offset, sizeof(hdr->bearer), "Bearer capabilities: %s (%u)", bearertype2str(bearer), bearer); offset += sizeof(hdr->bearer); frame = ntohl(hdr->frame); proto_tree_add_item(tree, offset, sizeof(hdr->frame), "Framing capabilities: %s (%u)", frametype2str(frame), frame); offset += sizeof(hdr->frame); proto_tree_add_item(tree, offset, sizeof(hdr->win_size), "Receive window size: %u", hdr->win_size); offset += sizeof(hdr->win_size); proto_tree_add_item(tree, offset, sizeof(hdr->delay), "Processing delay: %u", hdr->delay); offset += sizeof(hdr->delay); proto_tree_add_item(tree, offset, sizeof(hdr->phone_len), "Phone number length: %u", hdr->phone_len); offset += sizeof(hdr->phone_len); proto_tree_add_item(tree, offset, sizeof(hdr->resv), "Reserved: %u", hdr->resv); offset += sizeof(hdr->resv); proto_tree_add_item(tree, offset, sizeof(hdr->phone), "Phone number: %s", hdr->phone); offset += sizeof(hdr->phone); proto_tree_add_item(tree, offset, sizeof(hdr->subaddr), "Subaddress: %s", hdr->subaddr); offset += sizeof(hdr->subaddr); } static void dissect_out_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct out_reply * hdr = (struct out_reply *)(pd + offset); proto_tree_add_item(tree, offset, sizeof(hdr->call_id), "Call ID: %u", hdr->call_id); offset += sizeof(hdr->call_id); proto_tree_add_item(tree, offset, sizeof(hdr->peer_id), "Peer's call ID: %u", hdr->peer_id); offset += sizeof(hdr->peer_id); proto_tree_add_item(tree, offset, sizeof(hdr->result), "Result: %s (%u)", outresulttype2str(hdr->result), hdr->result); offset += sizeof(hdr->result); proto_tree_add_item(tree, offset, sizeof(hdr->error), "Error: %s (%u)", errortype2str(hdr->error), hdr->error); offset += sizeof(hdr->error); proto_tree_add_item(tree, offset, sizeof(hdr->cause), "Cause code: %u", hdr->cause); offset += sizeof(hdr->cause); proto_tree_add_item(tree, offset, sizeof(hdr->speed), "Connect speed: %u", hdr->speed); offset += sizeof(hdr->speed); proto_tree_add_item(tree, offset, sizeof(hdr->win_size), "Receive window size: %u", hdr->win_size); offset += sizeof(hdr->win_size); proto_tree_add_item(tree, offset, sizeof(hdr->delay), "Processing delay: %u", hdr->delay); offset += sizeof(hdr->delay); proto_tree_add_item(tree, offset, sizeof(hdr->channel_id), "Physical channel ID: %u", hdr->channel_id); offset += sizeof(hdr->channel_id); } static void dissect_in_req(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct in_req * hdr = (struct in_req *)(pd + offset); guint32 bearer; proto_tree_add_item(tree, offset, sizeof(hdr->call_id), "Call ID: %u", hdr->call_id); offset += sizeof(hdr->call_id); proto_tree_add_item(tree, offset, sizeof(hdr->call_serial), "Call serial number: %u", hdr->call_serial); offset += sizeof(hdr->call_serial); bearer = ntohl(hdr->bearer); proto_tree_add_item(tree, offset, sizeof(hdr->bearer), "Bearer capabilities: %s (%u)", bearertype2str(bearer), bearer); offset += sizeof(hdr->bearer); proto_tree_add_item(tree, offset, sizeof(hdr->channel_id), "Physical channel ID: %u", hdr->channel_id); offset += sizeof(hdr->channel_id); proto_tree_add_item(tree, offset, sizeof(hdr->dialed_len), "Dialed number length: %u", hdr->dialed_len); offset += sizeof(hdr->dialed_len); proto_tree_add_item(tree, offset, sizeof(hdr->dialing_len), "Dialing number length: %u", hdr->dialing_len); offset += sizeof(hdr->dialing_len); proto_tree_add_item(tree, offset, sizeof(hdr->dialed), "Dialed number: %s", hdr->dialed); offset += sizeof(hdr->dialed); proto_tree_add_item(tree, offset, sizeof(hdr->dialing), "Dialing number: %s", hdr->dialing); offset += sizeof(hdr->dialing); proto_tree_add_item(tree, offset, sizeof(hdr->subaddr), "Subaddress: %s", hdr->subaddr); offset += sizeof(hdr->subaddr); } static void dissect_in_reply(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct in_reply * hdr = (struct in_reply *)(pd + offset); proto_tree_add_item(tree, offset, sizeof(hdr->call_id), "Call ID: %u", hdr->call_id); offset += sizeof(hdr->call_id); proto_tree_add_item(tree, offset, sizeof(hdr->peer_id), "Peer's call ID: %u", hdr->peer_id); offset += sizeof(hdr->peer_id); proto_tree_add_item(tree, offset, sizeof(hdr->result), "Result: %s (%u)", inresulttype2str(hdr->result), hdr->result); offset += sizeof(hdr->result); proto_tree_add_item(tree, offset, sizeof(hdr->error), "Error: %s (%u)", errortype2str(hdr->error), hdr->error); offset += sizeof(hdr->error); proto_tree_add_item(tree, offset, sizeof(hdr->win_size), "Receive window size: %u", hdr->win_size); offset += sizeof(hdr->win_size); proto_tree_add_item(tree, offset, sizeof(hdr->delay), "Processing delay: %u", hdr->delay); offset += sizeof(hdr->delay); proto_tree_add_item(tree, offset, sizeof(hdr->resv), "Reserved: %u", hdr->resv); offset += sizeof(hdr->resv); } static void dissect_in_connected(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct in_connected * hdr = (struct in_connected *)(pd + offset); guint32 frame; proto_tree_add_item(tree, offset, sizeof(hdr->peer_id), "Peer's call ID: %u", hdr->peer_id); offset += sizeof(hdr->peer_id); proto_tree_add_item(tree, offset, sizeof(hdr->resv), "Reserved: %u", hdr->resv); offset += sizeof(hdr->resv); proto_tree_add_item(tree, offset, sizeof(hdr->speed), "Connect speed: %u", hdr->speed); offset += sizeof(hdr->speed); proto_tree_add_item(tree, offset, sizeof(hdr->win_size), "Receive window size: %u", hdr->win_size); offset += sizeof(hdr->win_size); proto_tree_add_item(tree, offset, sizeof(hdr->delay), "Processing delay: %u", hdr->delay); offset += sizeof(hdr->delay); frame = ntohl(hdr->frame); proto_tree_add_item(tree, offset, sizeof(hdr->frame), "Framing capabilities: %s (%u)", frametype2str(frame), frame); offset += sizeof(hdr->frame); } static void dissect_clear_req(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct clear_req * hdr = (struct clear_req *)(pd + offset); proto_tree_add_item(tree, offset, sizeof(hdr->call_id), "Call ID: %u", hdr->call_id); offset += sizeof(hdr->call_id); proto_tree_add_item(tree, offset, sizeof(hdr->resv), "Reserved: %u", hdr->resv); offset += sizeof(hdr->resv); } static void dissect_disc_notify(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct disc_notify * hdr = (struct disc_notify *)(pd + offset); proto_tree_add_item(tree, offset, sizeof(hdr->call_id), "Call ID: %u", hdr->call_id); offset += sizeof(hdr->call_id); proto_tree_add_item(tree, offset, sizeof(hdr->result), "Result: %s (%u)", discresulttype2str(hdr->result), hdr->result); offset += sizeof(hdr->result); proto_tree_add_item(tree, offset, sizeof(hdr->error), "Error: %s (%u)", errortype2str(hdr->error), hdr->error); offset += sizeof(hdr->error); proto_tree_add_item(tree, offset, sizeof(hdr->cause), "Cause code: %u", hdr->cause); offset += sizeof(hdr->cause); proto_tree_add_item(tree, offset, sizeof(hdr->resv), "Reserved: %u", hdr->resv); offset += sizeof(hdr->resv); proto_tree_add_item(tree, offset, sizeof(hdr->stats), "Call statistics: %s", hdr->stats); offset += sizeof(hdr->stats); } static void dissect_error_notify(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct error_notify * hdr = (struct error_notify *)(pd + offset); proto_tree_add_item(tree, offset, sizeof(hdr->peer_id), "Peer's call ID: %u", hdr->peer_id); offset += sizeof(hdr->peer_id); proto_tree_add_item(tree, offset, sizeof(hdr->resv), "Reserved: %u", hdr->resv); offset += sizeof(hdr->resv); proto_tree_add_item(tree, offset, sizeof(hdr->crc), "CRC errors: %u", hdr->crc); offset += sizeof(hdr->crc); proto_tree_add_item(tree, offset, sizeof(hdr->frame), "Framing errors: %u", hdr->frame); offset += sizeof(hdr->frame); proto_tree_add_item(tree, offset, sizeof(hdr->hardware), "Hardware overruns: %u", hdr->hardware); offset += sizeof(hdr->hardware); proto_tree_add_item(tree, offset, sizeof(hdr->buffer), "Buffer overruns: %u", hdr->buffer); offset += sizeof(hdr->buffer); proto_tree_add_item(tree, offset, sizeof(hdr->timeout), "Time-out errors: %u", hdr->timeout); offset += sizeof(hdr->timeout); proto_tree_add_item(tree, offset, sizeof(hdr->alignment), "Alignment errors: %u", hdr->alignment); offset += sizeof(hdr->alignment); } static void dissect_set_link(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { struct set_link * hdr = (struct set_link *)(pd + offset); proto_tree_add_item(tree, offset, sizeof(hdr->peer_id), "Peer's call ID: %u", hdr->peer_id); offset += sizeof(hdr->peer_id); proto_tree_add_item(tree, offset, sizeof(hdr->resv), "Reserved: %u", hdr->resv); offset += sizeof(hdr->resv); proto_tree_add_item(tree, offset, sizeof(hdr->send_acm), "Send ACCM: %#08x", hdr->send_acm); offset += sizeof(hdr->send_acm); proto_tree_add_item(tree, offset, sizeof(hdr->recv_acm), "Recv ACCM: %#08x", hdr->recv_acm); offset += sizeof(hdr->recv_acm); }
- Follow-Ups:
- Re: [ethereal-dev] Code for ISAKMP, GRE, and PPTP
- From: Jeff Jahr
- Re: [ethereal-dev] Code for ISAKMP, GRE, and PPTP
- Prev by Date: [ethereal-dev] dissect PPPoE.
- Next by Date: Re: [ethereal-dev] Code for ISAKMP, GRE, and PPTP
- Previous by thread: [ethereal-dev] dissect PPPoE.
- Next by thread: Re: [ethereal-dev] Code for ISAKMP, GRE, and PPTP
- Index(es):