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

📄 snmp_api.c

📁 -
💻 C
📖 第 1 页 / 共 2 页
字号:
 * of outstanding requests on this session, then send the pdu. * Returns the request id of the generated packet if applicable, otherwise 1. * On any error, 0 is returned. * The pdu is freed by snmp_send() unless a failure occured. */#if 0int snmp_send(struct snmp_session *session, struct snmp_pdu *pdu){    struct session_list *slp;    struct snmp_internal_session *isp = NULL;    u_char packet[PACKET_LENGTH];    int length = PACKET_LENGTH;    struct request_list *rp;    struct timeval tv;    if (Reqid == 0)	init_snmp();    for (slp = Sessions; slp; slp = slp->next) {	if (slp->session == session) {	    isp = slp->internal;	    break;	}    }    if (isp == NULL) {	snmp_errno = SNMPERR_BAD_SESSION;	return 0;    }    if (pdu->command == SNMP_PDU_GET ||	pdu->command == SNMP_PDU_GETNEXT ||	pdu->command == SNMP_PDU_RESPONSE ||	pdu->command == SNMP_PDU_SET) {	if (pdu->reqid == SNMP_DEFAULT_REQID)	    pdu->reqid = ++Reqid;	if (pdu->errstat == SNMP_DEFAULT_ERRSTAT)	    pdu->errstat = 0;	if (pdu->errindex == SNMP_DEFAULT_ERRINDEX)	    pdu->errindex = 0;    } else if (pdu->command == SNMP_PDU_INFORM ||	    pdu->command == SNMP_PDU_GETBULK ||	pdu->command == SNMP_PDU_V2TRAP) {	if (session->Version != SNMP_VERSION_2) {	    snmplib_debug(3, "Cant send SNMPv2 PDU's in SNMP message.\n");	    snmp_errno = SNMPERR_GENERR;	/* Fix this XXXXX */	    return 0;	}	if (pdu->reqid == SNMP_DEFAULT_REQID)	    pdu->reqid = ++Reqid;	if (pdu->errstat == SNMP_DEFAULT_ERRSTAT)	    pdu->errstat = 0;	if (pdu->errindex == SNMP_DEFAULT_ERRINDEX)	    pdu->errindex = 0;    } else {	/* fill in trap defaults */	pdu->reqid = 1;		/* give a bogus non-error reqid for traps */	if (pdu->enterprise_length == SNMP_DEFAULT_ENTERPRISE_LENGTH) {	    pdu->enterprise = (oid *) xmalloc(sizeof(DEFAULT_ENTERPRISE));	    xmemcpy((char *) pdu->enterprise, (char *) DEFAULT_ENTERPRISE,		sizeof(DEFAULT_ENTERPRISE));	    pdu->enterprise_length = sizeof(DEFAULT_ENTERPRISE) / sizeof(oid);	}	if (pdu->time == SNMP_DEFAULT_TIME)	    pdu->time = DEFAULT_TIME;    }    if (pdu->address.sin_addr.s_addr == SNMP_DEFAULT_ADDRESS) {	if (isp->addr.sin_addr.s_addr != SNMP_DEFAULT_ADDRESS) {	    xmemcpy((char *) &pdu->address, (char *) &isp->addr,		sizeof(pdu->address));	} else {	    snmplib_debug(3, "No remote IP address specified\n");	    snmp_errno = SNMPERR_BAD_ADDRESS;	    return 0;	}    }    if (snmp_build(session, pdu, packet, &length) < 0) {	snmplib_debug(3, "Error building packet\n");	snmp_errno = SNMPERR_GENERR;	return 0;    }    snmp_dump(packet, length, "sending", pdu->address.sin_addr);    gettimeofday(&tv, (struct timezone *) 0);    if (sendto(isp->sd, (char *) packet, length, 0,	    (struct sockaddr *) &pdu->address, sizeof(pdu->address)) < 0) {	perror("sendto");	snmp_errno = SNMPERR_GENERR;	return 0;    }    snmplib_debug(6, "LIBSNMP:  Sent PDU %s, Reqid %d\n",	snmp_pdu_type(pdu), pdu->reqid);    if (pdu->command == SNMP_PDU_GET ||	pdu->command == SNMP_PDU_GETNEXT ||	pdu->command == SNMP_PDU_SET ||	pdu->command == SNMP_PDU_GETBULK ||	pdu->command == SNMP_PDU_INFORM) {	snmplib_debug(6, "LIBSNMP:  Setting up to recieve a response for reqid %d\n",	    pdu->reqid);	/* set up to expect a response */	rp = (struct request_list *) xmalloc(sizeof(struct request_list));	rp->next_request = isp->requests;	isp->requests = rp;	rp->pdu = pdu;	rp->request_id = pdu->reqid;	rp->retries = 1;	rp->timeout = session->timeout;	rp->time = tv;	tv.tv_usec += rp->timeout;	tv.tv_sec += tv.tv_usec / 1000000L;	tv.tv_usec %= 1000000L;	rp->expire = tv;    }    return (pdu->reqid);}/* * Checks to see if any of the fd's set in the fdset belong to * snmp.  Each socket with it's fd set has a packet read from it * and snmp_parse is called on the packet received.  The resulting pdu * is passed to the callback routine for that session.  If the callback * routine returns successfully, the pdu and it's request are deleted. */voidsnmp_read(fdset)     fd_set *fdset;{    struct session_list *slp;    struct snmp_session *sp;    struct snmp_internal_session *isp;    u_char packet[PACKET_LENGTH];    struct sockaddr_in from;    int length, fromlength;    struct snmp_pdu *pdu;    struct request_list *rp, *orp;    u_char *bufp;    for (slp = Sessions; slp; slp = slp->next) {	if (FD_ISSET(slp->internal->sd, fdset)) {	    sp = slp->session;	    isp = slp->internal;	    fromlength = sizeof from;	    length = recvfrom(isp->sd, (char *) packet,		PACKET_LENGTH, 0, (struct sockaddr *) &from,		&fromlength);	    if (length == -1)		perror("recvfrom");	    snmp_dump(packet, length, "received", from.sin_addr);	    pdu = snmp_pdu_create(0);	    pdu->address = from;	    pdu->reqid = 0;	    /* Parse the incoming packet */	    bufp = snmp_parse(sp, pdu, packet, length);	    if (bufp == NULL) {		snmplib_debug(3, "Mangled packet\n");		snmp_free_pdu(pdu);		return;	    }	    if (sp->community)		xfree(sp->community);	    sp->community = bufp;	    sp->community_len = strlen((char *) bufp);	    snmplib_debug(6, "LIBSNMP:  Read PDU %s, ReqId %d\n", snmp_pdu_type(pdu), pdu->reqid);	    if (pdu->command == SNMP_PDU_RESPONSE) {		for (rp = isp->requests; rp; rp = rp->next_request) {		    if (rp->request_id == pdu->reqid) {			snmplib_debug(6, "LIBSNMP:  ReqId %d:  Calling callback\n", pdu->reqid);			if (sp->callback(RECEIVED_MESSAGE, sp,				pdu->reqid, pdu,				sp->callback_magic) == 1) {			    /* successful, so delete request */			    snmplib_debug(6, "LIBSNMP:  ReqId %d:  Success.  Removing ReqId.\n", pdu->reqid);			    orp = rp;			    if (isp->requests == orp) {				/* first in list */				isp->requests = orp->next_request;			    } else {				for (rp = isp->requests; rp; rp = rp->next_request) {				    if (rp->next_request == orp) {					/* link around it */					rp->next_request = orp->next_request;					break;				    }				}			    }			    snmp_free_pdu(orp->pdu);			    xfree((char *) orp);			    /* there shouldn't be another req with the same reqid */			    break;			}		    }		}	    } else if (pdu->command == SNMP_PDU_GET ||		    pdu->command == SNMP_PDU_GETNEXT ||		    pdu->command == TRP_REQ_MSG ||		    pdu->command == SNMP_PDU_SET ||		    pdu->command == SNMP_PDU_GETBULK ||		    pdu->command == SNMP_PDU_INFORM ||		pdu->command == SNMP_PDU_V2TRAP) {		sp->callback(RECEIVED_MESSAGE, sp, pdu->reqid,		    pdu, sp->callback_magic);	    }	    snmp_free_pdu(pdu);	}    }}/* * Returns info about what snmp requires from a select statement. * numfds is the number of fds in the list that are significant. * All file descriptors opened for SNMP are OR'd into the fdset. * If activity occurs on any of these file descriptors, snmp_read * should be called with that file descriptor set * * The timeout is the latest time that SNMP can wait for a timeout.  The * select should be done with the minimum time between timeout and any other * timeouts necessary.  This should be checked upon each invocation of select. * If a timeout is received, snmp_timeout should be called to check if the * timeout was for SNMP.  (snmp_timeout is idempotent) * * Block is 1 if the select is requested to block indefinitely, rather than time out. * If block is input as 1, the timeout value will be treated as undefined, but it must * be available for setting in snmp_select_info.  On return, if block is true, the value * of timeout will be undefined. * * snmp_select_info returns the number of open sockets.  (i.e. The number of sessions open) */intsnmp_select_info(numfds, fdset, timeout, block)     int *numfds;     fd_set *fdset;     struct timeval *timeout;     int *block;		/* should the select block until input arrives (i.e. no input) */{    struct session_list *slp;    struct snmp_internal_session *isp;    struct request_list *rp;    struct timeval now, earliest;    int active = 0, requests = 0;    timerclear(&earliest);    /*     * For each request outstanding, add it's socket to the fdset,     * and if it is the earliest timeout to expire, mark it as lowest.     */    for (slp = Sessions; slp; slp = slp->next) {	active++;	isp = slp->internal;	if ((isp->sd + 1) > *numfds)	    *numfds = (isp->sd + 1);	FD_SET(isp->sd, fdset);	snmplib_debug(6, "LIBSNMP:  select():  Adding port %d\n", isp->sd);	if (isp->requests) {	    /* found another session with outstanding requests */	    requests++;	    for (rp = isp->requests; rp; rp = rp->next_request) {		if (!timerisset(&earliest) ||		    timercmp(&rp->expire, &earliest, <))		    earliest = rp->expire;	    }	}    }    snmplib_debug(6, "LIBSNMP:  Select Info:  %d active, %d requests pending.\n",	active, requests);    if (requests == 0)		/* if none are active, skip arithmetic */	return active;    /*     * Now find out how much time until the earliest timeout.  This     * transforms earliest from an absolute time into a delta time, the     * time left until the select should timeout.     */    gettimeofday(&now, (struct timezone *) 0);    earliest.tv_sec--;		/* adjust time to make arithmetic easier */    earliest.tv_usec += 1000000L;    earliest.tv_sec -= now.tv_sec;    earliest.tv_usec -= now.tv_usec;    while (earliest.tv_usec >= 1000000L) {	earliest.tv_usec -= 1000000L;	earliest.tv_sec += 1;    }    if (earliest.tv_sec < 0) {	earliest.tv_sec = 0;	earliest.tv_usec = 0;    }    /* if it was blocking before or our delta time is less, reset timeout */    if (*block == 1 || timercmp(&earliest, timeout, <)) {	*timeout = earliest;	*block = 0;    }    return active;}/* * snmp_timeout should be called whenever the timeout from snmp_select_info  * expires, but it is idempotent, so snmp_timeout can be polled (probably a  * cpu expensive proposition).  snmp_timeout checks to see if any of the  * sessions have an outstanding request that has timed out.  If it finds one  * (or more), and that pdu has more retries available, a new packet is formed * from the pdu and is resent.  If there are no more retries available, the  * callback for the session is used to alert the user of the timeout. */void snmp_timeout(void){    struct session_list *slp;    struct snmp_session *sp;    struct snmp_internal_session *isp;    struct request_list *rp, *orp, *freeme = NULL;    struct timeval now;    gettimeofday(&now, (struct timezone *) 0);    /*     * For each request outstanding, check to see if it has expired.     */    for (slp = Sessions; slp; slp = slp->next) {	sp = slp->session;	isp = slp->internal;	orp = NULL;	snmplib_debug(6, "LIBSNMP:  Checking session %s\n",	    (sp->peername != NULL) ? sp->peername : "<NULL>");	for (rp = isp->requests; rp; rp = rp->next_request) {	    snmplib_debug(6, "LIBSNMP:  Checking session request %d, expire at %u, Retry %d/%d\n",		rp->request_id, rp->expire.tv_sec, rp->retries, sp->retries);	    if (freeme != NULL) {		/* frees rp's after the for loop goes on to the next_request */		xfree((char *) freeme);		freeme = NULL;	    }	    if (timercmp(&rp->expire, &now, <)) {		snmplib_debug(6, "LIBSNMP:  Expired.\n");		/* this timer has expired */		if (rp->retries >= sp->retries) {		    /* No more chances, delete this entry */		    sp->callback(TIMED_OUT, sp, rp->pdu->reqid,			rp->pdu, sp->callback_magic);		    if (orp == NULL) {			isp->requests = rp->next_request;		    } else {			orp->next_request = rp->next_request;		    }		    snmp_free_pdu(rp->pdu);		    freeme = rp;		    continue;	/* don't update orp below */		} else {		    u_char packet[PACKET_LENGTH];		    int length = PACKET_LENGTH;		    struct timeval tv;		    snmplib_debug(6, "LIBSNMP:  Retransmitting.\n");		    /* retransmit this pdu */		    rp->retries++;		    rp->timeout <<= 1;		    if (snmp_build(sp, rp->pdu, packet, &length) < 0) {			snmplib_debug(3, "Error building packet\n");		    }		    snmp_dump(packet, length,			"sending", rp->pdu->address.sin_addr);		    gettimeofday(&tv, (struct timezone *) 0);		    if (sendto(isp->sd, (char *) packet, length, 0, (struct sockaddr *) &rp->pdu->address, sizeof(rp->pdu->address)) < 0) {			perror("sendto");		    }		    rp->time = tv;		    tv.tv_usec += rp->timeout;		    tv.tv_sec += tv.tv_usec / 1000000L;		    tv.tv_usec %= 1000000L;		    rp->expire = tv;		}	    }	    orp = rp;	}	if (freeme != NULL) {	    xfree((char *) freeme);	    freeme = NULL;	}    }}/* Print some API stats */void snmp_api_stats(void *outP){    struct session_list *slp;    struct request_list *rp;    struct snmp_internal_session *isp;    FILE *out = (FILE *) outP;    int active = 0;    int requests = 0;    int count = 0;    int rcount = 0;    fprintf(out, "LIBSNMP: Session List Dump\n");    fprintf(out, "LIBSNMP: ----------------------------------------\n");    for (slp = Sessions; slp; slp = slp->next) {	isp = slp->internal;	active++;	count++;	fprintf(out, "LIBSNMP: %2d: Host %s\n", count,	    (slp->session->peername == NULL) ? "NULL" : slp->session->peername);	if (isp->requests) {	    /* found another session with outstanding requests */	    requests++;	    rcount = 0;	    for (rp = isp->requests; rp; rp = rp->next_request) {		rcount++;		{		    struct hostent *hp;		    hp = gethostbyaddr((char *) &(rp->pdu->address),			sizeof(u_int), AF_INET);		    fprintf(out, "LIBSNMP: %2d: ReqId %d (%s) (%s)\n",			rcount, rp->request_id, snmp_pdu_type(rp->pdu),			(hp == NULL) ? "NULL" : hp->h_name);		}	    }	}	fprintf(out, "LIBSNMP: ----------------------------------------\n");    }    fprintf(out, "LIBSNMP: Session List: %d active, %d have requests pending.\n",	active, requests);}#endif

⌨️ 快捷键说明

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