int smux_register (int sock) { u_char buf[BUFSIZ]; u_char *ptr; int len, ret; long priority; long operation; struct subtree *subtree; struct listnode *node; ret = 0; for (node = treelist->head; node; node = node->next) { ptr = buf; len = BUFSIZ; subtree = node->data; /* SMUX RReq Header. */ ptr = asn_build_header (ptr, &len, (u_char) SMUX_RREQ, 0); /* Register MIB tree. */ ptr = asn_build_objid (ptr, &len, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), subtree->name, subtree->name_len); /* Priority. */ priority = -1; ptr = asn_build_int (ptr, &len, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), &priority, sizeof (u_long)); /* Operation. */ operation = 2; /* Register R/W */ ptr = asn_build_int (ptr, &len, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), &operation, sizeof (u_long)); if (debug_smux) { smux_oid_dump ("SMUX register oid", subtree->name, subtree->name_len); zlog_info ("SMUX register priority: %ld", priority); zlog_info ("SMUX register operation: %ld", operation); } len = BUFSIZ; asn_build_header (buf, &len, (u_char) SMUX_RREQ, (ptr - buf) - 2); ret = send (sock, buf, (ptr - buf), 0); if (ret < 0) return ret; } return ret; }
//* //* create a packet identical to the input packet, except for the error status //* and the error index which are set according to the input variables. //* Returns 1 upon success and 0 upon failure. //* int create_identical( snmp_session *session, uint8 *snmp_in, uint8 *snmp_out, int snmp_length, long errstat, long errindex ) { uint8 *data; uint8 type; uint32 dummy; uint8 *headerPtr, *reqidPtr, *errstatPtr, *errindexPtr, *varListPtr; int headerLength, length; bcopy((char *)snmp_in, (char *)snmp_out, snmp_length); length = snmp_length; headerPtr = snmp_parse_auth(snmp_out, &length, community, &session->community_len, (long *)&dummy); community[session->community_len] = 0; if (headerPtr == NULL) return 0; reqidPtr = asn_parse_header(headerPtr, &length, (uint8 *)&dummy); if (reqidPtr == NULL) return 0; headerLength = length; errstatPtr = asn_parse_int(reqidPtr, &length, &type, (long *)&dummy, sizeof dummy); // request id if (errstatPtr == NULL) return 0; errindexPtr = asn_parse_int(errstatPtr, &length, &type, (long *)&dummy, sizeof dummy); // error status if (errindexPtr == NULL) return 0; varListPtr = asn_parse_int(errindexPtr, &length, &type, (long *)&dummy, sizeof dummy); // error index if (varListPtr == NULL) return 0; #if 0 data = asn_build_header(headerPtr, &headerLength, GET_RSP_MSG, headerLength); if (data != reqidPtr) return 0; #else /*bug fixed */ *headerPtr = GET_RSP_MSG; #endif length = snmp_length; type = (uint8)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER); data = asn_build_int(errstatPtr, &length, type, &errstat, sizeof errstat); if (data != errindexPtr) return 0; data = asn_build_int(errindexPtr, &length, type, &errindex, sizeof errindex); if (data != varListPtr) return 0; packet_end = snmp_out + snmp_length; return 1; }
/*******************************************************************-o-****** * snmp_comstr_build * * Parameters: * *data * *length * *psid * *slen * *version * messagelen * * Returns: * Pointer into 'data' after built section. * * * Build the header of a community string-based message such as that found * in SNMPv1 and SNMPv2c. * * NOTE: The length of the message will have to be inserted later, * if not known. * * NOTE: Version is an 'int'. (CMU had it as a long, but was passing * in a *int. Grrr.) Assign version to verfix and pass in * that to asn_build_int instead which expects a long. -- WH */ u_char * snmp_comstr_build(u_char * data, size_t * length, u_char * psid, size_t * slen, long *version, size_t messagelen) { long verfix = *version; u_char *h1 = data; u_char *h1e; size_t hlength = *length; /* * Build the the message wrapper (note length will be inserted later). */ data = asn_build_sequence(data, length, (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), 0); if (data == NULL) { return NULL; } h1e = data; /* * Store the version field. */ data = asn_build_int(data, length, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), &verfix, sizeof(verfix)); if (data == NULL) { return NULL; } /* * Store the community string. */ data = asn_build_string(data, length, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR), psid, *(u_char *) slen); if (data == NULL) { return NULL; } /* * Insert length. */ asn_build_sequence(h1, &hlength, (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), data - h1e + messagelen); return data; } /* end snmp_comstr_build() */
int smux_open (int sock) { u_char buf[BUFSIZ]; u_char *ptr; size_t len; u_long version; u_char progname[] = QUAGGA_PROGNAME "-" QUAGGA_VERSION; if (debug_smux) { smux_oid_dump ("SMUX open oid", smux_oid, smux_oid_len); zlog_debug ("SMUX open progname: %s", progname); zlog_debug ("SMUX open password: %s", smux_passwd); } ptr = buf; len = BUFSIZ; /* SMUX Header. As placeholder. */ ptr = asn_build_header (ptr, &len, (u_char) SMUX_OPEN, 0); /* SMUX Open. */ version = 0; ptr = asn_build_int (ptr, &len, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), &version, sizeof (version)); /* SMUX connection oid. */ ptr = asn_build_objid (ptr, &len, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), smux_oid, smux_oid_len); /* SMUX connection description. */ ptr = asn_build_string (ptr, &len, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR), progname, strlen (progname)); /* SMUX connection password. */ ptr = asn_build_string (ptr, &len, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR), smux_passwd, strlen (smux_passwd)); /* Fill in real SMUX header. We exclude ASN header size (2). */ len = BUFSIZ; asn_build_header (buf, &len, (u_char) SMUX_OPEN, (ptr - buf) - 2); return send (sock, buf, (ptr - buf), 0); }
u_char * snmp_msg_Encode(u_char * Buffer, int *BufLenP, u_char * Community, int CommLen, int Version, struct snmp_pdu *PDU) { u_char *bufp, *tmp; u_char *PDUHeaderPtr, *VARHeaderPtr; u_char *PDUDataStart, *VARDataStart; u_char *MsgPtr; int FakeArg = 1024; snmplib_debug(4, "Buffer=%p BufLenP=%p, buflen=%d\n", Buffer, BufLenP, *BufLenP); /* Header for the entire thing, with a false, large length */ bufp = asn_build_header(Buffer, BufLenP, (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), (*BufLenP)); if (bufp == NULL) { snmplib_debug(4, "snmp_msg_Encode:Error encoding SNMP Message Header (Header)!\n"); return (NULL); } MsgPtr = bufp; /* Version */ bufp = asn_build_int(bufp, BufLenP, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), (int *) (&Version), sizeof(Version)); if (bufp == NULL) { snmplib_debug(4, "snmp_msg_Encode:Error encoding SNMP Message Header (Version)!\n"); return (NULL); } snmplib_debug(8, "snmp_msg_Encode: Encoding community (%s) (%d)\n", Community, CommLen); /* Community */ bufp = asn_build_string(bufp, BufLenP, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR), Community, CommLen); if (bufp == NULL) { snmplib_debug(4, "snmp_msg_Encode:Error encoding SNMP Message Header (Community)!\n"); return (NULL); } /* Encode the rest. */ /* A nice header for this PDU. * Encoded with the wrong length. We'll fix it later. */ snmplib_debug(8, "snmp_msg_Encode:Encoding PDU Header at 0x%p (fake len %d) (%d bytes so far)\n", bufp, *BufLenP, *BufLenP); PDUHeaderPtr = bufp; bufp = asn_build_header(bufp, BufLenP, (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), (*BufLenP)); if (bufp == NULL) return (NULL); /* Encode this PDU. */ PDUDataStart = bufp; bufp = snmp_pdu_encode(bufp, BufLenP, PDU); if (bufp == NULL) return (NULL); /* snmp_pdu_encode registered failure */ VARHeaderPtr = bufp; bufp = asn_build_header(bufp, BufLenP, (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), FakeArg); if (bufp == NULL) return (NULL); VARDataStart = bufp; /* And build the variables */ bufp = snmp_var_EncodeVarBind(bufp, BufLenP, PDU->variables, Version); if (bufp == NULL) return (NULL); /* snmp_var_EncodeVarBind registered failure */ /* Cool. Now insert the appropriate lengths. */ #if DEBUG_MSG_ENCODE snmplib_debug(9, "Msg: Vars returned 0x%x. PDU Started at 0x%x\n", bufp, PDUHeaderPtr); snmplib_debug(9, "MSG: Entire PDU length is %d (0x%x - 0x%x)\n", (int) (bufp - PDUDataStart), PDUHeaderPtr, bufp); #endif tmp = asn_build_header(PDUHeaderPtr, &FakeArg, (u_char) PDU->command, (int) (bufp - PDUDataStart)); /* Length of the PDU and Vars */ if (tmp == NULL) return (NULL); #if DEBUG_MSG_ENCODE snmplib_debug(9, "MSG: Entire message length is %d (0x%x - 0x%x)\n", (int) (bufp - MsgPtr), MsgPtr, bufp); #endif tmp = asn_build_header(Buffer, &FakeArg, (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), (bufp - MsgPtr)); /* Length of everything */ if (tmp == NULL) return (NULL); tmp = asn_build_header(VARHeaderPtr, &FakeArg, (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), (bufp - VARDataStart)); /* Length of everything */ if (tmp == NULL) return (NULL); *BufLenP = (bufp - Buffer); return (u_char *) bufp; }
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); }
u_char * _docsis_snmp_build_var_op(u_char * data, oid * var_name, size_t * var_name_len, u_char var_val_type, size_t var_val_len, u_char * var_val, size_t * listlength) { size_t dummyLen, headerLen; u_char *dataPtr; dummyLen = *listlength; dataPtr = data; #if 0 data = asn_build_sequence(data, &dummyLen, (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), 0); if (data == NULL) { return NULL; } #endif if (dummyLen < 2) return NULL; data += 2; dummyLen -= 2; headerLen = data - dataPtr; *listlength -= headerLen; DEBUGDUMPHEADER("send", "Name"); data = asn_build_objid(data, listlength, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), var_name, *var_name_len); DEBUGINDENTLESS(); if (data == NULL) { ERROR_MSG("Can't build OID for variable"); return NULL; } DEBUGDUMPHEADER("send", "Value"); switch (var_val_type) { case ASN_INTEGER: data = asn_build_int(data, listlength, var_val_type, (long *) var_val, var_val_len); break; case ASN_GAUGE: case ASN_COUNTER: case ASN_TIMETICKS: case ASN_UINTEGER: data = asn_build_unsigned_int(data, listlength, var_val_type, (u_long *) var_val, var_val_len); break; #ifdef OPAQUE_SPECIAL_TYPES case ASN_OPAQUE_COUNTER64: case ASN_OPAQUE_U64: #endif case ASN_COUNTER64: data = asn_build_unsigned_int64(data, listlength, var_val_type, (struct counter64 *) var_val, var_val_len); break; case ASN_OCTET_STR: case ASN_IPADDRESS: case ASN_OPAQUE: case ASN_NSAP: data = asn_build_string(data, listlength, var_val_type, var_val, var_val_len); break; case ASN_OBJECT_ID: data = asn_build_objid(data, listlength, var_val_type, (oid *) var_val, var_val_len / sizeof(oid)); break; case ASN_NULL: data = asn_build_null(data, listlength, var_val_type); break; case ASN_BIT_STR: data = asn_build_bitstring(data, listlength, var_val_type, var_val, var_val_len); break; case SNMP_NOSUCHOBJECT: case SNMP_NOSUCHINSTANCE: case SNMP_ENDOFMIBVIEW: data = asn_build_null(data, listlength, var_val_type); break; #ifdef OPAQUE_SPECIAL_TYPES case ASN_OPAQUE_FLOAT: data = asn_build_float(data, listlength, var_val_type, (float *) var_val, var_val_len); break; case ASN_OPAQUE_DOUBLE: data = asn_build_double(data, listlength, var_val_type, (double *) var_val, var_val_len); break; case ASN_OPAQUE_I64: data = asn_build_signed_int64(data, listlength, var_val_type, (struct counter64 *) var_val, var_val_len); break; #endif /* OPAQUE_SPECIAL_TYPES */ default: ERROR_MSG("wrong type"); return NULL; } DEBUGINDENTLESS(); if (data == NULL) { ERROR_MSG("Can't build value"); return NULL; } dummyLen = (data - dataPtr) - headerLen; _docsis_asn_build_sequence(dataPtr, &dummyLen, (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), dummyLen); return data; }
/* Build a variable binding. * * RFC 1905: Protocol Operations for SNMPv2 * * VarBind ::= * SEQUENCE { * name ObjectName * CHOICE { * value ObjectSyntax * unSpecified NULL * noSuchObject[0] NULL * noSuchInstance[1] NULL * endOfMibView[2] NULL * } * } */ u_char *snmp_var_EncodeVarBind(u_char *Buffer, int *BufLenP, struct variable_list *VarList, int Version) { struct variable_list *Vars; u_char *bufp; u_char *HeaderStart; u_char *HeaderEnd; int FakeArg = *BufLenP; #ifdef DEBUG_VARS_ENCODE int StartLen = *BufLenP; int Counter = 1; #endif bufp = Buffer; #ifdef DEBUG_VARS_ENCODE printf("VARS: Encoding Variable list into buffer at 0x%x.\n", Buffer); #endif for (Vars=VarList; Vars; Vars=Vars->next_variable) { #ifdef DEBUG_VARS_ENCODE printf("VARS %d: Encoding Variable 0x%x.\n", Counter, Vars); printf("VARS %d: Starting at 0x%x (%d bytes left)\n", Counter, bufp, *BufLenP); #endif /* Build the header for this variable * * Use Maximum size. */ HeaderStart = bufp; HeaderEnd = asn_build_header(HeaderStart, BufLenP, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), FakeArg); if (HeaderEnd == NULL) return(NULL); #ifdef DEBUG_VARS_ENCODE printf("VARS %d: Encoding Object Identifier 0x%x (%d bytes) at 0x%x (%d bytes left)\n", Counter, Vars, Vars->name_length, HeaderEnd, *BufLenP); print_oid(Vars->name, Vars->name_length), #endif /* Now, let's put the Object Identifier into the buffer */ bufp = asn_build_objid(HeaderEnd, BufLenP, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), Vars->name, Vars->name_length); if (bufp == NULL) return(NULL); /* Now put the data in */ switch(Vars->type) { case ASN_INTEGER: #ifdef DEBUG_VARS_ENCODE printf("VARS %d: Encoding Integer %d at 0x%x\n", Counter, *(Vars->val.integer), bufp); #endif bufp = asn_build_int(bufp, BufLenP, Vars->type, (int *)Vars->val.integer, Vars->val_len); break; case SMI_COUNTER32: case SMI_GAUGE32: /* case SMI_UNSIGNED32: */ case SMI_TIMETICKS: #ifdef DEBUG_VARS_ENCODE printf("VARS %d: Encoding Timeticks %d at 0x%x\n", Counter, *(Vars->val.integer), bufp); #endif bufp = asn_build_unsigned_int(bufp, BufLenP, Vars->type, (u_int *)Vars->val.integer, Vars->val_len); break; case ASN_OCTET_STR: case SMI_IPADDRESS: case SMI_OPAQUE: #ifdef DEBUG_VARS_ENCODE printf("VARS %d: Encoding String %s (%d bytes) at 0x%x\n", Counter, (Vars->val.string), Vars->val_len, bufp); #endif bufp = asn_build_string(bufp, BufLenP, Vars->type, Vars->val.string, Vars->val_len); break; case ASN_OBJECT_ID: #ifdef DEBUG_VARS_ENCODE printf("VARS %d: Encoding Object Identifier (%d bytes) at 0x%x\n", Counter, Vars->val_len, bufp); #endif bufp = asn_build_objid(bufp, BufLenP, Vars->type, (oid *)Vars->val.objid, Vars->val_len / sizeof(oid)); break; case SMI_NOSUCHINSTANCE: case SMI_NOSUCHOBJECT: case SMI_ENDOFMIBVIEW: #ifdef DEBUG_VARS_ENCODE printf("VARS %d: Encoding NULL at 0x%x\n", Counter, bufp); #endif if (Version == SNMP_VERSION_1) { /* SNMP Version 1 does not support these error codes. */ bufp = asn_build_null(bufp, BufLenP, SMI_NOSUCHOBJECT); } else { bufp = asn_build_exception(bufp, BufLenP, Vars->type); } break; case ASN_NULL: #ifdef DEBUG_VARS_ENCODE printf("VARS %d: Encoding NULL at 0x%x\n", Counter, bufp); #endif bufp = asn_build_null(bufp, BufLenP, Vars->type); break; case SMI_COUNTER64: #ifdef STDERR_OUTPUT fprintf(stderr, WIDE("Unable to encode type SMI_COUNTER64!\n")); #endif /* Fall through */ default: snmp_set_api_error(SNMPERR_UNSUPPORTED_TYPE); return(NULL); } /* ASSERT: bufp should now point to the next valid byte. */ if (bufp == NULL) return(NULL); /* Rebuild the header with the appropriate length */ #ifdef DEBUG_VARS_ENCODE printf("VARS %d: Resetting length to %d at 0x%x (%d bytes left)\n", Counter, (bufp - HeaderEnd), HeaderStart, *BufLenP); #endif HeaderEnd = asn_build_header(HeaderStart, &FakeArg, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), (bufp - HeaderEnd)); /* Returns NULL */ if (HeaderEnd == NULL) return(NULL); #ifdef DEBUG_VARS_ENCODE Counter++; #endif } #ifdef DEBUG_VARS_ENCODE printf("VARS: Variable list of %d vars takes up %d bytes.\n", --Counter, StartLen - *BufLenP); #endif /* or the end of the entire thing */ return(bufp); }
int snmp_agent_parse( snmp_session *session, uint8 *indata, int inlength, uint8 *outdata, int *outlength ) { uint8 msgtype, type; long zero = 0; long reqid, errstat, errindex, dummyindex; uint8 *out_auth, *out_header, *out_reqid; uint8 *startData = indata; int startLength = inlength; long version; uint8 *origdata = indata; int origlen = inlength; // usecEntry *ue; int packet_len, ret = 0; #ifdef WEBADMIN int newoutdata; // add -- by arius 5/17/2000 int len; // add -- by arius 5/17/2000 #endif WEBADMIN session->community_len = COMMUNITY_MAX_LEN; //get community name indata = snmp_parse_auth(indata, &inlength, community, &session->community_len, &version); if (indata == NULL){ // increment_stat( SNMP_STAT_ENCODING_ERRORS ); ERROR("bad auth encoding"); return 0; } #if 1 //ONLY SUPPORT VERSION 1 if(version != SNMP_VERSION_1) { ERROR("wrong version"); snmp_inbadversions++; return 0; } #else //////////////////////////////////////////// if( version != SNMP_VERSION_1 && version != SNMP_VERSION_2C && version != SNMP_VERSION_2 ) { // increment_stat( SNMP_STAT_ENCODING_ERRORS ); ERROR("wrong version"); snmp_inbadversions++; return 0; } if( version == SNMP_VERSION_2C || version == SNMP_VERSION_2 ) { if( version == SNMP_VERSION_2 ) { ret = check_auth( session, origdata, origlen, indata - session->community_len, session->community_len, &ue ); *outlength = (SNMP_MAX_LEN < session->MMS) ? SNMP_MAX_LEN : session->MMS; session->MMS = SNMP_MAX_LEN; } else if( version == SNMP_VERSION_2C ) { ret = community_auth( session ); session->version = SNMP_VERSION_2C; } if( ret < 0 ) { // increment_stat( -ret ); if( (indata=asn_parse_header(indata, &inlength, &msgtype)) && asn_parse_int(indata, &inlength, &type, &reqid, sizeof(reqid)) ) { if( msgtype == REPORT_MSG ) return 0; if( !(session->qoS & USEC_QOS_GENREPORT) ) return 0; session->agentBoots = _agentBoots; session->agentClock = _agentStartTime; memcpy( session->agentID, _agentID, 12 ); session->MMS = SNMP_MAX_LEN; create_report( session, outdata, outlength, -ret, reqid ); return 1; } else { return 0; } } else if( ret > 0 ) { // increment_stat( ret ); return 0; } } else { #endif ///////////////////////////////////////////////////// //VERSION 1 if(community_auth( session )==0) return 0; // session->version = SNMP_VERSION_1; #if 0 //////// } #endif /////// indata = asn_parse_header(indata, &inlength, &msgtype); if (indata == NULL){ // increment_stat( SNMP_STAT_ENCODING_ERRORS ); ERROR("bad header"); return 0; } // XXX: increment by total number of vars at correct place: snmp_intotalreqvars++; if(msgtype == GET_REQ_MSG) snmp_ingetrequests++; else if (msgtype == GETNEXT_REQ_MSG) snmp_ingetnexts++; else if (msgtype == SET_REQ_MSG) snmp_insetrequests++; else return 0; // if (msgtype == GETBULK_REQ_MSG: //version 2 // Request ID indata = asn_parse_int(indata, &inlength, &type, &reqid, sizeof(reqid)); if (indata == NULL){ // increment_stat( SNMP_STAT_ENCODING_ERRORS ); ERROR("bad parse of reqid"); return 0; } //Error Status indata = asn_parse_int(indata, &inlength, &type, &errstat, sizeof(errstat)); if (indata == NULL){ // increment_stat( SNMP_STAT_ENCODING_ERRORS ); ERROR("bad parse of errstat"); snmp_inasnparseerrors++; return 0; } //Error Index indata = asn_parse_int(indata, &inlength, &type, &errindex, sizeof(errindex)); if (indata == NULL){ // increment_stat( SNMP_STAT_ENCODING_ERRORS ); ERROR("bad parse of errindex"); return 0; } // // Now start cobbling together what is known about the output packet. // The final lengths are not known now, so they will have to be recomputed // later. // // setup for response //Simon time( (time_t *) &session->agentTime ); //Simon session->agentClock = _agentStartTime; //Simon session->agentBoots = _agentBoots; //Simon memcpy( session->agentID, _agentID, 12 ); out_auth = outdata; //Set Resp Community out_header = snmp_build_auth(out_auth, outlength, community,session->community_len, (long)SNMP_VERSION_1,0); if (out_header == NULL){ ERROR("snmp_build_auth failed"); snmp_inasnparseerrors++; return 0; } out_reqid = asn_build_sequence(out_header, outlength, (uint8)GET_RSP_MSG, 0); if (out_reqid == NULL){ ERROR("out_reqid == NULL"); return 0; } //Set Resp ID type = (uint8)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER); // return identical request id outdata = asn_build_int(out_reqid, outlength, type, &reqid, sizeof(reqid)); if (outdata == NULL){ ERROR("build reqid failed"); return 0; } // assume that error status will be zero outdata = asn_build_int(outdata, outlength, type, &zero, sizeof(zero)); if (outdata == NULL){ ERROR("build errstat failed"); return 0; } // assume that error index will be zero outdata = asn_build_int(outdata, outlength, type, &zero, sizeof(zero)); if (outdata == NULL){ ERROR("build errindex failed"); return 0; } #if 0 /////////////////////////////////////////// if (msgtype == GETBULK_REQ_MSG) errstat = bulk_var_op_list(indata, inlength, outdata, *outlength, errstat, errindex, &errindex ); else #endif 0 //////////////////////////////////////// errstat = parse_var_op_list(session, indata, inlength, outdata, *outlength, &errindex, msgtype, RESERVE1); if (msgtype== SET_REQ_MSG){ if (errstat == SNMP_ERR_NOERROR) errstat = parse_var_op_list(session, indata, inlength, outdata, *outlength, &errindex, msgtype, RESERVE2); if (errstat == SNMP_ERR_NOERROR){ // //* SETS require 3-4 passes through the var_op_list. The first two //* passes verify that all types, lengths, and values are valid //* and may reserve resources and the third does the set and a //* fourth executes any actions. Then the identical GET RESPONSE //* packet is returned. //* If either of the first two passes returns an error, another //* pass is made so that any reserved resources can be freed. //* parse_var_op_list(session, indata, inlength, outdata, *outlength, &dummyindex, msgtype, COMMIT); parse_var_op_list(session, indata, inlength, outdata, *outlength, &dummyindex, msgtype, ACTION); if (create_identical(session, startData, out_auth, startLength, 0L, 0L )){ *outlength = packet_end - out_auth; return 1; } return 0; } else { parse_var_op_list(session, indata, inlength, outdata, *outlength, &dummyindex, msgtype, COMM_FREE); } } switch((short)errstat){ case SNMP_ERR_NOERROR: // re-encode the headers with the real lengths *outlength = packet_end - out_header; packet_len = *outlength; outdata = asn_build_sequence(out_header, outlength, GET_RSP_MSG, packet_end - out_reqid); // add --- By arius 5/17/2000 #ifdef WEBADMIN newoutdata = packet_end - outdata; // how many shifts len = packet_end - out_reqid; packet_end = outdata; // save new pointer end of packet outdata -= len; out_reqid = out_reqid - newoutdata; #endif WEBADMIN // end of here if (outdata != out_reqid){ ERROR("internal error: header"); return 0; } *outlength = packet_end - out_auth; outdata = snmp_build_auth(out_auth, outlength, community, session->community_len, (long)SNMP_VERSION_1, packet_end - out_header ); // add --- By arius 5/17/2000 #ifdef WEBADMIN out_header -= (packet_end - outdata); packet_end = outdata; // save new pointer end of packet #endif WEBADMIN // end of here *outlength = packet_end - out_auth; #if 0 // packet_end is correct for old SNMP. This dichotomy needs to be fixed. if (session->version == SNMP_VERSION_2) packet_end = out_auth + packet_len; #endif break; case SNMP_ERR_TOOBIG: snmp_intoobigs++; #if notdone if (session->version == SNMP_VERSION_2){ create_toobig(out_auth, *outlength, reqid, pi); break; } // else FALLTHRU #endif case SNMP_ERR_NOACCESS: case SNMP_ERR_WRONGTYPE: case SNMP_ERR_WRONGLENGTH: case SNMP_ERR_WRONGENCODING: case SNMP_ERR_WRONGVALUE: case SNMP_ERR_NOCREATION: case SNMP_ERR_INCONSISTENTVALUE: case SNMP_ERR_RESOURCEUNAVAILABLE: case SNMP_ERR_COMMITFAILED: case SNMP_ERR_UNDOFAILED: case SNMP_ERR_AUTHORIZATIONERROR: case SNMP_ERR_NOTWRITABLE: case SNMP_ERR_INCONSISTENTNAME: case SNMP_ERR_NOSUCHNAME: case SNMP_ERR_BADVALUE: case SNMP_ERR_READONLY: case SNMP_ERR_GENERR: if (create_identical(session, startData, out_auth, startLength, errstat, errindex)){ *outlength = packet_end - out_auth; return 1; } return 0; default: return 0; } #if 0 if( session->qoS & USEC_QOS_AUTH ) { md5Digest( out_auth, *outlength, outdata - (session->contextLen + 16), outdata - (session->contextLen + 16) ); } #endif return 1; }
/* * 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); }
//* //*--------------------------------------------------------------------------------- //* Function Name: snmp_build_auth //* Description : Encodes the community name and version number in BER encoding //* rules. //* Return Value : pointer of message with community name and version number encoded //* in it. //*--------------------------------------------------------------------------------- //* uint8 *snmp_build_auth( uint8 *outdata, int *outlength, uint8 *community, int community_len, long version, int messagelen ) { // build the the message wrapper (30 82 Length) // 5 bytes = version header + version value + community header // add -- By arius 5/17/2000 #ifdef WEBADMIN uint8 *oldoutdata; int newoutlength; oldoutdata = outdata; outdata = asn_build_sequence(outdata, outlength, (uint8)(ASN_SEQUENCE | ASN_CONSTRUCTOR), 0); #else outdata = asn_build_sequence(outdata, outlength, (uint8)(ASN_SEQUENCE | ASN_CONSTRUCTOR), messagelen + community_len + 5); #endif WEBADMIN // end of here if (outdata == NULL){ ERROR("buildheader"); return NULL; } // store the version field (02 length version) outdata = asn_build_int(outdata, outlength, (uint8)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), &version, sizeof(version)); if(outdata == NULL){ ERROR("buildint"); return NULL; } outdata = asn_build_string(outdata, outlength, (uint8)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STRING), community, community_len); if(outdata == NULL){ ERROR("buildstring"); return NULL; } // add -- By arius 5/17/2000 #ifdef WEBADMIN if (messagelen) { newoutlength = *outlength + (community_len + 5 + 4); // (default 4) include 30 82 Length outdata = asn_build_sequence(oldoutdata, &newoutlength , (uint8)(ASN_SEQUENCE | ASN_CONSTRUCTOR), messagelen + community_len + 5); } #endif WEBADMIN // end of here return outdata; }
/* Build a variable binding. * * RFC 1905: Protocol Operations for SNMPv2 * * VarBind ::= * SEQUENCE { * name ObjectName * CHOICE { * value ObjectSyntax * unSpecified NULL * noSuchObject[0] NULL * noSuchInstance[1] NULL * endOfMibView[2] NULL * } * } */ u_char * snmp_var_EncodeVarBind(u_char * Buffer, int *BufLenP, variable_list * VarList, int Version) { struct variable_list *Vars; u_char *bufp; u_char *HeaderStart; u_char *HeaderEnd; int FakeArg = *BufLenP; bufp = Buffer; for (Vars = VarList; Vars; Vars = Vars->next_variable) { /* Build the header for this variable * * Use Maximum size. */ HeaderStart = bufp; HeaderEnd = asn_build_header(HeaderStart, BufLenP, (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), FakeArg); if (HeaderEnd == NULL) return (NULL); /* Now, let's put the Object Identifier into the buffer */ bufp = asn_build_objid(HeaderEnd, BufLenP, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), Vars->name, Vars->name_length); if (bufp == NULL) return (NULL); /* Now put the data in */ switch (Vars->type) { case ASN_INTEGER: bufp = asn_build_int(bufp, BufLenP, Vars->type, (int *) Vars->val.integer, Vars->val_len); break; case SMI_COUNTER32: case SMI_GAUGE32: /* case SMI_UNSIGNED32: */ case SMI_TIMETICKS: bufp = asn_build_unsigned_int(bufp, BufLenP, Vars->type, (u_int *) Vars->val.integer, Vars->val_len); break; case ASN_OCTET_STR: case SMI_IPADDRESS: case SMI_OPAQUE: bufp = asn_build_string(bufp, BufLenP, Vars->type, Vars->val.string, Vars->val_len); break; case ASN_OBJECT_ID: bufp = asn_build_objid(bufp, BufLenP, Vars->type, (oid *) Vars->val.objid, Vars->val_len / sizeof(oid)); break; case SMI_NOSUCHINSTANCE: case SMI_NOSUCHOBJECT: case SMI_ENDOFMIBVIEW: if (Version == SNMP_VERSION_1) { /* SNMP Version 1 does not support these error codes. */ bufp = asn_build_null(bufp, BufLenP, SMI_NOSUCHOBJECT); } else { bufp = asn_build_exception(bufp, BufLenP, Vars->type); } break; case ASN_NULL: bufp = asn_build_null(bufp, BufLenP, Vars->type); break; case SMI_COUNTER64: snmplib_debug(2, "Unable to encode type SMI_COUNTER64!\n"); /* Fall through */ default: snmp_set_api_error(SNMPERR_UNSUPPORTED_TYPE); return (NULL); } /* ASSERT: bufp should now point to the next valid byte. */ if (bufp == NULL) return (NULL); /* Rebuild the header with the appropriate length */ HeaderEnd = asn_build_header(HeaderStart, &FakeArg, (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), (bufp - HeaderEnd)); /* Returns NULL */ if (HeaderEnd == NULL) return (NULL); } /* or the end of the entire thing */ return (bufp); }
u_char *snmp_pdu_encode(u_char *DestBuf, int *DestBufLen, struct snmp_pdu *PDU) { u_char *bufp; #ifdef DEBUG_PDU_ENCODE printf("PDU: Encoding %d\n", PDU->command); #endif /* ASN.1 Header */ switch (PDU->command) { /**********************************************************************/ case TRP_REQ_MSG: /* SNMPv1 Trap */ /* enterprise */ bufp = asn_build_objid(DestBuf, DestBufLen, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), (oid *)PDU->enterprise, PDU->enterprise_length); if (bufp == NULL) return(NULL); /* agent-addr */ bufp = asn_build_string(bufp, DestBufLen, (u_char)(SMI_IPADDRESS | ASN_PRIMITIVE), (u_char *)&PDU->agent_addr.sin_addr.s_addr, sizeof(PDU->agent_addr.sin_addr.s_addr)); if (bufp == NULL) return(NULL); /* generic trap */ bufp = asn_build_int(bufp, DestBufLen, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), (int *)&PDU->trap_type, sizeof(PDU->trap_type)); if (bufp == NULL) return(NULL); /* specific trap */ bufp = asn_build_int(bufp, DestBufLen, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), (int *)&PDU->specific_type, sizeof(PDU->specific_type)); if (bufp == NULL) return(NULL); /* timestamp */ bufp = asn_build_unsigned_int(bufp, DestBufLen, (u_char)(SMI_TIMETICKS | ASN_PRIMITIVE), &PDU->time, sizeof(PDU->time)); if (bufp == NULL) return(NULL); break; /**********************************************************************/ case SNMP_PDU_GETBULK: /* SNMPv2 Bulk Request */ /* request id */ bufp = asn_build_int(DestBuf, DestBufLen, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), &PDU->reqid, sizeof(PDU->reqid)); if (bufp == NULL) return(NULL); /* non-repeaters */ bufp = asn_build_int(bufp, DestBufLen, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), &PDU->non_repeaters, sizeof(PDU->non_repeaters)); if (bufp == NULL) return(NULL); /* max-repetitions */ bufp = asn_build_int(bufp, DestBufLen, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), &PDU->max_repetitions, sizeof(PDU->max_repetitions)); if (bufp == NULL) return(NULL); break; /**********************************************************************/ default: /* Normal PDU Encoding */ /* request id */ #ifdef DEBUG_PDU_ENCODE printf("PDU: Request ID %d (0x%x)\n", PDU->reqid, DestBuf); #endif bufp = asn_build_int(DestBuf, DestBufLen, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), &PDU->reqid, sizeof(PDU->reqid)); if (bufp == NULL) return(NULL); /* error status */ #ifdef DEBUG_PDU_ENCODE printf("PDU: Error Status %d (0x%x)\n", PDU->errstat, bufp); #endif bufp = asn_build_int(bufp, DestBufLen, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), &PDU->errstat, sizeof(PDU->errstat)); if (bufp == NULL) return(NULL); /* error index */ #ifdef DEBUG_PDU_ENCODE printf("PDU: Error index %d (0x%x)\n", PDU->errindex, bufp); #endif bufp = asn_build_int(bufp, DestBufLen, (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), &PDU->errindex, sizeof(PDU->errindex)); if (bufp == NULL) return(NULL); break; } /* End of encoding */ return(bufp); }