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

📄 smux.c

📁 Snmp(简单网管协议)软件包。
💻 C
📖 第 1 页 / 共 4 页
字号:
                        /* we could receive the reply or another trap */                    } else {                         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;                     }                 } /* while (1) */ 		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_INFO, "[smux_accept] accepted fd %d from %s:%d\n",		    fd, inet_ntoa(in_socket.sin_addr), ntohs(in_socket.sin_port));		if (npeers + 1 == SMUXMAXPEERS) {			snmp_log (LOG_ERR, "[smux_accept] denied peer on fd %d, limit %d reached", fd, SMUXMAXPEERS);			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_accept: setsockopt SO_RCVTIMEO");                }#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);		DEBUGMSGTL (("smux","[smux_pdu_process] type is %d\n", (int) type));		switch (type) {		case SMUX_OPEN:			smux_send_close(fd, SMUXC_PROTOCOLERROR);			DEBUGMSGTL (("smux","[smux_pdu_process] peer on fd %d sent duplicate open?\n", fd));			smux_peer_cleanup(fd);			error = -1;			break;		case SMUX_CLOSE:			ptr = smux_close_process(fd, ptr, &len);			smux_peer_cleanup(fd);			error = -1;			break;		case SMUX_RREQ:			ptr = smux_rreq_process(fd, ptr, &len);			break;		case SMUX_RRSP:			error = -1;			smux_send_close(fd, SMUXC_PROTOCOLERROR);			smux_peer_cleanup(fd);			DEBUGMSGTL (("smux","[smux_pdu_process] peer on fd %d sent RRSP!\n", fd));			break;		case SMUX_SOUT:			error = -1;			smux_send_close(fd, SMUXC_PROTOCOLERROR);			smux_peer_cleanup(fd);			DEBUGMSGTL (("smux","This shouldn't have happened!\n"));			break;		case SMUX_TRAP:			snmp_log(LOG_INFO, "Got trap from peer on fd %d\n", fd);			ptr = smux_trap_process(ptr, &len);			/* watch out for close on top of this...should return correct end */			/* debug this... */			ptr = NULL;			break;		default:			smux_send_close(fd, SMUXC_PACKETFORMAT);			smux_peer_cleanup(fd);			DEBUGMSGTL (("smux","[smux_pdu_process] Wrong type %d\n", (int)type));			error = -1;			break;		}	}	return error;}static u_char *smux_open_process(int fd, u_char *ptr, size_t *len, int *fail){	u_char type;	long version;	oid oid_name[MAX_OID_LEN];	char passwd[SMUXMAXSTRLEN];	char descr[SMUXMAXSTRLEN];	char oid_print[SMUXMAXSTRLEN];	int i;	size_t oid_name_len, string_len;	if (!(ptr = asn_parse_int(ptr, len, &type, &version, sizeof(version)))) {		DEBUGMSGTL (("smux","[smux_open_process] version parse failed\n"));		*fail = TRUE;		return((ptr += *len));	}	DEBUGMSGTL(("smux",                    "[smux_open_process] version %d, len %d, type %d\n",                     version, *len, (int)type));	oid_name_len = MAX_OID_LEN;	if ((ptr = asn_parse_objid(ptr, len, &type, oid_name,	    &oid_name_len)) == NULL) {		DEBUGMSGTL (("smux","[smux_open_process] oid parse failed\n"));		*fail = TRUE;		return((ptr += *len));	}	sprint_objid(oid_print, oid_name, oid_name_len);        if (snmp_get_do_debugging()) {	    DEBUGMSGTL (("smux","[smux_open_process] smux peer: %s\n", oid_print)); 	    DEBUGMSGTL (("smux","[smux_open_process] len %d, type %d\n", *len, (int)type));        }	string_len = SMUXMAXSTRLEN;	if ((ptr = asn_parse_string(ptr, len, &type, (u_char *)descr,	    &string_len)) == NULL) {		DEBUGMSGTL (("smux","[smux_open_process] descr parse failed\n"));		*fail = TRUE;		return((ptr += *len));	}        if (snmp_get_do_debugging()) {          DEBUGMSGTL (("smux","[smux_open_process] smux peer descr: "));           for (i=0; i < (int)string_len; i++)             DEBUGMSG (("smux","%c", descr[i]));          DEBUGMSG (("smux","\n"));          DEBUGMSGTL (("smux","[smux_open_process] len %d, type %d\n", *len, (int)type));        }	descr[string_len] = 0;	string_len = SMUXMAXSTRLEN;	if ((ptr = asn_parse_string(ptr, len, &type, (u_char *)passwd,	    &string_len)) == NULL) {		DEBUGMSGTL (("smux","[smux_open_process] passwd parse failed\n"));		*fail = TRUE;		return((ptr += *len));	}        if (snmp_get_do_debugging()) {          DEBUGMSGTL (("smux","[smux_open_process] smux peer passwd: "));           for (i=0; i < (int)string_len; i++)             DEBUGMSG (("smux","%c", passwd[i]));          DEBUGMSG (("smux","\n"));          DEBUGMSGTL (("smux","[smux_open_process] len %d, type %d\n", *len, (int)type));        }	passwd[string_len] = '\0';	if(!smux_auth_peer(oid_name, oid_name_len, passwd, fd)) {	    snmp_log(LOG_WARNING, "refused smux peer: oid %s, password %s, descr %s\n",		     oid_print, passwd, descr);	    *fail = TRUE;	    return ptr;	}	snmp_log(LOG_INFO, "accepted smux peer: oid %s, password %s, descr %s\n",		 oid_print, passwd, descr);	*fail = FALSE;	return ptr;}static voidsmux_send_close(int fd, int reason){    u_char outpacket[3], *ptr;    ptr = outpacket;    *(ptr++) = (u_char)SMUX_CLOSE;    *(ptr++) = (u_char)1;    *ptr = (u_char)(reason & 0xFF);    if(snmp_get_do_debugging()) 	DEBUGMSGTL (("smux","[smux_close] sending close to fd %d, reason %d\n", fd, reason));    /* send a response back */     if (send (fd, (char *)outpacket, 3, 0) < 0) {        snmp_log_perror("[smux_snmp_close] send failed");    }}        static intsmux_auth_peer(oid *name, size_t namelen, char *passwd, int fd){	int i;	for (i = 0; i < nauths; i++) {		if (snmp_oid_compare(Auths[i]->sa_oid, Auths[i]->sa_oid_len,		    name, namelen) == 0) {			if(!(strcmp(Auths[i]->sa_passwd, passwd)) &&			    (Auths[i]->sa_active_fd == -1)) {				/* matched, mark the auth */				Auths[i]->sa_active_fd = fd;				return 1;			}			else				return 0;		}	}	/* did not match oid and passwd */	return 0;}/*  * XXX - Bells and Whistles: * Need to catch signal when snmpd goes down and send close pdu to gated  */static u_char *smux_close_process(int fd, u_char *ptr, size_t *len){	long down = 0;	int length = *len;	/* This is the integer part of the close pdu */	while (length--) {		down = (down << 8) | (long)*ptr;		ptr++;	}	DEBUGMSGTL (("smux","[smux_close_process] close from peer on fd %d reason %d\n", fd, down));	smux_peer_cleanup(fd);	return NULL;}static u_char *smux_rreq_process(int sd, u_char *ptr, size_t *len){	long priority, rpriority;	long operation;	oid oid_name[MAX_OID_LEN];	size_t oid_name_len;	int i, result;	u_char type;	smux_reg *rptr, *nrptr;	oid_name_len = MAX_OID_LEN;	ptr = asn_parse_objid(ptr, len, &type, oid_name, &oid_name_len);     DEBUGMSGTL(("smux", "[smux_rreq_process] smux subtree: "));    DEBUGMSGOID(("smux", oid_name, oid_name_len));    DEBUGMSG(("smux","\n"));	if ((ptr = asn_parse_int(ptr, len, &type, &priority, 	    sizeof(priority))) == NULL) {		DEBUGMSGTL (("smux","[smux_rreq_process] priority parse failed\n"));		smux_send_rrsp(sd, -1);		return NULL;	}	DEBUGMSGTL (("smux","[smux_rreq_process] priority %d\n", priority));	if ((ptr = asn_parse_int(ptr, len, &type, &operation, 	    sizeof(operation))) == NULL) {		DEBUGMSGTL (("smux","[smux_rreq_process] operation parse failed\n"));		smux_send_rrsp(sd, -1);		return NULL;	}	DEBUGMSGTL (("smux","[smux_rreq_process] operation %d\n", operation));	if(operation == SMUX_REGOP_DELETE) {		/* search the active list for this registration */		rptr = smux_find_match(ActiveRegs, sd, oid_name, oid_name_len, priority);		if (rptr) {			rpriority = rptr->sr_priority;			/* unregister the mib */			unregister_mib(rptr->sr_name, rptr->sr_name_len);			/* find a replacement */			nrptr = smux_find_replacement(rptr->sr_name, rptr->sr_name_len);			if (nrptr) {				/* found one */				smux_replace_active(rptr, nrptr);			} else {				/* no replacement found */				smux_list_detach(&ActiveRegs, &rptr);				free(rptr);			}			smux_send_rrsp(sd, rpriority);			return ptr;		}		/* search the passive list for this registration */		rptr = smux_find_match(PassiveRegs, sd, oid_name, oid_name_len, priority);		if (rptr) {			rpriority = rptr->sr_priority;			smux_list_detach(&PassiveRegs, &rptr);

⌨️ 快捷键说明

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