1e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes/* Copyright (c) 2015, bugyo 2e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes * All rights reserved. 3e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes * 4e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes * Redistribution and use in source and binary forms, with or without 5e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes * modification, are permitted provided that the following conditions are met: 6e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes * 1. Redistributions of source code must retain the above copyright notice, 7e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes * this list of conditions and the following disclaimer. 8e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes * 2. Redistributions in binary form must reproduce the above copyright notice, 9e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes * this list of conditions and the following disclaimer in the documentation 10e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes * and/or other materials provided with the distribution. 11e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes * 12e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 13e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 14e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 16e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 18e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 19e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes */ 23e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes 24e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes/* \summary: Network Service Header (NSH) printer */ 25e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes 26e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes/* specification: draft-ietf-sfc-nsh-01 */ 27e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes 28e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes#ifdef HAVE_CONFIG_H 29e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes#include "config.h" 30e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes#endif 31e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes 32e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes#include <netdissect-stdinc.h> 33e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes 34e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes#include "netdissect.h" 35e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes#include "extract.h" 36e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes 37e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughesstatic const char tstr[] = " [|NSH]"; 38e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughesstatic const struct tok nsh_flags [] = { 39e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes { 0x20, "O" }, 40e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes { 0x10, "C" }, 41e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes { 0, NULL } 42e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes}; 43e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes 44e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes#define NSH_BASE_HDR_LEN 4 45e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes#define NSH_SERVICE_PATH_HDR_LEN 4 46e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes#define NSH_HDR_WORD_SIZE 4U 47e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes 48e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughesvoid 49e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughesnsh_print(netdissect_options *ndo, const u_char *bp, u_int len) 50e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes{ 51e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes int n, vn; 52e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes uint8_t ver; 53e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes uint8_t flags; 54e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes uint8_t length; 55e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes uint8_t md_type; 56e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes uint8_t next_protocol; 57e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes uint32_t service_path_id; 58e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes uint8_t service_index; 59e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes uint32_t ctx; 60e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes uint16_t tlv_class; 61e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes uint8_t tlv_type; 62e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes uint8_t tlv_len; 63e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes u_int next_len; 64e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes 65e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes /* print Base Header and Service Path Header */ 66e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes if (len < NSH_BASE_HDR_LEN + NSH_SERVICE_PATH_HDR_LEN) 67e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes goto trunc; 68e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes 69e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes ND_TCHECK2(*bp, NSH_BASE_HDR_LEN + NSH_SERVICE_PATH_HDR_LEN); 70e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes 71e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes ver = (uint8_t)(*bp >> 6); 72e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes flags = *bp; 73e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes bp += 1; 74e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes length = *bp; 75e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes bp += 1; 76e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes md_type = *bp; 77e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes bp += 1; 78e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes next_protocol = *bp; 79e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes bp += 1; 80e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes service_path_id = EXTRACT_24BITS(bp); 81e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes bp += 3; 82e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes service_index = *bp; 83e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes bp += 1; 84e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes 85e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes ND_PRINT((ndo, "NSH, ")); 86e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes if (ndo->ndo_vflag > 1) { 87e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes ND_PRINT((ndo, "ver %d, ", ver)); 88e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes } 89e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes ND_PRINT((ndo, "flags [%s], ", bittok2str_nosep(nsh_flags, "none", flags))); 90e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes if (ndo->ndo_vflag > 2) { 91e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes ND_PRINT((ndo, "length %d, ", length)); 92e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes ND_PRINT((ndo, "md type 0x%x, ", md_type)); 93e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes } 94e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes if (ndo->ndo_vflag > 1) { 95e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes ND_PRINT((ndo, "next-protocol 0x%x, ", next_protocol)); 96e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes } 97e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes ND_PRINT((ndo, "service-path-id 0x%06x, ", service_path_id)); 98e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes ND_PRINT((ndo, "service-index 0x%x", service_index)); 99e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes 100e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes /* Make sure we have all the headers */ 101e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes if (len < length * NSH_HDR_WORD_SIZE) 102e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes goto trunc; 103e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes 104e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes ND_TCHECK2(*bp, length * NSH_HDR_WORD_SIZE); 105e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes 106e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes /* 107e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes * length includes the lengths of the Base and Service Path headers. 108e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes * That means it must be at least 2. 109e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes */ 110e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes if (length < 2) 111e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes goto trunc; 112e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes 113e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes /* 114e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes * Print, or skip, the Context Headers. 115e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes * (length - 2) is the length of those headers. 116e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes */ 117e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes if (ndo->ndo_vflag > 2) { 118e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes if (md_type == 0x01) { 119e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes for (n = 0; n < length - 2; n++) { 120e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes ctx = EXTRACT_32BITS(bp); 121e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes bp += NSH_HDR_WORD_SIZE; 122e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes ND_PRINT((ndo, "\n Context[%02d]: 0x%08x", n, ctx)); 123e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes } 124e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes } 125e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes else if (md_type == 0x02) { 126e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes n = 0; 127e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes while (n < length - 2) { 128e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes tlv_class = EXTRACT_16BITS(bp); 129e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes bp += 2; 130e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes tlv_type = *bp; 131e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes bp += 1; 132e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes tlv_len = *bp; 133e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes bp += 1; 134e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes 135e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes ND_PRINT((ndo, "\n TLV Class %d, Type %d, Len %d", 136e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes tlv_class, tlv_type, tlv_len)); 137e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes 138e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes n += 1; 139e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes 140e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes if (length - 2 < n + tlv_len) { 141e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes ND_PRINT((ndo, " ERROR: invalid-tlv-length")); 142e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes return; 143e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes } 144e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes 145e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes for (vn = 0; vn < tlv_len; vn++) { 146e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes ctx = EXTRACT_32BITS(bp); 147e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes bp += NSH_HDR_WORD_SIZE; 148e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes ND_PRINT((ndo, "\n Value[%02d]: 0x%08x", vn, ctx)); 149e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes } 150e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes n += tlv_len; 151e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes } 152e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes } 153e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes else { 154e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes ND_PRINT((ndo, "ERROR: unknown-next-protocol")); 155e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes return; 156e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes } 157e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes } 158e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes else { 159e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes bp += (length - 2) * NSH_HDR_WORD_SIZE; 160e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes } 161e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes ND_PRINT((ndo, ndo->ndo_vflag ? "\n " : ": ")); 162e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes 163e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes /* print Next Protocol */ 164e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes next_len = len - length * NSH_HDR_WORD_SIZE; 165e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes switch (next_protocol) { 166e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes case 0x1: 167e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes ip_print(ndo, bp, next_len); 168e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes break; 169e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes case 0x2: 170e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes ip6_print(ndo, bp, next_len); 171e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes break; 172e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes case 0x3: 173e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes ether_print(ndo, bp, next_len, ndo->ndo_snapend - bp, NULL, NULL); 174e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes break; 175e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes default: 176e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes ND_PRINT((ndo, "ERROR: unknown-next-protocol")); 177e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes return; 178e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes } 179e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes 180e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes return; 181e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes 182e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughestrunc: 183e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes ND_PRINT((ndo, "%s", tstr)); 184e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes} 185e2e3bd11bd7561bc9d6686283a668fa94e1206b7Elliott Hughes 186