Beispiel #1
0
/*------------------------------------------------------------------------
 * parseoidlist - read a list of oid's from the input line
 *------------------------------------------------------------------------
 */
LOCAL int
parseoidlist(
    struct req_desc	*rqdp,
    char		**word)
{
	struct	snbentry *bl;
	
	while (**word != NULLCH) {
	        if ((bl = parseoid(word)) == (struct snbentry *) SYSERR) {
		        snfreebl(&rqdp->bindlf);  /* Canberra */
			return SYSERR;
		}
		if (rqdp->bindlf == NULLCH)
			rqdp->bindlf = rqdp->bindle = bl;
		else {
			bl->sb_prev = rqdp->bindle;
			rqdp->bindle = rqdp->bindle->sb_next = bl;
		}
	}
	return OK;
}
Beispiel #2
0
/*------------------------------------------------------------------------
 * snparse - convert the ASN.1-encoded SNMP packet into internal form
 *   N.B. the binding list rqdp->bindlf must either be NULL or a valid
 *        binding list, in which case I'll free it up.
 *------------------------------------------------------------------------
 */
int
snparse(struct req_desc *rqdp, u_char *snmppack, int len)
{
	struct snbentry *bl, *lastbl = 0;
	register u_char *packp;
	int 		totpacklen = 0, commlen = 0;
	int		pdulen, totbindlen = 0;
	u_int		lenlen;
	int		varbindlen = 0;
	u_char 		*packendp;

	packp = snmppack;
	packendp = snmppack + len;

	/* sequence operator and total packet length */
	if (*packp++ != ASN1_SEQ ||
	    (totpacklen = a1readlen(packp, &lenlen)) < 0) {
		return SYSERR;
	}
	packp += lenlen;

	/* verify total length, version, community */
	if (packendp != packp + totpacklen ||
	    *packp++ != ASN1_INT ||
	    *packp++ != SVERS_LEN ||
	    *packp++ != SVERSION ||
	    *packp++ != ASN1_OCTSTR ||
	    (commlen = a1readlen(packp, &lenlen)) < 0) {
		return SYSERR;
	}
	packp += lenlen;
	if (strncmp((char *)packp, SCOMM_STR, commlen) != 0) {
		return SYSERR;
	}
	packp += commlen;

	/* PDU type and length */
	if (*packp == PDU_TRAP)
		return SYSERR;
	rqdp->pdutype_pos = packp - snmppack;
	rqdp->reqtype = *packp++;
	if ((pdulen = a1readlen(packp, &lenlen)) < 0) {
		return SYSERR;
	}
	packp += lenlen;

	/* verify PDU length */
	if (packendp != packp + pdulen) {
		return SYSERR;
	}
	/* request id */
	if (*packp++ != ASN1_INT ||
	    (rqdp->reqidlen = a1readlen(packp, &lenlen)) < 0) {
		return SYSERR;
	}
	packp += lenlen;
	memcpy(rqdp->reqid, packp, rqdp->reqidlen);
	packp += rqdp->reqidlen;

	/* error status */
	if (*packp++ != ASN1_INT || *packp++ != 1) {
		return SYSERR;
	}
	rqdp->err_stat = *packp;
	rqdp->err_stat_pos = packp++ - snmppack;

	/* error index */
	if (*packp++ != ASN1_INT || *packp++ != 1) {
		return SYSERR;
	}
	rqdp->err_idx = *packp;
	rqdp->err_idx_pos = packp++ - snmppack;

	/* sequence of variable bindings */
	if (*packp++ != ASN1_SEQ ||
	    (totbindlen = a1readlen(packp, &lenlen)) < 0) {
		return SYSERR;
	}
	packp += lenlen;

	/* canberra bug fix - rqdp might already have old dynamic memory */
	/* attached, free before overwriting pointers */
	snfreebl(&rqdp->bindlf);

	/* verify variable bindings length */
	if (packendp != packp + totbindlen)
		return SYSERR;
	/* build doubly-linked bindings list; fill in only sb_a1str's	*/
	rqdp->bindlf = rqdp->bindle = (struct snbentry *) NULL;
	do {
		bl = (struct snbentry *) getmem(sizeof(struct snbentry));
		bl->sb_next = 0;
		bl->sb_prev = 0;
		if (rqdp->bindlf) {
			lastbl->sb_next = bl;
			bl->sb_prev = lastbl;
			lastbl = bl;
		} else
			lastbl = rqdp->bindlf = bl;
		bl->sb_a1str = packp;
		bl->sb_a1dynstr = FALSE;  /* not dynamically allocated */
		if (*packp++ != ASN1_SEQ ||
		    (varbindlen = a1readlen(packp, &lenlen)) < 0) {
			return SYSERR;
		}
		packp += lenlen;
		bl->sb_a1slen = varbindlen;
		packp += varbindlen;
	} while (packp < packendp);
	/* check that the entire packet has now been parsed */
	if (packp != packendp) {
		return SYSERR;
	}
	rqdp->bindle = lastbl;
	return OK;
}
Beispiel #3
0
/*------------------------------------------------------------------------
 * snmpd - open the SNMP port and handle incoming queries
 *------------------------------------------------------------------------
 */
int snmpd()
{
	int 		snmpdev, len;
	struct xgram	*query;
	struct req_desc	rqd;
    char    str[128];
    IPaddr  from;
    
	sninit();
	query = (struct xgram *) getmem(sizeof (struct xgram));
	/* open the SNMP server port */
    if ((snmpdev = xinu_open(UDP, ANYFPORT, SNMPPORT)) == SYSERR)
        return SYSERR;
	while (TRUE) {
		/*
		 * In this mode, give read the size of xgram, it returns
		 * number of bytes of *data* in xgram.
		 */
		len = xinu_read(snmpdev, query, sizeof(struct xgram));
        blkcopy(from, query->xg_fip, IP_ALEN);
        xinu_sprintf(str, "\n snmpd: from %u.%u.%u.%u",
			BYTE(from, 0), BYTE(from, 1),
			BYTE(from, 2), BYTE(from, 3));
        xinu_write(SNMPLOG, str, xinu_strlen(str));

        /* parse the packet into the request desc. structure */
		if (snparse(&rqd, query->xg_data, len) == SYSERR) {
            snfreebl(rqd.bindlf);
			continue;
		}
		/* convert ASN.1 representations to internal forms */
		if (sna2b(&rqd) == SYSERR) {
            snfreebl(rqd.bindlf);
			continue;
		}
        if (snrslv(&rqd) == SYSERR) {
            len = mksnmp(&rqd, query->xg_data, PDU_RESP);
             /* above call frees string memory */
            query->xg_data[rqd.pdutype_pos] = PDU_RESP;
			query->xg_data[rqd.err_stat_pos] = rqd.err_stat;
			query->xg_data[rqd.err_idx_pos] = rqd.err_idx;
			if (xinu_write(snmpdev, query, len) == SYSERR)
				return SYSERR;
			snfreebl(rqd.bindlf);
            continue;
		}
		len = mksnmp(&rqd, query->xg_data, PDU_RESP);
		if (len == SYSERR) {
			query->xg_data[rqd.pdutype_pos] = PDU_RESP;
			query->xg_data[rqd.err_stat_pos] = rqd.err_stat;
			query->xg_data[rqd.err_idx_pos] = rqd.err_idx;
			if (xinu_write(snmpdev, query, len) == SYSERR)
				return SYSERR;
			snfreebl(rqd.bindlf);
			continue;	
		}
		if (xinu_write(snmpdev, query, len) == SYSERR) 
			return SYSERR;
		snfreebl(rqd.bindlf);
	}
}
Beispiel #4
0
/*------------------------------------------------------------------------
 * sendquery - parse the input line and send the query.  Input has
 * one of the following forms:
 * 		 [object-name]+
 * 		 next [object-name]+ 
 * 		 set [object-name type value]+
 *------------------------------------------------------------------------
 */
LOCAL int
sendquery(
    int		stdout,
    char	*server)
{
	struct req_desc	rqd;
	struct snbentry	*bl;
	char		*word;
	int 		repl;

	initgetword(buf);
	rqd.reqtype = PDU_GET;		/* by default */
	rqd.bindle = rqd.bindlf = NULLCH;

	getword(&word);
	if (*word == '\0')
		return OK;

	if (strequ(word, "next")) {
		rqd.reqtype = PDU_GETN;
		getword(&word);
		if (parseoidlist(&rqd, &word) == SYSERR) {
			fprintf(stdout, "unknown variable\n");
			return SYSERR;
		}
		if ((bl = rqd.bindlf) == (void *)NULLPTR) {
			if (lastoidset) { /* no oids so use last one */
				rqd.bindlf = rqd.bindle = bl = getnewbl();
				bl->sb_oid.len = lastobjid.len;
				memcpy(bl->sb_oid.id, lastobjid.id,
					lastobjid.len*2);
				SVTYPE(bl) = ASN1_NULL;
			} else {
				fprintf(stdout, "bad syntax\n");
				return SYSERR;
			}
		}
	} else if (strequ(word, "set")) {
		rqd.reqtype = PDU_SET;
		if (parseset(&rqd, stdout) == SYSERR)
			return SYSERR;
	} else if (parseoidlist(&rqd, &word) == SYSERR) {
		fprintf(stdout, "unknown variable\n");
		return SYSERR;
	}
	repl = snclient(&rqd, server, stdout);
	switch (repl) {
	case SCL_OK:
		if (rqd.err_stat == SNMP_OK)
		    snmpprint(stdout, rqd.bindlf);
		else
		    snerr(stdout, &rqd);
		break;
	case SCL_OPENF:
		fprintf(stdout, "snmp: open failed\n");
		break;
	case SCL_WRITEF:
		fprintf(stdout, "snmp: write failed\n");
		break;
	case SCL_NORESP:
		fprintf(stdout, "snmp: No response from server %s\n", server);
		break;
	case SCL_READF:
		fprintf(stdout, "snmp: read failed\n");
		break;
	case SCL_BADRESP:
		fprintf(stdout, "snmp: received bad response\n");
		break;
	}
	
	/* save this object for use with the "next" operation */
	lastobjid.len = rqd.bindlf->sb_oid.len;
	memcpy(lastobjid.id, rqd.bindlf->sb_oid.id,
		rqd.bindlf->sb_oid.len*2);
	lastoidset = TRUE;

	snfreebl(&rqd.bindlf);
	return OK;
}