/*
 * $Id: bgp_proto.h,v 2.2 2000/05/23 08:02:07 masaki Exp $
 */

#ifndef	_BGP_PROTO_H_
#define	_BGP_PROTO_H_		/* nothing */


/* This file copied from Gated Release 3.5 
 * Copyright (c) 1990,1991,1992,1993,1994 by Cornell University. All rights 
 * reserved. Refer to Particulars and other Copyright notices at the end 
 * of this file. 
 */


#ifndef byte
#define byte u_char
#endif


/*
 *	Protocol definitions for BGP.  The stuff in here is related to
 *	the BGP protocol itself and should be independent of gated.
 */

/*
 * Some basic constants.
 */
#define	BGP_PORT		179	/* Port number to use with BGP */
#define	BGPMAXPACKETSIZE	4096	/* Maximum message size */

/*
 * BGP message types
 */
#define	BGP_OPEN	1		/* open message */
#define	BGP_UPDATE	2		/* update message */
#define	BGP_NOTIFY	3		/* notification message */
#define	BGP_KEEPALIVE	4		/* keepalive message */
#define	BGP_PACKET_MAX	5


/*
 * Minimum length of a BGP message is the length of the header.  If you
 * haven't got this, you haven't got anything.
 */
#define	BGP_HEADER_LEN	19

/*
 * Authentication types.  We only know one type at this point.
 */
#define	BGP_AUTH_NONE	0

/*
 * AS numbers of significance to BGP
 */
#define	BGP_AS_ANON	0
#define	BGP_AS_HIGH	65535

/*
 * BGP message parsing.  We assume no particular alignment anywhere
 * so that we can parse a stream.  Because of this we use no structure
 * overlays.  Instead we use macros which know the packet formats to
 * pull values out of the stream.  This avoids most byte order issues
 * as well.
 */

/*
 * The length of a BGP route in the message (4 bytes currently).
 */
#define	BGP_ROUTE_LENGTH	4

/*
 * Macros to get various length values from the stream.  cp must be a
 * (byte *)
 */
#define	BGP_GET_BYTE(val, cp)		MRT_GET_BYTE(val, cp)
#define	BGP_GET_SHORT(val, cp)		MRT_GET_SHORT(val, cp)
#define	BGP_GET_LONG(val, cp) 		MRT_GET_LONG(val, cp)
#define	BGP_GET_NETLONG(val, cp)	MRT_GET_NETLONG(val, cp)

/*
 * Extract the BGP header from the stream.  Note that a pointer to
 * the marker is returned, rather than the marker itself.
 *
 * The header is a 16 byte marker, followed by a 2 byte length and
 * a 1 byte message type code.
 */
#define	BGP_HEADER_MARKER_LEN	16

#define	BGP_GET_HEADER(marker, length, type, cp) \
	do { \
		(marker) = (cp); \
		(cp) += BGP_HEADER_MARKER_LEN; \
		BGP_GET_SHORT((length), (cp)); \
		BGP_GET_BYTE((type), (cp)); \
	} while (0)

#define	BGP_GET_HDRLEN(length, cp) \
	do { \
		register int Xlen; \
		Xlen = ((int)*(u_char *)((cp) + 16)) << 8; \
		Xlen |= (int)*(u_char *)((cp) + 17); \
		(length) = Xlen; \
	} while (0)

#define BGP_GET_HDRTYPE(type, cp)	((type) = *(u_char *)((cp) + 18))


/*
 * Extract open message data.  We treat version 2 and version 3
 * open messages separately since they are different lengths.
 * The following extracts the version from the current point.
 */
#define	BGP_GET_VERSION(cp)	(*(cp))

#define	BGP_OPEN_MIN_LEN	10
#define	BGP_GET_OPEN(version, as, holdtime, id, optlen, cp) \
	do { \
		BGP_GET_BYTE((version), (cp)); \
		BGP_GET_SHORT((as), (cp)); \
		BGP_GET_SHORT((holdtime), (cp)); \
		BGP_GET_NETLONG((id), (cp)); \
		BGP_GET_BYTE((optlen), (cp)); \
	} while (0)

/*
 * The overall minimum length for V4 open message
 */
#define	BGP_OPEN_MIN_LEN	10


/*
 * The update message is essentially a 2 byte length for the attribute
 * data, followed by the attribute buffer, followed by a list of
 * networks.  The attribute data is dealt with by separate code,
 * so all we really need to do is to return the length and a pointer
 * to the attribute buffer.
 */
#define	BGP_UPDATE_MIN_LEN	2	/* make sure we've enough for length */
#define	BGP_GET_UPDATE(attrlen, attrp, cp) \
	do { \
		register int Xlen; \
		Xlen = (*(u_char *)(cp)++) << 8; \
		Xlen |= *(u_char *)(cp)++; \
		(attrlen) = Xlen; \
		(attrp) = (cp); \
		(cp) += Xlen; \
	} while (0)

/*
 * The BGP version 4 update message is more complex, consisting of a
 * 2 byte count of unreachable prefixes, followed by the prefixes, followed
 * by a 2 byte path attribute length, followed by the path attributes,
 * followed by reachable prefixes with those attributes.  The minimum
 * length of this is 4 bytes, and we'll need an extra macro to dig out
 * the unreachable prefix count.
 */
#define	BGP_V4UPDATE_MIN_LEN	4
#define	BGP_GET_V4UPDATE_UNREACH(count, cp)	BGP_GET_SHORT((count), (cp))

/*
 * The size of the version 4 unreachable routes length
 */
#define	BGP_UNREACH_SIZE_LEN	2

/*
 * The size of the total path attribute length in an UPDATE
 */
#define	BGP_ATTR_SIZE_LEN	2

/*
 * The following macro extracts network addresses from the stream.  It
 * is used to decode the end of update messages, and understands that
 * network numbers are stored internally in network byte order.
 */
#define	BGP_GET_ADDR(addr, cp) 		MRT_GET_ADDR(addr, cp)
#define	BGP_GET_ADDR6(addr, cp)		MRT_GET_ADDR6(addr, cp)

/*
 * These macros, the alternative to the above, extract BGP4-style
 * address prefixes from the stream.  The bit count is returned
 * by the first, the next couple are for testing (to see if the
 * bitcount is okay and there is space) and the remainder set the
 * address.
 */
#define	BGP_BITCOUNT_LEN	1

#define	BGP_GET_BITCOUNT(bitcount, cp)	((bitcount) = *(u_char *)(cp)++)

#define	BGP_OKAY_BITCOUNT(bc)	((bc) <= 32)

#define	BGP_OKAY_BITCOUNT6(bc)	((bc) <= 128)

#define	BGP_PREFIX_LEN(bc)	(((bc)+7) >> 3)

#define	BGP_GET_PREFIX(bitcount, addr, cp) \
	do { \
		register byte *Xap; \
		Xap = (byte *)(addr); \
		switch (BGP_PREFIX_LEN(bitcount)) { \
		case 1: \
		    *Xap++ = *(cp)++; \
		    *Xap++ = 0; \
		    *Xap++ = 0; \
		    *Xap++ = 0; \
		    break; \
		case 2: \
		    *Xap++ = *(cp)++; \
		    *Xap++ = *(cp)++; \
		    *Xap++ = 0; \
		    *Xap++ = 0; \
		    break; \
		case 3: \
		    *Xap++ = *(cp)++; \
		    *Xap++ = *(cp)++; \
		    *Xap++ = *(cp)++; \
		    *Xap++ = 0; \
		    break; \
		case 4: \
		    *Xap++ = *(cp)++; \
		    *Xap++ = *(cp)++; \
		    *Xap++ = *(cp)++; \
		    *Xap++ = *(cp)++; \
		    break; \
		default: \
		    *Xap++ = 0; \
		    *Xap++ = 0; \
		    *Xap++ = 0; \
		    *Xap++ = 0; \
		    break; \
		} \
	} while (0)

#define	BGP_GET_PREFIX6(bitcount, addr, cp) \
	do { \
		register byte *Xap; \
		int i, j = BGP_PREFIX_LEN(bitcount); \
		Xap = (byte *)(addr); \
		for (i = 0; i < 16; i++) \
			if (i < j) \
				*Xap++ = *(cp)++; \
			else \
				*Xap++ = 0; \
	} while (0)

/*
 * The notification message contains a 2 byte code/subcode followed by
 * optional data.  Return the code and subcode.
 */
#define	BGP_NOTIFY_MIN_LEN	2	/* code/subcode pair */
#define	BGP_GET_NOTIFY(code, subcode, cp) \
	do { \
		BGP_GET_BYTE((code), (cp)); \
		BGP_GET_BYTE((subcode), (cp)); \
	} while (0)


/*
 * That is it for incoming messages.  The next set of macroes are used
 * for forming outgoing messages.
 */
#define	BGP_PUT_BYTE(val, cp)		MRT_PUT_BYTE(val, cp)
#define	BGP_PUT_SHORT(val, cp)		MRT_PUT_SHORT(val, cp)
#define	BGP_PUT_LONG(val, cp)		MRT_PUT_LONG(val, cp)
#define	BGP_PUT_NETLONG(val, cp)	MRT_PUT_NETLONG(val, cp)

#define	BGP_GET_DATA(data, len, cp)	MRT_GET_DATA(data, len, cp)
#define	BGP_PUT_DATA(data, len, cp)	MRT_PUT_DATA(data, len, cp)
#define	BGP_PUT_ZERO(len, cp)		MRT_PUT_ZERO(len, cp)

/*
 * During normal message formation the header is inserted after
 * the rest of the message is fully formed.  The following just
 * leaves space for the header.
 */
#define	BGP_SKIP_HEADER(cp)    ((cp) += BGP_HEADER_LEN)

/*
 * The following are used to insert the length and type into the
 * header given a pointer to the beginning of the message.
 */
#define	BGP_PUT_HDRLEN(length, cp) \
	do { \
		register u_short Xlen; \
		Xlen = (u_short)(length); \
		*((cp) + 16) = (byte)(Xlen >> 8); \
		*((cp) + 17) = (byte)Xlen; \
	} while (0)

#define BGP_PUT_HDRTYPE(type, cp)	(*((cp) + 18) = (byte)(type))

/*
 * Version three and four are the same, with the addition of a 4 byte
 * ID field after the hold time to version two.
 */
#define	BGP_PUT_OPEN(version, as, holdtime, id, optlen, cp) \
	do { \
		BGP_PUT_BYTE((version), (cp)); \
		BGP_PUT_SHORT((as), (cp)); \
		BGP_PUT_SHORT((holdtime), (cp)); \
		BGP_PUT_NETLONG((id), (cp)); \
		BGP_PUT_BYTE((optlen), (cp)); \
	} while (0)

/*
 * The attributes in the update message are another case where we
 * must insert the data before inserting the length.  This just
 * skips the length field, it will be filled in later.
 */
#define	BGP_SKIP_ATTRLEN(cp)	((cp) += BGP_UPDATE_MIN_LEN)


/*
 * The following puts a network address into the buffer in the
 * form a BGP update message would like.  We know the address
 * is in network byte order already.
 */
#define	BGP_PUT_ADDR(addr, cp)		MRT_PUT_ADDR(addr, cp)
#define	BGP_PUT_ADDR6(addr, cp)		MRT_PUT_ADDR6(addr, cp)

/*
 * The following puts an address prefix into the buffer in the
 * format BGP4 update messages like it, and is the alternative to
 * the above.
 */
#define	BGP_PUT_PREFIX(bitcount, addr, cp) \
	do { \
		register byte *Xap; \
		register byte Xbc = (byte)(bitcount); \
		*(cp)++ = Xbc; \
		if (Xbc != 0) { \
			Xap = (byte *)(addr); \
			switch((unsigned) (Xbc + 7) >> 3) { \
			case 4: \
				*(cp)++ = *Xap++; \
			case 3: \
				*(cp)++ = *Xap++; \
			case 2: \
				*(cp)++ = *Xap++; \
			case 1: \
				*(cp)++ = *Xap++; \
			default: \
				break; \
			} \
		} \
	} while (0)


#define	BGP_PUT_PREFIX6(bitcount, addr, cp) \
	do { \
		register byte *Xap; \
		register byte Xbc = (byte)(bitcount); \
		register int i = (bitcount + 7) >> 3; \
		*(cp)++ = Xbc; \
		if ((bitcount > 128) || (bitcount <= 0)) \
			break; \
		Xap = (byte *)(addr); \
		while (--i >= 0) \
			*(cp)++ = *Xap++; \
	} while (0)


/*
 * The notification message contains a 2 byte code/subcode followed by
 * optional data.  Insert the code/subcode and optional data, if any.
 * Note that we evaluate macro arguments more than once here.
 */
#define	BGP_PUT_NOTIFY(code, subcode, datalen, data, cp) \
	do { \
		BGP_PUT_BYTE((code), (cp)); \
		BGP_PUT_BYTE((subcode), (cp)); \
		if ((datalen) > 0) { \
			register int Xi = (datalen); \
			register byte *Xdp = (byte *)(data); \
			while (Xi-- > 0) \
				*(cp)++ = *Xdp++; \
		} \
	} while (0)


/*
 * BGP error processing is a little tedious.  The following are
 * the error codes/subcodes we use.
 */
#define	BGP_ERR_HEADER		1	/* message header error */
#define	BGP_ERR_OPEN		2	/* open message error */
#define	BGP_ERR_UPDATE		3	/* update message error */
#define	BGP_ERR_HOLDTIME	4	/* hold timer expired */
#define	BGP_ERR_FSM		5	/* finite state machine error */
#define	BGP_CEASE		6	/* cease message (not an error) */
#define	BGP_ERR_MAX		7

/*
 * The unspecified subcode is sent when we don't have anything better.
 */
#define	BGP_ERR_UNSPEC		0

/*
 * These subcodes are sent with header errors
 */
#define	BGP_ERRHDR_UNSYNC	1	/* loss of connection synchronization */
#define	BGP_ERRHDR_LENGTH	2	/* bad length */
#define	BGP_ERRHDR_TYPE		3	/* bad message type */
#define	BGP_ERRHDR_MAX		4

/*
 * These are used with open errors
 */
#define	BGP_ERROPN_VERSION	1	/* a version we don't do */
#define	BGP_ERROPN_AS		2	/* something wrong with the AS */
#define	BGP_ERROPN_BGPID	3	/* we don't like BGP ID (V.3 only) */
#define	BGP_ERROPN_OPTPARAM	4	/* unsupported optinal parameter */
#define	BGP_ERROPN_AUTH		5	/* authentication failure */
#define	BGP_ERROPN_BADHOLDTIME	6	/* don't like the hold time */
#define	BGP_ERROPN_CAPABILITY	7	/* unsupported capability */
#define	BGP_ERROPN_MAX		8

/*
 * These are used with update errors.  N.B. the path support code also
 * knows these errors.  The lists should be kept in sync.
 */
#define	BGP_ERRUPD_ATTRLIST	1	/* screwed up attribute list */
#define	BGP_ERRUPD_UNKNOWN	2	/* don't know well known attribute */
#define	BGP_ERRUPD_MISSING	3	/* missing well known attribute */
#define	BGP_ERRUPD_FLAGS	4	/* attribute flags error */
#define	BGP_ERRUPD_LENGTH	5	/* attribute length error */
#define	BGP_ERRUPD_ORIGIN	6	/* origin given is bad */
#define	BGP_ERRUPD_ASLOOP	7	/* routing loop in AS path */
#define	BGP_ERRUPD_NEXTHOP	8	/* next hop screwed up */
#define	BGP_ERRUPD_OPTATTR	9	/* error with optional attribute */
#define	BGP_ERRUPD_BADNET	10	/* bad network */
#define	BGP_ERRUPD_ASPATH	11	/* screwed up AS path structure */
#define	BGP_ERRUPD_MAX		12

/*
 * Protocol States
 */
#define	BGPSTATE_IDLE		1	/* idle state - ignore everything */
#define	BGPSTATE_CONNECT	2	/* connect state - trying to connect */
#define BGPSTATE_ACTIVE		3	/* waiting for a connection */
#define	BGPSTATE_OPENSENT	4	/* open packet has been sent */
#define	BGPSTATE_OPENCONFIRM	5	/* waiting for a keepalive or notify */
#define	BGPSTATE_ESTABLISHED	6	/* connection has been established */
#define BGPSTATE_DESTROYED      7       /* used internally to sync children */

/*
 * Events
 */
#define	BGPEVENT_START		1	/* Start */
#define	BGPEVENT_STOP		2	/* Stop */
#define	BGPEVENT_OPEN		3	/* Transport connection open */
#define	BGPEVENT_CLOSED		4	/* Transport connection closed */
#define	BGPEVENT_OPENFAIL	5	/* Transport connection open failed */
#define	BGPEVENT_ERROR		6	/* Transport error */
#define	BGPEVENT_CONNRETRY	7	/* Connection retry timer expired */
#define	BGPEVENT_HOLDTIME	8	/* Holdtime expired */
#define	BGPEVENT_KEEPALIVE	9	/* KeepAlive timer */
#define	BGPEVENT_RECVOPEN	10	/* Receive Open message */
#define	BGPEVENT_RECVKEEPALIVE	11	/* Receive KeepAlive message */
#define	BGPEVENT_RECVUPDATE	12	/* Receive Update message */
#define	BGPEVENT_RECVNOTIFY	13	/* Receive Notification message */

#endif				/* __BGP_PROTO_H__ */
