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

📄 rsvp_util2.c

📁 radius协议源码÷The Radius Stack will connect to a Radius Server. This stack implementation is built upo
💻 C
字号:
/* * @(#) $Id: rsvp_util2.c,v 1.1.1.1 2000/05/08 22:51:24 wenqing Exp $ *//************************ rsvp_util.c  ******************************* *                                                                   * *     Common routines for managing state and parsing protocol       * *     data structure (flowspecs, filterspecs, flow descriptors...)  * *     Used by rsvp_path.c and rsvp_resv.c                           * *                                                                   * *********************************************************************//****************************************************************************            RSVPD -- ReSerVation Protocol Daemon                USC Information Sciences Institute                Marina del Rey, California            Original Version: Shai Herzog, Nov. 1993.            Current Version:  Steven Berson & Bob Braden, May 1996.  Copyright (c) 1996 by the University of Southern California  All rights reserved.  Permission to use, copy, modify, and distribute this software and its  documentation in source and binary forms for any purpose and without  fee is hereby granted, provided that both the above copyright notice  and this permission notice appear in all copies. and that any  documentation, advertising materials, and other materials related to  such distribution and use acknowledge that the software was developed  in part by the University of Southern California, Information  Sciences Institute.  The name of the University may not be used to  endorse or promote products derived from this software without  specific prior written permission.  THE UNIVERSITY OF SOUTHERN CALIFORNIA makes no representations about  the suitability of this software for any purpose.  THIS SOFTWARE IS  PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,  INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  Other copyrights might apply to parts of this software and are so  noted when applicable.********************************************************************/#include "rsvp_daemon.h"/*	External declarations */extern void	del_from_timer();extern int	IsRoutePSB2nhop(Session *, PSB *, RSVP_HOP *);extern Object_header * copy_object(Object_header *);/*	Forward declarations */int		match_filter(FILTER_SPEC *, FILTER_SPEC *);int		match_policy(POLICY_DATA *, POLICY_DATA *);void		scope_catf(SCOPE **, FILTER_SPEC *);int		form_scope_union(Session *);void		clear_scope_union(Session *);Session		*locate_session(SESSION *);Session		*locate_session_p(SESSION *);/* *   match_filter(): Compares two FILTER_SPEC objects for equality, *	returns Boolean value. */intmatch_filter(FILTER_SPEC *f1, FILTER_SPEC *f2)	{	if (!f1 && !f2 )		return(1);	if (!f1 || !f2)		return(0);	if (Obj_CType(f2) != Obj_CType(f1))		return(0);	switch (Obj_CType(f1)) {	    case ctype_FILTER_SPEC_ipv4:		{		FILTER_SPEC_ipv4 *f1a = &f1->filt4;		FILTER_SPEC_ipv4 *f2a = &f2->filt4;		return (IN_ARE_ADDR_EQUAL(&f1a->filt_ipaddr,&inaddr_any)		     ||  IN_ARE_ADDR_EQUAL(&f2a->filt_ipaddr,&inaddr_any)		     || (IN_ARE_ADDR_EQUAL(&f1a->filt_ipaddr,&f2a->filt_ipaddr)		        && f1a->filt_port == f2a->filt_port) );		}	    case ctype_FILTER_SPEC_ipv4GPI:		{		FILTER_SPEC_ipv4GPI *f1a = &f1->filtgpi4;		FILTER_SPEC_ipv4GPI *f2a = &f2->filtgpi4;		return (IN_ARE_ADDR_EQUAL(&f1a->filt_ipaddr,&inaddr_any)		     || IN_ARE_ADDR_EQUAL(&f2a->filt_ipaddr,&inaddr_any)		     || (IN_ARE_ADDR_EQUAL(&f1a->filt_ipaddr,&f2a->filt_ipaddr)		        	 && f1a->filt_gpi == f2a->filt_gpi) );		}	#ifdef	USE_IPV6	    case ctype_FILTER_SPEC_ipv6:		{		FILTER_SPEC_ipv6 *f1a = &f1->filt6;		FILTER_SPEC_ipv6 *f2a = &f2->filt6;		return (IN6_ARE_ADDR_EQUAL(&f1a->filt_ipaddr,&in6addr_any)		     ||  IN6_ARE_ADDR_EQUAL(&f2a->filt_ipaddr,&in6addr_any)		     || (IN6_ARE_ADDR_EQUAL(&f1a->filt_ipaddr,&f2a->filt_ipaddr)		        && f1a->filt_port == f2a->filt_port) );		}	    case ctype_FILTER_SPEC_ipv6GPI:		{		FILTER_SPEC_ipv6GPI *f1a = &f1->filtgpi6;		FILTER_SPEC_ipv6GPI *f2a = &f2->filtgpi6;		return (IN6_ARE_ADDR_EQUAL(&f1a->filt_ipaddr,&in6addr_any)		     || IN6_ARE_ADDR_EQUAL(&f2a->filt_ipaddr,&in6addr_any)		     || (IN6_ARE_ADDR_EQUAL(&f1a->filt_ipaddr,&f2a->filt_ipaddr)		        	 && f1a->filt_gpi == f2a->filt_gpi) );		}	#endif	/* USE_IPV6 */	    default:		/* Treat unknown type as not matching.		 *	XXX This is actually a bug... each refresh with an		 *	unknown sender template makes new path state...!		 */		return(0);	}}/*	Same, but second argument is SENDER_TEMPLATE.  Really just *	type matching. */intmatch_sender_filter(FILTER_SPEC *f1, SENDER_TEMPLATE *f2)	{	return( match_filter(f1, (FILTER_SPEC *)f2) );}intmatch_policy(POLICY_DATA *pdo1p, POLICY_DATA *pdo2p)	{	if (Obj_Length(pdo1p) != Obj_Length(pdo2p))		return(0);	if (memcmp((char *)pdo1p, (char *)pdo2p, Obj_Length(pdo1p)))		return 0;	return(1);}/* *	Session hash function */intSess_hashf(SESSION *session){	int i,size;	u_int32_t n = 0,*lp;	switch(Obj_CType(session)) {		case ctype_SESSION_ipv4:		case ctype_SESSION_ipv4GPI:			size = sizeof(struct in_addr) / sizeof(n);			lp = (u_int32_t *) &session->sess4_addr;			break;#ifdef	USE_IPV6		case ctype_SESSION_ipv6:		case ctype_SESSION_ipv6GPI:			size = sizeof(struct in6_addr) / sizeof(n);			lp = (u_int32_t *) &session->sess6_addr;			break;#endif	/* USE_IPV6 */		default:			return(0);	}	for (i = 0;i < size; i++)		n ^= *lp++;	return(n % SESS_HASH_SIZE);}/* *  Locate Session block for given SESSION object *	Return 0 if no match, -1 if there is confusion about zero *	ports, and the Session struct address otherwise. */Session    *locate_session_p(SESSION *sessp)	{	Session	*destp;	int		hash = Sess_hashf(sessp);	for (destp = session_hash[hash]; destp ; destp = destp->d_next) {		if (session_eq_except_flags(destp->d_session,sessp))			return (destp);		if (session_eq_except_port(destp->d_session,sessp))			return ((Session *) -1);	}	return (NULL);}/*	locate_session(): Same as locate_session_p, except do not check *		for confusion about zero ports; require exact match. */Session    *locate_session(SESSION *sessp)	{	Session	*destp;	int		hash = Sess_hashf(sessp);	for (destp = session_hash[hash]; destp ; destp = destp->d_next) {		if (session_eq_except_flags(destp->d_session,sessp))			return (destp);	}	return (NULL);}/* * 	Create Session block for new session */Session *make_session(SESSION *sessp)	{	Session		*destp;	int		hash = Sess_hashf(sessp);	int		i;	destp = (Session *) calloc(1, sizeof(Session));	if (!destp) {		Log_Mem_Full("New session");		return(NULL);	}	/*	 *   Initialize fields of Session structure.	 */	destp->d_PSB_list = NULL;	/* no senders yet  */	destp->d_session = (SESSION *)copy_object((Object_header *)sessp);	Init_Object(&destp->d_timevalp, TIME_VALUES, TIME_VALUES_CTYPE)	destp->d_timevalp.timev_R = 0;	Init_Object(&destp->d_timevalr, TIME_VALUES, TIME_VALUES_CTYPE)	destp->d_timevalr.timev_R = 0;	destp->d_flags = 0;	destp->d_LLB_listv = (void *) calloc(if_num, sizeof(void *));	if (!destp->d_LLB_listv) {		free((char *) destp);		return(NULL);	}	for (i = 0; i < if_num; i++)		destp->d_LLB_listv[i] = NULL;	/*	 *  Insert new destination first in hast list	 */	destp->d_next = session_hash[hash];	session_hash[hash] = destp;	return(destp);}/* * kill_session():  All senders and reservations for this Session have *	been deleted; complete cleanup of the session and delete the *	Session (session) block itself. */intkill_session(Session *sessp)	{	Session	**d;	int	hash = Sess_hashf(sessp->d_session);#if DEBUG	int	i;	assert(!sessp->d_PSB_list && !sessp->d_RSB_list);	for (i = 0; i < if_num; i++)		assert(sessp->d_LLB_listv[i] == NULL);#endif /* DEBUG */	free(sessp->d_LLB_listv);	free(sessp->d_session);	/*  Take dest off hash list, and then delete all its timer events.	 *  Finally, free the control block.	 */	for (d = &session_hash[hash]; (*d) != NULL && (*d) != sessp;						 d = &((*d)->d_next));	assert(*d);	*d = sessp->d_next;	del_from_timer((char *) sessp, TIMEV_RESV);	del_from_timer((char *) sessp, TIMEV_PATH);	free((char *) sessp);	return (1);}intscope_count(SCOPE *scope){	if (Obj_Class(scope) != class_SCOPE)		return(0);	switch(Obj_CType(scope)) {		case ctype_SCOPE_list_ipv4:			return(Obj_datalen(scope) / sizeof(SCOPE_list_ipv4));#ifdef	USE_IPV6		case ctype_SCOPE_list_ipv6:			return(Obj_datalen(scope) / sizeof(SCOPE_list_ipv6));#endif	/* USE_IPV6 */		default:			return(0);	}}/* *	Create new SCOPE object with specified number of slots. */SCOPE *new_scope_obj(int count,u_char ctype){	int size;	SCOPE *scp;	switch(ctype) {		case ctype_SCOPE_list_ipv4:			size = sizeof(SCOPE_list_ipv4);			break;#ifdef	USE_IPV6		case ctype_SCOPE_list_ipv6:			size = sizeof(SCOPE_list_ipv6);			break;#endif	/* USE_IPV6 */		default:			return(NULL);	}	size = count * size + sizeof(Object_header);	scp = (SCOPE *)malloc(size);	assert(scp);	Init_Var_Obj(scp,SCOPE,NULL,size);	Obj_CType(scp) = ctype;	return(scp);}#define INIT_SCOPE_LEN 64#define MAX_SCOPE_LEN 65536/* *	scope_catf():  Catenate IP address from given FILTER_SPEC onto *			existing SCOPE list, which is assumed to be ordered, *			and return pointer to new SCOPE list.  Create SCOPE *			list if necessary.  Ignore a duplicate address. */voidscope_catf(SCOPE ** scppp, FILTER_SPEC *filtp)	{	int N, L, ctype, addrsize;	char *cp,*end,*addr;	SCOPE	*scpp, *new_scpp;	switch (Obj_CType(filtp)) {	    case ctype_FILTER_SPEC_ipv4:		ctype = ctype_SCOPE_list_ipv4;		addrsize = sizeof(struct in_addr);		addr = (char *) &filtp->filt4_srcaddr;		break;	    case ctype_FILTER_SPEC_ipv4GPI:		ctype = ctype_SCOPE_list_ipv4;		addrsize = sizeof(struct in_addr);		addr = (char *) &filtp->filtgpi4_srcaddr;		break;#ifdef	USE_IPV6	    case ctype_FILTER_SPEC_ipv6:		ctype = ctype_SCOPE_list_ipv6;		addr = (char *) &filtp->filt6_srcaddr;		addrsize = sizeof(struct in6_addr);		break;	    case ctype_FILTER_SPEC_ipv6GPI:		ctype = ctype_SCOPE_list_ipv6;		addr = (char *) &filtp->filtgpi6_srcaddr;		addrsize = sizeof(struct in6_addr);		break;#endif	/* USE_IPV6 */	    default:		return;	}	scpp = *scppp;	if (!scpp) {		/*	First time... set up object		 *	We use the object length field to keep track of		 *	the number of entries at present.  The size of		 *	malloc'd area is nearest power of 2 that is >=		 *	this len, but at least INIT_SCOPE_LEN.		 */		scpp = new_scope_obj(INIT_SCOPE_LEN,ctype);		if (!scpp)			return;		Obj_Length(scpp) = sizeof(Object_header);	}	else {		if (Obj_CType(scpp) != ctype)			return;		/*	Ignore a duplicate ip addr in list.		 */		end = ((char *) scpp) + Obj_Length(scpp);		for (cp = (char *) Obj_data(scpp);cp < end; cp += addrsize)			if (memcmp(cp,addr,addrsize) == 0)				return;	}	/*	Compute size of existing area	 */	L = Obj_Length(scpp);	for (N = INIT_SCOPE_LEN; N < MAX_SCOPE_LEN; N <<= 1)		if (N >= L)			break;	if (L + addrsize > N) {		/* Overflow.  Malloc a new object area of double size,		 *	copy into it, and free original one.		 */		new_scpp = (SCOPE *) malloc(N+N);		if (!new_scpp) {			/* XXX ?? */			return;		}		memset(new_scpp, 0, N+N);		memcpy(new_scpp, scpp, L);		free(scpp);		scpp = new_scpp;	}	memcpy(((char *) scpp) + Obj_Length(scpp),addr,addrsize);	Obj_Length(scpp) += addrsize;	*scppp = scpp;}/* *  form_scope_union(): Form global union of all SCOPE lists for given session, *		if it does not already exist, with local senders removed. * *		Turn on scope bit in each matching PSB. */intform_scope_union(Session *destp)	{	RSB		*rp;	PSB		*sp;	if (destp->d_flags & SESSF_HaveScope)		return(0);	for (rp = destp->d_RSB_list; rp != NULL; rp = rp->rs_next) {	    for (sp = destp->d_PSB_list ; sp != NULL; sp = sp->ps_next) {		if (IsHopAPI(&sp->ps_phop))			continue;		if (rp->rs_scope) {			/*			 *	Merge scope list into scope union, by turning			 *	on scope bit in each matching PSB that is not 			 *	local API. (Doing linear search of PSBs, but 			 *	could use hash table)			 */			if (hop_in_scope(&sp->ps_phop, rp->rs_scope))				sp->ps_flags |= PSBF_InScope;		}		else {			/*	No scope list.  Add to union all senders that 			 *	route to this RSB.		 	*/			if (IsRoutePSB2nhop(destp, sp, &rp->rs_rsvp_nhop)) 				sp->ps_flags |= PSBF_InScope;		}	    }	}	destp->d_flags |= SESSF_HaveScope;	return(0);}/* *  clear_scope_union(): Delete existing scope union (ie turn off scope *	flag bits in all PSBs.  Union will be recomputed when needed. * *	This is called when a new PSB is created, an PSB is deleted, a new *	RSB is created, an RSB with SCOPE list is deleted, or the SCOPE list *	of an existing RSB changes. */voidclear_scope_union(Session *destp)	{	PSB	*sp;	if ((destp->d_flags & SESSF_HaveScope) == 0)		return;	for (sp = destp->d_PSB_list ; sp != NULL; sp = sp->ps_next)		sp->ps_flags &= ~PSBF_InScope;	destp->d_flags &= ~SESSF_HaveScope;}	/* *  Check to see if two SCOPE's are equal * *	return 1 if true, and 0 otherwise */intmatch_scope(SCOPE *s1, SCOPE *s2) {	int size;	char *cp1,*end1,*cp2,*end2;	if (!s1) {		return(!s2);	}	else if (!s2)		return(0);	if (Obj_CType(s1) != Obj_CType(s2))		return(0);	if (Obj_Length(s1) != Obj_Length(s2))		return(0);	size = Obj_datalen(s1) / scope_count(s1);	end1 = ((char *) s1) + Obj_Length(s1);	end2 = ((char *) s2) + Obj_Length(s2);	for (cp1 = (char *) Obj_data(s1);cp1 < end1; cp1 += size) {		for (cp2 = (char *) Obj_data(s2);cp2 < end2; cp2 += size)			if (memcmp(cp1,cp2,size) == 0)				break;		if (cp2 >= end2)			return(0);	}	return(1);}

⌨️ 快捷键说明

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