1190203Srpaulo/* 2190203Srpaulo * Copyright (c) 1998-2006 The TCPDUMP project 3190203Srpaulo * 4190203Srpaulo * Redistribution and use in source and binary forms, with or without 5190203Srpaulo * modification, are permitted provided that: (1) source code 6190203Srpaulo * distributions retain the above copyright notice and this paragraph 7190203Srpaulo * in its entirety, and (2) distributions including binary code include 8190203Srpaulo * the above copyright notice and this paragraph in its entirety in 9190203Srpaulo * the documentation or other materials provided with the distribution. 10190203Srpaulo * THIS SOFTWARE IS PROVIDED ``AS IS'' AND 11190203Srpaulo * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT 12190203Srpaulo * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 13190203Srpaulo * FOR A PARTICULAR PURPOSE. 14190203Srpaulo * 15190203Srpaulo * support for the IEEE MPCP protocol as per 802.3ah 16190203Srpaulo * 17190203Srpaulo * Original code by Hannes Gredler (hannes@juniper.net) 18190203Srpaulo */ 19190203Srpaulo 20190203Srpaulo#ifndef lint 21190203Srpaulostatic const char rcsid[] _U_ = 22190203Srpaulo "@(#) $Header: /tcpdump/master/tcpdump/print-mpcp.c,v 1.2 2006-02-10 17:24:55 hannes Exp $"; 23190203Srpaulo#endif 24190203Srpaulo 25190203Srpaulo#ifdef HAVE_CONFIG_H 26190203Srpaulo#include "config.h" 27190203Srpaulo#endif 28190203Srpaulo 29190203Srpaulo#include <tcpdump-stdinc.h> 30190203Srpaulo 31190203Srpaulo#include <stdio.h> 32190203Srpaulo#include <stdlib.h> 33190203Srpaulo#include <string.h> 34190203Srpaulo 35190203Srpaulo#include "interface.h" 36190203Srpaulo#include "extract.h" 37190203Srpaulo#include "addrtoname.h" 38190203Srpaulo#include "ether.h" 39190203Srpaulo 40190203Srpaulo#define MPCP_TIMESTAMP_LEN 4 41190203Srpaulo#define MPCP_TIMESTAMP_DURATION_LEN 2 42190203Srpaulo 43190203Srpaulostruct mpcp_common_header_t { 44190203Srpaulo u_int8_t opcode[2]; 45190203Srpaulo u_int8_t timestamp[MPCP_TIMESTAMP_LEN]; 46190203Srpaulo}; 47190203Srpaulo 48190203Srpaulo#define MPCP_OPCODE_PAUSE 0x0001 49190203Srpaulo#define MPCP_OPCODE_GATE 0x0002 50190203Srpaulo#define MPCP_OPCODE_REPORT 0x0003 51190203Srpaulo#define MPCP_OPCODE_REG_REQ 0x0004 52190203Srpaulo#define MPCP_OPCODE_REG 0x0005 53190203Srpaulo#define MPCP_OPCODE_REG_ACK 0x0006 54190203Srpaulo 55190203Srpaulostatic const struct tok mpcp_opcode_values[] = { 56190203Srpaulo { MPCP_OPCODE_PAUSE, "Pause" }, 57190203Srpaulo { MPCP_OPCODE_GATE, "Gate" }, 58190203Srpaulo { MPCP_OPCODE_REPORT, "Report" }, 59190203Srpaulo { MPCP_OPCODE_REG_REQ, "Register Request" }, 60190203Srpaulo { MPCP_OPCODE_REG, "Register" }, 61190203Srpaulo { MPCP_OPCODE_REG_ACK, "Register ACK" }, 62190203Srpaulo { 0, NULL} 63190203Srpaulo}; 64190203Srpaulo 65190203Srpaulo#define MPCP_GRANT_NUMBER_LEN 1 66190203Srpaulo#define MPCP_GRANT_NUMBER_MASK 0x7 67190203Srpaulostatic const struct tok mpcp_grant_flag_values[] = { 68190203Srpaulo { 0x08, "Discovery" }, 69190203Srpaulo { 0x10, "Force Grant #1" }, 70190203Srpaulo { 0x20, "Force Grant #2" }, 71190203Srpaulo { 0x40, "Force Grant #3" }, 72190203Srpaulo { 0x80, "Force Grant #4" }, 73190203Srpaulo { 0, NULL} 74190203Srpaulo}; 75190203Srpaulo 76190203Srpaulostruct mpcp_grant_t { 77190203Srpaulo u_int8_t starttime[MPCP_TIMESTAMP_LEN]; 78190203Srpaulo u_int8_t duration[MPCP_TIMESTAMP_DURATION_LEN]; 79190203Srpaulo}; 80190203Srpaulo 81190203Srpaulostruct mpcp_reg_req_t { 82190203Srpaulo u_int8_t flags; 83190203Srpaulo u_int8_t pending_grants; 84190203Srpaulo}; 85190203Srpaulo 86190203Srpaulo 87190203Srpaulostatic const struct tok mpcp_reg_req_flag_values[] = { 88190203Srpaulo { 1, "Register" }, 89190203Srpaulo { 3, "De-Register" }, 90190203Srpaulo { 0, NULL} 91190203Srpaulo}; 92190203Srpaulo 93190203Srpaulostruct mpcp_reg_t { 94190203Srpaulo u_int8_t assigned_port[2]; 95190203Srpaulo u_int8_t flags; 96190203Srpaulo u_int8_t sync_time[MPCP_TIMESTAMP_DURATION_LEN]; 97190203Srpaulo u_int8_t echoed_pending_grants; 98190203Srpaulo}; 99190203Srpaulo 100190203Srpaulostatic const struct tok mpcp_reg_flag_values[] = { 101190203Srpaulo { 1, "Re-Register" }, 102190203Srpaulo { 2, "De-Register" }, 103190203Srpaulo { 3, "ACK" }, 104190203Srpaulo { 4, "NACK" }, 105190203Srpaulo { 0, NULL} 106190203Srpaulo}; 107190203Srpaulo 108190203Srpaulo#define MPCP_REPORT_QUEUESETS_LEN 1 109190203Srpaulo#define MPCP_REPORT_REPORTBITMAP_LEN 1 110190203Srpaulostatic const struct tok mpcp_report_bitmap_values[] = { 111190203Srpaulo { 0x01, "Q0" }, 112190203Srpaulo { 0x02, "Q1" }, 113190203Srpaulo { 0x04, "Q2" }, 114190203Srpaulo { 0x08, "Q3" }, 115190203Srpaulo { 0x10, "Q4" }, 116190203Srpaulo { 0x20, "Q5" }, 117190203Srpaulo { 0x40, "Q6" }, 118190203Srpaulo { 0x80, "Q7" }, 119190203Srpaulo { 0, NULL} 120190203Srpaulo}; 121190203Srpaulo 122190203Srpaulostruct mpcp_reg_ack_t { 123190203Srpaulo u_int8_t flags; 124190203Srpaulo u_int8_t echoed_assigned_port[2]; 125190203Srpaulo u_int8_t echoed_sync_time[MPCP_TIMESTAMP_DURATION_LEN]; 126190203Srpaulo}; 127190203Srpaulo 128190203Srpaulostatic const struct tok mpcp_reg_ack_flag_values[] = { 129190203Srpaulo { 0, "NACK" }, 130190203Srpaulo { 1, "ACK" }, 131190203Srpaulo { 0, NULL} 132190203Srpaulo}; 133190203Srpaulo 134190203Srpaulovoid 135190203Srpaulompcp_print(register const u_char *pptr, register u_int length) { 136190203Srpaulo 137190203Srpaulo union { 138190203Srpaulo const struct mpcp_common_header_t *common_header; 139190203Srpaulo const struct mpcp_grant_t *grant; 140190203Srpaulo const struct mpcp_reg_req_t *reg_req; 141190203Srpaulo const struct mpcp_reg_t *reg; 142190203Srpaulo const struct mpcp_reg_ack_t *reg_ack; 143190203Srpaulo } mpcp; 144190203Srpaulo 145190203Srpaulo 146190203Srpaulo const u_char *tptr; 147190203Srpaulo u_int16_t opcode; 148190203Srpaulo u_int8_t grant_numbers, grant; 149190203Srpaulo u_int8_t queue_sets, queue_set, report_bitmap, report; 150190203Srpaulo 151190203Srpaulo tptr=pptr; 152190203Srpaulo mpcp.common_header = (const struct mpcp_common_header_t *)pptr; 153190203Srpaulo 154190203Srpaulo if (!TTEST2(*tptr, sizeof(const struct mpcp_common_header_t))) 155190203Srpaulo goto trunc; 156190203Srpaulo opcode = EXTRACT_16BITS(mpcp.common_header->opcode); 157190203Srpaulo printf("MPCP, Opcode %s", tok2str(mpcp_opcode_values, "Unknown (%u)", opcode)); 158190203Srpaulo if (opcode != MPCP_OPCODE_PAUSE) { 159190203Srpaulo printf(", Timestamp %u ticks", EXTRACT_32BITS(mpcp.common_header->timestamp)); 160190203Srpaulo } 161190203Srpaulo printf(", length %u", length); 162190203Srpaulo 163190203Srpaulo if (!vflag) 164190203Srpaulo return; 165190203Srpaulo 166190203Srpaulo tptr += sizeof(const struct mpcp_common_header_t); 167190203Srpaulo 168190203Srpaulo switch (opcode) { 169190203Srpaulo case MPCP_OPCODE_PAUSE: 170190203Srpaulo break; 171190203Srpaulo 172190203Srpaulo case MPCP_OPCODE_GATE: 173190203Srpaulo if (!TTEST2(*tptr, MPCP_GRANT_NUMBER_LEN)) 174190203Srpaulo goto trunc; 175190203Srpaulo grant_numbers = *tptr & MPCP_GRANT_NUMBER_MASK; 176190203Srpaulo printf("\n\tGrant Numbers %u, Flags [ %s ]", 177190203Srpaulo grant_numbers, 178190203Srpaulo bittok2str(mpcp_grant_flag_values, 179190203Srpaulo "?", 180190203Srpaulo *tptr &~ MPCP_GRANT_NUMBER_MASK)); 181190203Srpaulo tptr++; 182190203Srpaulo 183190203Srpaulo for (grant = 1; grant <= grant_numbers; grant++) { 184190203Srpaulo if (!TTEST2(*tptr, sizeof(const struct mpcp_grant_t))) 185190203Srpaulo goto trunc; 186190203Srpaulo mpcp.grant = (const struct mpcp_grant_t *)tptr; 187190203Srpaulo printf("\n\tGrant #%u, Start-Time %u ticks, duration %u ticks", 188190203Srpaulo grant, 189190203Srpaulo EXTRACT_32BITS(mpcp.grant->starttime), 190190203Srpaulo EXTRACT_16BITS(mpcp.grant->duration)); 191190203Srpaulo tptr += sizeof(const struct mpcp_grant_t); 192190203Srpaulo } 193190203Srpaulo 194190203Srpaulo if (!TTEST2(*tptr, MPCP_TIMESTAMP_DURATION_LEN)) 195190203Srpaulo goto trunc; 196190203Srpaulo printf("\n\tSync-Time %u ticks", EXTRACT_16BITS(tptr)); 197190203Srpaulo break; 198190203Srpaulo 199190203Srpaulo 200190203Srpaulo case MPCP_OPCODE_REPORT: 201190203Srpaulo if (!TTEST2(*tptr, MPCP_REPORT_QUEUESETS_LEN)) 202190203Srpaulo goto trunc; 203190203Srpaulo queue_sets = *tptr; 204190203Srpaulo tptr+=MPCP_REPORT_QUEUESETS_LEN; 205190203Srpaulo printf("\n\tTotal Queue-Sets %u", queue_sets); 206190203Srpaulo 207190203Srpaulo for (queue_set = 1; queue_set < queue_sets; queue_set++) { 208190203Srpaulo if (!TTEST2(*tptr, MPCP_REPORT_REPORTBITMAP_LEN)) 209190203Srpaulo goto trunc; 210190203Srpaulo report_bitmap = *(tptr); 211190203Srpaulo printf("\n\t Queue-Set #%u, Report-Bitmap [ %s ]", 212190203Srpaulo queue_sets, 213190203Srpaulo bittok2str(mpcp_report_bitmap_values, "Unknown", report_bitmap)); 214190203Srpaulo tptr++; 215190203Srpaulo 216190203Srpaulo report=1; 217190203Srpaulo while (report_bitmap != 0) { 218190203Srpaulo if (report_bitmap & 1) { 219190203Srpaulo if (!TTEST2(*tptr, MPCP_TIMESTAMP_DURATION_LEN)) 220190203Srpaulo goto trunc; 221190203Srpaulo printf("\n\t Q%u Report, Duration %u ticks", 222190203Srpaulo report, 223190203Srpaulo EXTRACT_16BITS(tptr)); 224190203Srpaulo tptr+=MPCP_TIMESTAMP_DURATION_LEN; 225190203Srpaulo } 226190203Srpaulo report++; 227190203Srpaulo report_bitmap = report_bitmap >> 1; 228190203Srpaulo } 229190203Srpaulo } 230190203Srpaulo break; 231190203Srpaulo 232190203Srpaulo case MPCP_OPCODE_REG_REQ: 233190203Srpaulo if (!TTEST2(*tptr, sizeof(const struct mpcp_reg_req_t))) 234190203Srpaulo goto trunc; 235190203Srpaulo mpcp.reg_req = (const struct mpcp_reg_req_t *)tptr; 236190203Srpaulo printf("\n\tFlags [ %s ], Pending-Grants %u", 237190203Srpaulo bittok2str(mpcp_reg_req_flag_values, "Reserved", mpcp.reg_req->flags), 238190203Srpaulo mpcp.reg_req->pending_grants); 239190203Srpaulo break; 240190203Srpaulo 241190203Srpaulo case MPCP_OPCODE_REG: 242190203Srpaulo if (!TTEST2(*tptr, sizeof(const struct mpcp_reg_t))) 243190203Srpaulo goto trunc; 244190203Srpaulo mpcp.reg = (const struct mpcp_reg_t *)tptr; 245190203Srpaulo printf("\n\tAssigned-Port %u, Flags [ %s ]" \ 246190203Srpaulo "\n\tSync-Time %u ticks, Echoed-Pending-Grants %u", 247190203Srpaulo EXTRACT_16BITS(mpcp.reg->assigned_port), 248190203Srpaulo bittok2str(mpcp_reg_flag_values, "Reserved", mpcp.reg->flags), 249190203Srpaulo EXTRACT_16BITS(mpcp.reg->sync_time), 250190203Srpaulo mpcp.reg->echoed_pending_grants); 251190203Srpaulo break; 252190203Srpaulo 253190203Srpaulo case MPCP_OPCODE_REG_ACK: 254190203Srpaulo if (!TTEST2(*tptr, sizeof(const struct mpcp_reg_ack_t))) 255190203Srpaulo goto trunc; 256190203Srpaulo mpcp.reg_ack = (const struct mpcp_reg_ack_t *)tptr; 257190203Srpaulo printf("\n\tEchoed-Assigned-Port %u, Flags [ %s ]" \ 258190203Srpaulo "\n\tEchoed-Sync-Time %u ticks", 259190203Srpaulo EXTRACT_16BITS(mpcp.reg_ack->echoed_assigned_port), 260190203Srpaulo bittok2str(mpcp_reg_ack_flag_values, "Reserved", mpcp.reg_ack->flags), 261190203Srpaulo EXTRACT_16BITS(mpcp.reg_ack->echoed_sync_time)); 262190203Srpaulo break; 263190203Srpaulo 264190203Srpaulo default: 265190203Srpaulo /* unknown opcode - hexdump for now */ 266190203Srpaulo print_unknown_data(pptr, "\n\t", length); 267190203Srpaulo break; 268190203Srpaulo } 269190203Srpaulo 270190203Srpaulo return; 271190203Srpaulo 272190203Srpaulotrunc: 273190203Srpaulo printf("\n\t[|MPCP]"); 274190203Srpaulo} 275