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