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

📄 rapi_lib.c

📁 radius协议源码÷The Radius Stack will connect to a Radius Server. This stack implementation is built upo
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * @(#) $Id: rapi_lib.c,v 1.1.1.1 2000/05/08 22:51:24 wenqing Exp $ *//****************************************************************************            RSVPD -- ReSerVation Protocol Daemon                USC Information Sciences Institute                Marina del Rey, California		Original Version: Don Hoffman, Sun Microsystems		Current Version:  Bob Braden, May 1996.  Copyright (c) 1998 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.********************************************************************//*  History: *   Oct 94  Vers 1: Original code written by Don Hoffman @ Sun Microsystems *   ??? 95  Vers 2: Updated by Bob Braden @ ISI *   Aug 95  Vers 3: Update client calls to match ID07 protocol spec. *   Sep 95  Vers 3.10: Add new calls rapi_session(), rapi_sender() as *			alternative to rapi_register().  Also, included			improvements developed by Joshua Gahm (JBG) at BBN. *   Sep 95  Vers 3.11: Include adspecs in upcalls. *   Apr 96  Vers 4.0: Remove non-reentrant rapi_errno variable. *			Remove obs parameters and add some new ones. *			Allow null rapi_sender call to imply path_tear. *   Jun 97  Vers 5.01: [Rel4.1a6] Conform to final int-serv specs, and *			to coming XOPEN document. *   Aug 98  Vers 5.1:  [Rel4.2a4] Support network byte order in pipe to *			daemon.  Require event_rtn param in session call. */#include <stdio.h>#include <string.h>#include <stdlib.h>#include <ctype.h>#include <unistd.h>#include <math.h>#include <sys/types.h>#include <sys/time.h>#include <sys/socket.h>#include <netinet/in.h>#include <errno.h>#include <netdb.h>#include <arpa/inet.h>#include <sys/un.h>#include <sys/uio.h>#include <signal.h>#include <fcntl.h>#include <stddef.h>#include "config.h"#include "rsvp_socks.h"#include "rsvp.h"#include "rapi_lib.h"#include "rsvp_api.h"#include "rsvp_specs.h"/*	IP protocol Ids for IPSEC: should come from some system *	file. XXX */#define IPPROTID_IPSEC_ESP	50#define IPPROTID_IPSEC_AH	51/* Serial numbers to use in calls to connect_to_daemon to    distinguish UNIX filenames for the pipes.  NB: can only    have one outstanding DEBUG connection to the server at a    time, so not safe for multi-threaded use. */  #define MAIN_RSVP_CONNECTION_SERIAL_NUM 0 #define DEBUG_RSVP_CONNECTION_SERIAL_NUM 1 /* *	Define an entry in client session table. */typedef struct Sid_info {	api_addr		dest;	/* Destination addr, port  */	u_char			protid; /* Protocol Id		*/	u_char			in_use;	/* in-use flag 		*/	u_char			flags;	/* Session flags	*/	rapi_event_rtn_t	event_rtn;	void			*event_rtn_arg;}               sid_rec;/* *	Client session table;   index into this table is *	the session handle given to application. */static sid_rec	sid_vec[MAX_RAPI_SESS];/* *	Global variables */static int	rapi_errno = RAPI_ERR_OK;static int	pid, init_flag = 0;static int	max_sid = 0;	/* (To shorten linear search time) */char		client_namestr[70]; /* Name of client send of socket */api_addr	api_address2;net_addr	api_address;/*	Define empty RAPI and API objects: just header (framing) */int		Empty_RObj[2] = {sizeof(rapi_hdr_t), 0};#define Empty_APIObj	Empty_RObj		/* empty API object */#define Empty_Flowspec (rapi_flowspec_t *) &Empty_RObj#define Empty_Filter (rapi_filter_t *) &Empty_RObj	/*	JBG: the single socket that will be connected to the  *	RSVP server.  All individual sids will have their socket   *	fields set to this value when they are in use.  */ static int              rsvp_socket = -1; static int              rsvp_socket_refs = 0; #define mark_sid_inuse(sid_to_mark) \if (! sid_vec[sid_to_mark].in_use) \     rsvp_socket_refs++; \sid_vec[sid_to_mark].in_use = 1;  #define mark_sid_free(sid_to_mark) \if (sid_vec[sid_to_mark].in_use) \     rsvp_socket_refs--; \sid_vec[sid_to_mark].in_use = 0; /* *	Forward declarations */static rapi_sid_t		common_register(rapi_sid_t, struct sockaddr *, int,		   rapi_filter_t *, rapi_tspec_t *,		   rapi_adspec_t *, rapi_policy_t *, int);static int	rapi_dispatch_fd(int);static int	Get_free_slot();static void	sig_pipe(int sig);static int	init_rapi();static int	connect_to_daemon(int);static int	send_req(rsvp_req *, int, long, int);static char	*copy_policy_i2d(rapi_policy_t *, rapi_policy_t *, char *, int);static char	*copy_flowspec_i2d(rapi_flowspec_t *, API_Flowspec *, char *);static char	*copy_tspec_i2d(rapi_tspec_t *, API_TSpec *, char *);static char	*copy_adspec_i2d(rapi_adspec_t *, API_Adspec *, char *);static char	*copy_filterspec_i2d(rapi_filter_t *, API_FilterSpec *, char *);static int	copy_flowspec_d2i(API_Flowspec *, rapi_flowspec_t *, char *, 							int);static int	copy_tspec_d2i(API_TSpec *, rapi_tspec_t *, char *, int);static int	copy_filterspec_d2i(API_FilterSpec *, rapi_filter_t *, char *);static int	copy_adspec_d2i(API_Adspec *, rapi_adspec_t *, char *, int);static char	*copy_sender_desc(rapi_filter_t *, rapi_tspec_t *, 				rapi_adspec_t *, API_FlowDesc *, char *);void		sockaddr2filterbase(struct sockaddr *, rapi_filter_t *);int		CSZXtoG_spec(qos_flowspecx_t *, IS_specbody_t *);int		CSZXtoGen_tspec(qos_tspecx_t *, IS_tspbody_t *);int		CSZXtoCL_spec(qos_flowspecx_t *, IS_specbody_t *);int		CSZXtoIS_adspec(qos_adspecx_t *, IS_adsbody_t *);int		CLtoCSZX_spec(IS_specbody_t *, qos_flowspecx_t *);int		GtoCSZX_spec(IS_specbody_t *, qos_flowspecx_t *);int		GentoCSZX_tspec(IS_tspbody_t *, qos_tspecx_t *);int		IStoCSZX_adspec(IS_adsbody_t *, qos_adspecx_t *);int		writev();int		List_Length(char *, int);int		vDstPort_OK(api_addr *, int);int		api_addr_assign(api_addr *addr,const struct sockaddr *s);int		sockaddr_assign(struct sockaddr *s,const api_addr *addr);#ifdef USE_NET_BOvoid		hton_rapi_cmd(rapi_cmd_t *);/*	External declarations * */int	hton_rapi_flowspec();int	ntoh_rapi_flowspec();int	hton_rapi_adspec();int	ntoh_rapi_adspec();#endif /* USE_NET_BO */#ifdef	sunextern int gethostname(char *,int);#endif	/* sun */#define is_valid(sid) (init_flag && sid <= max_sid && (sid_vec[sid].in_use))#define IS2RAPI_len(x) (4*(x) + sizeof(rapi_hdr_t) + sizeof(IS_main_hdr_t))#define RAPI2IS_len(y) wordsof((y)- sizeof(rapi_hdr_t) - sizeof(IS_main_hdr_t))#define API_IsPath(x)  ((x)->resp_type == RAPI_PATH_EVENT || \		        (x)->resp_type == RAPI_PATH_ERROR || \		        (x)->resp_type == RAPI_PATH_STATUS)/*	Check "GPI-ness" of filter spec or sender template: it should *	have form _GPI or _GPI6 if and only if the session has the GPI *	flag on. Return TRUE iff GPI-ness matches. */#define GPIness_matches(fp)  (((flags&RAPI_GPI_SESSION)!=0) == \	((fp->form == RAPI_FILTERFORM_GPI)|(fp->form == RAPI_FILTERFORM_GPI6)))#define Protid_OK(pid, flags)	(!(flags&RAPI_GPI_SESSION) || \	pid == IPPROTID_IPSEC_AH || pid == IPPROTID_IPSEC_ESP)/*	For IPSEC, (virtual) dest port must be non-zero. *	(I have no idea why...!) */char       *rapi_rstyle_names[] = {"?", "WF", "FF", "SE"};/********************************************************** *       	Visible RAPI Routines * **********************************************************//*  rapi_session(): *	Register with the RSVP daemon, creating a new API session. *	If successful, return local session id, else return -1 and *	set error code in variable. */rapi_sid_trapi_session(	struct sockaddr		*dest,	/* Destination host, port */	int			protid,	int			flags,	rapi_event_rtn_t	event_rtn,	void *			event_rtn_arg,	int			*errnop)	{	rapi_sid_t		sid = NULL_SID;	if (dest == NULL || event_rtn == NULL) {		rapi_errno = RAPI_ERR_INVAL;		goto exit;	}	if (!init_flag) {		if (init_rapi() < 0) {			rapi_errno = RAPI_ERR_NORSVP;			goto exit;		}	}	/* Locate empty session slot */	if ((int)(sid = Get_free_slot()) < 0) {		rapi_errno = RAPI_ERR_MAXSESS;		goto exit;	}	mark_sid_inuse(sid);		/* Mark it in use */	sid_vec[sid].protid = protid;	sid_vec[sid].flags =			(flags &= (RAPI_USE_INTSERV|RAPI_GPI_SESSION));	api_addr_assign(&sid_vec[sid].dest,dest);	sid_vec[sid].event_rtn = event_rtn;	sid_vec[sid].event_rtn_arg = event_rtn_arg;	/*	For GPI_SESSION flag (IPSEC), check that protocol Id	 *	is correct for IPSEC.  (because the spec calls for it).	 */	if (!Protid_OK(protid, flags)) {		rapi_errno = RAPI_ERR_BADPROTO;		goto exit;	}	if (!vDstPort_OK(&sid_vec[sid].dest, flags)) {		rapi_errno = RAPI_ERR_BADVDPORT;		goto exit;	}	rapi_errno = common_register(sid, NULL, flags,					NULL, NULL,					NULL,NULL, 0);exit:	if (rapi_errno != RAPI_ERR_OK) {		mark_sid_free(sid);		sid = NULL_SID;	}	if (errnop)		*errnop = rapi_errno;	return sid;}/*  rapi_sender(): *	Set/modify sender parameters. */intrapi_sender(	rapi_sid_t		sid,	int			flags,	/* Currently, none used */	struct sockaddr 	*LHost,	/* Sender host, port (optional) */	rapi_filter_t *		sender_template,	rapi_tspec_t  *		sender_tspec,	rapi_adspec_t *		sender_adspec,	rapi_policy_t *		sender_policy,	int			ttl)	{	rapi_errno = RAPI_ERR_OK;	if (!is_valid(sid))		return RAPI_ERR_BADSID;	/*  sid_vec[sid].flags |= flags;  (None defined) */	/* Assumes session and sender flags are distinct. */	if ((LHost||sender_template) && !sender_tspec)			return RAPI_ERR_NOTSPEC;	rapi_errno = common_register(sid, LHost, flags,			sender_template, sender_tspec,			sender_adspec, sender_policy, ttl);	return (rapi_errno);}/*  rapi_reserve(): *	Make/modify/delete reservation for session. * */intrapi_reserve(	rapi_sid_t		sid,	int			rflags,	struct sockaddr *	rhost,	/* Receiver host (optional) */	rapi_styleid_t		styleid,	rapi_stylex_t	*	style_ext,   /* style extension */        rapi_policy_t	*	rcvr_policy,	int			n_filter,	rapi_filter_t	*	filter_spec_list,	int			n_flow,	rapi_flowspec_t	*	flowspec_list)	{	char			*req_buf = NULL, *cp, *End_buf;	rsvp_req		*req = (rsvp_req *) req_buf;	int			i, len, n1, n2, nflwd, flags;	rapi_filter_t		*rfiltp;	rapi_flowspec_t		*rflowp;	rapi_errno = RAPI_ERR_OK;	if (!is_valid(sid))		return RAPI_ERR_BADSID;	/*	Check parameters according to style	 */	flags = sid_vec[sid].flags;	/* session flags */	rfiltp = filter_spec_list;	rflowp = flowspec_list;	nflwd = 0;	switch (styleid) {	    case RAPI_RSTYLE_WILDCARD:		if (n_flow == 0)			break;	/* Teardown case */		if (n_filter < 0 || n_filter > 1 || n_flow != 1)			return RAPI_ERR_N_FFS;		if (rflowp == NULL)			return RAPI_ERR_INVAL;		nflwd = 1;		break;	    case RAPI_RSTYLE_FIXED:		if (n_flow == 0)			break;	/* Teardown case */		if (n_filter != n_flow || n_filter <= 0)			return RAPI_ERR_N_FFS;		if (rfiltp == NULL || rflowp == NULL)			return RAPI_ERR_INVAL;		nflwd = n_filter;		break;	    case RAPI_RSTYLE_SE:		if (n_flow == 0)			break;	/* Teardown case */		if (n_flow != 1 || n_filter <= 0) {			return RAPI_ERR_N_FFS;		}		if (rfiltp == NULL || rflowp == NULL)			return RAPI_ERR_INVAL;		nflwd = n_filter;		break;	    default:		return RAPI_ERR_BADSTYLE;	}	/*	Must scan parm lists to get total length in order to	 *	dynamically alloc buffer.	 */	if ((n1 = List_Length( (char *)rflowp, n_flow)) < 0 ||	    (n2 = List_Length( (char *)rfiltp, n_filter)) < 0) {		return RAPI_ERR_INVAL;	}	else len = sizeof(rsvp_req) + n1 + n2 + 				abs(n_flow - n_filter)*sizeof( Empty_RObj ); 	if (!(req_buf = malloc(len)))		return RAPI_ERR_MEMFULL;	req = (rsvp_req *) req_buf;	End_buf = req_buf + len;	memset((char *)req, 0, len);	req->rq_style = (u_char) styleid;	req->rq_type = API2_RESV;	req->rq_dest = sid_vec[sid].dest;	req->rq_protid = sid_vec[sid].protid;	if (rhost)		api_addr_assign(&req->rq_host, rhost);	else		req->rq_host = api_address2;	req->rq_nflwd = nflwd;#ifdef USE_NET_BO	HTON16(req->rq_nflwd);#endif	req->rq_flags = (rflags &= (RAPI_REQ_CONFIRM));	cp = copy_policy_i2d(rcvr_policy, req->rq_policy, End_buf, 1);	if (!cp)		goto exit;	/*  If n_flow == 0, simply remove existing reservation (without	 *  releasing API session).	 */	if (n_flow == 0) {		req->rq_nflwd = 0;		(void)send_req(req, cp - req_buf, sid, rsvp_socket);		goto exit;	}	/*	 *	Copy ({flowspec|EMPTY}, {filter_spec|EMPTY}) pairs	 *	into request.  Note that copy_xxxx_i2d() routines	 *	check that there is room in buffer and if not, set	 *	rapi_errno and return NULL.	 *	 *	copy_flowspec_i2d translates contents into Intserv format.	 *	copy_filterspec_i2d (currently) simply copies without change.	 */	for (i = 0; i < nflwd; i++) {		if (i < n_filter) {			if (!GPIness_matches(rfiltp)) {				/* The IPSEC document does not say this must be				 * checked in the API, but for consistency it 				 * should be.				 */				rapi_errno = RAPI_ERR_GPI_CONFLICT;				goto exit;			}		}		cp = (char *)copy_filterspec_i2d(				(i < n_filter)? rfiltp : Empty_Filter,				(API_FilterSpec *)cp, End_buf);		if (!cp)			goto exit;		cp = copy_flowspec_i2d((i < n_flow)? rflowp : Empty_Flowspec,				(API_Flowspec *)cp, End_buf);		if (!cp)			goto exit;		if (i < n_filter)			rfiltp = (rapi_filter_t *) After_RAPIObj(rfiltp);		if (i < n_flow)			rflowp = (rapi_flowspec_t *) After_RAPIObj(rflowp);	}	(void)send_req(req, cp - req_buf, sid, rsvp_socket);exit:	if (req_buf)		free(req_buf);	return rapi_errno;}/*  rapi_release(): *	Delete API session and free session handle. */intrapi_release(rapi_sid_t sid)	{	char		req_buf[MAX_MSG];	/* TBD: dyn alloc */	rsvp_req       *req = (rsvp_req *) req_buf;	if (!is_valid(sid))		return RAPI_ERR_BADSID;	memset(req_buf, 0, sizeof req_buf);	/* Redundant, but cautious */	req->rq_nflwd = 0;	req->rq_type = API_CLOSE;	(void)send_req(req, sizeof(rsvp_req), sid, rsvp_socket);	mark_sid_free(sid);	return (RAPI_ERR_OK);}/*  rapi_getfd(): *	Return file descriptor for socket used now. */intrapi_getfd(rapi_sid_t sid)	{	if (!is_valid(sid))		return -1;	return rsvp_socket;}/*  rapi_dispatch(): *	Dispatch upcalls. */intrapi_dispatch()	{    	fd_set  tmp_fds;	int     fd_wid;	struct  timeval tout;	rapi_errno = RAPI_ERR_OK;	if (rsvp_socket == -1)		return RAPI_ERR_OK;	FD_ZERO(&tmp_fds);	FD_SET(rsvp_socket, &tmp_fds);	fd_wid = rsvp_socket+1;	memset(&tout, 0, sizeof(tout));	/* Poll for input ready on socket	 */	if (select(fd_wid, &tmp_fds, NULL, NULL, &tout) <= 0)		return RAPI_ERR_OK;	if (FD_ISSET(rsvp_socket, &tmp_fds))

⌨️ 快捷键说明

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