/* 
 * $Id: idrp_validate.c,v 1.3 1995/10/08 17:05:22 skh Exp $
 * Merit IDRP release 1.1 (gated 3.5.4).  Copyright (c) 1994 by Merit Network, Inc. 
 */

#include "include.h"
#include "iso.h"
#include "idrp.h"
#include <stdio.h>
#include "md4global.h"	/* RSAREF globals and constants */
#include "md4.h"	/* md4-specific includes */


/* idrp_validate.c
 *  
 * pdu validation routines
 *	checksum_ok(peer,pdu,length) - validate checksum for recvd pdu
 *      idrp_rib_id(att_mask) - calculate internal rib id from
 * 	              		idrp attribute record mask bits 
 * 	valid_header(peer,pdu,length) - validate header 
 */ 
  
 

/*
 * checksum_ok(peer,pdu,length)
 *    -  validate the received checksum
 * return - TRUE/FALSE
 */
int 
checksum_ok(peer,pdu,length)
idrpPeer *peer;
idrpPdu *pdu;
int length;
{
/* check which type of checksum we are working on */
u_char checksum_pdu[IDRP_AUTH_CODE_SIZE];
u_char digest[IDRP_AUTH_CODE_SIZE];
u_int *p_checksum;
u_int return_code = FALSE;

	/* md4 zeros out the digest.    */

	switch (peer->AuthType) 
		{
		case IDRP_AUTH_CODE_TEST:
			return_code = TRUE;
			break;
	
		case IDRP_AUTH_CODE_CLEAR:
			bcopy(&pdu->header.validation,&checksum_pdu,IDRP_AUTH_CODE_SIZE);
			bzero(&pdu->header.validation,IDRP_AUTH_CODE_SIZE);
			md4((u_char *)pdu,length,digest);
			if (!bcmp(&checksum_pdu, &digest, IDRP_AUTH_CODE_SIZE))
				{
				return_code = TRUE;
				}	 
			break;

		case IDRP_AUTH_CODE_CRYPT:
			trace_tf(idrp_trace_options, TR_NORMAL,0,("Peer %s trying to do encrypted validation - no support",peer->name));
			break;

		case IDRP_AUTH_CODE_SIMPLE:
			trace_tf(idrp_trace_options, TR_NORMAL,0,("Peer %s trying to do simple validation - no support",peer->name));
		 	break;	
		}

return(return_code);   
}




int 
valid_header(peer,pdu,length)
idrpPeer *peer;
idrpPdu *pdu;
int	length;
{

/* Below are checks from section 7.21.1 from the IDRP document.
 * These checks will result in the pdu being discarded
 * and the HEADER error event being generated 
 */
 
	switch(pdu->header.pdu_type)
		{
		case IDRP_OPEN_TYPE:
			if (length < IDRP_MIN_OPEN_PDU_SIZE || 
				length > IDRP_MAX_OPEN_PDU_SIZE)
				{
				trace_tf(idrp_trace_options, TR_NORMAL,0,("failed open type header check peer %s",peer->name));
				return(FALSE);
				}
			else
				{
				return (TRUE);
				}	
			break;
			
		case IDRP_UPDATE_TYPE:
			if (length < IDRP_MIN_UPDATE_SIZE)
				{
				trace_tf(idrp_trace_options, TR_NORMAL,0,("failed update type header check peer %s",peer->name));
				return (FALSE);
				}
			break;

		case IDRP_KEEPALIVE_TYPE:
			if (length != IDRP_KEEPALIVE_SIZE)
				{
				trace_tf(idrp_trace_options, TR_NORMAL,0,("failed keepalive type header check peer %s",peer->name));
				return(FALSE);
				}
			break;

		case IDRP_ERROR_TYPE:
		case IDRP_CEASE_TYPE:
		case IDRP_RIB_REFRESH_TYPE:
#ifdef	ECHOKLUDGE
		case IDRP_ECHO_TYPE:
		case IDRP_ECHO_REPLY_TYPE:
#endif
			return(TRUE);
			break;

		default:
			/* the unknown type */
			trace_tf(idrp_trace_options, TR_NORMAL,0,("failed unknown type header check peer %s",peer->name));
			return (FALSE);
			break;
		}

	/* 7.21.1 a) check that the PDU length does not exceed maximum size 
	 * that peer is suppose to send
 	 */

	if (length > peer->pdu_maxsendsize)
		{
		trace_tf(idrp_trace_options, TR_NORMAL,0,("peer %s failed pdu over max pdu size ",peer->name));
		return (FALSE);
		}
	return(TRUE);

}
