print-mpcp.c revision 1.8
1/* 2 * Copyright (c) 1998-2006 The TCPDUMP project 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that: (1) source code 6 * distributions retain the above copyright notice and this paragraph 7 * in its entirety, and (2) distributions including binary code include 8 * the above copyright notice and this paragraph in its entirety in 9 * the documentation or other materials provided with the distribution. 10 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 11 * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT 12 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 13 * FOR A PARTICULAR PURPOSE. 14 * 15 * Original code by Hannes Gredler (hannes@gredler.at) 16 */ 17 18/* \summary: IEEE 802.3ah Multi-Point Control Protocol (MPCP) printer */ 19 20#include <sys/cdefs.h> 21#ifndef lint 22__RCSID("$NetBSD: print-mpcp.c,v 1.8 2017/09/08 14:01:13 christos Exp $"); 23#endif 24 25#ifdef HAVE_CONFIG_H 26#include "config.h" 27#endif 28 29#include <netdissect-stdinc.h> 30 31#include "netdissect.h" 32#include "extract.h" 33 34#define MPCP_TIMESTAMP_LEN 4 35#define MPCP_TIMESTAMP_DURATION_LEN 2 36 37struct mpcp_common_header_t { 38 uint8_t opcode[2]; 39 uint8_t timestamp[MPCP_TIMESTAMP_LEN]; 40}; 41 42#define MPCP_OPCODE_PAUSE 0x0001 43#define MPCP_OPCODE_GATE 0x0002 44#define MPCP_OPCODE_REPORT 0x0003 45#define MPCP_OPCODE_REG_REQ 0x0004 46#define MPCP_OPCODE_REG 0x0005 47#define MPCP_OPCODE_REG_ACK 0x0006 48 49static const struct tok mpcp_opcode_values[] = { 50 { MPCP_OPCODE_PAUSE, "Pause" }, 51 { MPCP_OPCODE_GATE, "Gate" }, 52 { MPCP_OPCODE_REPORT, "Report" }, 53 { MPCP_OPCODE_REG_REQ, "Register Request" }, 54 { MPCP_OPCODE_REG, "Register" }, 55 { MPCP_OPCODE_REG_ACK, "Register ACK" }, 56 { 0, NULL} 57}; 58 59#define MPCP_GRANT_NUMBER_LEN 1 60#define MPCP_GRANT_NUMBER_MASK 0x7 61static const struct tok mpcp_grant_flag_values[] = { 62 { 0x08, "Discovery" }, 63 { 0x10, "Force Grant #1" }, 64 { 0x20, "Force Grant #2" }, 65 { 0x40, "Force Grant #3" }, 66 { 0x80, "Force Grant #4" }, 67 { 0, NULL} 68}; 69 70struct mpcp_grant_t { 71 uint8_t starttime[MPCP_TIMESTAMP_LEN]; 72 uint8_t duration[MPCP_TIMESTAMP_DURATION_LEN]; 73}; 74 75struct mpcp_reg_req_t { 76 uint8_t flags; 77 uint8_t pending_grants; 78}; 79 80 81static const struct tok mpcp_reg_req_flag_values[] = { 82 { 1, "Register" }, 83 { 3, "De-Register" }, 84 { 0, NULL} 85}; 86 87struct mpcp_reg_t { 88 uint8_t assigned_port[2]; 89 uint8_t flags; 90 uint8_t sync_time[MPCP_TIMESTAMP_DURATION_LEN]; 91 uint8_t echoed_pending_grants; 92}; 93 94static const struct tok mpcp_reg_flag_values[] = { 95 { 1, "Re-Register" }, 96 { 2, "De-Register" }, 97 { 3, "ACK" }, 98 { 4, "NACK" }, 99 { 0, NULL} 100}; 101 102#define MPCP_REPORT_QUEUESETS_LEN 1 103#define MPCP_REPORT_REPORTBITMAP_LEN 1 104static const struct tok mpcp_report_bitmap_values[] = { 105 { 0x01, "Q0" }, 106 { 0x02, "Q1" }, 107 { 0x04, "Q2" }, 108 { 0x08, "Q3" }, 109 { 0x10, "Q4" }, 110 { 0x20, "Q5" }, 111 { 0x40, "Q6" }, 112 { 0x80, "Q7" }, 113 { 0, NULL} 114}; 115 116struct mpcp_reg_ack_t { 117 uint8_t flags; 118 uint8_t echoed_assigned_port[2]; 119 uint8_t echoed_sync_time[MPCP_TIMESTAMP_DURATION_LEN]; 120}; 121 122static const struct tok mpcp_reg_ack_flag_values[] = { 123 { 0, "NACK" }, 124 { 1, "ACK" }, 125 { 0, NULL} 126}; 127 128void 129mpcp_print(netdissect_options *ndo, register const u_char *pptr, register u_int length) 130{ 131 union { 132 const struct mpcp_common_header_t *common_header; 133 const struct mpcp_grant_t *grant; 134 const struct mpcp_reg_req_t *reg_req; 135 const struct mpcp_reg_t *reg; 136 const struct mpcp_reg_ack_t *reg_ack; 137 } mpcp; 138 139 140 const u_char *tptr; 141 uint16_t opcode; 142 uint8_t grant_numbers, grant; 143 uint8_t queue_sets, queue_set, report_bitmap, report; 144 145 tptr=pptr; 146 mpcp.common_header = (const struct mpcp_common_header_t *)pptr; 147 148 ND_TCHECK2(*tptr, sizeof(const struct mpcp_common_header_t)); 149 opcode = EXTRACT_16BITS(mpcp.common_header->opcode); 150 ND_PRINT((ndo, "MPCP, Opcode %s", tok2str(mpcp_opcode_values, "Unknown (%u)", opcode))); 151 if (opcode != MPCP_OPCODE_PAUSE) { 152 ND_PRINT((ndo, ", Timestamp %u ticks", EXTRACT_32BITS(mpcp.common_header->timestamp))); 153 } 154 ND_PRINT((ndo, ", length %u", length)); 155 156 if (!ndo->ndo_vflag) 157 return; 158 159 tptr += sizeof(const struct mpcp_common_header_t); 160 161 switch (opcode) { 162 case MPCP_OPCODE_PAUSE: 163 break; 164 165 case MPCP_OPCODE_GATE: 166 ND_TCHECK2(*tptr, MPCP_GRANT_NUMBER_LEN); 167 grant_numbers = *tptr & MPCP_GRANT_NUMBER_MASK; 168 ND_PRINT((ndo, "\n\tGrant Numbers %u, Flags [ %s ]", 169 grant_numbers, 170 bittok2str(mpcp_grant_flag_values, 171 "?", 172 *tptr &~ MPCP_GRANT_NUMBER_MASK))); 173 tptr++; 174 175 for (grant = 1; grant <= grant_numbers; grant++) { 176 ND_TCHECK2(*tptr, sizeof(const struct mpcp_grant_t)); 177 mpcp.grant = (const struct mpcp_grant_t *)tptr; 178 ND_PRINT((ndo, "\n\tGrant #%u, Start-Time %u ticks, duration %u ticks", 179 grant, 180 EXTRACT_32BITS(mpcp.grant->starttime), 181 EXTRACT_16BITS(mpcp.grant->duration))); 182 tptr += sizeof(const struct mpcp_grant_t); 183 } 184 185 ND_TCHECK2(*tptr, MPCP_TIMESTAMP_DURATION_LEN); 186 ND_PRINT((ndo, "\n\tSync-Time %u ticks", EXTRACT_16BITS(tptr))); 187 break; 188 189 190 case MPCP_OPCODE_REPORT: 191 ND_TCHECK2(*tptr, MPCP_REPORT_QUEUESETS_LEN); 192 queue_sets = *tptr; 193 tptr+=MPCP_REPORT_QUEUESETS_LEN; 194 ND_PRINT((ndo, "\n\tTotal Queue-Sets %u", queue_sets)); 195 196 for (queue_set = 1; queue_set < queue_sets; queue_set++) { 197 ND_TCHECK2(*tptr, MPCP_REPORT_REPORTBITMAP_LEN); 198 report_bitmap = *(tptr); 199 ND_PRINT((ndo, "\n\t Queue-Set #%u, Report-Bitmap [ %s ]", 200 queue_sets, 201 bittok2str(mpcp_report_bitmap_values, "Unknown", report_bitmap))); 202 tptr++; 203 204 report=1; 205 while (report_bitmap != 0) { 206 if (report_bitmap & 1) { 207 ND_TCHECK2(*tptr, MPCP_TIMESTAMP_DURATION_LEN); 208 ND_PRINT((ndo, "\n\t Q%u Report, Duration %u ticks", 209 report, 210 EXTRACT_16BITS(tptr))); 211 tptr+=MPCP_TIMESTAMP_DURATION_LEN; 212 } 213 report++; 214 report_bitmap = report_bitmap >> 1; 215 } 216 } 217 break; 218 219 case MPCP_OPCODE_REG_REQ: 220 ND_TCHECK2(*tptr, sizeof(const struct mpcp_reg_req_t)); 221 mpcp.reg_req = (const struct mpcp_reg_req_t *)tptr; 222 ND_PRINT((ndo, "\n\tFlags [ %s ], Pending-Grants %u", 223 bittok2str(mpcp_reg_req_flag_values, "Reserved", mpcp.reg_req->flags), 224 mpcp.reg_req->pending_grants)); 225 break; 226 227 case MPCP_OPCODE_REG: 228 ND_TCHECK2(*tptr, sizeof(const struct mpcp_reg_t)); 229 mpcp.reg = (const struct mpcp_reg_t *)tptr; 230 ND_PRINT((ndo, "\n\tAssigned-Port %u, Flags [ %s ]" \ 231 "\n\tSync-Time %u ticks, Echoed-Pending-Grants %u", 232 EXTRACT_16BITS(mpcp.reg->assigned_port), 233 bittok2str(mpcp_reg_flag_values, "Reserved", mpcp.reg->flags), 234 EXTRACT_16BITS(mpcp.reg->sync_time), 235 mpcp.reg->echoed_pending_grants)); 236 break; 237 238 case MPCP_OPCODE_REG_ACK: 239 ND_TCHECK2(*tptr, sizeof(const struct mpcp_reg_ack_t)); 240 mpcp.reg_ack = (const struct mpcp_reg_ack_t *)tptr; 241 ND_PRINT((ndo, "\n\tEchoed-Assigned-Port %u, Flags [ %s ]" \ 242 "\n\tEchoed-Sync-Time %u ticks", 243 EXTRACT_16BITS(mpcp.reg_ack->echoed_assigned_port), 244 bittok2str(mpcp_reg_ack_flag_values, "Reserved", mpcp.reg_ack->flags), 245 EXTRACT_16BITS(mpcp.reg_ack->echoed_sync_time))); 246 break; 247 248 default: 249 /* unknown opcode - hexdump for now */ 250 print_unknown_data(ndo,pptr, "\n\t", length); 251 break; 252 } 253 254 return; 255 256trunc: 257 ND_PRINT((ndo, "\n\t[|MPCP]")); 258} 259/* 260 * Local Variables: 261 * c-style: whitesmith 262 * c-basic-offset: 8 263 * End: 264 */ 265