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 #ifdef HAVE_CONFIG_H 21 #include <config.h> 22 #endif 23 24 #include "netdissect-stdinc.h" 25 26 #include "netdissect.h" 27 #include "extract.h" 28 29 struct mpcp_common_header_t { 30 nd_uint16_t opcode; 31 nd_uint32_t timestamp; 32 }; 33 34 #define MPCP_OPCODE_PAUSE 0x0001 35 #define MPCP_OPCODE_GATE 0x0002 36 #define MPCP_OPCODE_REPORT 0x0003 37 #define MPCP_OPCODE_REG_REQ 0x0004 38 #define MPCP_OPCODE_REG 0x0005 39 #define MPCP_OPCODE_REG_ACK 0x0006 40 41 static const struct tok mpcp_opcode_values[] = { 42 { MPCP_OPCODE_PAUSE, "Pause" }, 43 { MPCP_OPCODE_GATE, "Gate" }, 44 { MPCP_OPCODE_REPORT, "Report" }, 45 { MPCP_OPCODE_REG_REQ, "Register Request" }, 46 { MPCP_OPCODE_REG, "Register" }, 47 { MPCP_OPCODE_REG_ACK, "Register ACK" }, 48 { 0, NULL} 49 }; 50 51 #define MPCP_GRANT_NUMBER_LEN 1 52 #define MPCP_GRANT_NUMBER_MASK 0x7 53 static const struct tok mpcp_grant_flag_values[] = { 54 { 0x08, "Discovery" }, 55 { 0x10, "Force Grant #1" }, 56 { 0x20, "Force Grant #2" }, 57 { 0x40, "Force Grant #3" }, 58 { 0x80, "Force Grant #4" }, 59 { 0, NULL} 60 }; 61 62 struct mpcp_grant_t { 63 nd_uint32_t starttime; 64 nd_uint16_t duration; 65 }; 66 67 struct mpcp_reg_req_t { 68 nd_uint8_t flags; 69 nd_uint8_t pending_grants; 70 }; 71 72 73 static const struct tok mpcp_reg_req_flag_values[] = { 74 { 1, "Register" }, 75 { 3, "De-Register" }, 76 { 0, NULL} 77 }; 78 79 struct mpcp_reg_t { 80 nd_uint16_t assigned_port; 81 nd_uint8_t flags; 82 nd_uint16_t sync_time; 83 nd_uint8_t echoed_pending_grants; 84 }; 85 86 static const struct tok mpcp_reg_flag_values[] = { 87 { 1, "Re-Register" }, 88 { 2, "De-Register" }, 89 { 3, "ACK" }, 90 { 4, "NACK" }, 91 { 0, NULL} 92 }; 93 94 #define MPCP_REPORT_QUEUESETS_LEN 1 95 #define MPCP_REPORT_REPORTBITMAP_LEN 1 96 static const struct tok mpcp_report_bitmap_values[] = { 97 { 0x01, "Q0" }, 98 { 0x02, "Q1" }, 99 { 0x04, "Q2" }, 100 { 0x08, "Q3" }, 101 { 0x10, "Q4" }, 102 { 0x20, "Q5" }, 103 { 0x40, "Q6" }, 104 { 0x80, "Q7" }, 105 { 0, NULL} 106 }; 107 108 struct mpcp_reg_ack_t { 109 nd_uint8_t flags; 110 nd_uint16_t echoed_assigned_port; 111 nd_uint16_t echoed_sync_time; 112 }; 113 114 static const struct tok mpcp_reg_ack_flag_values[] = { 115 { 0, "NACK" }, 116 { 1, "ACK" }, 117 { 0, NULL} 118 }; 119 120 void 121 mpcp_print(netdissect_options *ndo, const u_char *pptr, u_int length) 122 { 123 const struct mpcp_common_header_t *mpcp_common_header; 124 const struct mpcp_reg_req_t *mpcp_reg_req; 125 const struct mpcp_reg_t *mpcp_reg; 126 const struct mpcp_reg_ack_t *mpcp_reg_ack; 127 128 129 const u_char *tptr; 130 uint16_t opcode; 131 uint32_t timestamp; 132 uint8_t grant_numbers, grant; 133 uint8_t queue_sets, queue_set, report_bitmap, report; 134 135 ndo->ndo_protocol = "mpcp"; 136 tptr=pptr; 137 mpcp_common_header = (const struct mpcp_common_header_t *)pptr; 138 139 opcode = GET_BE_U_2(mpcp_common_header->opcode); 140 timestamp = GET_BE_U_4(mpcp_common_header->timestamp); 141 ND_PRINT("MPCP, Opcode %s", tok2str(mpcp_opcode_values, "Unknown (%u)", opcode)); 142 if (opcode != MPCP_OPCODE_PAUSE) { 143 ND_PRINT(", Timestamp %u ticks", timestamp); 144 } 145 ND_PRINT(", length %u", length); 146 147 if (!ndo->ndo_vflag) 148 return; 149 150 tptr += sizeof(struct mpcp_common_header_t); 151 152 switch (opcode) { 153 case MPCP_OPCODE_PAUSE: 154 break; 155 156 case MPCP_OPCODE_GATE: 157 grant_numbers = GET_U_1(tptr) & MPCP_GRANT_NUMBER_MASK; 158 ND_PRINT("\n\tGrant Numbers %u, Flags [ %s ]", 159 grant_numbers, 160 bittok2str(mpcp_grant_flag_values, 161 "?", 162 GET_U_1(tptr) & ~MPCP_GRANT_NUMBER_MASK)); 163 tptr++; 164 165 for (grant = 1; grant <= grant_numbers; grant++) { 166 const struct mpcp_grant_t *mpcp_grant = (const struct mpcp_grant_t *)tptr; 167 ND_PRINT("\n\tGrant #%u, Start-Time %u ticks, duration %u ticks", 168 grant, 169 GET_BE_U_4(mpcp_grant->starttime), 170 GET_BE_U_2(mpcp_grant->duration)); 171 tptr += sizeof(struct mpcp_grant_t); 172 } 173 174 ND_PRINT("\n\tSync-Time %u ticks", GET_BE_U_2(tptr)); 175 break; 176 177 178 case MPCP_OPCODE_REPORT: 179 queue_sets = GET_U_1(tptr); 180 tptr+=MPCP_REPORT_QUEUESETS_LEN; 181 ND_PRINT("\n\tTotal Queue-Sets %u", queue_sets); 182 183 for (queue_set = 1; queue_set < queue_sets; queue_set++) { 184 report_bitmap = GET_U_1(tptr); 185 ND_PRINT("\n\t Queue-Set #%u, Report-Bitmap [ %s ]", 186 queue_sets, 187 bittok2str(mpcp_report_bitmap_values, "Unknown", report_bitmap)); 188 tptr++; 189 190 report=1; 191 while (report_bitmap != 0) { 192 if (report_bitmap & 1) { 193 ND_PRINT("\n\t Q%u Report, Duration %u ticks", 194 report, 195 GET_BE_U_2(tptr)); 196 tptr += 2; 197 } 198 report++; 199 report_bitmap = report_bitmap >> 1; 200 } 201 } 202 break; 203 204 case MPCP_OPCODE_REG_REQ: 205 mpcp_reg_req = (const struct mpcp_reg_req_t *)tptr; 206 ND_PRINT("\n\tFlags [ %s ], Pending-Grants %u", 207 bittok2str(mpcp_reg_req_flag_values, "Reserved", GET_U_1(mpcp_reg_req->flags)), 208 GET_U_1(mpcp_reg_req->pending_grants)); 209 break; 210 211 case MPCP_OPCODE_REG: 212 mpcp_reg = (const struct mpcp_reg_t *)tptr; 213 ND_PRINT("\n\tAssigned-Port %u, Flags [ %s ]" 214 "\n\tSync-Time %u ticks, Echoed-Pending-Grants %u", 215 GET_BE_U_2(mpcp_reg->assigned_port), 216 bittok2str(mpcp_reg_flag_values, "Reserved", GET_U_1(mpcp_reg->flags)), 217 GET_BE_U_2(mpcp_reg->sync_time), 218 GET_U_1(mpcp_reg->echoed_pending_grants)); 219 break; 220 221 case MPCP_OPCODE_REG_ACK: 222 mpcp_reg_ack = (const struct mpcp_reg_ack_t *)tptr; 223 ND_PRINT("\n\tEchoed-Assigned-Port %u, Flags [ %s ]" 224 "\n\tEchoed-Sync-Time %u ticks", 225 GET_BE_U_2(mpcp_reg_ack->echoed_assigned_port), 226 bittok2str(mpcp_reg_ack_flag_values, "Reserved", GET_U_1(mpcp_reg_ack->flags)), 227 GET_BE_U_2(mpcp_reg_ack->echoed_sync_time)); 228 break; 229 230 default: 231 /* unknown opcode - hexdump for now */ 232 print_unknown_data(ndo,pptr, "\n\t", length); 233 break; 234 } 235 } 236