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