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