xref: /netbsd-src/external/bsd/tcpdump/dist/print-mpcp.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  *
1572c96ff3Schristos  * Original code by Hannes Gredler (hannes@gredler.at)
160f74e101Schristos  */
170f74e101Schristos 
18dc860a36Sspz /* \summary: IEEE 802.3ah Multi-Point Control Protocol (MPCP) printer */
19dc860a36Sspz 
2011b3aaa1Schristos #include <sys/cdefs.h>
210f74e101Schristos #ifndef lint
22*26ba0b50Schristos __RCSID("$NetBSD: print-mpcp.c,v 1.10 2024/09/02 16:15:32 christos Exp $");
230f74e101Schristos #endif
240f74e101Schristos 
25c74ad251Schristos #include <config.h>
260f74e101Schristos 
27c74ad251Schristos #include "netdissect-stdinc.h"
280f74e101Schristos 
29fdccd7e4Schristos #include "netdissect.h"
300f74e101Schristos #include "extract.h"
310f74e101Schristos 
320f74e101Schristos struct mpcp_common_header_t {
33c74ad251Schristos     nd_uint16_t opcode;
34c74ad251Schristos     nd_uint32_t timestamp;
350f74e101Schristos };
360f74e101Schristos 
370f74e101Schristos #define	MPCP_OPCODE_PAUSE   0x0001
380f74e101Schristos #define	MPCP_OPCODE_GATE    0x0002
390f74e101Schristos #define	MPCP_OPCODE_REPORT  0x0003
400f74e101Schristos #define	MPCP_OPCODE_REG_REQ 0x0004
410f74e101Schristos #define	MPCP_OPCODE_REG     0x0005
420f74e101Schristos #define	MPCP_OPCODE_REG_ACK 0x0006
430f74e101Schristos 
440f74e101Schristos static const struct tok mpcp_opcode_values[] = {
450f74e101Schristos     { MPCP_OPCODE_PAUSE, "Pause" },
460f74e101Schristos     { MPCP_OPCODE_GATE, "Gate" },
470f74e101Schristos     { MPCP_OPCODE_REPORT, "Report" },
480f74e101Schristos     { MPCP_OPCODE_REG_REQ, "Register Request" },
490f74e101Schristos     { MPCP_OPCODE_REG, "Register" },
500f74e101Schristos     { MPCP_OPCODE_REG_ACK, "Register ACK" },
510f74e101Schristos     { 0, NULL}
520f74e101Schristos };
530f74e101Schristos 
540f74e101Schristos #define MPCP_GRANT_NUMBER_LEN 1
550f74e101Schristos #define	MPCP_GRANT_NUMBER_MASK 0x7
560f74e101Schristos static const struct tok mpcp_grant_flag_values[] = {
570f74e101Schristos     { 0x08, "Discovery" },
580f74e101Schristos     { 0x10, "Force Grant #1" },
590f74e101Schristos     { 0x20, "Force Grant #2" },
600f74e101Schristos     { 0x40, "Force Grant #3" },
610f74e101Schristos     { 0x80, "Force Grant #4" },
620f74e101Schristos     { 0, NULL}
630f74e101Schristos };
640f74e101Schristos 
650f74e101Schristos struct mpcp_grant_t {
66c74ad251Schristos     nd_uint32_t starttime;
67c74ad251Schristos     nd_uint16_t duration;
680f74e101Schristos };
690f74e101Schristos 
700f74e101Schristos struct mpcp_reg_req_t {
71c74ad251Schristos     nd_uint8_t flags;
72c74ad251Schristos     nd_uint8_t pending_grants;
730f74e101Schristos };
740f74e101Schristos 
750f74e101Schristos 
760f74e101Schristos static const struct tok mpcp_reg_req_flag_values[] = {
770f74e101Schristos     { 1, "Register" },
780f74e101Schristos     { 3, "De-Register" },
790f74e101Schristos     { 0, NULL}
800f74e101Schristos };
810f74e101Schristos 
820f74e101Schristos struct mpcp_reg_t {
83c74ad251Schristos     nd_uint16_t assigned_port;
84c74ad251Schristos     nd_uint8_t  flags;
85c74ad251Schristos     nd_uint16_t sync_time;
86c74ad251Schristos     nd_uint8_t  echoed_pending_grants;
870f74e101Schristos };
880f74e101Schristos 
890f74e101Schristos static const struct tok mpcp_reg_flag_values[] = {
900f74e101Schristos     { 1, "Re-Register" },
910f74e101Schristos     { 2, "De-Register" },
920f74e101Schristos     { 3, "ACK" },
930f74e101Schristos     { 4, "NACK" },
940f74e101Schristos     { 0, NULL}
950f74e101Schristos };
960f74e101Schristos 
970f74e101Schristos #define MPCP_REPORT_QUEUESETS_LEN    1
980f74e101Schristos #define MPCP_REPORT_REPORTBITMAP_LEN 1
990f74e101Schristos static const struct tok mpcp_report_bitmap_values[] = {
1000f74e101Schristos     { 0x01, "Q0" },
1010f74e101Schristos     { 0x02, "Q1" },
1020f74e101Schristos     { 0x04, "Q2" },
1030f74e101Schristos     { 0x08, "Q3" },
1040f74e101Schristos     { 0x10, "Q4" },
1050f74e101Schristos     { 0x20, "Q5" },
1060f74e101Schristos     { 0x40, "Q6" },
1070f74e101Schristos     { 0x80, "Q7" },
1080f74e101Schristos     { 0, NULL}
1090f74e101Schristos };
1100f74e101Schristos 
1110f74e101Schristos struct mpcp_reg_ack_t {
112c74ad251Schristos     nd_uint8_t  flags;
113c74ad251Schristos     nd_uint16_t echoed_assigned_port;
114c74ad251Schristos     nd_uint16_t echoed_sync_time;
1150f74e101Schristos };
1160f74e101Schristos 
1170f74e101Schristos static const struct tok mpcp_reg_ack_flag_values[] = {
1180f74e101Schristos     { 0, "NACK" },
1190f74e101Schristos     { 1, "ACK" },
1200f74e101Schristos     { 0, NULL}
1210f74e101Schristos };
1220f74e101Schristos 
1230f74e101Schristos void
124c74ad251Schristos mpcp_print(netdissect_options *ndo, const u_char *pptr, u_int length)
125ba2ff121Schristos {
126c74ad251Schristos     const struct mpcp_common_header_t *mpcp_common_header;
127c74ad251Schristos     const struct mpcp_reg_req_t *mpcp_reg_req;
128c74ad251Schristos     const struct mpcp_reg_t *mpcp_reg;
129c74ad251Schristos     const struct mpcp_reg_ack_t *mpcp_reg_ack;
1300f74e101Schristos 
1310f74e101Schristos 
1320f74e101Schristos     const u_char *tptr;
133b3a00663Schristos     uint16_t opcode;
134c74ad251Schristos     uint32_t timestamp;
135b3a00663Schristos     uint8_t grant_numbers, grant;
136b3a00663Schristos     uint8_t queue_sets, queue_set, report_bitmap, report;
1370f74e101Schristos 
138c74ad251Schristos     ndo->ndo_protocol = "mpcp";
1390f74e101Schristos     tptr=pptr;
140c74ad251Schristos     mpcp_common_header = (const struct mpcp_common_header_t *)pptr;
1410f74e101Schristos 
142c74ad251Schristos     opcode = GET_BE_U_2(mpcp_common_header->opcode);
143c74ad251Schristos     timestamp = GET_BE_U_4(mpcp_common_header->timestamp);
144c74ad251Schristos     ND_PRINT("MPCP, Opcode %s", tok2str(mpcp_opcode_values, "Unknown (%u)", opcode));
1450f74e101Schristos     if (opcode != MPCP_OPCODE_PAUSE) {
146c74ad251Schristos         ND_PRINT(", Timestamp %u ticks", timestamp);
1470f74e101Schristos     }
148c74ad251Schristos     ND_PRINT(", length %u", length);
1490f74e101Schristos 
150b3a00663Schristos     if (!ndo->ndo_vflag)
1510f74e101Schristos         return;
1520f74e101Schristos 
153c74ad251Schristos     tptr += sizeof(struct mpcp_common_header_t);
1540f74e101Schristos 
1550f74e101Schristos     switch (opcode) {
1560f74e101Schristos     case MPCP_OPCODE_PAUSE:
1570f74e101Schristos         break;
1580f74e101Schristos 
1590f74e101Schristos     case MPCP_OPCODE_GATE:
160c74ad251Schristos         grant_numbers = GET_U_1(tptr) & MPCP_GRANT_NUMBER_MASK;
161c74ad251Schristos         ND_PRINT("\n\tGrant Numbers %u, Flags [ %s ]",
1620f74e101Schristos                grant_numbers,
1630f74e101Schristos                bittok2str(mpcp_grant_flag_values,
1640f74e101Schristos                           "?",
165c74ad251Schristos                           GET_U_1(tptr) & ~MPCP_GRANT_NUMBER_MASK));
1660f74e101Schristos         tptr++;
1670f74e101Schristos 
1680f74e101Schristos         for (grant = 1; grant <= grant_numbers; grant++) {
169c74ad251Schristos             const struct mpcp_grant_t *mpcp_grant = (const struct mpcp_grant_t *)tptr;
170c74ad251Schristos             ND_PRINT("\n\tGrant #%u, Start-Time %u ticks, duration %u ticks",
1710f74e101Schristos                    grant,
172c74ad251Schristos                    GET_BE_U_4(mpcp_grant->starttime),
173c74ad251Schristos                    GET_BE_U_2(mpcp_grant->duration));
174c74ad251Schristos             tptr += sizeof(struct mpcp_grant_t);
1750f74e101Schristos         }
1760f74e101Schristos 
177c74ad251Schristos         ND_PRINT("\n\tSync-Time %u ticks", GET_BE_U_2(tptr));
1780f74e101Schristos         break;
1790f74e101Schristos 
1800f74e101Schristos 
1810f74e101Schristos     case MPCP_OPCODE_REPORT:
182c74ad251Schristos         queue_sets = GET_U_1(tptr);
1830f74e101Schristos         tptr+=MPCP_REPORT_QUEUESETS_LEN;
184c74ad251Schristos         ND_PRINT("\n\tTotal Queue-Sets %u", queue_sets);
1850f74e101Schristos 
1860f74e101Schristos         for (queue_set = 1; queue_set < queue_sets; queue_set++) {
187c74ad251Schristos             report_bitmap = GET_U_1(tptr);
188c74ad251Schristos             ND_PRINT("\n\t  Queue-Set #%u, Report-Bitmap [ %s ]",
1890f74e101Schristos                    queue_sets,
190c74ad251Schristos                    bittok2str(mpcp_report_bitmap_values, "Unknown", report_bitmap));
1910f74e101Schristos             tptr++;
1920f74e101Schristos 
1930f74e101Schristos             report=1;
1940f74e101Schristos             while (report_bitmap != 0) {
1950f74e101Schristos                 if (report_bitmap & 1) {
196c74ad251Schristos                     ND_PRINT("\n\t    Q%u Report, Duration %u ticks",
1970f74e101Schristos                            report,
198c74ad251Schristos                            GET_BE_U_2(tptr));
199c74ad251Schristos                     tptr += 2;
2000f74e101Schristos                 }
2010f74e101Schristos                 report++;
2020f74e101Schristos                 report_bitmap = report_bitmap >> 1;
2030f74e101Schristos             }
2040f74e101Schristos         }
2050f74e101Schristos         break;
2060f74e101Schristos 
2070f74e101Schristos     case MPCP_OPCODE_REG_REQ:
208c74ad251Schristos         mpcp_reg_req = (const struct mpcp_reg_req_t *)tptr;
209c74ad251Schristos         ND_PRINT("\n\tFlags [ %s ], Pending-Grants %u",
210c74ad251Schristos                bittok2str(mpcp_reg_req_flag_values, "Reserved", GET_U_1(mpcp_reg_req->flags)),
211c74ad251Schristos                GET_U_1(mpcp_reg_req->pending_grants));
2120f74e101Schristos         break;
2130f74e101Schristos 
2140f74e101Schristos     case MPCP_OPCODE_REG:
215c74ad251Schristos         mpcp_reg = (const struct mpcp_reg_t *)tptr;
216c74ad251Schristos         ND_PRINT("\n\tAssigned-Port %u, Flags [ %s ]"
2170f74e101Schristos                "\n\tSync-Time %u ticks, Echoed-Pending-Grants %u",
218c74ad251Schristos                GET_BE_U_2(mpcp_reg->assigned_port),
219c74ad251Schristos                bittok2str(mpcp_reg_flag_values, "Reserved", GET_U_1(mpcp_reg->flags)),
220c74ad251Schristos                GET_BE_U_2(mpcp_reg->sync_time),
221c74ad251Schristos                GET_U_1(mpcp_reg->echoed_pending_grants));
2220f74e101Schristos         break;
2230f74e101Schristos 
2240f74e101Schristos     case MPCP_OPCODE_REG_ACK:
225c74ad251Schristos         mpcp_reg_ack = (const struct mpcp_reg_ack_t *)tptr;
226c74ad251Schristos         ND_PRINT("\n\tEchoed-Assigned-Port %u, Flags [ %s ]"
2270f74e101Schristos                "\n\tEchoed-Sync-Time %u ticks",
228c74ad251Schristos                GET_BE_U_2(mpcp_reg_ack->echoed_assigned_port),
229c74ad251Schristos                bittok2str(mpcp_reg_ack_flag_values, "Reserved", GET_U_1(mpcp_reg_ack->flags)),
230c74ad251Schristos                GET_BE_U_2(mpcp_reg_ack->echoed_sync_time));
2310f74e101Schristos         break;
2320f74e101Schristos 
2330f74e101Schristos     default:
2340f74e101Schristos         /* unknown opcode - hexdump for now */
235b3a00663Schristos         print_unknown_data(ndo,pptr, "\n\t", length);
2360f74e101Schristos         break;
2370f74e101Schristos     }
2380f74e101Schristos }
239