Blame tests/decode.c

Packit e9ba0d
/* -*- mode: c; c-file-style: "openbsd" -*- */
Packit e9ba0d
/*
Packit e9ba0d
 * Copyright (c) 2015 Vincent Bernat <bernat@luffy.cx>
Packit e9ba0d
 *
Packit e9ba0d
 * Permission to use, copy, modify, and/or distribute this software for any
Packit e9ba0d
 * purpose with or without fee is hereby granted, provided that the above
Packit e9ba0d
 * copyright notice and this permission notice appear in all copies.
Packit e9ba0d
 *
Packit e9ba0d
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
Packit e9ba0d
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
Packit e9ba0d
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
Packit e9ba0d
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
Packit e9ba0d
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
Packit e9ba0d
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Packit e9ba0d
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Packit e9ba0d
 */
Packit e9ba0d
Packit e9ba0d
#include <stdlib.h>
Packit e9ba0d
#include <unistd.h>
Packit e9ba0d
#include <inttypes.h>
Packit e9ba0d
#include <sys/types.h>
Packit e9ba0d
#include <sys/stat.h>
Packit e9ba0d
#include <fcntl.h>
Packit e9ba0d
#include <arpa/inet.h>
Packit e9ba0d
#include "common.h"
Packit e9ba0d
Packit e9ba0d
#define BUFSIZE 2000
Packit e9ba0d
Packit e9ba0d
char filenameprefix[] = "decode";
Packit e9ba0d
Packit e9ba0d
static void
Packit e9ba0d
usage(void)
Packit e9ba0d
{
Packit e9ba0d
	fprintf(stderr, "Usage:   %s PCAP\n", "decode");
Packit e9ba0d
	fprintf(stderr, "Version: %s\n", PACKAGE_STRING);
Packit e9ba0d
Packit e9ba0d
	fprintf(stderr, "\n");
Packit e9ba0d
Packit e9ba0d
	fprintf(stderr, "Decode content of PCAP files and display a summary\n");
Packit e9ba0d
	fprintf(stderr, "on standard output. Only the first packet is decoded.\n");
Packit e9ba0d
	exit(1);
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
char*
Packit e9ba0d
tohex(char *str, size_t len)
Packit e9ba0d
{
Packit e9ba0d
	static char *hex = NULL;
Packit e9ba0d
	free(hex); hex = NULL;
Packit e9ba0d
	if ((hex = malloc(len * 3 + 1)) == NULL) return NULL;
Packit e9ba0d
	for (size_t i = 0; i < len; i++)
Packit e9ba0d
		snprintf(hex + 3*i, 4, "%02X ", (unsigned char)str[i]);
Packit e9ba0d
	return hex;
Packit e9ba0d
}
Packit e9ba0d
Packit e9ba0d
/* We need an assert macro which doesn't abort */
Packit e9ba0d
#define assert(x) while (!(x)) { \
Packit e9ba0d
		fprintf(stderr, "%s:%d: %s: Assertion  `%s' failed.\n", \
Packit e9ba0d
		    __FILE__, __LINE__, __func__, #x); \
Packit e9ba0d
		exit(5); \
Packit e9ba0d
	}
Packit e9ba0d
Packit e9ba0d
int
Packit e9ba0d
main(int argc, char **argv)
Packit e9ba0d
{
Packit e9ba0d
	if (argc != 2 ||
Packit e9ba0d
	    !strcmp(argv[1], "-h") ||
Packit e9ba0d
	    !strcmp(argv[1], "--help"))
Packit e9ba0d
		usage();
Packit e9ba0d
Packit e9ba0d
	int fd = open(argv[1], O_RDONLY);
Packit e9ba0d
	assert(fd != -1);
Packit e9ba0d
Packit e9ba0d
	char buf[BUFSIZE];
Packit e9ba0d
	ssize_t len = read(fd, buf, BUFSIZE);
Packit e9ba0d
	assert(len != -1);
Packit e9ba0d
Packit e9ba0d
	struct pcap_hdr hdr;
Packit e9ba0d
	assert(len >= sizeof(hdr));
Packit e9ba0d
	memcpy(&hdr, buf, sizeof(hdr));
Packit e9ba0d
	assert(hdr.magic_number == 0xa1b2c3d4); /* Assume the same byte order as us */
Packit e9ba0d
	assert(hdr.version_major == 2);
Packit e9ba0d
	assert(hdr.version_minor == 4);
Packit e9ba0d
	assert(hdr.thiszone == 0);
Packit e9ba0d
	/* Don't care about other flags */
Packit e9ba0d
Packit e9ba0d
	struct pcaprec_hdr rechdr;
Packit e9ba0d
	assert(len >= sizeof(hdr) + sizeof(rechdr));
Packit e9ba0d
	memcpy(&rechdr, buf + sizeof(hdr), sizeof(rechdr));
Packit e9ba0d
	assert(len >= sizeof(hdr) + sizeof(rechdr) + rechdr.incl_len);
Packit e9ba0d
Packit e9ba0d
	/* For decoding, we only need a very basic hardware */
Packit e9ba0d
	struct lldpd_hardware hardware;
Packit e9ba0d
	memset(&hardware, 0, sizeof(struct lldpd_hardware));
Packit e9ba0d
	hardware.h_mtu = 1500;
Packit e9ba0d
	strlcpy(hardware.h_ifname, "test", sizeof(hardware.h_ifname));
Packit e9ba0d
Packit e9ba0d
	char *frame = buf + sizeof(hdr) + sizeof(rechdr);
Packit e9ba0d
	struct lldpd_chassis *nchassis = NULL;
Packit e9ba0d
	struct lldpd_port *nport = NULL;
Packit e9ba0d
	int decoded = 0;
Packit e9ba0d
	if (lldp_decode(NULL, frame, rechdr.incl_len, &hardware, &nchassis, &nport) == -1) {
Packit e9ba0d
		fprintf(stderr, "Not decoded as a LLDP frame\n");
Packit e9ba0d
	} else {
Packit e9ba0d
		fprintf(stderr, "Decoded as a LLDP frame\n");
Packit e9ba0d
		decoded = 1;
Packit e9ba0d
	}
Packit e9ba0d
#if defined ENABLE_CDP || defined ENABLE_FDP
Packit e9ba0d
	if (cdp_decode(NULL, frame, rechdr.incl_len, &hardware, &nchassis, &nport) == -1) {
Packit e9ba0d
		fprintf(stderr, "Not decoded as a CDP frame\n");
Packit e9ba0d
	} else {
Packit e9ba0d
		fprintf(stderr, "Decoded as a CDP frame\n");
Packit e9ba0d
		decoded = 1;
Packit e9ba0d
	}
Packit e9ba0d
#endif
Packit e9ba0d
#ifdef ENABLE_SONMP
Packit e9ba0d
	if (sonmp_decode(NULL, frame, rechdr.incl_len, &hardware, &nchassis, &nport) == -1) {
Packit e9ba0d
		fprintf(stderr, "Not decoded as a SONMP frame\n");
Packit e9ba0d
	} else {
Packit e9ba0d
		fprintf(stderr, "Decoded as a SONMP frame\n");
Packit e9ba0d
		decoded = 1;
Packit e9ba0d
	}
Packit e9ba0d
#endif
Packit e9ba0d
#ifdef ENABLE_EDP
Packit e9ba0d
	if (edp_decode(NULL, frame, rechdr.incl_len, &hardware, &nchassis, &nport) == -1) {
Packit e9ba0d
		fprintf(stderr, "Not decoded as a EDP frame\n");
Packit e9ba0d
	} else {
Packit e9ba0d
		fprintf(stderr, "Decoded as a EDP frame\n");
Packit e9ba0d
		decoded = 1;
Packit e9ba0d
	}
Packit e9ba0d
#endif
Packit e9ba0d
	if (!decoded) exit(1);
Packit e9ba0d
Packit e9ba0d
	printf("Chassis:\n");
Packit e9ba0d
	printf(" Index: %" PRIu16 "\n", nchassis->c_index);
Packit e9ba0d
	printf(" Protocol: %" PRIu8 "\n", nchassis->c_protocol);
Packit e9ba0d
	printf(" ID subtype: %" PRIu8 "\n", nchassis->c_id_subtype);
Packit e9ba0d
	printf(" ID: %s\n", tohex(nchassis->c_id, nchassis->c_id_len));
Packit e9ba0d
	printf(" Name: %s\n", nchassis->c_name?nchassis->c_name:"(null)");
Packit e9ba0d
	printf(" Description: %s\n", nchassis->c_descr?nchassis->c_descr:"(null)");
Packit e9ba0d
	printf(" Cap available: %" PRIu16 "\n", nchassis->c_cap_available);
Packit e9ba0d
	printf(" Cap enabled: %" PRIu16 "\n", nchassis->c_cap_enabled);
Packit e9ba0d
	struct lldpd_mgmt *mgmt;
Packit e9ba0d
	TAILQ_FOREACH(mgmt, &nchassis->c_mgmt, m_entries) {
Packit e9ba0d
		char ipaddress[INET6_ADDRSTRLEN + 1];
Packit e9ba0d
		int af; size_t alen;
Packit e9ba0d
		switch (mgmt->m_family) {
Packit e9ba0d
		case LLDPD_AF_IPV4:
Packit e9ba0d
			alen = INET_ADDRSTRLEN + 1;
Packit e9ba0d
			af  = AF_INET;
Packit e9ba0d
			break;
Packit e9ba0d
		case LLDPD_AF_IPV6:
Packit e9ba0d
			alen = INET6_ADDRSTRLEN + 1;
Packit e9ba0d
			af = AF_INET6;
Packit e9ba0d
			break;
Packit e9ba0d
		default:
Packit e9ba0d
			len = 0;
Packit e9ba0d
		}
Packit e9ba0d
		if (len == 0) continue;
Packit e9ba0d
		if (inet_ntop(af, &mgmt->m_addr, ipaddress, alen) == NULL)
Packit e9ba0d
			break;
Packit e9ba0d
		printf(" mgmt: %s\n", ipaddress);
Packit e9ba0d
	}
Packit e9ba0d
#ifdef ENABLE_LLDPMED
Packit e9ba0d
	printf(" MED cap: %" PRIu16 "\n", nchassis->c_med_cap_available);
Packit e9ba0d
	printf(" MED type: %" PRIu8 "\n", nchassis->c_med_type);
Packit e9ba0d
	printf(" MED HW: %s\n", nchassis->c_med_hw?nchassis->c_med_hw:"(null)");
Packit e9ba0d
	printf(" MED FW: %s\n", nchassis->c_med_fw?nchassis->c_med_fw:"(null)");
Packit e9ba0d
	printf(" MED SW: %s\n", nchassis->c_med_sw?nchassis->c_med_sw:"(null)");
Packit e9ba0d
	printf(" MED SN: %s\n", nchassis->c_med_sn?nchassis->c_med_sn:"(null)");
Packit e9ba0d
	printf(" MED manufacturer: %s\n", nchassis->c_med_manuf?nchassis->c_med_manuf:"(null)");
Packit e9ba0d
	printf(" MED model: %s\n", nchassis->c_med_model?nchassis->c_med_model:"(null)");
Packit e9ba0d
	printf(" MED asset: %s\n", nchassis->c_med_asset?nchassis->c_med_asset:"(null)");
Packit e9ba0d
#endif
Packit e9ba0d
Packit e9ba0d
	printf("Port:\n");
Packit e9ba0d
	printf(" ID subtype: %" PRIu8 "\n", nport->p_id_subtype);
Packit e9ba0d
	printf(" ID: %s\n", tohex(nport->p_id, nport->p_id_len));
Packit e9ba0d
	printf(" Description: %s\n", nport->p_descr?nport->p_descr:"(null)");
Packit e9ba0d
	printf(" MFS: %" PRIu16 "\n", nport->p_mfs);
Packit e9ba0d
	printf(" TTL: %" PRIu16 "\n", nport->p_ttl);
Packit e9ba0d
#ifdef ENABLE_DOT3
Packit e9ba0d
	printf(" Dot3 aggrID: %" PRIu32 "\n", nport->p_aggregid);
Packit e9ba0d
	printf(" Dot3 MAC/phy autoneg supported: %" PRIu8 "\n", nport->p_macphy.autoneg_support);
Packit e9ba0d
	printf(" Dot3 MAC/phy autoneg enabled: %" PRIu8 "\n", nport->p_macphy.autoneg_enabled);
Packit e9ba0d
	printf(" Dot3 MAC/phy autoneg advertised: %" PRIu16 "\n", nport->p_macphy.autoneg_advertised);
Packit e9ba0d
	printf(" Dot3 MAC/phy MAU type: %" PRIu16 "\n", nport->p_macphy.mau_type);
Packit e9ba0d
	printf(" Dot3 power device type: %" PRIu8 "\n", nport->p_power.devicetype);
Packit e9ba0d
	printf(" Dot3 power supported: %" PRIu8 "\n", nport->p_power.supported);
Packit e9ba0d
	printf(" Dot3 power enabled: %" PRIu8 "\n", nport->p_power.enabled);
Packit e9ba0d
	printf(" Dot3 power pair control: %" PRIu8 "\n", nport->p_power.paircontrol);
Packit e9ba0d
	printf(" Dot3 power pairs: %" PRIu8 "\n", nport->p_power.pairs);
Packit e9ba0d
	printf(" Dot3 power class: %" PRIu8 "\n", nport->p_power.class);
Packit e9ba0d
	printf(" Dot3 power type: %" PRIu8 "\n", nport->p_power.powertype);
Packit e9ba0d
	printf(" Dot3 power source: %" PRIu8 "\n", nport->p_power.source);
Packit e9ba0d
	printf(" Dot3 power priority: %" PRIu8 "\n", nport->p_power.priority);
Packit e9ba0d
	printf(" Dot3 power requested: %" PRIu16 "\n", nport->p_power.requested);
Packit e9ba0d
	printf(" Dot3 power allocated: %" PRIu16 "\n", nport->p_power.allocated);
Packit e9ba0d
#endif
Packit e9ba0d
#ifdef ENABLE_LLDPMED
Packit e9ba0d
	printf(" MED cap: %" PRIu16 "\n", nport->p_med_cap_enabled);
Packit e9ba0d
	for (int i = 0; i < LLDP_MED_APPTYPE_LAST; i++) {
Packit e9ba0d
		if (nport->p_med_policy[i].type == 0) continue;
Packit e9ba0d
		printf(" MED policy type: %" PRIu8 "\n", nport->p_med_policy[i].type);
Packit e9ba0d
		printf(" MED policy unknown: %" PRIu8 "\n", nport->p_med_policy[i].unknown);
Packit e9ba0d
		printf(" MED policy tagged: %" PRIu8 "\n", nport->p_med_policy[i].tagged);
Packit e9ba0d
		printf(" MED policy vid: %" PRIu16 "\n", nport->p_med_policy[i].vid);
Packit e9ba0d
		printf(" MED policy priority: %" PRIu8 "\n", nport->p_med_policy[i].priority);
Packit e9ba0d
		printf(" MED policy dscp: %" PRIu8 "\n", nport->p_med_policy[i].dscp);
Packit e9ba0d
	}
Packit e9ba0d
	for (int i = 0; i < LLDP_MED_LOCFORMAT_LAST; i++) {
Packit e9ba0d
		if (nport->p_med_location[i].format == 0) continue;
Packit e9ba0d
		printf(" MED location format: %" PRIu8 "\n", nport->p_med_location[i].format);
Packit e9ba0d
		printf(" MED location: %s\n", tohex(nport->p_med_location[i].data,
Packit e9ba0d
			nport->p_med_location[i].data_len));
Packit e9ba0d
	}
Packit e9ba0d
	printf(" MED power device type: %" PRIu8 "\n", nport->p_med_power.devicetype);
Packit e9ba0d
	printf(" MED power source: %" PRIu8 "\n", nport->p_med_power.source);
Packit e9ba0d
	printf(" MED power priority: %" PRIu8 "\n", nport->p_med_power.priority);
Packit e9ba0d
	printf(" MED power value: %" PRIu16 "\n", nport->p_med_power.val);
Packit e9ba0d
#endif
Packit e9ba0d
#ifdef ENABLE_DOT1
Packit e9ba0d
	printf(" Dot1 PVID: %" PRIu16 "\n", nport->p_pvid);
Packit e9ba0d
	struct lldpd_vlan *vlan;
Packit e9ba0d
	TAILQ_FOREACH(vlan, &nport->p_vlans, v_entries) {
Packit e9ba0d
		printf(" Dot1 VLAN: %s (%" PRIu16 ")\n", vlan->v_name, vlan->v_vid);
Packit e9ba0d
	}
Packit e9ba0d
	struct lldpd_ppvid *ppvid;
Packit e9ba0d
	TAILQ_FOREACH(ppvid, &nport->p_ppvids, p_entries) {
Packit e9ba0d
		printf(" Dot1 PPVID: %" PRIu16 " (status: %" PRIu8 ")\n",
Packit e9ba0d
		    ppvid->p_ppvid, ppvid->p_cap_status);
Packit e9ba0d
	}
Packit e9ba0d
	struct lldpd_pi *pid;
Packit e9ba0d
	TAILQ_FOREACH(pid, &nport->p_pids, p_entries) {
Packit e9ba0d
		printf(" Dot1 PI: %s\n", tohex(pid->p_pi, pid->p_pi_len));
Packit e9ba0d
	}
Packit e9ba0d
#endif
Packit e9ba0d
#ifdef ENABLE_CUSTOM
Packit e9ba0d
	struct lldpd_custom *custom;
Packit e9ba0d
	TAILQ_FOREACH(custom, &nport->p_custom_list, next) {
Packit e9ba0d
		printf(" Custom OUI: %s\n",
Packit e9ba0d
		    tohex((char*)custom->oui, sizeof(custom->oui)));
Packit e9ba0d
		printf(" Custom subtype: %" PRIu8 "\n", custom->subtype);
Packit e9ba0d
		printf(" Custom info: %s\n",
Packit e9ba0d
		    tohex((char*)custom->oui_info, custom->oui_info_len));
Packit e9ba0d
	}
Packit e9ba0d
#endif
Packit e9ba0d
	exit(0);
Packit e9ba0d
}