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

📄 smux.c

📁 Snmp(简单网管协议)软件包。
💻 C
📖 第 1 页 / 共 4 页
字号:
			free(rptr);			smux_send_rrsp(sd, rpriority);			return ptr;		}		/* This peer cannot unregister the tree, it does not		 * belong to him.  Send him an error.		 */		smux_send_rrsp(sd, -1);		return ptr;	} else if ((operation == SMUX_REGOP_REGISTER_RO) ||	    (operation == SMUX_REGOP_REGISTER_RW)) {		if (priority < -1) {			DEBUGMSGTL (("smux","[smux_rreq_process] peer fd %d invalid priority", sd, priority));			smux_send_rrsp(sd, -1);			return NULL;		}		if((nrptr = malloc(sizeof(smux_reg))) == NULL) {                        snmp_log_perror("[smux_rreq_process] malloc");			smux_send_rrsp(sd, -1);			return NULL;		}		nrptr->sr_priority = priority;		nrptr->sr_name_len = oid_name_len;		nrptr->sr_fd = sd;		for(i = 0; i < (int)oid_name_len; i++)			nrptr->sr_name[i] = oid_name[i];		/* See if this tree matches or scopes any of the		 * active trees.		 */		for (rptr = ActiveRegs; rptr; rptr = rptr->sr_next) {			result = snmp_oid_compare(oid_name, oid_name_len, rptr->sr_name,			    rptr->sr_name_len);			if (result == 0) {				if ((oid_name_len == rptr->sr_name_len)) {					if ((nrptr->sr_priority == -1)) {						nrptr->sr_priority = rptr->sr_priority;						do {							nrptr->sr_priority++;						} while(smux_list_add(&PassiveRegs, nrptr));						goto done;					}					else if (nrptr->sr_priority < rptr->sr_priority) {						/* Better priority.  There are no better						 * priorities for this tree in the passive list,						 * so replace the current active tree.						 */						smux_replace_active(rptr, nrptr);						goto done;					} else {						/* Equal or worse priority */						do {							nrptr->sr_priority++;						} while (smux_list_add(&PassiveRegs, nrptr) == -1);						goto done;					}				} else if (oid_name_len < rptr->sr_name_len) {					/* This tree scopes a current active					 * tree.  Replace the current active tree.					 */					smux_replace_active(rptr, nrptr);					goto done;				} else { /* oid_name_len > rptr->sr_name_len */					/* This tree is scoped by a current					 * active tree.  					 */					do {						nrptr->sr_priority++;					} while (smux_list_add(&PassiveRegs, nrptr) == -1);					goto done;				}			}		}		/* We didn't find it in the active list.  Add it at		 * the requested priority.		 */		if (nrptr->sr_priority == -1)			nrptr->sr_priority = 0;		smux_list_add(&ActiveRegs, nrptr);		register_mib("smux", (struct variable *)		    smux_variables, sizeof(struct variable2),		    1, nrptr->sr_name, nrptr->sr_name_len);done:		smux_send_rrsp(sd, nrptr->sr_priority);		return ptr;	} else {		DEBUGMSGTL (("smux","[smux_rreq_process] unknown operation\n"));		smux_send_rrsp(sd, -1);		return NULL;	}}/* * Find the registration with a matching descriptor, OID and priority.  If * the priority is -1 then find a registration with a matching descriptor, * a matching OID, and the highest priority. */static smux_reg *smux_find_match(smux_reg *regs, int sd, oid *oid_name, size_t oid_name_len, long priority){	smux_reg *rptr, *bestrptr;	bestrptr = NULL;	for (rptr = regs; rptr; rptr = rptr->sr_next) {		if (rptr->sr_fd != sd)			continue;		if (snmp_oid_compare(rptr->sr_name, rptr->sr_name_len, oid_name, oid_name_len))			continue;		if (rptr->sr_priority == priority)			return rptr;		if (priority != -1)			continue;		if (bestrptr) {			if (bestrptr->sr_priority > rptr->sr_priority)				bestrptr = rptr;		} else {			bestrptr = rptr;		}	}	return bestrptr;}static voidsmux_replace_active(smux_reg *actptr, smux_reg *pasptr){	smux_list_detach(&ActiveRegs, &actptr);	unregister_mib(actptr->sr_name, actptr->sr_name_len);	smux_list_detach(&PassiveRegs, &pasptr);	(void)smux_list_add(&ActiveRegs, pasptr);	register_mib("smux", (struct variable *)smux_variables,	    sizeof(struct variable2), 1, pasptr->sr_name,	    pasptr->sr_name_len);	free(actptr);}static voidsmux_list_detach(smux_reg **head, smux_reg **m_remove){	smux_reg *rptr, *rptr2;	if (*head == NULL) {		DEBUGMSGTL (("smux","[smux_list_detach] Ouch!"));		return;	}	if (*head == *m_remove) {		*m_remove = *head;		*head = (*head)->sr_next;		return;	}	for (rptr = *head, rptr2 = rptr->sr_next; rptr2;	    rptr2 = rptr2->sr_next, rptr = rptr->sr_next) {		if(rptr2 == *m_remove) {			*m_remove = rptr2;			rptr->sr_next = rptr2->sr_next;			return;		}	}}/* * Attempt to add a registration (in order) to a list.  If the * add fails (because of an existing registration with equal * priority) return -1. */static intsmux_list_add(smux_reg **head, smux_reg *add){	smux_reg *rptr;	int result;	if(*head == NULL) {		*head = add;		(*head)->sr_next = NULL;		return 0;	}	for (rptr = *head; rptr->sr_next; rptr = rptr->sr_next) {		result = snmp_oid_compare(add->sr_name, add->sr_name_len,		    rptr->sr_name, rptr->sr_name_len);		if ((result == 0) && (add->sr_priority == rptr->sr_priority)) {			/* same tree, same pri, nope */			return -1;		} else if (result < 0) {			/* this can only happen if we go before the head */			add->sr_next = *head;			*head = add;			return 0;		} else if ((snmp_oid_compare(add->sr_name, add->sr_name_len,		    rptr->sr_next->sr_name, rptr->sr_next->sr_name_len)) < 0) {			/* insert here */			add->sr_next = rptr->sr_next;			rptr->sr_next = add;			return 0;		}	}	/* compare the last one */	if ((snmp_oid_compare(add->sr_name, add->sr_name_len, rptr->sr_name,	    rptr->sr_name_len) == 0) && add->sr_priority == rptr->sr_priority)		return -1;	else {		rptr->sr_next = add;		add->sr_next = NULL;	}	return 0;}/* * Find a replacement for this registration.  In order * of preference: * * 	- Least difference in subtree length *	- Best (lowest) priority * * For example, if we need to replace .1.3.6.1.69,  * we would pick .1.3.6.1.69.1 instead of .1.3.6.69.1.1 * */static smux_reg *smux_find_replacement(oid *name, size_t name_len){	smux_reg *rptr, *bestptr;	int bestlen, difflen;	bestlen = SMUX_MAX_PRIORITY;	bestptr = NULL;	for (rptr = PassiveRegs; rptr; rptr = rptr->sr_next) {		if (!compare_tree(rptr->sr_name, rptr->sr_name_len,		    name, name_len)) {			if ((difflen = rptr->sr_name_len - name_len)			    < bestlen) {				bestlen = difflen;				bestptr = rptr;			} else if ((difflen == bestlen) &&			    (rptr->sr_priority < bestptr->sr_priority)) 				bestptr = rptr;		}	}	return bestptr;}u_char *smux_snmp_process(int exact,	oid *objid,	size_t *len,	size_t *return_len,	u_char *return_type,	int sd){	u_char packet[SMUXMAXPKTSIZE], *ptr, result[SMUXMAXPKTSIZE];	size_t length = SMUXMAXPKTSIZE;	u_char type;        size_t packet_len; 		/* 	 * Send the query to the peer	 */	smux_reqid++;	if (exact)		type = SMUX_GET;	else		type = SMUX_GETNEXT;	if (smux_build(type, smux_reqid, objid, len, 0, NULL, 	    *len, packet, &length) < 0) {	 snmp_log(LOG_ERR, "[smux_snmp_process]: smux_build failed\n");		return NULL;	}    DEBUGMSGTL(("smux", "[smux_snmp_process] oid from build: "));    DEBUGMSGOID(("smux", objid, *len));    DEBUGMSG(("smux","\n"));	if (send(sd, (char *)packet, length, 0) < 0) {		snmp_log_perror("[smux_snmp_process] send failed");	}	DEBUGMSGTL(("smux",                    "[smux_snmp_process] Sent %d request to peer; %d bytes\n",                     (int)type, length));        while (1) {             /*              * peek at what's received              */             length = recv(sd, (char *)result, SMUXMAXPKTSIZE, MSG_PEEK);             if (length < 0) {                 snmp_log_perror("[smux_snmp_process] peek failed");                 smux_peer_cleanup(sd);                 return NULL;             }             DEBUGMSGTL (("smux","[smux_snmp_process] Peeked at %d bytes\n",                         length));             DEBUGDUMPSETUP("smux_snmp_process", result, length);             /*              * determine if we received more than one packet              */             packet_len = length;             ptr = asn_parse_header(result, &packet_len, &type);             packet_len += (ptr - result);             if (length > packet_len) {                 /* set length to receive only the first packet */                length = packet_len;             }             /*              * receive the first packet              */            length = recv(sd, (char *)result, length, 0);             if (length < 0) {                 snmp_log_perror("[smux_snmp_process] recv failed");                 smux_peer_cleanup(sd);                 return NULL;             }             DEBUGMSGTL (("smux","[smux_snmp_process] Received %d bytes\n", length));             if (result[0] == SMUX_TRAP) {                 DEBUGMSGTL (("smux","[smux_snmp_process] Received trap\n"));                 snmp_log(LOG_INFO, "Got trap from peer on fd %d\n", sd);                 ptr = asn_parse_header(result, &length, &type);                 smux_trap_process(ptr, &length);                 /* go and peek at received data again */                /* we could receive the reply or another trap */            } else {                 /* Interpret reply */                 ptr = smux_parse(result, objid, len, return_len, return_type);                 /* ptr will point to query result or NULL if error */                 break;             }         } /* while (1) */	return ptr;}static u_char *smux_parse(u_char *rsp,	oid *objid,	size_t *oidlen,	size_t *return_len,	u_char *return_type){	size_t length = SMUXMAXPKTSIZE; 	u_char *ptr, type;	long reqid, errstat, errindex;	ptr = rsp;	/*	 * Return pointer to the snmp/smux return value.	 * return_len should contain the number of bytes in the value	 * returned above.	 * objid is the next object, with len for GETNEXT.	 * objid and len are not changed for GET	 */ 	ptr = asn_parse_header(ptr, &length, &type);	if (ptr == NULL || type != SNMP_MSG_RESPONSE)		return NULL;	if ((ptr = asn_parse_int(ptr, &length, &type, &reqid,	    sizeof(reqid))) == NULL) {		DEBUGMSGTL (("smux","[smux_parse] parse of reqid failed\n"));		return NULL;	}	if ((ptr = asn_parse_int(ptr, &length, &type, &errstat,	    sizeof(errstat))) == NULL) {		DEBUGMSGTL (("smux","[smux_parse] parse of error status failed\n"));		return NULL;	}	if ((ptr = asn_parse_int(ptr, &length, &type, &errindex,	    sizeof(errindex))) == NULL) {		DEBUGMSGTL (("smux","[smux_parse] parse of error index failed\n"));		return NULL;	}	/* XXX How to send something intelligent back in case of an error */	DEBUGMSGTL (("smux","[smux_parse] Message type %d, reqid %d, errstat %d, \n\terrindex %d\n", (int)type, reqid, errstat, errindex));	if (ptr == NULL || errstat != SNMP_ERR_NOERROR)		return NULL;	/* stuff to return */	return (smux_parse_var(ptr, &length, objid, oidlen, return_len, return_type));}static u_char *smux_parse_var(u_char *varbind,	size_t *varbindlength,	oid *objid,	size_t *oidlen,	size_t *varlength,	u_char *vartype){	oid var_name[MAX_OID_LEN];	size_t var_name_len;	size_t var_val_len;	u_char *var_val;	size_t str_len, objid_len;	size_t len;	u_char *ptr;	u_char type;        	ptr = varbind;	len = *varbindlength;    DEBUGMSGTL(("smux", "[smux_parse_var] before any processing: "));    DEBUGMSGOID(("smux", objid, *oidlen));    DEBUGMSG(("smux","\n"));	ptr = asn_parse_header(ptr, &len, &type);	if (ptr == NULL || type != (ASN_SEQUENCE | ASN_CONSTRUCTOR)) {	 snmp_log(LOG_NOTICE, "[smux_parse_var] Panic: type %d\n", (int)type);		return NULL;	}	/* get hold of the objid and the asn1 coded value */	var_name_len = MAX_OID_LEN;	ptr = snmp_parse_var_op(ptr, var_name, &var_name_len, vartype,				&var_val_len, &var_val, &len);

⌨️ 快捷键说明

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