⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 encoding.c

📁 Net-CDP-0.09 cdp相关源包
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * $Id: encoding.c,v 1.1 2005/07/20 13:44:13 mchapman Exp $ */#include <system.h>#include <encoding.h>#define GRAB(target, type, func) \	((length >= sizeof(type)) && \		( \			target = func(*((type *)data)), \			length -= sizeof(type), \			data += sizeof(type), \			1 \		))#define SKIP(bytes) \	((length >= (bytes)) && \		( \			length -= (bytes), \			data += (bytes), \			1 \		))#define GRAB_UINT8(target) GRAB(target, uint8_t, )#define GRAB_UINT16(target) GRAB(target, uint16_t, ntohs)#define GRAB_UINT32(target) GRAB(target, uint32_t, ntohl)#define GRAB_STRING(target, bytes) \	((length >= (bytes)) && \		( \			target = SALLOC((bytes) + 1), \			memcpy((target), data, (bytes) * sizeof(char)), \			length -= (bytes), \			data += (bytes), \			1 \		))/* Hmm, egcs doesn't have variadic macros... */#define _DECODE_ERROR(e)      sprintf(errors, "Corrupt CDP packet: " e)#define _DECODE_ERROR2(e, e2) sprintf(errors, "Corrupt CDP packet: " e, e2)#define _EOP(e)           _DECODE_ERROR("end-of-packet while reading " e)#define _EOP2(e, e2)      _DECODE_ERROR2("end-of-packet while reading " e, e2)#define _INVALID(e)       _DECODE_ERROR("invalid " e)#define _INVALID2(e, e2)  _DECODE_ERROR2("invalid " e, e2)#define _DUPLICATE(e)     _DECODE_ERROR("duplicate " e);#define EOP(e)          do { _EOP(e);          goto fail; } while (0)#define EOP2(e, e2)     do { _EOP2(e, e2);     goto fail; } while (0)#define INVALID(e)      do { _INVALID(e);      goto fail; } while (0)#define INVALID2(e, e2) do { _INVALID2(e, e2); goto fail; } while (0)#define DUPLICATE(e)    do { _DUPLICATE(e);    goto fail; } while (0)struct cdp_packet *cdp_decode(const void *data, size_t length, char *errors) {	struct cdp_packet *packet;	assert(data);	assert(errors);	if (!SKIP(LIBNET_802_2SNAP_H + LIBNET_802_3_H)) {		_EOP("ethernet header");		return NULL;	}	if (cdp_checksum(data, length)) {		_INVALID("checksum");		return NULL;	}	packet = CALLOC(1, struct cdp_packet);	packet->packet_length = length;	/*	 * We allocate BUFSIZ here, not length, so that cdp_packet_update	 * can work reliably.	 */	packet->packet = MALLOC_VOIDP(BUFSIZ);	memcpy(packet->packet, data, length);	if (!GRAB_UINT8(packet->version)) EOP("version"); 	if (!GRAB_UINT8(packet->ttl)) EOP("TTL");	if (!GRAB_UINT16(packet->checksum)) EOP("checksum");	if ((1 > packet->version) || (packet->version > 2))		INVALID("version (not 1 or 2)");	while (length) {		uint16_t tlv_type;		uint16_t tlv_length;		if (!GRAB_UINT16(tlv_type)) EOP("TLV type");		if (!GRAB_UINT16(tlv_length)) EOP("TLV length");		tlv_length -= 2 * sizeof(uint16_t);		switch (tlv_type) {			uint32_t i, count;		case CDP_TYPE_DEVICE_ID:			if (packet->device_id) DUPLICATE("Device-ID TLV");			if (!GRAB_STRING(packet->device_id, tlv_length))				EOP("Device-ID TLV");			break;		case CDP_TYPE_ADDRESS:			if (packet->addresses) DUPLICATE("Address TLV");			if (!GRAB_UINT32(count))				EOP("number of addresses in Address TLV");			packet->addresses = cdp_llist_new(				(cdp_dup_fn_t)cdp_address_dup,				(cdp_free_fn_t)cdp_address_free			);			for (i = 0; i < count; i++) {				uint8_t protocol_type, protocol_length;				uint16_t address_length;				const void *protocol, *address;				if (!GRAB_UINT8(protocol_type))					EOP2("protocol type for address %d in Address TLV", i);				if (!GRAB_UINT8(protocol_length))					EOP2("protocol length for address %d in Address TLV", i);				protocol = data;				if (!SKIP(protocol_length))					EOP2("protocol for address %d in Address TLV", i);				if (!GRAB_UINT16(address_length))					EOP2("address length for address %d in Address TLV", i);				address = data;				if (!SKIP(address_length))					EOP2("address for address %d in Address TLV", i);				cdp_llist_append(packet->addresses,					cdp_address_new(						protocol_type, protocol_length,						protocol, address_length,						address					)				);			}			break;		case CDP_TYPE_PORT_ID:			if (packet->port_id) DUPLICATE("Port-ID TLV");			if (!GRAB_STRING(packet->port_id, tlv_length))				EOP("Port-ID TLV");			break;		case CDP_TYPE_CAPABILITIES:			if (packet->capabilities) DUPLICATE("Capabilities TLV");			if (tlv_length != sizeof(uint32_t))				INVALID2("Capabilities TLV length (not %d)",					sizeof(uint32_t));			{				uint32_t capabilities;				if (!GRAB_UINT32(capabilities))					EOP("Capabilities TLV");				NEW(packet->capabilities, capabilities, uint32_t);			}			break;		case CDP_TYPE_IOS_VERSION:			if (packet->ios_version) DUPLICATE("Version TLV");			if (!GRAB_STRING(packet->ios_version, tlv_length))				EOP("Version TLV");			break;		case CDP_TYPE_PLATFORM:			if (packet->platform) DUPLICATE("Platform TLV");			if (!GRAB_STRING(packet->platform, tlv_length))				EOP("Platform TLV");			break;		case CDP_TYPE_IP_PREFIX:			if (packet->ip_prefixes) DUPLICATE("IP Prefixes TLV");						/*			 * Yuck... apparently the TLV length can be 0 to			 * represent no data. At least, that's the impression			 * I got upon reading			 * http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm#21923			 */			if (tlv_length == 0xfffc) tlv_length = 0;						if (tlv_length % 5) INVALID("IP Prefixes TLV length (not a multiple of 5)");						count = tlv_length / 5;			packet->ip_prefixes = cdp_llist_new(				(cdp_dup_fn_t)cdp_ip_prefix_dup,				(cdp_free_fn_t)cdp_ip_prefix_free			);			for (i = 0; i < count; i++) {				struct in_addr network;				uint8_t length;				if (!GRAB_UINT32(network.s_addr))					EOP2("network for IP prefix %d in IP Prefixes TLV", i);				if (!GRAB_UINT8(length))					EOP2("length for IP prefix %d in IP Prefixes TLV", i);				if (length > 32)					INVALID2("length for IP prefix %d in IP Prefixes TLV (should be no more than 32)", i);				cdp_llist_append(					packet->ip_prefixes,					cdp_ip_prefix_new(network, length)				);			}			break;/*		FIXME -- not documented				case CDP_TYPE_PROTOCOL_HELLO:*/		case CDP_TYPE_VTP_MGMT_DOMAIN:			if (packet->vtp_mgmt_domain)				DUPLICATE("VTP Management Domain TLV");			if (!GRAB_STRING(packet->vtp_mgmt_domain, tlv_length))				EOP("VTP Management Domain TLV");			break;		case CDP_TYPE_NATIVE_VLAN:			if (packet->native_vlan) DUPLICATE("Native VLAN TLV");			if (tlv_length != sizeof(uint16_t))				INVALID2("Native VLAN TLV length (not %d)",					sizeof(uint16_t));			{				uint16_t native_vlan;				if (!GRAB_UINT16(native_vlan))					EOP("Native VLAN TLV");				NEW(packet->native_vlan, native_vlan, uint16_t);			}			break;		case CDP_TYPE_DUPLEX:			if (packet->duplex) DUPLICATE("Duplex Mode TLV");			if (tlv_length != sizeof(uint8_t))				INVALID2("Duplex Mode TLV length (not %d)",					sizeof(uint8_t));			{				uint8_t duplex;				if (!GRAB_UINT8(duplex)) EOP("Duplex Mode TLV");				NEW(packet->duplex, duplex, uint8_t);			}			break;/*		FIXME -- not documented				case CDP_TYPE_UNKNOWN_0x000c:*//*		FIXME -- not documented				case CDP_TYPE_UNKNOWN_0x000d:*/		case CDP_TYPE_APPLIANCE_REPLY:			if (packet->appliance)				DUPLICATE("Appliance VLAN-ID Reply TLV");			if (tlv_length != sizeof(uint8_t) + sizeof(uint16_t))				INVALID2("Appliance VLAN-ID Reply TLV length (not %d)",					sizeof(uint8_t) + sizeof(uint16_t));			{				uint8_t id;				uint16_t vlan;				if (!GRAB_UINT8(id))					EOP("appliance ID in Appliance VLAN-ID Reply TLV");				if (!GRAB_UINT16(vlan))					EOP("appliance VLAN in Appliance VLAN-ID Reply TLV");				packet->appliance = cdp_appliance_new(id, vlan);			}			break;		case CDP_TYPE_APPLIANCE_QUERY:			if (packet->appliance_query)				DUPLICATE("Appliance VLAN-ID Query TLV");			if (tlv_length != sizeof(uint8_t) + sizeof(uint16_t))				INVALID2("Appliance VLAN-ID TLV Query length (not %d)",					sizeof(uint8_t) + sizeof(uint16_t));			{				uint8_t id;				uint16_t vlan;				if (!GRAB_UINT8(id))					EOP("appliance ID in Appliance VLAN-ID Query TLV");				if (!GRAB_UINT16(vlan))					EOP("appliance VLAN in Appliance VLAN-ID Query TLV");				packet->appliance_query =					cdp_appliance_new(id, vlan);			}			break;		case CDP_TYPE_POWER_CONSUMPTION:			if (packet->power_consumption)				DUPLICATE("Power Consumption TLV");			if (tlv_length != sizeof(uint16_t))				INVALID2("Power Consumption TLV length (not %d)", sizeof(uint16_t));			{				uint16_t power_consumption;				if (!GRAB_UINT16(power_consumption))					EOP("Power Consumption TLV");				NEW(packet->power_consumption,					power_consumption, uint16_t);			}			break;		case CDP_TYPE_MTU:			if (packet->mtu) DUPLICATE("MTU TLV");			if (tlv_length != sizeof(uint32_t))				INVALID2("MTU TLV length (not %d)",					sizeof(uint32_t));			{				uint32_t mtu;				if (!GRAB_UINT32(mtu))					EOP("MTU TLV");				NEW(packet->mtu, mtu, uint32_t);			}			break;		case CDP_TYPE_EXTENDED_TRUST:			if (packet->extended_trust)				DUPLICATE("Extended Trust TLV");			if (tlv_length != sizeof(uint8_t))				INVALID2("Extended Trust TLV length (not %d)",					sizeof(uint8_t));			{				uint8_t extended_trust;				if (!GRAB_UINT8(extended_trust))					EOP("Extended Trust TLV");				NEW(packet->extended_trust,					extended_trust, uint8_t);			}			break;		case CDP_TYPE_UNTRUSTED_COS:			if (packet->untrusted_cos)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -