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