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

📄 smux.c

📁 非常不错的网管开发包
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Smux module authored by Rohit Dube. * Rewritten by Nick Amato <naamato@merit.net>. */#include <config.h>#include <sys/types.h>#include <ctype.h>#if HAVE_IO_H  /* win32 */#include <io.h>#endif#include <stdio.h>#if HAVE_STDLIB_H#include <stdlib.h>#endif#if HAVE_STRING_H#include <string.h>#else#include <strings.h>#endif#if HAVE_UNISTD_H#include <unistd.h>#endif#if HAVE_ERR_H#include <err.h>#endif#if TIME_WITH_SYS_TIME# ifdef WIN32#  include <sys/timeb.h># else#  include <sys/time.h># endif# include <time.h>#else# if HAVE_SYS_TIME_H#  include <sys/time.h># else#  include <time.h># endif#endif#include <errno.h>#if HAVE_NETDB_H#include <netdb.h>#endif#include <sys/stat.h>#if HAVE_SYS_SOCKET_H#include <sys/socket.h>#elif HAVE_WINSOCK_H#include <winsock.h>#endif#if HAVE_SYS_FILIO_H#include <sys/filio.h>#endif#if HAVE_NETINET_IN_H#include <netinet/in.h>#endif#if HAVE_SYS_IOCTL_H#include <sys/ioctl.h>#endif#include "../../../snmplib/system.h"#include "asn1.h"#include "mibincl.h"#include "mib.h"#include "read_config.h"#include "snmp.h"#include "snmp_api.h"#include "snmp_client.h"#include "snmp_impl.h"#include "smux.h"#include "var_struct.h"#include "util_funcs.h"#include "mibdefs.h"long smux_long;u_long smux_ulong;struct sockaddr_in smux_sa;struct counter64 smux_counter64;oid smux_objid[MAX_OID_LEN];u_char smux_str[SMUXMAXSTRLEN];extern int smux_listen_sd;static struct timeval smux_rcv_timeout;static u_long smux_reqid;void 		init_smux (void);static u_char	*smux_open_process (int, u_char *, size_t *, int *);static u_char	*smux_rreq_process (int, u_char *, size_t *);static u_char	*smux_close_process (int, u_char *, size_t *);static u_char	*smux_trap_process (u_char *, size_t *);static u_char	*smux_parse (u_char *, oid *, size_t *, size_t *, u_char *);static u_char	*smux_parse_var (u_char *, size_t *, oid *, size_t *, size_t *, u_char *);static void 	smux_send_close (int, int);static void 	smux_list_detach (smux_reg **, smux_reg **);static void 	smux_replace_active (smux_reg *, smux_reg *);static void 	smux_peer_cleanup (int);static int 	smux_auth_peer (oid *, size_t, char *, int);static int 	smux_build (u_char, u_long, oid *,                            size_t *, u_char, u_char *, size_t, u_char *, size_t *);static 		int smux_list_add (smux_reg **, smux_reg *);static int	smux_pdu_process(int, u_char *, size_t);static 		int smux_send_rrsp (int, int);static		smux_reg *smux_find_match(smux_reg *, int, oid *, size_t, long);static 		smux_reg *smux_find_replacement (oid *, size_t);u_char 	*var_smux (struct variable *, oid *, size_t *, int, size_t *,                           WriteMethod **write_method);int 		var_smux_write (int, u_char *, u_char, size_t, u_char *, oid *, size_t);static smux_reg *ActiveRegs;		/* Active registrations 		*/static smux_reg *PassiveRegs;		/* Currently unused registrations 	*/static smux_peer_auth *Auths[SMUX_MAX_PEERS];	/* Configured peers */static int nauths, npeers = 0;struct variable2 smux_variables[] = {  /* bogus entry, as in pass.c */  {MIBINDEX, ASN_PRIV_DELEGATED, RWRITE, var_smux, 0, {MIBINDEX}},};voidsmux_parse_peer_auth(const char *token, char *cptr){	smux_peer_auth *aptr;	if ((aptr = (smux_peer_auth *)calloc(1, sizeof(smux_peer_auth))) == NULL) {		snmp_log_perror("smux_parse_peer_auth: malloc");		return;	}	aptr->sa_active_fd = -1;	if (!cptr) {		/* null passwords OK */		Auths[nauths++] = aptr;        	DEBUGMSGTL(("smux_conf", "null password\n"));		return;	}	if(*cptr == '.')		cptr++;	if (!isdigit(*cptr)) {		config_perror("second token is not an OID");		free((char *)aptr);		return;	}	/* oid */	aptr->sa_oid_len = parse_miboid(cptr, aptr->sa_oid);        DEBUGMSGTL(("smux_conf", "parsing registration for: %s\n", cptr));	while (isdigit(*cptr) || *cptr == '.')		 cptr++;	cptr = skip_white(cptr);        /* password */        if (cptr)          strcpy(aptr->sa_passwd, cptr);        	Auths[nauths++] = aptr;}voidsmux_free_peer_auth(void){	int i;	for(i = 0; i < nauths; i++) {		free(Auths[i]);		Auths[i] = NULL;	}}voidinit_smux(void){	struct sockaddr_in lo_socket;	int one = 1;        snmpd_register_config_handler("smuxpeer", smux_parse_peer_auth,                                      smux_free_peer_auth,                                      "OID-IDENTITY PASSWORD");	/* Reqid */	smux_reqid = 0;	smux_listen_sd = -1;	/* Receive timeout */	smux_rcv_timeout.tv_sec = 0;	smux_rcv_timeout.tv_usec = 500000;		/* Get ready to listen on the SMUX port*/	memset (&lo_socket,(0), sizeof (lo_socket));	lo_socket.sin_family = AF_INET;	lo_socket.sin_port = htons((u_short) SMUXPORT);	if ((smux_listen_sd = socket (AF_INET, SOCK_STREAM, 0)) <  0) {		snmp_log_perror("[init_smux] socket failed");		return;	}	if (bind (smux_listen_sd, (struct sockaddr *) &lo_socket, 	    sizeof (lo_socket)) < 0) {		snmp_log_perror("[init_smux] bind failed");		close(smux_listen_sd);		smux_listen_sd = -1;		return;	}#ifdef	SO_KEEPALIVE	if (setsockopt (smux_listen_sd, SOL_SOCKET, SO_KEEPALIVE, (char *)&one, 			sizeof (one)) < 0) {		snmp_log_perror("[init_smux] setsockopt(SO_KEEPALIVE) failed");		close(smux_listen_sd);		smux_listen_sd = -1;		return;	}#endif 	/* SO_KEEPALIVE */	if(listen(smux_listen_sd, SOMAXCONN) == -1) {		snmp_log_perror("[init_smux] listen failed");		close(smux_listen_sd);		smux_listen_sd = -1;		return;	}	DEBUGMSGTL(("smux_init", "[smux_init] done; smux listen sd is %d, smux port is %d\n", smux_listen_sd, ntohs(lo_socket.sin_port)));}u_char *var_smux(struct variable *vp,	oid *name,	size_t *length,	int exact,	size_t *var_len,	WriteMethod **write_method){	u_char *valptr, val_type;	smux_reg *rptr;	*write_method = NULL;	/* search the active registration list */	for (rptr = ActiveRegs; rptr; rptr = rptr->sr_next) {		if (!compare_tree(name, *length, rptr->sr_name,		    rptr->sr_name_len))			break;	}	if (rptr == NULL)		return NULL;	else if (exact && (*length < rptr->sr_name_len))		return NULL;	*write_method = var_smux_write; 	valptr = smux_snmp_process(exact, name, length,	    var_len, &val_type, rptr->sr_fd);	if (valptr == NULL)		return NULL;	if ((compare_tree(name, *length, rptr->sr_name,	    rptr->sr_name_len)) != 0) {		/* the peer has returned a value outside		 * of the registered tree		 */		return NULL;	} else {		/* set the type and return the value */		vp->type = val_type;		return valptr;	}}int var_smux_write(	int action,	u_char *var_val,	u_char var_val_type,	size_t var_val_len,	u_char *statP,	oid *name,	size_t name_len){	smux_reg *rptr;	u_char buf[SMUXMAXPKTSIZE], *ptr, sout[3], type;	int reterr;	size_t len, var_len, datalen, name_length;	long reqid, errsts, erridx;	u_char var_type, *dataptr;	DEBUGMSGTL (("smux","[var_smux_write] entering var_smux_write\n"));	len = SMUXMAXPKTSIZE;	reterr = SNMP_ERR_NOERROR;	var_len = var_val_len;	var_type = var_val_type;	name_length = name_len;	/* XXX find the descriptor again */	for (rptr = ActiveRegs; rptr; rptr = rptr->sr_next) {		if (!compare_tree(name, name_len, rptr->sr_name,		     rptr->sr_name_len))			break;	}	switch (action) {	case RESERVE1:		DEBUGMSGTL (("smux","[var_smux_write] entering RESERVE1\n"));		/* length might be long */		var_len += (*(var_val + 1) & ASN_LONG_LEN) ?		    var_len + ((*(var_val + 1) & 0x7F) + 2) : 2;		switch (var_val_type) {		case ASN_INTEGER:		case ASN_OCTET_STR:		case ASN_COUNTER:		case ASN_GAUGE:		case ASN_TIMETICKS:		case ASN_UINTEGER:		case ASN_COUNTER64:		case ASN_IPADDRESS:		case ASN_OPAQUE:		case ASN_NSAP:		case ASN_OBJECT_ID:		case ASN_BIT_STR:			datalen = var_val_len;			dataptr = var_val;			break;		case SNMP_NOSUCHOBJECT:        case SNMP_NOSUCHINSTANCE:		case SNMP_ENDOFMIBVIEW:		case ASN_NULL:		default:			DEBUGMSGTL (("smux","[var_smux_write] variable not supported\n"));			return SNMP_ERR_GENERR;			break;		}		if ((smux_build((u_char)SMUX_SET, smux_reqid,		    name, &name_length, var_val_type, dataptr, 		    datalen, buf, &len)) < 0) {			DEBUGMSGTL (("smux","[var_smux_write] smux build failed\n"));			return SNMP_ERR_GENERR;		}		if (send(rptr->sr_fd, buf, len, 0) < 0) {			DEBUGMSGTL (("smux","[var_smux_write] send failed\n"));			return SNMP_ERR_GENERR;		}		if ((len = recv(rptr->sr_fd, buf,		    SMUXMAXPKTSIZE, 0)) <= 0) {			DEBUGMSGTL (("smux","[var_smux_write] recv failed or timed out\n"));			/* do we need to do a peer cleanup in this case?? */			smux_peer_cleanup(rptr->sr_fd);			return SNMP_ERR_GENERR;		}		ptr = buf;		ptr = asn_parse_header(ptr, &len, &type);		if ((ptr == NULL) || type != SNMP_MSG_RESPONSE) 			return SNMP_ERR_GENERR;		ptr = asn_parse_int(ptr, &len, &type, &reqid, sizeof(reqid));		if ((ptr == NULL) || type != ASN_INTEGER) 			return SNMP_ERR_GENERR;		ptr = asn_parse_int(ptr, &len, &type, &errsts, sizeof(errsts));		if ((ptr == NULL) || type != ASN_INTEGER) 			return SNMP_ERR_GENERR;		if (errsts) {			DEBUGMSGTL (("smux","[var_smux_write] errsts returned\n"));			return (errsts);		}		ptr = asn_parse_int(ptr, &len, &type, &erridx, sizeof(erridx));		if ((ptr == NULL) || type != ASN_INTEGER) 			return SNMP_ERR_GENERR;		reterr = SNMP_ERR_NOERROR;		break;	/* case Action == RESERVE1 */	case RESERVE2:		DEBUGMSGTL (("smux","[var_smux_write] entering RESERVE2\n"));		reterr = SNMP_ERR_NOERROR;		break;	/* case Action == RESERVE2 */	case FREE:	case COMMIT:		ptr = sout;		*(ptr++) = (u_char)SMUX_SOUT;		*(ptr++) = (u_char)1;		if (action==FREE) {			*ptr = (u_char)1;	/* rollback */			DEBUGMSGTL (("smux","[var_smux_write] entering FREE - sending RollBack \n"));		}		else {			*ptr = (u_char)0;	/* commit */			DEBUGMSGTL (("smux","[var_smux_write] entering FREE - sending Commit \n"));		}		if ((send(rptr->sr_fd, sout, 3, 0)) < 0) {			DEBUGMSGTL (("smux","[var_smux_write] send rollback/commit failed\n"));			return SNMP_ERR_GENERR;		} 		reterr = SNMP_ERR_NOERROR;		break;	/* case Action == COMMIT */	default:		break;	}	return reterr;}intsmux_accept(int sd){	u_char data[SMUXMAXPKTSIZE], *ptr, type;	struct sockaddr_in in_socket;	struct timeval tv;	int fail, fd, alen;	size_t length, len;	alen = sizeof(struct sockaddr_in);	/* this may be too high */	tv.tv_sec = 5;	tv.tv_usec = 0;	/* connection request */	DEBUGMSGTL (("smux","[smux_accept] Calling accept()\n"));	errno = 0;	if((fd = accept(sd, (struct sockaddr *)&in_socket, &alen)) < 0) {		snmp_log_perror("[smux_accept] accept failed");		return -1;	} else {		snmp_log(LOG_ERR, "[smux_accept] accepted fd %d - errno %d\n", fd, errno);		if (npeers + 1 == SMUXMAXPEERS) {			DEBUGMSGTL (("smux","[smux_accept] denied peer on fd %d, limit reached", fd));			close(sd);			return -1;		}		/* now block for an OpenPDU */		if ((length = recv(fd, (char *)data, SMUXMAXPKTSIZE, 0)) <= 0) {			DEBUGMSGTL (("smux","[smux_accept] peer on fd %d died or timed out\n", fd));			close(fd);			return -1;		}		/* try to authorize him */		ptr = data;		len = length;		if ((ptr = asn_parse_header(ptr, &len, &type)) == NULL) {			smux_send_close(fd, SMUXC_PACKETFORMAT);			close(fd);			DEBUGMSGTL (("smux","[smux_accept] peer on %d sent bad open"));			return -1;		} else if (type != (u_char)SMUX_OPEN) {			smux_send_close(fd, SMUXC_PROTOCOLERROR);			close(fd);			DEBUGMSGTL (("smux","[smux_accept] peer on %d did not send open: (%d)\n", type));			return -1;		}		ptr = smux_open_process(fd, ptr, &len, &fail);		if (fail) {			smux_send_close(fd, SMUXC_AUTHENTICATIONFAILURE);			close(fd);			DEBUGMSGTL (("smux","[smux_accept] peer on %d failed authentication\n", fd));			return -1;		}		/* he's OK */#ifdef SO_RCVTIMEO		if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv, sizeof(tv)) < 0) {			DEBUGMSGTL (("smux","[smux_accept] setsockopt(SO_RCVTIMEO) failed fd %d\n", fd));                        snmp_log_perror("smux/setsockopt");                }#endif		npeers++;		DEBUGMSGTL (("smux","[smux_accept] fd %d\n", fd));	 	/* Process other PDUs already read, e.g. a registerRequest. */		len = length - (ptr - data);	 	if (smux_pdu_process(fd, ptr, len) < 0) {			/* Easy come, easy go.  Clean-up is already done. */			return -1;		}	}	return fd;}intsmux_process(int fd){	size_t length;	u_char data[SMUXMAXPKTSIZE];	length = recv(fd, (char *)data, SMUXMAXPKTSIZE, 0);	if (length <= 0) {		/* the peer went away, close this descriptor 		 * and delete it from the list		 */		DEBUGMSGTL (("smux","[smux_process] peer on fd %d died or timed out\n", fd));		smux_peer_cleanup(fd);		return -1;	}	return smux_pdu_process(fd, data, length);}static intsmux_pdu_process(int fd, u_char *data, size_t length){	int error;	size_t len;	u_char *ptr, type;	DEBUGMSGTL (("smux","[smux_pdu_process] Processing %d bytes\n", length));	error = 0;	ptr = data;	while (error == 0 && ptr != NULL && ptr < data + length) {		len = length - (ptr - data);		ptr = asn_parse_header(ptr, &len, &type);

⌨️ 快捷键说明

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