xref: /netbsd-src/external/bsd/tcpdump/dist/print-vqp.c (revision 26ba0b503b498a5194a71ac319838b7f5497f3fe)
10f74e101Schristos /*
20f74e101Schristos  * Copyright (c) 1998-2006 The TCPDUMP project
30f74e101Schristos  *
40f74e101Schristos  * Redistribution and use in source and binary forms, with or without
50f74e101Schristos  * modification, are permitted provided that: (1) source code
60f74e101Schristos  * distributions retain the above copyright notice and this paragraph
70f74e101Schristos  * in its entirety, and (2) distributions including binary code include
80f74e101Schristos  * the above copyright notice and this paragraph in its entirety in
90f74e101Schristos  * the documentation or other materials provided with the distribution.
100f74e101Schristos  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
110f74e101Schristos  * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
120f74e101Schristos  * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
130f74e101Schristos  * FOR A PARTICULAR PURPOSE.
140f74e101Schristos  *
150f74e101Schristos  * Original code by Carles Kishimoto <Carles.Kishimoto@bsc.es>
160f74e101Schristos  */
170f74e101Schristos 
18dc860a36Sspz /* \summary: Cisco VLAN Query Protocol (VQP) printer */
19dc860a36Sspz 
2011b3aaa1Schristos #include <sys/cdefs.h>
210f74e101Schristos #ifndef lint
22*26ba0b50Schristos __RCSID("$NetBSD: print-vqp.c,v 1.9 2024/09/02 16:15:33 christos Exp $");
230f74e101Schristos #endif
240f74e101Schristos 
25c74ad251Schristos #include <config.h>
260f74e101Schristos 
27c74ad251Schristos #include "netdissect-stdinc.h"
280f74e101Schristos 
29c74ad251Schristos #define ND_LONGJMP_FROM_TCHECK
30fdccd7e4Schristos #include "netdissect.h"
310f74e101Schristos #include "extract.h"
320f74e101Schristos #include "addrtoname.h"
330f74e101Schristos 
340f74e101Schristos #define VQP_VERSION 1
350f74e101Schristos 
360f74e101Schristos /*
370f74e101Schristos  * VQP common header
380f74e101Schristos  *
390f74e101Schristos  *  0                   1                   2                   3
400f74e101Schristos  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
410f74e101Schristos  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
420f74e101Schristos  * |   Constant    | Packet type   |  Error Code   |    nitems     |
430f74e101Schristos  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
440f74e101Schristos  * |                Packet Sequence Number (4 bytes)               |
450f74e101Schristos  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
460f74e101Schristos  */
470f74e101Schristos 
480f74e101Schristos struct vqp_common_header_t {
49c74ad251Schristos     nd_uint8_t  version;
50c74ad251Schristos     nd_uint8_t  msg_type;
51c74ad251Schristos     nd_uint8_t  error_code;
52c74ad251Schristos     nd_uint8_t  nitems;
53c74ad251Schristos     nd_uint32_t sequence;
540f74e101Schristos };
550f74e101Schristos 
560f74e101Schristos struct vqp_obj_tlv_t {
57c74ad251Schristos     nd_uint32_t obj_type;
58c74ad251Schristos     nd_uint16_t obj_length;
590f74e101Schristos };
600f74e101Schristos 
610f74e101Schristos #define VQP_OBJ_REQ_JOIN_PORT  0x01
620f74e101Schristos #define VQP_OBJ_RESP_VLAN      0x02
630f74e101Schristos #define VQP_OBJ_REQ_RECONFIRM  0x03
640f74e101Schristos #define VQP_OBJ_RESP_RECONFIRM 0x04
650f74e101Schristos 
660f74e101Schristos static const struct tok vqp_msg_type_values[] = {
670f74e101Schristos     { VQP_OBJ_REQ_JOIN_PORT, "Request, Join Port"},
680f74e101Schristos     { VQP_OBJ_RESP_VLAN, "Response, VLAN"},
690f74e101Schristos     { VQP_OBJ_REQ_RECONFIRM, "Request, Reconfirm"},
700f74e101Schristos     { VQP_OBJ_RESP_RECONFIRM, "Response, Reconfirm"},
710f74e101Schristos     { 0, NULL}
720f74e101Schristos };
730f74e101Schristos 
740f74e101Schristos static const struct tok vqp_error_code_values[] = {
750f74e101Schristos     { 0x00, "No error"},
760f74e101Schristos     { 0x03, "Access denied"},
770f74e101Schristos     { 0x04, "Shutdown port"},
780f74e101Schristos     { 0x05, "Wrong VTP domain"},
790f74e101Schristos     { 0, NULL}
800f74e101Schristos };
810f74e101Schristos 
820f74e101Schristos /* FIXME the heading 0x0c looks ugly - those must be flags etc. */
830f74e101Schristos #define VQP_OBJ_IP_ADDRESS    0x0c01
840f74e101Schristos #define VQP_OBJ_PORT_NAME     0x0c02
850f74e101Schristos #define VQP_OBJ_VLAN_NAME     0x0c03
860f74e101Schristos #define VQP_OBJ_VTP_DOMAIN    0x0c04
870f74e101Schristos #define VQP_OBJ_ETHERNET_PKT  0x0c05
880f74e101Schristos #define VQP_OBJ_MAC_NULL      0x0c06
890f74e101Schristos #define VQP_OBJ_MAC_ADDRESS   0x0c08
900f74e101Schristos 
910f74e101Schristos static const struct tok vqp_obj_values[] = {
920f74e101Schristos     { VQP_OBJ_IP_ADDRESS, "Client IP Address" },
930f74e101Schristos     { VQP_OBJ_PORT_NAME, "Port Name" },
940f74e101Schristos     { VQP_OBJ_VLAN_NAME, "VLAN Name" },
950f74e101Schristos     { VQP_OBJ_VTP_DOMAIN, "VTP Domain" },
960f74e101Schristos     { VQP_OBJ_ETHERNET_PKT, "Ethernet Packet" },
970f74e101Schristos     { VQP_OBJ_MAC_NULL, "MAC Null" },
980f74e101Schristos     { VQP_OBJ_MAC_ADDRESS, "MAC Address" },
990f74e101Schristos     { 0, NULL}
1000f74e101Schristos };
1010f74e101Schristos 
1020f74e101Schristos void
103c74ad251Schristos vqp_print(netdissect_options *ndo, const u_char *pptr, u_int len)
1040f74e101Schristos {
1050f74e101Schristos     const struct vqp_common_header_t *vqp_common_header;
1060f74e101Schristos     const struct vqp_obj_tlv_t *vqp_obj_tlv;
1070f74e101Schristos 
1080f74e101Schristos     const u_char *tptr;
109c74ad251Schristos     uint8_t version;
110b3a00663Schristos     uint16_t vqp_obj_len;
111b3a00663Schristos     uint32_t vqp_obj_type;
11272c96ff3Schristos     u_int tlen;
113b3a00663Schristos     uint8_t nitems;
1140f74e101Schristos 
115c74ad251Schristos     ndo->ndo_protocol = "vqp";
1160f74e101Schristos     tptr=pptr;
1170f74e101Schristos     tlen = len;
1180f74e101Schristos     vqp_common_header = (const struct vqp_common_header_t *)pptr;
119c74ad251Schristos     ND_TCHECK_SIZE(vqp_common_header);
12072c96ff3Schristos     if (sizeof(struct vqp_common_header_t) > tlen)
121c74ad251Schristos         goto invalid;
122c74ad251Schristos     version = GET_U_1(vqp_common_header->version);
1230f74e101Schristos 
1240f74e101Schristos     /*
1250f74e101Schristos      * Sanity checking of the header.
1260f74e101Schristos      */
127c74ad251Schristos     if (version != VQP_VERSION) {
128c74ad251Schristos 	ND_PRINT("VQP version %u packet not supported",
129c74ad251Schristos                version);
1300f74e101Schristos 	return;
1310f74e101Schristos     }
1320f74e101Schristos 
1330f74e101Schristos     /* in non-verbose mode just lets print the basic Message Type */
134b3a00663Schristos     if (ndo->ndo_vflag < 1) {
135c74ad251Schristos         ND_PRINT("VQPv%u %s Message, error-code %s (%u), length %u",
136c74ad251Schristos                version,
137c74ad251Schristos                tok2str(vqp_msg_type_values, "unknown (%u)",GET_U_1(vqp_common_header->msg_type)),
138c74ad251Schristos                tok2str(vqp_error_code_values, "unknown", GET_U_1(vqp_common_header->error_code)),
139c74ad251Schristos                GET_U_1(vqp_common_header->error_code),
140c74ad251Schristos                len);
1410f74e101Schristos         return;
1420f74e101Schristos     }
1430f74e101Schristos 
1440f74e101Schristos     /* ok they seem to want to know everything - lets fully decode it */
145c74ad251Schristos     nitems = GET_U_1(vqp_common_header->nitems);
146c74ad251Schristos     ND_PRINT("\n\tVQPv%u, %s Message, error-code %s (%u), seq 0x%08x, items %u, length %u",
147c74ad251Schristos            version,
148c74ad251Schristos 	   tok2str(vqp_msg_type_values, "unknown (%u)",GET_U_1(vqp_common_header->msg_type)),
149c74ad251Schristos 	   tok2str(vqp_error_code_values, "unknown", GET_U_1(vqp_common_header->error_code)),
150c74ad251Schristos 	   GET_U_1(vqp_common_header->error_code),
151c74ad251Schristos 	   GET_BE_U_4(vqp_common_header->sequence),
1520f74e101Schristos 	   nitems,
153c74ad251Schristos            len);
1540f74e101Schristos 
1550f74e101Schristos     /* skip VQP Common header */
156c74ad251Schristos     tptr+=sizeof(struct vqp_common_header_t);
157c74ad251Schristos     tlen-=sizeof(struct vqp_common_header_t);
1580f74e101Schristos 
159c74ad251Schristos     while (nitems != 0 && tlen != 0) {
1600f74e101Schristos 
1610f74e101Schristos         vqp_obj_tlv = (const struct vqp_obj_tlv_t *)tptr;
162c74ad251Schristos         ND_TCHECK_SIZE(vqp_obj_tlv);
16372c96ff3Schristos         if (sizeof(struct vqp_obj_tlv_t) > tlen)
164c74ad251Schristos             goto invalid;
165c74ad251Schristos         vqp_obj_type = GET_BE_U_4(vqp_obj_tlv->obj_type);
166c74ad251Schristos         vqp_obj_len = GET_BE_U_2(vqp_obj_tlv->obj_length);
1670f74e101Schristos         tptr+=sizeof(struct vqp_obj_tlv_t);
1680f74e101Schristos         tlen-=sizeof(struct vqp_obj_tlv_t);
1690f74e101Schristos 
170c74ad251Schristos         ND_PRINT("\n\t  %s Object (0x%08x), length %u, value: ",
1710f74e101Schristos                tok2str(vqp_obj_values, "Unknown", vqp_obj_type),
172c74ad251Schristos                vqp_obj_type, vqp_obj_len);
1730f74e101Schristos 
1740f74e101Schristos         /* basic sanity check */
1750f74e101Schristos         if (vqp_obj_type == 0 || vqp_obj_len ==0) {
1760f74e101Schristos             return;
1770f74e101Schristos         }
1780f74e101Schristos 
1790f74e101Schristos         /* did we capture enough for fully decoding the object ? */
180c74ad251Schristos         ND_TCHECK_LEN(tptr, vqp_obj_len);
18172c96ff3Schristos         if (vqp_obj_len > tlen)
182c74ad251Schristos             goto invalid;
1830f74e101Schristos 
1840f74e101Schristos         switch(vqp_obj_type) {
1850f74e101Schristos 	case VQP_OBJ_IP_ADDRESS:
18672c96ff3Schristos             if (vqp_obj_len != 4)
187c74ad251Schristos                 goto invalid;
188c74ad251Schristos             ND_PRINT("%s (0x%08x)", GET_IPADDR_STRING(tptr),
189c74ad251Schristos                      GET_BE_U_4(tptr));
1900f74e101Schristos             break;
1910f74e101Schristos             /* those objects have similar semantics - fall through */
1920f74e101Schristos         case VQP_OBJ_PORT_NAME:
1930f74e101Schristos 	case VQP_OBJ_VLAN_NAME:
1940f74e101Schristos 	case VQP_OBJ_VTP_DOMAIN:
1950f74e101Schristos 	case VQP_OBJ_ETHERNET_PKT:
196c74ad251Schristos             nd_printjnp(ndo, tptr, vqp_obj_len);
1970f74e101Schristos             break;
1980f74e101Schristos             /* those objects have similar semantics - fall through */
1990f74e101Schristos 	case VQP_OBJ_MAC_ADDRESS:
2000f74e101Schristos 	case VQP_OBJ_MAC_NULL:
201c74ad251Schristos             if (vqp_obj_len != MAC_ADDR_LEN)
202c74ad251Schristos                 goto invalid;
203c74ad251Schristos 	      ND_PRINT("%s", GET_ETHERADDR_STRING(tptr));
2040f74e101Schristos               break;
2050f74e101Schristos         default:
206b3a00663Schristos             if (ndo->ndo_vflag <= 1)
207b3a00663Schristos                 print_unknown_data(ndo,tptr, "\n\t    ", vqp_obj_len);
2080f74e101Schristos             break;
2090f74e101Schristos         }
2100f74e101Schristos 	tptr += vqp_obj_len;
2110f74e101Schristos 	tlen -= vqp_obj_len;
2120f74e101Schristos 	nitems--;
2130f74e101Schristos     }
2140f74e101Schristos     return;
215c74ad251Schristos invalid:
216c74ad251Schristos     nd_print_invalid(ndo);
2170f74e101Schristos }
218