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

📄 smux.c

📁 radius server在linux下的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * smux.c	SNMP support * * Version:	$Id: smux.c,v 1.15 2004/02/26 19:04:26 aland Exp $ * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2 of the License, or *   (at your option) any later version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * * Copyright 2000  The FreeRADIUS server project * Copyright 1999  Jochen Friedrich <jochen@scram.de> * Copyright 1999  Kunihiro Ishiguro <kunihiro@zebra.org> */static const char rcsid[] ="$Id: smux.c,v 1.15 2004/02/26 19:04:26 aland Exp $";#include "autoconf.h"#ifdef WITH_SNMP#include "libradius.h"#include <sys/socket.h>#include <sys/file.h>#ifdef HAVE_NETINET_IN_H#include <netinet/in.h>#endif#include <stdio.h>#include <stdlib.h>#include <string.h>#include <netdb.h>#include <fcntl.h>#include <ctype.h>#include "radiusd.h"#include "radius_snmp.h"#include "smux.h"#define min(A,B) ((A) < (B) ? (A) : (B))/* internal prototypes */static int oid_compare (oid *, int, oid *, int);/* SMUX subtree vector. */static struct list *treelist = NULL;/* SMUX oid. */static oid *smux_oid;static size_t smux_oid_len;static void *oid_copy (void *dest, void *src, size_t size){  return memcpy (dest, src, size * sizeof (oid));}#if 0static voidoid2in_addr (oid my_oid[], int len, struct in_addr *addr){	int i;	u_char *pnt;	if (len == 0)		return;	pnt = (u_char *) addr;	for (i = 0; i < len; i++)		*pnt++ = my_oid[i];}static voidoid_copy_addr (oid my_oid[], struct in_addr *addr, int len){	int i;	u_char *pnt;	if (len == 0)		return;	pnt = (u_char *) addr;	for (i = 0; i < len; i++)		my_oid[i] = *pnt++;}#endif /* NOT USED */static intoid_compare (oid *o1, int o1_len, oid *o2, int o2_len){	int i;	for (i = 0; i < min (o1_len, o2_len); i++) {			if (o1[i] < o2[i])				return -1;			else if (o1[i] > o2[i])				return 1;	}	if (o1_len < o2_len)		return -1;	if (o1_len > o2_len)		return 1;	return 0;}static intoid_compare_part (oid *o1, int o1_len, oid *o2, int o2_len){	int i;	for (i = 0; i < min (o1_len, o2_len); i++) {			if (o1[i] < o2[i])				return -1;			else if (o1[i] > o2[i])				return 1;	}	if (o1_len < o2_len)		return -1;	return 0;}static voidsmux_oid_dump(const char *prefix, oid *my_oid, size_t oid_len){	int i;	int first = 1;	char buf[MAX_OID_LEN * 3];	buf[0] = '\0';	for (i = 0; i < oid_len; i++) {			sprintf (buf + strlen (buf), "%s%d", first ? "" : ".", (int) my_oid[i]);			first = 0;	}	DEBUG2 ("%s: %s", prefix, buf);}static intsmux_sock (void){	int ret;	int on = 1;#ifdef HAVE_IPV6	struct addrinfo hints, *res0, *res;	int gai;#else	struct sockaddr_in serv;	struct servent *sp;#endif	int fd;#ifdef HAVE_IPV6	memset(&hints, 0, sizeof(hints));	hints.ai_family = PF_UNSPEC;	hints.ai_socktype = SOCK_STREAM;	gai = getaddrinfo(NULL, "smux", &hints, &res0);	if (gai == EAI_SERVICE) {		char servbuf[NI_MAXSERV];		sprintf(servbuf,"%d",SMUX_PORT_DEFAULT);		gai = getaddrinfo(NULL, servbuf, &hints, &res0);	}	if (gai) {		DEBUG("Cannot locate loopback service smux");		return -1;	}	for(res=res0; res; res=res->ai_next) {		fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);		if (fd < 0)			continue;		setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof (on));#ifdef SO_REUSEPORT		setsockopt (fd, SOL_SOCKET, SO_REUSEPORT, (void *)&on, sizeof (on));#endif		ret = connect (fd, res->ai_addr, res->ai_addrlen);		if (ret < 0) {			close(fd);			fd = -1;			continue;		}		break;	}	freeaddrinfo(res0);	if (fd < 0)		DEBUG ("Can't connect to SNMP agent with SMUX");#else	fd = socket (AF_INET, SOCK_STREAM, 0);	if (fd < 0) {		DEBUG ("Can't make socket for SNMP");		return -1;	}	memset (&serv, 0, sizeof (struct sockaddr_in));	serv.sin_family = AF_INET;#ifdef HAVE_SIN_LEN	serv.sin_len = sizeof (struct sockaddr_in);#endif /* HAVE_SIN_LEN */	sp = getservbyname ("smux", "tcp");	if (sp != NULL)		serv.sin_port = sp->s_port;	else		serv.sin_port = htons (SMUX_PORT_DEFAULT);	serv.sin_addr.s_addr = htonl (INADDR_LOOPBACK);	setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof (on));#ifdef SO_REUSEPORT	setsockopt (fd, SOL_SOCKET, SO_REUSEPORT, (void *)&on, sizeof (on));#endif	ret = connect (fd, (struct sockaddr *) &serv, sizeof (struct sockaddr_in));	if (ret < 0) {		close (fd);		DEBUG ("Can't connect to SNMP agent with SMUX: %s", strerror(errno));		fd = -1;	}#endif	return fd;}static voidsmux_getresp_send (oid objid[], size_t objid_len, long reqid, long errstat,		long errindex, u_char val_type, const void *arg, size_t arg_len){	int ret;	u_char buf[BUFSIZ];	u_char *ptr, *h1, *h1e, *h2, *h2e;	int len, length;	ptr = buf;	len = BUFSIZ;	length = len;	DEBUG2("SMUX GETRSP send");	DEBUG2("SMUX GETRSP reqid: %ld", reqid);	h1 = ptr;	/* Place holder h1 for complete sequence */	ptr = asn_build_sequence (ptr, &len, (u_char) SMUX_GETRSP, 0);	h1e = ptr;	ptr = asn_build_int (ptr, &len,			(u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),			&reqid, sizeof (reqid));	DEBUG2("SMUX GETRSP errstat: %ld", errstat);	ptr = asn_build_int (ptr, &len,			(u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),			&errstat, sizeof (errstat));	DEBUG2("SMUX GETRSP errindex: %ld", errindex);	ptr = asn_build_int (ptr, &len,			(u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),			&errindex, sizeof (errindex));	h2 = ptr;	/* Place holder h2 for one variable */	ptr = asn_build_sequence (ptr, &len,			(u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR),			0);	h2e = ptr;	ptr = snmp_build_var_op (ptr, objid, &objid_len,			val_type, arg_len, arg, &len);	/* Now variable size is known, fill in size */	asn_build_sequence(h2,&length,(u_char)(ASN_SEQUENCE|ASN_CONSTRUCTOR),ptr-h2e);	/* Fill in size of whole sequence */	asn_build_sequence(h1,&length,(u_char)SMUX_GETRSP,ptr-h1e);	DEBUG2("SMUX getresp send: %d", ptr - buf);	ret = send (rad_snmp.smux_fd, buf, (ptr - buf), 0);}static char *smux_var (char *ptr, int len, oid objid[], size_t *objid_len,		size_t *var_val_len,		u_char *var_val_type,		void **var_value){	u_char type;	u_char val_type;	size_t val_len;	u_char *val;	DEBUG2("SMUX var parse: len %d", len);	/* Parse header. */	ptr = asn_parse_header (ptr, &len, &type);	DEBUG2("SMUX var parse: type %d len %d", type, len);	DEBUG2("SMUX var parse: type must be %d", (ASN_SEQUENCE | ASN_CONSTRUCTOR));	/* Parse var option. */	*objid_len = MAX_OID_LEN;	ptr = snmp_parse_var_op(ptr, objid, objid_len, &val_type,				&val_len, &val, &len);	if (var_val_len)		*var_val_len = val_len;	if (var_value)		*var_value = (void*) val;	if (var_val_type)		*var_val_type = val_type;	/* Requested object id length is objid_len. */	smux_oid_dump ("Request OID", objid, *objid_len);	DEBUG2 ("SMUX val_type: %d", val_type);	/* Check request value type. */	switch (val_type) {		case ASN_NULL:			/* In case of SMUX_GET or SMUX_GET_NEXT val_type is set to				 ASN_NULL. */			DEBUG2 ("ASN_NULL");			break;		case ASN_INTEGER:			DEBUG2 ("ASN_INTEGER");			break;		case ASN_COUNTER:		case ASN_GAUGE:		case ASN_TIMETICKS:		case ASN_UINTEGER:			DEBUG2 ("ASN_COUNTER");			break;		case ASN_COUNTER64:			DEBUG2 ("ASN_COUNTER64");			break;		case ASN_IPADDRESS:			DEBUG2 ("ASN_IPADDRESS");			break;		case ASN_OCTET_STR:			DEBUG2 ("ASN_OCTET_STR");			break;		case ASN_OPAQUE:		case ASN_NSAP:		case ASN_OBJECT_ID:			DEBUG2 ("ASN_OPAQUE");			break;		case SNMP_NOSUCHOBJECT:			DEBUG2 ("SNMP_NOSUCHOBJECT");			break;		case SNMP_NOSUCHINSTANCE:			DEBUG2 ("SNMP_NOSUCHINSTANCE");			break;		case SNMP_ENDOFMIBVIEW:			DEBUG2 ("SNMP_ENDOFMIBVIEW");			break;		case ASN_BIT_STR:			DEBUG2 ("ASN_BIT_STR");			break;		default:			DEBUG2 ("Unknown type");			break;	}	return ptr;}/* NOTE: all 3 functions (smux_set, smux_get & smux_getnext) are based on	 ucd-snmp smux and as such suppose, that the peer receives in the message	 only one variable. Fortunately, IBM seems to do the same in AIX. */static intsmux_set (oid *reqid, size_t *reqid_len,		u_char val_type, void *val, size_t val_len, int action){	int j;	struct subtree *subtree;	struct variable *v;	struct list *l;	int subresult;	oid *suffix;	int suffix_len;	int result;	const unsigned char *statP = NULL;	WriteMethod *write_method = NULL;	if (!rad_snmp.snmp_write_access)		return SNMP_ERR_NOSUCHNAME;	/* Check */	for (l = treelist; l; l=l->next) {		subtree = l->data;		subresult = oid_compare_part (reqid, *reqid_len,				subtree->name, subtree->name_len);		/* Subtree matched. */		if (subresult == 0) {			/* Prepare suffix. */			suffix = reqid + subtree->name_len;			suffix_len = *reqid_len - subtree->name_len;			result = subresult;			/* Check variables. */			for (j = 0; j < subtree->variables_num; j++) {				v = &subtree->variables[j];				/* Always check suffix */				result = oid_compare_part (suffix, suffix_len,						v->name, v->namelen);				/* This is exact match so result must be zero. */				if (result == 0) {					DEBUG2 ("SMUX function call index is %d", v->magic);					statP = (*v->findVar) (v, suffix, &suffix_len, 1,					&val_len, &write_method);					if (write_method) {						return (*write_method)(action, val, val_type, val_len, statP, suffix, suffix_len);					} else {						return SNMP_ERR_READONLY;					}				}				/* If above execution is failed or oid is small (so				   there is no further match). */				if (result < 0)					return SNMP_ERR_NOSUCHNAME;			}		}	}	return SNMP_ERR_NOSUCHNAME;}static intsmux_get (oid *reqid, size_t *reqid_len, int exact,		u_char *val_type,const void **val, size_t *val_len){	int j;	struct subtree *subtree;	struct variable *v;	struct list *l;	int subresult;	oid *suffix;	int suffix_len;	int result;	WriteMethod *write_method=NULL;	/* Check */	for (l = treelist; l; l=l->next) {		subtree = l->data;		subresult = oid_compare_part (reqid, *reqid_len,				subtree->name, subtree->name_len);		/* Subtree matched. */		if (subresult == 0) {			/* Prepare suffix. */			suffix = reqid + subtree->name_len;			suffix_len = *reqid_len - subtree->name_len;			result = subresult;			/* Check variables. */			for (j = 0; j < subtree->variables_num; j++) {				v = &subtree->variables[j];				/* Always check suffix */				result = oid_compare_part (suffix, suffix_len,						v->name, v->namelen);				/* This is exact match so result must be zero. */				if (result == 0) {					DEBUG2 ("SMUX function call index is %d", v->magic);					*val = (*v->findVar) (v, suffix, &suffix_len, exact,							val_len, &write_method);					/* There is no instance. */					if (*val == NULL)						return SNMP_ERR_NOSUCHNAME;					/* Call is suceed. */					*val_type = v->type;					return 0;				}				/* If above execution is failed or oid is small (so				   there is no further match). */				if (result < 0)					return SNMP_ERR_NOSUCHNAME;			}		}	}	return SNMP_ERR_NOSUCHNAME;}static intsmux_getnext (oid *reqid, size_t *reqid_len, int exact,		u_char *val_type, const void **val, size_t *val_len){	int j;	oid save[MAX_OID_LEN];	int savelen = 0;	struct subtree *subtree;	struct variable *v;	struct list *l;	int subresult;	oid *suffix;	int suffix_len;	int result;	WriteMethod *write_method=NULL;	/* Save incoming request. */	oid_copy (save, reqid, *reqid_len);	savelen = *reqid_len;	/* Check for best matching subtree */	for (l = treelist; l; l=l->next) {		subtree = l->data;		subresult = oid_compare_part (reqid, *reqid_len,				subtree->name, subtree->name_len);		 /* If request is in the tree. The agent has to make sure we		    only receive requests we have registered for. */		 /* Unfortunately, that's not true. In fact, a SMUX subagent has to		    behave as if it manages the whole SNMP MIB tree itself. It's the		    duty of the master agent to collect the best answer and return it		    to the manager. See RFC 1227 chapter 3.1.6 for the glory details		    :-). ucd-snmp really behaves bad here as it actually might ask		    multiple times for the same GETNEXT request as it throws away the		    answer when it expects it in a different subtree and might come		    back later with the very same request. --jochen */		if (subresult <= 0) {				/* Prepare suffix. */				suffix = reqid + subtree->name_len;				suffix_len = *reqid_len - subtree->name_len;				if (subresult < 0) {					oid_copy(reqid, subtree->name, subtree->name_len);					*reqid_len = subtree->name_len;				}			for (j = 0; j < subtree->variables_num; j++) {				result = subresult;				v = &subtree->variables[j];				/* Next then check result >= 0. */				if (result == 0)					result = oid_compare_part (suffix, suffix_len,							v->name, v->namelen);				if (result <= 0) {					DEBUG2 ("SMUX function call index is %d", v->magic);

⌨️ 快捷键说明

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