int smux_trap (oid *name, size_t namelen, oid *iname, size_t inamelen, struct trap_object *trapobj, size_t trapobjlen, unsigned int tick, u_char sptrap) { unsigned int i; u_char buf[BUFSIZ]; u_char *ptr; size_t len, length; struct in_addr addr; unsigned long val; u_char *h1, *h1e; ptr = buf; len = BUFSIZ; length = len; /* When SMUX connection is not established. */ if (smux_sock < 0) return 0; /* SMUX header. */ ptr = asn_build_header (ptr, &len, (u_char) SMUX_TRAP, 0); /* Sub agent enterprise oid. */ ptr = asn_build_objid (ptr, &len, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), smux_oid, smux_oid_len); /* IP address. */ addr.s_addr = 0; ptr = asn_build_string (ptr, &len, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_IPADDRESS), (u_char *)&addr, sizeof (addr)); /* Generic trap integer. */ val = SNMP_TRAP_ENTERPRISESPECIFIC; ptr = asn_build_int (ptr, &len, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), &val, sizeof (val)); /* Specific trap integer. */ val = sptrap; ptr = asn_build_int (ptr, &len, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), &val, sizeof (val)); /* Timeticks timestamp. */ val = 0; ptr = asn_build_unsigned_int (ptr, &len, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_TIMETICKS), &val, sizeof (val)); /* Variables. */ h1 = ptr; ptr = asn_build_sequence (ptr, &len, (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), 0); /* Iteration for each objects. */ h1e = ptr; for (i = 0; i < trapobjlen; i++) { int ret; oid oid[MAX_OID_LEN]; size_t oid_len; void *val; size_t val_len; u_char val_type; /* Make OID. */ if (trapobj[i].namelen > 0) { oid_copy (oid, name, namelen); oid_copy (oid + namelen, trapobj[i].name, trapobj[i].namelen); oid_copy (oid + namelen + trapobj[i].namelen, iname, inamelen); oid_len = namelen + trapobj[i].namelen + inamelen; } else { oid_copy (oid, name, namelen); oid_copy (oid + namelen, trapobj[i].name, trapobj[i].namelen * (-1)); oid_len = namelen + trapobj[i].namelen * (-1) ; } if (debug_smux) { smux_oid_dump ("Trap", name, namelen); if (trapobj[i].namelen < 0) smux_oid_dump ("Trap", trapobj[i].name, (- 1) * (trapobj[i].namelen)); else { smux_oid_dump ("Trap", trapobj[i].name, (trapobj[i].namelen)); smux_oid_dump ("Trap", iname, inamelen); } smux_oid_dump ("Trap", oid, oid_len); zlog_info ("BUFSIZ: %d // oid_len: %d", BUFSIZ, oid_len); } ret = smux_get (oid, &oid_len, 1, &val_type, &val, &val_len); if (debug_smux) zlog_debug ("smux_get result %d", ret); if (ret == 0) ptr = snmp_build_var_op (ptr, oid, &oid_len, val_type, val_len, val, &len); } /* Now variable size is known, fill in size */ asn_build_sequence(h1, &length, (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), ptr - h1e); /* Fill in size of whole sequence */ len = BUFSIZ; asn_build_header (buf, &len, (u_char) SMUX_TRAP, (ptr - buf) - 2); return send (smux_sock, buf, (ptr - buf), 0); }
void smux_getresp_send (oid objid[], size_t objid_len, long reqid, long errstat, long errindex, u_char val_type, void *arg, size_t arg_len) { int ret; u_char buf[BUFSIZ]; u_char *ptr, *h1, *h1e, *h2, *h2e; size_t len, length; ptr = buf; len = BUFSIZ; length = len; if (debug_smux) { zlog_debug ("SMUX GETRSP send"); zlog_debug ("SMUX GETRSP reqid: %ld", reqid); } h1 = ptr; /* Place holder h1 for complete sequence */ ptr = asn_build_sequence (ptr, &len, (u_char) SMUX_GETRSP, 0); h1e = ptr; ptr = asn_build_int (ptr, &len, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), &reqid, sizeof (reqid)); if (debug_smux) zlog_debug ("SMUX GETRSP errstat: %ld", errstat); ptr = asn_build_int (ptr, &len, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), &errstat, sizeof (errstat)); if (debug_smux) zlog_debug ("SMUX GETRSP errindex: %ld", errindex); ptr = asn_build_int (ptr, &len, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), &errindex, sizeof (errindex)); h2 = ptr; /* Place holder h2 for one variable */ ptr = asn_build_sequence (ptr, &len, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), 0); h2e = ptr; ptr = snmp_build_var_op (ptr, objid, &objid_len, val_type, arg_len, arg, &len); /* Now variable size is known, fill in size */ asn_build_sequence(h2,&length,(u_char)(ASN_SEQUENCE|ASN_CONSTRUCTOR),ptr-h2e); /* Fill in size of whole sequence */ asn_build_sequence(h1,&length,(u_char)SMUX_GETRSP,ptr-h1e); if (debug_smux) zlog_debug ("SMUX getresp send: %ld", (ptr - buf)); ret = send (smux_sock, buf, (ptr - buf), 0); }
//* //* Parse_var_op_list goes through the list of variables and retrieves each one, //* placing it's value in the output packet. In the case of a set request, //* if action is RESERVE, the value is just checked for correct type and //* value, and resources may need to be reserved. If the action is COMMIT, //* the variable is set. If the action is FREE, an error was discovered //* somewhere in the previous RESERVE pass, so any reserved resources //* should be FREE'd. //* If any error occurs, an error code is returned. //* int parse_var_op_list( snmp_session *session, uint8 *data, //point to variable-binding of in-packet data int length, //in packet data length uint8 *out_data, //point to variable-binding of out-packet data int out_length, //out packet buffer length long *index, //error-index (output) int msgtype, //message type int action //??? ) { uint8 type; oid var_name[SNMP_MAX_NAME_LEN]; int var_name_len, var_val_len; uint8 var_val_type, *var_val, statType; uint8 *statP; int statLen; uint16 acl; int (*write_method)(); uint8 *headerP, *var_list_start; int dummyLen; #ifdef WEBADMIN int dummyLen1; // add -- By arius 5/17/2000 uint8 *newpacket_end; // add -- By arius 5/17/2000 #endif WEBADMIN int noSuchObject; int (*WriteMethod)(int,uint8 *,uint8,int,uint8 *,oid *,int); int err, exact; // if (msgtype== SET_REQ_MSG) rw = SNMP_WRITE; // else rw = SNMP_READ; if (msgtype == GETNEXT_REQ_MSG) exact = FALSE; else exact = TRUE; //Parse variable-binging header data = asn_parse_header(data, &length, &type); if (data == NULL){ ERROR("not enough space for varlist"); return PARSE_ERROR; } if (type != (uint8)(ASN_SEQUENCE | ASN_CONSTRUCTOR)){ ERROR("wrong type"); return PARSE_ERROR; } headerP = out_data; //Set Resp variable-binging header out_data = asn_build_sequence(out_data, &out_length, (uint8)(ASN_SEQUENCE | ASN_CONSTRUCTOR), 0); if (out_data == NULL){ ERROR("not enough space in output packet"); return BUILD_ERROR; } var_list_start = out_data; *index = 1; while((int)length > 0){ // parse the name, value pair var_name_len = SNMP_MAX_NAME_LEN; data = snmp_parse_var_op(data, var_name, &var_name_len, &var_val_type, &var_val_len, &var_val, (int *)&length); if (data == NULL) return PARSE_ERROR; // now attempt to retrieve the variable on the local entity statP = getStatPtr(var_name, &var_name_len, &statType, &statLen, &acl, exact, &write_method, SNMP_VERSION_1, &noSuchObject, (msgtype==SET_REQ_MSG? (session->access & SNMP_ACCESS_WRITE): (session->access & SNMP_ACCESS_READ) ) ); if (/* session->version == SNMP_VERSION_1 &&*/ statP == NULL && (msgtype != SET_REQ_MSG || !write_method)) { //** XXX: happens when running // XXX: snmpwalk localhost public .1 // XXX: fix me some day. //** //** ERROR("warning: internal v1_error"); ** return SNMP_ERR_NOSUCHNAME; } // check if this variable is read-write (in the MIB sense). if( msgtype == SET_REQ_MSG && acl != RWRITE ) return SNMP_ERR_READONLY; // return session->version == SNMP_VERSION_1 ? SNMP_ERR_NOSUCHNAME : SNMP_ERR_NOTWRITABLE; //* Its bogus to check here on getnexts - the whole packet shouldn't // be dumped - this should should be the loop in getStatPtr // luckily no objects are set unreadable. This can still be // useful for sets to determine which are intrinsically writable if (msgtype== SET_REQ_MSG){ if (write_method == NULL){ if (statP != NULL){ // see if the type and value is consistent with this entity's variable if (!goodValue(var_val_type, var_val_len, statType,statLen)) { // if (session->version != SNMP_VERSION_1) // return SNMP_ERR_WRONGTYPE; // poor approximation // else { snmp_inbadvalues++; return SNMP_ERR_BADVALUE; } } // actually do the set if necessary if (action == COMMIT) setVariable(var_val, var_val_type, var_val_len,statP, statLen); } else { // if (session->version != SNMP_VERSION_1) // return SNMP_ERR_NOCREATION; // else return SNMP_ERR_NOSUCHNAME; } } else { WriteMethod = (int (*)(int,uint8 *,uint8,int,uint8 *,oid *,int)) write_method; err = (*WriteMethod)(action, var_val, var_val_type, var_val_len, statP, var_name, var_name_len); //* //* Map the SNMPv2 error codes to SNMPv1 error codes (RFC 2089). //* // if (session->version == SNMP_VERSION_1) { switch (err) { case SNMP_ERR_NOERROR: // keep the no-error error: break; case SNMP_ERR_WRONGVALUE: case SNMP_ERR_WRONGENCODING: case SNMP_ERR_WRONGTYPE: case SNMP_ERR_WRONGLENGTH: case SNMP_ERR_INCONSISTENTVALUE: err = SNMP_ERR_BADVALUE; break; case SNMP_ERR_NOACCESS: case SNMP_ERR_NOTWRITABLE: case SNMP_ERR_NOCREATION: case SNMP_ERR_INCONSISTENTNAME: case SNMP_ERR_AUTHORIZATIONERROR: err = SNMP_ERR_NOSUCHNAME; break; default: err = SNMP_ERR_GENERR; break; // } }//if(session->version == SNMP_VERSION_1) .... if (err != SNMP_ERR_NOERROR){ // if (session->version == SNMP_VERSION_1) { snmp_inbadvalues++; // } return err; } } } else { //* retrieve the value of the variable and place it into the //* outgoing packet if (statP == NULL){ statLen = 0; if (exact){ if (noSuchObject == TRUE){ statType = SNMP_NOSUCHOBJECT; } else { statType = SNMP_NOSUCHINSTANCE; } } else { statType = SNMP_ENDOFMIBVIEW; } } //if (statP == NULL) ... out_data = snmp_build_var_op(out_data, var_name, &var_name_len, statType, statLen, statP, &out_length); if (out_data == NULL){ return SNMP_ERR_TOOBIG; } } //if (msgtype== SET_REQ_MSG) ... (*index)++; } //while((int)length > 0) .... if(msgtype!= SET_REQ_MSG){ // save a pointer to the end of the packet packet_end = out_data; // Now rebuild header with the actual lengths dummyLen = packet_end - var_list_start; // modified by ---- Arius 5/17/2000 #ifdef WEBADMIN dummyLen1 = packet_end - headerP; newpacket_end = asn_build_sequence(headerP, &dummyLen1, (uint8)(ASN_SEQUENCE | ASN_CONSTRUCTOR), dummyLen); var_list_start -= (packet_end - newpacket_end); out_length += (packet_end - newpacket_end); // save new pointer to the end of the packet when the sapces will be adjust packet_end = newpacket_end; if (headerP == NULL) #else if (asn_build_sequence(headerP, &dummyLen, (uint8)(ASN_SEQUENCE | ASN_CONSTRUCTOR), dummyLen) == NULL) #endif WEBADMIN // end of here { return SNMP_ERR_TOOBIG; // bogus error ???? } } *index = 0; return SNMP_ERR_NOERROR; }
unsigned int encode_vbind (char *oid_string, char oid_asntype, union t_val *value, unsigned char *out_buffer, size_t out_size) { oid var_name[MAX_OID_LEN]; size_t name_len = MAX_OID_LEN; oid oid_value[MAX_OID_LEN]; size_t oid_value_len = MAX_OID_LEN; unsigned char *data_ptr; unsigned char buf[SPRINT_MAX_LEN]; unsigned int ltmp; struct tree *tp; struct range_list *rp; long len=0; int rv; long longval; unsigned long ulongval; memset (buf, 0, SPRINT_MAX_LEN); if (!get_node (oid_string, var_name, &name_len)) { if (!read_objid (oid_string, var_name, &name_len)) { /* enable random access */ if (!netsnmp_ds_get_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_RANDOM_ACCESS)) { netsnmp_ds_toggle_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_RANDOM_ACCESS); } if (!get_node (oid_string, var_name, &name_len)) { /* Not found, try UCD style OID access */ netsnmp_ds_toggle_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_READ_UCD_STYLE_OID); if (!netsnmp_ds_get_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_READ_UCD_STYLE_OID)) { netsnmp_ds_toggle_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_READ_UCD_STYLE_OID); } if (!read_objid (oid_string, var_name, &name_len)) { /* Hmm, still not found, go back to net-snmp-style OID and try regex access */ netsnmp_ds_toggle_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_READ_UCD_STYLE_OID); if (!netsnmp_ds_get_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_REGEX_ACCESS)) { netsnmp_ds_toggle_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_REGEX_ACCESS); } if (!get_wild_node (oid_string, var_name, &name_len)) { /* Ran out of ideas. */ fprintf(stderr, "/* Error: Can't find oid %s at line %d */\n", oid_string, line); snmp_perror ("encode_vbind"); return 0; } } } } } switch (oid_asntype) { case 'i': longval = value->intval; data_ptr = _docsis_snmp_build_var_op (out_buffer, var_name, &name_len, ASN_INTEGER, sizeof (long), (unsigned char *) &longval, &out_size); return data_ptr - out_buffer; break; ;; case 'g': ulongval = value->intval; data_ptr = _docsis_snmp_build_var_op (out_buffer, var_name, &name_len, ASN_GAUGE, sizeof (unsigned long), (unsigned char *) &ulongval, &out_size); return data_ptr - out_buffer; break; ;; case 'c': ulongval = value->intval; data_ptr = _docsis_snmp_build_var_op (out_buffer, var_name, &name_len, ASN_COUNTER, sizeof (unsigned long), (unsigned char *) &ulongval, &out_size); return data_ptr - out_buffer; break; ;; case 'u': ulongval = value->intval; data_ptr = _docsis_snmp_build_var_op (out_buffer, var_name, &name_len, ASN_GAUGE, sizeof (unsigned long), (unsigned char *) &ulongval, &out_size); return data_ptr - out_buffer; break; ;; case 't': ulongval = value->intval; data_ptr = _docsis_snmp_build_var_op (out_buffer, var_name, &name_len, ASN_TIMETICKS, sizeof (unsigned long), (unsigned char *) &ulongval, &out_size); return data_ptr - out_buffer; break; ;; case 's': case 'x': case 'd': if (oid_asntype == 'd') { /* ltmp = ascii_to_binary(value->strval, buf); strncpy((char*)buf, value, SPRINT_MAX_BUF); ltmp = strlen((char*)buf); */ } else if (oid_asntype == 's') { strncpy ((char *) buf, value->strval, SPRINT_MAX_LEN); len = strlen ((char *) buf); } else if (oid_asntype == 'x') { if ((rv = hexadecimal_to_binary (value->strval, buf)) == -1) { fprintf(stderr, "Invalid hexadecimal string at line %d\n", line); return 0; } ltmp = (unsigned int) rv; len = ltmp; } if (len < 0 || len > SPRINT_MAX_LEN - 1) { fprintf(stderr, "String too long at line %d, max allowed %d\n", line, SPRINT_MAX_LEN); return 0; break; } tp = get_tree (var_name, name_len, get_tree_head ()); if (tp && tp->ranges && !netsnmp_ds_get_boolean (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DONT_CHECK_RANGE)) { rp = tp->ranges; while (rp) { if (rp->low <= len && len <= rp->high) break; rp = rp->next; } if (!rp) { fprintf(stderr, "Value too long at line %d\n", line); return 0; break; } } /* If length is more than 127, won't fit into a 1-byte quantity */ if (len+name_len+8 < 0x7f ) { data_ptr = _docsis_snmp_build_var_op (out_buffer, var_name, &name_len, ASN_OCTET_STR, len, (unsigned char *) buf, &out_size); } else { data_ptr = snmp_build_var_op (out_buffer, var_name, &name_len, ASN_OCTET_STR, len, (unsigned char *) buf, &out_size); } #ifdef DEBUG fprintf (stderr, "encoded len %ld var_len %d leftover %ud difference %d\n", len, name_len, out_size, (data_ptr - out_buffer) ); #endif return data_ptr - out_buffer; break; ;; case 'a': if (!inet_aton (value->strval, (struct in_addr *) <mp)) { fprintf(stderr, "Invalid IP address %s at line %d\n", value->strval, line); return 0; } data_ptr = _docsis_snmp_build_var_op (out_buffer, var_name, &name_len, ASN_IPADDRESS, sizeof (struct in_addr), (unsigned char *) <mp, &out_size); return data_ptr - out_buffer; break; ;; case 'o': strncpy ((char *) buf, value->strval, SPRINT_MAX_LEN); len = strlen ((char *) buf); if (!read_objid ((char *) buf, oid_value, &oid_value_len)) { fprintf(stderr, "Can't find oid %s at line %d\n", buf, line); return 0; } data_ptr = _docsis_snmp_build_var_op (out_buffer, var_name, &name_len, ASN_OBJECT_ID, oid_value_len*sizeof(oid), (unsigned char *) &oid_value, &out_size); return data_ptr - out_buffer; break; ;; default: fprintf(stderr, "Variable type %s not supported yet\n", &oid_asntype); return 0; ;; } /* NOTREACHED */ }
/* * Takes a session and a pdu and serializes the ASN PDU into the area * pointed to by packet. out_length is the size of the data area available. * Returns the length of the completed packet in out_length. If any errors * occur, -1 is returned. If all goes well, 0 is returned. */ int snmp_build_trap( snmp_session *session, snmp_pdu *pdu, uint8 *packet, int *out_length ) { uint8 buf[SNMP_MAX_TRAP_LEN]; uint8 *cp; #ifdef WEBADMIN uint8 *newpacket; // add -- by arius 5/18/2000 #endif WEBADMIN variable_list *vp; int totallength; int length; length = *out_length; cp = packet; for(vp = pdu->variables; vp; vp = vp->next){ cp = snmp_build_var_op(cp, vp->name, &vp->name_len, vp->type, vp->val_len, (uint8 *)vp->val.string, &length); if (cp == NULL) return (FALSE); } totallength = cp - packet; length = SNMP_MAX_TRAP_LEN; cp = asn_build_header(buf, &length, (uint8)(ASN_SEQUENCE | ASN_CONSTRUCTOR), totallength); if (cp == NULL) return (FALSE); bcopy((char *)packet, (char *)cp, totallength); totallength += cp - buf; length = *out_length; if (pdu->command != TRP_REQ_MSG){ // request id cp = asn_build_int(packet, &length, (uint8)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), (long *)&pdu->reqid, sizeof(pdu->reqid)); if (cp == NULL) return (FALSE); // error status cp = asn_build_int(cp, &length, (uint8)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), (long *)&pdu->errstatus, sizeof(pdu->errstatus)); if(cp == NULL) return (FALSE); // error index cp = asn_build_int(cp, &length, (uint8)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), (long *)&pdu->errindex, sizeof(pdu->errindex)); if(cp == NULL) return (FALSE); } else { // this is a trap message // enterprise cp = asn_build_objid(packet, &length, (uint8)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), (oid *)SnmpVersionID, SNMP_VER_LEN); if (cp == NULL) return (FALSE); // agent-addr cp = asn_build_string(cp, &length, (uint8)IPADDRESS, (uint8 *)&pdu->agent_addr.sin_addr.s_addr, sizeof(pdu->agent_addr.sin_addr.s_addr)); if(cp == NULL) return (FALSE); // generic trap cp = asn_build_int(cp, &length, (uint8)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), (long *)&pdu->generic_trap, sizeof(pdu->generic_trap)); if (cp == NULL) return (FALSE); // specific trap cp = asn_build_int(cp, &length, (uint8)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), (long *)&pdu->specific_trap, sizeof(pdu->specific_trap)); if (cp == NULL) return (FALSE); // timestamp cp = asn_build_int(cp, &length, (uint8)TIMETICKS, (long *)&pdu->time_stamp, sizeof(pdu->time_stamp)); if (cp == NULL) return (FALSE); } if (length < totallength) return (FALSE); bcopy((char *)buf, (char *)cp, totallength); totallength += cp - packet; length = SNMP_MAX_TRAP_LEN; cp = asn_build_header(buf, &length, (uint8)pdu->command, totallength); if (cp == NULL) return (FALSE); if (length < totallength) return (FALSE); bcopy((char *)packet, (char *)cp, totallength); totallength += cp - buf; length = *out_length; // modified -- by arius 5/18/2000 #ifdef WEBADMIN newpacket = packet; cp = snmp_build_auth( newpacket, &length, session->community, session->community_len,(long) SNMP_VERSION_1, totallength); cp -= totallength; // save new pointer #else cp = snmp_build_auth( packet, &length, session->community, session->community_len,(long) SNMP_VERSION_1, totallength); #endif WEBADMIN // end of here if (cp == NULL) return (FALSE); if ((*out_length - (cp - packet)) < totallength) return (FALSE); bcopy((char *)buf, (char *)cp, totallength); totallength += cp - packet; *out_length = totallength; // if( session->qoS & USEC_QOS_AUTH ) // md5Digest( packet, totallength, cp - (session->contextLen + 16), // cp - (session->contextLen + 16) ); return (TRUE); }