2022-08-02 14:04:25 +00:00
/*
* BIRD - - Simple Network Management Protocol ( SNMP )
*
* ( c ) 2022 Vojtech Vilimek < vojtech . vilimek @ nic . cz >
* ( c ) 2022 CZ . NIC z . s . p . o
*
* Can be freely distributed and used under the terms of the GNU GPL .
*
*/
2022-08-10 15:31:32 +00:00
# include "lib/unaligned.h"
# include "subagent.h"
2022-11-15 15:29:03 +00:00
# include "snmp_utils.h"
2022-09-20 12:28:57 +00:00
# include "bgp_mib.h"
2022-08-02 14:04:25 +00:00
2022-09-06 16:04:29 +00:00
/* =============================================================
* Problems
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*
2022-09-30 07:36:09 +00:00
* change of remote ip - > no notification , no update
2022-09-06 16:04:29 +00:00
* same ip , different ports
* distinct VRF ( two interfaces with overlapping private addrs )
2022-09-20 12:28:57 +00:00
* posible link - local addresses in LOCAL_IP
2022-09-06 16:04:29 +00:00
*
2023-07-26 12:30:34 +00:00
* context is allocated as copied , is it approach really needed ? wouldn ' t it
* sufficient just use the context in rx - buffer ?
*
2022-09-06 16:04:29 +00:00
*/
2023-07-26 12:30:34 +00:00
//static byte *snmp_mib_fill(struct snmp_proto *p, struct oid *oid, u8 mib_class, struct snmp_pdu_context *c);
2022-11-29 15:30:20 +00:00
2023-07-26 12:30:34 +00:00
static void snmp_mib_fill2 ( struct snmp_proto * p , struct oid * oid , struct snmp_pdu_context * c ) ;
2023-03-14 13:10:08 +00:00
static uint parse_response ( struct snmp_proto * p , byte * buf , uint size ) ;
2023-07-26 12:30:34 +00:00
//static uint parse_response(struct snmp_proto *p, byte *buf, uint size);
2022-12-17 17:16:19 +00:00
// static int snmp_stop_ack(sock *sk, uint size);
2023-03-14 13:10:08 +00:00
static void do_response ( struct snmp_proto * p , byte * buf , uint size ) ;
2023-07-26 12:30:34 +00:00
//static uint parse_gets_pdu(struct snmp_proto *p, byte *buf, uint size, uint *skip);
static uint parse_gets2_pdu ( struct snmp_proto * p , byte * buf , uint size , uint * skip ) ;
//static uint parse_gets_pdu(struct snmp_proto *p, struct snmp_pdu_context *c);
// static uint parse_close_pdu(struct snmp_proto *p, struct snmp_pdu_context *c);
2023-03-14 13:10:08 +00:00
static uint parse_close_pdu ( struct snmp_proto * p , byte * buf , uint size ) ;
2023-07-26 12:30:34 +00:00
static struct agentx_response * prepare_response ( struct snmp_proto * p , struct snmp_pdu_context * c ) ;
//static byte *prepare_response(struct snmp_proto *p, struct snmp_pdu_context *c);
//static struct agentx_response *prepare_response(struct snmp_proto *p, byte *buf, uint size);
static void response_err_ind ( struct agentx_response * res , uint err , uint ind ) ;
static void update_packet_size ( struct snmp_proto * p , struct agentx_header * h , byte * start , byte * end ) ;
//static void response_err_ind(byte *buf, uint err, uint ind);
//static struct oid *search_mib(struct snmp_proto *p, struct oid *o_start, struct oid *o_end, struct oid *o_curr, u8 mib_class, struct snmp_pdu_context *c);
static struct oid * search_mib ( struct snmp_proto * p , const struct oid * o_start , const struct oid * o_end , struct oid * o_curr , struct snmp_pdu_context * c , enum snmp_search_res * result ) ;
//static struct oid *search_mib(struct snmp_proto *p, struct oid *o_start, struct oid *o_end, struct oid *o_curr, u8 mib_class, uint contid);
2022-12-17 17:16:19 +00:00
// static inline byte *find_n_fill(struct snmp_proto *p, struct oid *o, byte *buf, uint size, uint contid, int byte_ord);
2023-07-26 12:30:34 +00:00
int snmp_send ( struct snmp_proto * p , struct snmp_pdu_context * c ) ;
2022-11-29 15:30:20 +00:00
2022-08-10 15:31:32 +00:00
static const char * const snmp_errs [ ] = {
# define SNMP_ERR_SHIFT 256
2022-12-17 17:16:19 +00:00
[ AGENTX_RES_OPEN_FAILED - SNMP_ERR_SHIFT ] = " Open failed " ,
[ AGENTX_RES_NOT_OPEN - SNMP_ERR_SHIFT ] = " Not open " ,
[ AGENTX_RES_INDEX_WRONG_TYPE - SNMP_ERR_SHIFT ] = " Index wrong type " ,
2022-08-10 15:31:32 +00:00
[ AGENTX_RES_INDEX_ALREADY_ALLOC - SNMP_ERR_SHIFT ] = " Index already allocated " ,
2022-12-17 17:16:19 +00:00
[ AGENTX_RES_INDEX_NONE_AVAIL - SNMP_ERR_SHIFT ] = " Index none availlable " ,
[ AGENTX_RES_NOT_ALLOCATED - SNMP_ERR_SHIFT ] = " Not allocated " ,
2022-08-10 15:31:32 +00:00
[ AGENTX_RES_UNSUPPORTED_CONTEXT - SNMP_ERR_SHIFT ] = " Unsupported contex " ,
2022-12-17 17:16:19 +00:00
[ AGENTX_RES_DUPLICATE_REGISTER - SNMP_ERR_SHIFT ] = " Duplicate registration " ,
[ AGENTX_RES_UNKNOWN_REGISTER - SNMP_ERR_SHIFT ] = " Unknown registration " ,
[ AGENTX_RES_UNKNOWN_AGENT_CAPS - SNMP_ERR_SHIFT ] = " Unknown agent caps " ,
[ AGENTX_RES_PARSE_ERROR - SNMP_ERR_SHIFT ] = " Parse error " ,
[ AGENTX_RES_REQUEST_DENIED - SNMP_ERR_SHIFT ] = " Request denied " ,
[ AGENTX_RES_PROCESSING_ERR - SNMP_ERR_SHIFT ] = " Processing error " ,
2022-08-10 15:31:32 +00:00
} ;
2022-08-02 14:04:25 +00:00
2022-12-10 17:08:00 +00:00
static const char * const snmp_pkt_type [ ] = {
[ AGENTX_OPEN_PDU ] = " Open-PDU " ,
[ AGENTX_CLOSE_PDU ] = " Close-PDU " ,
[ AGENTX_REGISTER_PDU ] = " Register-PDU " ,
[ AGENTX_UNREGISTER_PDU ] = " Unregister-PDU " ,
[ AGENTX_GET_PDU ] = " Get-PDU " ,
[ AGENTX_GET_NEXT_PDU ] = " GetNext-PDU " ,
[ AGENTX_GET_BULK_PDU ] = " GetBulk-PDU " ,
[ AGENTX_TEST_SET_PDU ] = " TestSet-PDU " ,
[ AGENTX_COMMIT_SET_PDU ] = " CommitSet-PDU " ,
[ AGENTX_UNDO_SET_PDU ] = " UndoSet-PDU " ,
[ AGENTX_CLEANUP_SET_PDU ] = " CleanupSet-PDU " ,
[ AGENTX_NOTIFY_PDU ] = " Notify-PDU " ,
[ AGENTX_PING_PDU ] = " Ping-PDU " ,
[ AGENTX_INDEX_ALLOCATE_PDU ] = " IndexAllocate-PDU " ,
[ AGENTX_INDEX_DEALLOCATE_PDU ] = " IndexDeallocate-PDU " ,
[ AGENTX_ADD_AGENT_CAPS_PDU ] = " AddAgentCaps-PDU " ,
[ AGENTX_REMOVE_AGENT_CAPS_PDU ] = " RemoveAgentCaps-PDU " ,
[ AGENTX_RESPONSE_PDU ] = " Response-PDU " ,
} ;
2022-09-06 16:04:29 +00:00
static void
open_pdu ( struct snmp_proto * p , struct oid * oid )
2022-08-10 15:31:32 +00:00
{
2022-09-06 16:04:29 +00:00
sock * sk = p - > sock ;
2023-07-26 12:30:34 +00:00
struct snmp_pdu_context c = {
. buffer = sk - > tpos ,
. size = sk - > tbuf + sk - > tbsize - sk - > tpos ,
} ;
byte * buf = c . buffer ;
2022-09-06 16:04:29 +00:00
2023-07-26 12:30:34 +00:00
// TODO should be configurable; with check on string length
2022-09-06 16:04:29 +00:00
const char * str = " bird " ;
2023-07-26 12:30:34 +00:00
/* +4 for timeout (1B with 4B alignment) */
if ( c . size < AGENTX_HEADER_SIZE + snmp_oid_size ( oid ) + snmp_str_size ( str ) + 4 )
2022-08-10 15:31:32 +00:00
{
2023-07-26 12:30:34 +00:00
snmp_manage_tbuf ( p , & c ) ;
buf = c . buffer ;
}
2022-09-06 16:04:29 +00:00
2023-07-26 12:30:34 +00:00
c . size - = ( AGENTX_HEADER_SIZE + snmp_oid_size ( oid ) + snmp_str_size ( str ) + 4 ) ;
snmp_log ( " open_pdu() " ) ;
2022-09-06 16:04:29 +00:00
2023-07-26 12:30:34 +00:00
struct agentx_header * h = ( struct agentx_header * ) c . buffer ;
SNMP_BLANK_HEADER ( h , AGENTX_OPEN_PDU ) ;
2022-09-06 16:04:29 +00:00
2023-07-26 12:30:34 +00:00
STORE_U32 ( h - > session_id , 1 ) ;
STORE_U32 ( h - > transaction_id , 1 ) ;
STORE_U32 ( h - > packet_id , 1 ) ;
2022-09-06 16:04:29 +00:00
2023-07-26 12:30:34 +00:00
c . buffer = snmp_put_fbyte ( c . buffer , p - > timeout ) ;
c . buffer = snmp_put_oid ( c . buffer , oid ) ;
c . buffer = snmp_put_str ( c . buffer , str ) ;
2022-09-06 16:04:29 +00:00
2023-07-26 12:30:34 +00:00
update_packet_size ( p , h , buf , c . buffer ) ;
2022-09-06 16:04:29 +00:00
2023-07-26 12:30:34 +00:00
snmp_log ( " send PDU data (open) ... " ) ;
snmp_send ( p , & c ) ;
}
#if 0
static int
de_allocate_pdu ( struct snmp_proto * p , struct oid * oids [ ] , uint len ,
struct agentx_alloc_context * ac , u8 type )
{
sock * sk = p - > sock ;
//byte *buf = sk->tbuf;
//uint size = sk->tbsize;
byte * buf = sk - > tpos ;
uint size = sk - > tbuf + sk - > tbsize - sk - > tpos ;
uint total_len = 0 ;
struct oid * o_curr = NULL ;
for ( uint i = 0 ; i < len ; i + + )
{
o_curr = oids [ i ] ;
uint sz = snmp_oid_size ( o_curr ) ;
total_len + = sz ;
2022-08-10 15:31:32 +00:00
}
2022-09-06 16:04:29 +00:00
2023-07-26 12:30:34 +00:00
if ( total_len = = 0 )
return 0 ;
if ( size < AGENTX_HEADER_SIZE + total_len )
{
// need bigger tx buffer (more mem)
return 0 ;
}
int blank = AGENTX_FLAG_BLANK ;
struct agentx_header * h ;
SNMP_CREATE ( buf , struct agentx_header , h ) ;
SNMP_HEADER ( h , type ,
( ac - > is_instance ? AGENTX_FLAG_INSTANCE_REGISTRATION : blank )
| ( ac - > new_index ? AGENTX_FLAG_NEW_INDEX : blank )
| ( ac - > any_index ? AGENTX_FLAG_ANY_INDEX : blank ) ) ;
ADVANCE ( buf , size , AGENTX_HEADER_SIZE ) ;
STORE ( h - > payload , total_len ) ;
for ( uint i = 0 ; i < len ; i + + )
{
o_curr = oids [ i ] ;
// TODO fix copy to buffer
memcpy ( buf , o_curr , snmp_oid_size ( o_curr ) ) ;
ADVANCE ( buf , size , snmp_oid_size ( o_curr ) ) ;
}
// increment p->packet_id
// queue the allocation request
int ret = sk_send ( sk , total_len ) ;
if ( ret = = 0 )
{
snmp_log ( " sk_send sleep " ) ;
return 1 ;
}
else if ( ret < 0 )
{
snmp_log ( " sk_send err %d " , ret ) ;
return 1 ;
}
2022-08-10 15:31:32 +00:00
else
2023-07-26 12:30:34 +00:00
{
snmp_log ( " sk_send ok !! " ) ;
return 0 ;
}
2022-08-10 15:31:32 +00:00
}
2023-07-26 12:30:34 +00:00
static int UNUSED
index_allocate_pdu ( struct snmp_proto * p , struct oid * oids [ ] , uint len , struct
agentx_alloc_context * ac )
{
return de_allocate_pdu ( p , oids , len , ac , AGENTX_INDEX_ALLOCATE_PDU ) ;
}
static int UNUSED
index_deallocate_pdu ( struct snmp_proto * p , struct oid * oids [ ] , uint len , struct
agentx_alloc_context * ac )
{
return de_allocate_pdu ( p , oids , len , ac , AGENTX_INDEX_DEALLOCATE_PDU ) ;
}
# endif
2022-09-06 16:04:29 +00:00
/* index allocate / deallocate pdu * /
2022-08-10 15:31:32 +00:00
static void
2022-09-06 16:04:29 +00:00
de_allocate_pdu ( struct snmp_proto * p , struct oid * oid , u8 type )
2022-08-10 15:31:32 +00:00
{
sock * sk = p - > sock ;
2022-09-06 16:04:29 +00:00
byte * buf , * pkt ;
2022-08-10 15:31:32 +00:00
buf = pkt = sk - > tbuf ;
uint size = sk - > tbsize ;
2023-07-26 12:34:01 +00:00
2022-09-06 16:04:29 +00:00
if ( size > AGENTX_HEADER_SIZE + )
{
2022-12-10 12:22:37 +00:00
snmp_log ( " de_allocate_pdu() " ) ;
2022-08-10 15:31:32 +00:00
2022-09-06 16:04:29 +00:00
struct agentx_header * h ;
SNMP_CREATE ( pkt , struct agentx_header , h ) ;
2023-07-26 12:30:34 +00:00
SNMP_BLANK_HEADER ( h , type ) ;
2022-09-06 16:04:29 +00:00
SNMP_SESSION ( h , p ) ;
2022-08-10 15:31:32 +00:00
2022-09-06 16:04:29 +00:00
struct agentx_varbind * vb = ( struct agentx_varbind * ) pkt ;
STORE_16 ( vb - > type , AGENTX_OBJECT_ID ) ;
STORE ( vb - > oid ,
}
else
2022-12-10 12:22:37 +00:00
snmp_log ( " de_allocate_pdu(): insufficient size " ) ;
2022-09-06 16:04:29 +00:00
}
*/
/* register / unregister pdu */
static void
un_register_pdu ( struct snmp_proto * p , struct oid * oid , uint index , uint len , u8 type )
{
sock * sk = p - > sock ;
2023-07-26 12:30:34 +00:00
//buf = pkt = sk->tbuf;
//uint size = sk->tbsize;
struct snmp_pdu_context c = {
. buffer = sk - > tpos ,
. size = sk - > tbuf + sk - > tbsize - sk - > tpos ,
} ;
byte * buf = c . buffer ;
2022-09-06 16:04:29 +00:00
/* conditional +4 for upper-bound */
2023-07-26 12:30:34 +00:00
if ( c . size < AGENTX_HEADER_SIZE + snmp_oid_size ( oid ) + ( ( len > 1 ) ? 4 : 0 ) )
2022-08-10 15:31:32 +00:00
{
2023-07-26 12:30:34 +00:00
snmp_log ( " un_register_pdu() insufficient size " ) ;
snmp_manage_tbuf ( p , & c ) ;
buf = c . buffer ;
}
2022-09-06 16:04:29 +00:00
2023-07-26 12:30:34 +00:00
snmp_log ( " un_register_pdu() " ) ;
struct agentx_un_register_pdu * ur = ( struct agentx_un_register_pdu * ) c . buffer ;
ADVANCE ( c . buffer , c . size , sizeof ( struct agentx_un_register_pdu ) ) ;
struct agentx_header * h = & ur - > h ;
// FIXME correctly set INSTANCE REGISTRATION bit
SNMP_HEADER ( h , type , AGENTX_FLAG_INSTANCE_REGISTRATION ) ;
/* use new transactionID, reset packetID */
p - > transaction_id + + ;
p - > packet_id = 1 ;
SNMP_SESSION ( h , p ) ;
/* do not override timeout */
STORE_U32 ( ur - > timeout , 15 ) ;
/* default priority */
STORE_U32 ( ur - > priority , AGENTX_PRIORITY ) ;
STORE_U32 ( ur - > range_subid , ( len > 1 ) ? index : 0 ) ;
snmp_put_oid ( c . buffer , oid ) ;
ADVANCE ( c . buffer , c . size , snmp_oid_size ( oid ) ) ;
// snmp_log("pkt - buf : %lu sizeof %u", pkt -buf, AGENTX_HEADER_SIZE);
/* place upper-bound if needed */
if ( len > 1 )
{
STORE_PTR ( c . buffer , len ) ;
ADVANCE ( c . buffer , c . size , 4 ) ;
}
2022-09-06 16:04:29 +00:00
2023-07-26 12:30:34 +00:00
/* buf - start, pkt - end */
update_packet_size ( p , h , buf , c . buffer ) ;
2022-08-10 15:31:32 +00:00
2023-07-26 12:30:34 +00:00
/*
for ( uint i = 0 ; i < pkt - buf ; i + + )
snmp_log ( " %p: %02X " , buf + i , * ( buf + i ) ) ;
*/
2022-08-10 15:31:32 +00:00
2023-07-26 12:30:34 +00:00
snmp_log ( " sending (un)register %s " , snmp_pkt_type [ type ] ) ;
snmp_send ( p , & c ) ;
2022-09-06 16:04:29 +00:00
}
/* register pdu */
2022-12-10 17:08:00 +00:00
void
2022-09-06 16:04:29 +00:00
snmp_register ( struct snmp_proto * p , struct oid * oid , uint index , uint len )
{
un_register_pdu ( p , oid , index , len , AGENTX_REGISTER_PDU ) ;
}
/* unregister pdu */
2022-12-10 17:08:00 +00:00
void UNUSED
2022-09-06 16:04:29 +00:00
snmp_unregister ( struct snmp_proto * p , struct oid * oid , uint index , uint len )
{
un_register_pdu ( p , oid , index , len , AGENTX_UNREGISTER_PDU ) ;
2022-08-10 15:31:32 +00:00
}
static void
close_pdu ( struct snmp_proto * p , u8 reason )
2022-08-02 14:04:25 +00:00
{
2022-08-10 15:31:32 +00:00
sock * sk = p - > sock ;
2023-07-26 12:30:34 +00:00
struct snmp_pdu_context c = {
. buffer = sk - > tpos ,
. size = sk - > tbuf + sk - > tbsize - sk - > tpos ,
} ;
byte * buf = c . buffer ;
snmp_log ( " close_pdu() size: %u %c %u " , c . size , ( c . size > AGENTX_HEADER_SIZE + 4 )
2022-08-10 15:31:32 +00:00
? ' > ' : ' < ' , AGENTX_HEADER_SIZE ) ;
2022-08-02 14:04:25 +00:00
2022-08-10 15:31:32 +00:00
/* +4B for reason */
2023-07-26 12:30:34 +00:00
if ( c . size < AGENTX_HEADER_SIZE + 4 )
2022-08-10 15:31:32 +00:00
{
2023-07-26 12:30:34 +00:00
snmp_manage_tbuf ( p , & c ) ;
buf = c . buffer ;
}
struct agentx_header * h = ( struct agentx_header * ) c . buffer ;
ADVANCE ( c . buffer , c . size , AGENTX_HEADER_SIZE ) ;
SNMP_BLANK_HEADER ( h , AGENTX_CLOSE_PDU ) ;
SNMP_SESSION ( h , p ) ;
snmp_put_fbyte ( c . buffer , reason ) ;
ADVANCE ( c . buffer , c . size , 4 ) ;
update_packet_size ( p , h , buf , c . buffer ) ;
snmp_log ( " preparing to sk_send() (close) " ) ;
snmp_send ( p , & c ) ;
}
#if 0
static void UNUSED
parse_testset_pdu ( struct snmp_proto * p )
{
sock * sk = p - > sock ;
sk_send ( sk , 0 ) ;
}
static void UNUSED
parse_commitset_pdu ( struct snmp_proto * p )
{
sock * sk = p - > sock ;
sk_send ( sk , 0 ) ;
}
static void UNUSED
parse_undoset_pdu ( struct snmp_proto * p )
{
sock * sk = p - > sock ;
sk_send ( sk , 0 ) ;
}
static void UNUSED
parse_cleanupset_pdu ( struct snmp_proto * p )
{
sock * sk = p - > sock ;
sk_send ( sk , 0 ) ;
}
static void UNUSED
addagentcaps_pdu ( struct snmp_proto * p , struct oid * cap , char * descr ,
uint descr_len , struct agentx_context * c )
{
ASSUME ( descr ! = NULL & & descr_len > 0 ) ;
sock * sk = p - > sock ;
//byte *buf = sk->tbuf;
//uint size = sk->tbsize;
// TODO rename to pkt and add pkt_start
byte * buf = sk - > tpos ;
uint size = sk - > tbuf + sk - > tbsize - sk - > tpos ;
if ( size < AGENTX_HEADER_SIZE + snmp_context_size ( c ) + snmp_oid_size ( cap ) + snmp_str_size_from_len ( descr_len ) )
{
/* TODO need more mem */
return ;
}
struct agentx_header * h ;
SNMP_CREATE ( buf , struct agentx_header , h ) ;
SNMP_BLANK_HEADER ( h , AGENTX_ADD_AGENT_CAPS_PDU ) ;
SNMP_SESSION ( h , p ) ;
ADVANCE ( buf , size , AGENTX_HEADER_SIZE ) ;
2022-08-02 14:04:25 +00:00
2023-07-26 12:30:34 +00:00
uint in_pkt ;
if ( c & & c - > length )
{
SNMP_HAS_CONTEXT ( h ) ;
in_pkt = snmp_put_nstr ( buf , c - > context , c - > length ) - buf ;
ADVANCE ( buf , size , in_pkt ) ;
}
2022-08-02 14:04:25 +00:00
2023-07-26 12:30:34 +00:00
memcpy ( buf , cap , snmp_oid_size ( cap ) ) ;
ADVANCE ( buf , size , snmp_oid_size ( cap ) ) ;
2022-08-02 14:12:09 +00:00
2023-07-26 12:30:34 +00:00
in_pkt = snmp_put_nstr ( buf , descr , descr_len ) - buf ;
ADVANCE ( buf , size , in_pkt ) ;
// make a note in the snmp_proto structure
//int ret = sk_send(sk, buf - sk->tbuf);
int ret = sk_send ( sk , buf - sk - > tpos ) ;
if ( ret = = 0 )
snmp_log ( " sk_send sleep " ) ;
else if ( ret < 0 )
snmp_log ( " sk_send err " ) ;
else
log ( L_INFO , " sk_send ok !! " ) ;
}
static void UNUSED
removeagentcaps_pdu ( struct snmp_proto * p , struct oid * cap , struct agentx_context * c )
{
sock * sk = p - > sock ;
//byte *buf = sk->tbuf;
//uint size = sk->tbsize;
// TODO rename to pkt and add pkt_start
byte * buf = sk - > tpos ;
uint size = sk - > tbuf + sk - > tbsize - sk - > tpos ;
if ( size < AGENTX_HEADER_SIZE + snmp_context_size ( c ) + snmp_oid_size ( cap ) )
{
/* TODO need more mem */
return ;
}
2022-08-02 14:04:25 +00:00
2023-07-26 12:30:34 +00:00
struct agentx_header * h ;
SNMP_CREATE ( buf , struct agentx_header , h ) ;
SNMP_SESSION ( h , p ) ;
ADVANCE ( buf , size , AGENTX_HEADER_SIZE ) ;
2022-08-10 15:31:32 +00:00
2023-07-26 12:34:01 +00:00
uint in_pkt ;
if ( c & & c - > length )
{
SNMP_HAS_CONTEXT ( h ) ;
in_pkt = snmp_put_nstr ( buf , c - > context , c - > length ) - buf ;
ADVANCE ( buf , size , in_pkt ) ;
2022-08-10 15:31:32 +00:00
}
2023-07-26 12:34:01 +00:00
memcpy ( buf , cap , snmp_oid_size ( cap ) ) ;
ADVANCE ( buf , size , snmp_oid_size ( cap ) ) ;
// update state in snmp_proto structure
//int ret = sk_send(sk, buf - sk->tbuf);
int ret = sk_send ( sk , buf - sk - > tpos ) ;
if ( ret = = 0 )
snmp_log ( " sk_send sleep " ) ;
else if ( ret < 0 )
snmp_log ( " sk_send err " ) ;
else
log ( L_INFO , " sk_send ok !! " ) ;
2022-08-10 15:31:32 +00:00
}
2023-07-26 12:34:01 +00:00
# endif
2022-08-10 15:31:32 +00:00
2022-09-06 16:04:29 +00:00
static inline void
refresh_ids ( struct snmp_proto * p , struct agentx_header * h )
{
int byte_ord = h - > flags & AGENTX_NETWORK_BYTE_ORDER ;
p - > transaction_id = LOAD ( h - > transaction_id , byte_ord ) ;
p - > packet_id = LOAD ( h - > packet_id , byte_ord ) ;
}
2023-03-14 13:10:08 +00:00
/**
* parse_pkt - parse recieved response packet
* @ p :
* @ pkt : packet buffer
* @ size : number of packet bytes in buffer
* retval number of byte parsed
*
2023-03-24 14:02:23 +00:00
* function parse_ptk ( ) parses response - pdu and calls do_response ( ) .
* returns number of bytes parsed by function excluding size of header .
2023-03-14 13:10:08 +00:00
*/
static uint
2023-07-26 12:30:34 +00:00
parse_pkt ( struct snmp_proto * p , byte * pkt , uint size , uint * skip )
2022-08-10 15:31:32 +00:00
{
2023-03-14 13:10:08 +00:00
snmp_log ( " parse_ptk() pkt start: %p " , pkt ) ;
2023-07-26 12:30:34 +00:00
//snmp_dump_packet(p->sock->tbuf, 64);
2023-03-14 13:10:08 +00:00
2023-07-26 12:30:34 +00:00
if ( size < AGENTX_HEADER_SIZE )
2022-08-10 15:31:32 +00:00
return 0 ;
2023-03-14 13:10:08 +00:00
uint parsed_len = 0 ;
struct agentx_header * h = ( void * ) pkt ;
2022-12-10 17:08:00 +00:00
snmp_log ( " parse_pkt got type %s " , snmp_pkt_type [ h - > type ] ) ;
2023-07-26 12:30:34 +00:00
snmp_dump_packet ( ( void * ) h , MIN ( h - > payload , 256 ) ) ;
//snmp_dump_packet((void *)h, LOAD(h->payload, h->flags & AGENTX_NETWORK_BYTE_ORDER));
2022-08-10 15:31:32 +00:00
switch ( h - > type )
{
case AGENTX_RESPONSE_PDU :
2023-03-14 13:10:08 +00:00
snmp_log ( " parse_pkt returning parse_response " ) ;
parsed_len = parse_response ( p , pkt , size ) ;
break ;
2022-09-06 16:04:29 +00:00
2022-09-20 12:28:57 +00:00
/*
2022-09-06 16:04:29 +00:00
case AGENTX_GET_PDU :
refresh_ids ( p , h ) ;
2023-03-14 13:10:08 +00:00
return parse_get_pdu ( p , pkt , size ) ;
2022-09-20 12:28:57 +00:00
*/
case AGENTX_GET_PDU :
case AGENTX_GET_NEXT_PDU :
2022-09-30 07:36:09 +00:00
case AGENTX_GET_BULK_PDU :
2022-09-20 12:28:57 +00:00
refresh_ids ( p , h ) ;
2023-07-26 12:30:34 +00:00
//parsed_len = parse_gets_pdu(p, &c);
//parsed_len = parse_gets_pdu(p, pkt, size, skip);
parsed_len = parse_gets2_pdu ( p , pkt , size , skip ) ;
2022-09-30 07:36:09 +00:00
break ;
2022-08-10 15:31:32 +00:00
2023-03-14 13:10:08 +00:00
/* during testing the connection should stay opened (we die if we screw up
* and get CLOSE_PDU in response )
case AGENTX_CLOSE_PDU :
refresh_ids ( p , h ) ;
parsed_len = parse_close_pdu ( p , pkt , size ) ;
break ;
*/
2022-08-10 15:31:32 +00:00
/* should not happen */
default :
2023-07-26 12:30:34 +00:00
snmp_log ( " unknown packet type %u " , h - > type ) ;
return 0 ;
//die("unknown packet type %u", h->type);
2022-08-10 15:31:32 +00:00
}
2022-09-30 07:36:09 +00:00
2023-07-26 12:30:34 +00:00
/* We will process the same header again later * /
if ( * skip | | parsed_len < size )
2022-09-30 07:36:09 +00:00
{
2023-07-26 12:30:34 +00:00
/ * We split our answer to multiple packet , we should differentiate them * /
h - > packet_id + + ;
2022-09-30 07:36:09 +00:00
}
2023-03-14 13:10:08 +00:00
*/
2022-09-30 07:36:09 +00:00
2023-03-14 13:10:08 +00:00
snmp_log ( " parse_pkt returning parsed length " ) ;
2023-07-26 12:30:34 +00:00
//snmp_dump_packet(p->sock->tbuf, 64);
2023-03-14 13:10:08 +00:00
return parsed_len ;
2022-08-10 15:31:32 +00:00
}
2023-03-14 13:10:08 +00:00
static uint
parse_response ( struct snmp_proto * p , byte * res , uint size )
2022-08-10 15:31:32 +00:00
{
2022-12-17 17:16:19 +00:00
snmp_log ( " parse_response() g%u h%u " , size , sizeof ( struct agentx_header ) ) ;
2023-07-26 12:30:34 +00:00
//snmp_dump_packet(res, size);
2022-12-17 17:16:19 +00:00
2022-08-10 15:31:32 +00:00
if ( size < sizeof ( struct agentx_response ) )
return 0 ;
2023-03-14 13:10:08 +00:00
struct agentx_response * r = ( void * ) res ;
2022-08-10 15:31:32 +00:00
struct agentx_header * h = & r - > h ;
2023-03-14 13:10:08 +00:00
int byte_ord = h - > flags & AGENTX_NETWORK_BYTE_ORDER ;
2023-07-26 12:30:34 +00:00
2023-03-14 13:10:08 +00:00
uint pkt_size = LOAD ( h - > payload , byte_ord ) ;
snmp_log ( " p_res pkt_size %u " , pkt_size ) ;
2023-07-26 12:30:34 +00:00
if ( size < pkt_size + AGENTX_HEADER_SIZE ) {
2023-03-14 13:10:08 +00:00
snmp_log ( " parse_response early return " ) ;
return 0 ;
}
2023-07-26 12:30:34 +00:00
snmp_log ( " endianity: %s, session %u, transaction: %u " ,
( h - > flags & AGENTX_NETWORK_BYTE_ORDER ) ? " big end " : " little end " ,
h - > session_id , h - > transaction_id ) ;
2022-12-17 17:16:19 +00:00
snmp_log ( " sid: %3u \t tid: %3u \t pid: %3u " , p - > session_id , p - > transaction_id ,
2023-03-24 14:02:23 +00:00
p - > packet_id ) ;
2022-09-06 16:04:29 +00:00
2022-12-10 17:08:00 +00:00
snmp_log ( " pkt size %u " , h - > payload ) ;
2022-09-06 16:04:29 +00:00
2023-07-26 12:30:34 +00:00
if ( r - > error = = AGENTX_RES_NO_ERROR )
2023-03-14 13:10:08 +00:00
do_response ( p , res , size ) ;
2022-09-06 16:04:29 +00:00
else
2023-03-14 13:10:08 +00:00
/* erronous packet should be dropped quietly */
2023-07-26 12:30:34 +00:00
snmp_log ( " an error occured '%s' " , snmp_errs [ get_u16 ( & r - > error ) - SNMP_ERR_SHIFT ] ) ;
2022-09-06 16:04:29 +00:00
2023-07-26 12:30:34 +00:00
return pkt_size + AGENTX_HEADER_SIZE ;
2022-09-06 16:04:29 +00:00
}
2022-12-10 17:08:00 +00:00
static inline int
snmp_registered_all ( struct snmp_proto * p )
{
2022-12-17 17:16:19 +00:00
snmp_log ( " snmp_registered_all() %u " , list_length ( & p - > register_queue ) ) ;
2022-12-10 17:08:00 +00:00
return p - > register_to_ack = = 0 ;
}
static void
2023-07-26 12:34:01 +00:00
snmp_register_mibs ( struct snmp_proto * p )
{
2022-12-10 17:08:00 +00:00
snmp_log ( " snmp_register_mibs() " ) ;
snmp_bgp_register ( p ) ;
snmp_log ( " registering all done " ) ;
}
2023-03-14 13:10:08 +00:00
static void
2022-09-20 12:28:57 +00:00
do_response ( struct snmp_proto * p , byte * buf , uint size UNUSED )
2022-09-06 16:04:29 +00:00
{
2022-12-10 17:08:00 +00:00
snmp_log ( " do_response() " ) ;
2022-09-06 16:04:29 +00:00
struct agentx_response * r = ( void * ) buf ;
struct agentx_header * h = & r - > h ;
2023-07-26 12:30:34 +00:00
int byte_ord = h - > flags & AGENTX_NETWORK_BYTE_ORDER ;
2022-12-17 17:16:19 +00:00
2023-03-14 13:10:08 +00:00
/* TO DO make it asynchronous for better speed */
2022-09-06 16:04:29 +00:00
switch ( p - > state )
2022-08-10 15:31:32 +00:00
{
2022-09-06 16:04:29 +00:00
case SNMP_INIT :
2023-07-26 12:30:34 +00:00
/* copy session info from recieved packet */
p - > session_id = LOAD ( h - > session_id , byte_ord ) ;
refresh_ids ( p , h ) ;
2022-09-06 16:04:29 +00:00
2022-12-17 17:16:19 +00:00
/* the state needs to be changed before sending registering PDUs to
* use correct do_response action on them
*/
2022-12-10 17:08:00 +00:00
snmp_log ( " changing state to REGISTER " ) ;
2022-12-17 17:16:19 +00:00
p - > state = SNMP_REGISTER ;
snmp_register_mibs ( p ) ;
snmp_log ( " do_response state SNMP_INIT register list %u " , list_length ( & p - > register_queue ) ) ;
2022-12-10 17:08:00 +00:00
2022-08-10 15:31:32 +00:00
break ;
2022-09-06 16:04:29 +00:00
2022-12-17 17:16:19 +00:00
case SNMP_REGISTER :
snmp_log ( " do_response state SNMP_REGISTER register list %u " , list_length ( & p - > register_queue ) ) ;
snmp_register_ack ( p , h ) ;
2022-12-10 17:08:00 +00:00
if ( snmp_registered_all ( p ) ) {
snmp_log ( " changing proto_snmp state to CONNECTED " ) ;
p - > state = SNMP_CONN ;
}
2022-08-10 15:31:32 +00:00
break ;
2022-09-06 16:04:29 +00:00
case SNMP_CONN :
2022-12-10 17:08:00 +00:00
// proto_notify_state(&p->p, PS_UP);
2022-09-06 16:04:29 +00:00
break ;
2022-12-17 17:16:19 +00:00
case SNMP_STOP :
/* do nothing here */
break ;
2022-09-06 16:04:29 +00:00
default :
die ( " unkonwn SNMP state " ) ;
2022-08-10 15:31:32 +00:00
}
2022-09-06 16:04:29 +00:00
}
2023-07-26 12:30:34 +00:00
u8
snmp_get_mib_class ( const struct oid * oid )
2022-11-05 15:29:00 +00:00
{
2023-07-26 12:30:34 +00:00
// TODO check code paths for oid->n_subid < 3
2022-11-05 15:29:00 +00:00
if ( oid - > prefix ! = 2 & & oid - > ids [ 0 ] ! = 1 )
return SNMP_CLASS_INVALID ;
switch ( oid - > ids [ 1 ] )
{
case SNMP_BGP4_MIB :
return SNMP_CLASS_BGP ;
default :
return SNMP_CLASS_END ;
2022-12-10 17:08:00 +00:00
}
2022-11-05 15:29:00 +00:00
}
2022-09-20 12:28:57 +00:00
2023-07-26 12:30:34 +00:00
#if 0
2022-11-19 22:00:02 +00:00
static byte *
snmp_get_next ( struct snmp_proto * p , struct oid * o_start , struct oid * o_end ,
2023-07-26 12:30:34 +00:00
u8 mib_class , struct snmp_pdu_context * c )
2022-11-19 22:00:02 +00:00
{
2022-12-10 12:22:37 +00:00
snmp_log ( " type GetNext-PDU " ) ;
2023-07-26 12:30:34 +00:00
enum snmp_search_res r ;
struct oid * o_copy = search_mib ( p , o_start , o_end , NULL , c , & r ) ;
2022-11-19 22:00:02 +00:00
2022-12-10 12:22:37 +00:00
snmp_log ( " search result " ) ;
2022-11-19 22:00:02 +00:00
snmp_oid_dump ( o_copy ) ;
2023-07-26 12:30:34 +00:00
byte * read ;
2022-11-19 22:00:02 +00:00
if ( o_copy )
{
2023-07-26 12:30:34 +00:00
read = snmp_mib_fill ( p , o_copy , mib_class , c ) ;
2022-11-19 22:00:02 +00:00
mb_free ( o_copy ) ;
}
2022-11-29 15:30:20 +00:00
else
{
2023-07-26 12:30:34 +00:00
struct agentx_varbind * vb = snmp_create_varbind ( c - > buffer , o_start ) ;
c - > buffer + = snmp_varbind_header_size ( vb ) ;
vb - > type = snmp_search_res_to_type ( r ) ;
//vb->type = AGENTX_NO_SUCH_OBJECT;
2022-11-29 15:30:20 +00:00
}
2022-11-19 22:00:02 +00:00
2022-12-10 12:22:37 +00:00
snmp_log ( " over HERE " ) ;
2023-07-26 12:30:34 +00:00
return read ;
2022-11-19 22:00:02 +00:00
}
2023-07-26 12:30:34 +00:00
# endif
2022-11-19 22:00:02 +00:00
2023-07-26 12:30:34 +00:00
static void
snmp_get_next2 ( struct snmp_proto * p , struct oid * o_start , struct oid * o_end ,
struct snmp_pdu_context * c )
{
snmp_log ( " get_next2() " ) ;
enum snmp_search_res r ;
snmp_log ( " next2() o_end %p " , o_end ) ;
struct oid * o_copy = search_mib ( p , o_start , o_end , NULL , c , & r ) ;
snmp_log ( " next2()2 o_end %p " , o_end ) ;
if ( o_copy )
snmp_mib_fill2 ( p , o_copy , c ) ;
else
{
// FIXME check that we have enough space
struct agentx_varbind * vb = snmp_create_varbind ( c - > buffer , o_start ) ;
vb - > type = AGENTX_NO_SUCH_OBJECT ;
/* snmp_varbind_size depends on vb->type */
ADVANCE ( c - > buffer , c - > size , snmp_varbind_size ( vb , c - > byte_ord ) ) ;
}
}
#if 0
2022-11-19 22:00:02 +00:00
static byte *
2023-07-26 12:30:34 +00:00
snmp_get_bulk ( struct snmp_proto * p , struct oid * o_start , struct oid * o_end ,
struct agentx_bulk_state * state , struct snmp_pdu_context * c )
2022-11-19 22:00:02 +00:00
{
2022-12-10 12:22:37 +00:00
snmp_log ( " type GetBulk-PDU " ) ;
2023-03-14 13:10:08 +00:00
// TODO add state cache (to prevent O(n^2) complexity)
2022-11-19 22:00:02 +00:00
if ( state - > index < = state - > getbulk . non_repeaters )
{
2023-07-26 12:30:34 +00:00
( void ) 0 ;
//return snmp_get_next(p, o_start, o_end, mib_class, c);
//return snmp_get_next(p, o_start, o_end, pkt, size, contid, mib_class, byte_ord);
return NULL ;
2022-11-19 22:00:02 +00:00
}
else
{
2023-07-26 12:30:34 +00:00
u8 mib_class ;
2022-11-19 22:00:02 +00:00
struct oid * o_curr = NULL ;
2023-07-26 12:30:34 +00:00
struct oid * o_predecessor = NULL ;
enum snmp_search_res r ;
2022-11-19 22:00:02 +00:00
uint i = 0 ;
do
{
o_predecessor = o_curr ;
2023-07-26 12:30:34 +00:00
o_curr = search_mib ( p , o_start , o_end , o_curr , c , & r ) ;
//o_curr = search_mib(p, o_start, o_end, o_curr, mib_class, contid);
mib_class = snmp_get_mib_class ( o_curr ) ;
2022-11-19 22:00:02 +00:00
i + + ;
} while ( o_curr ! = NULL & & i < state - > repetition ) ;
log ( " bulk search result - repeating " ) ;
snmp_oid_dump ( o_curr ) ;
2023-07-26 12:30:34 +00:00
if ( ! o_curr & & i = = 0 )
{
//vb->name = o_start;
//vb->type = AGENTX_RES_END_OF_MIB_VIEW;
return NULL ;
}
if ( ! o_curr )
{
ASSUME ( o_predecessor ! = NULL ) ;
//vb->name = o_predecessor;
//vb->type = AGENTX_RES_END_OF_MIB_VIEW;
return NULL ;
}
( void ) mib_class ;
//return snmp_mib_fill(p, o_curr, mib_class, c);
return NULL ;
}
}
# endif
static void
snmp_get_bulk2 ( struct snmp_proto * p , struct oid * o_start , struct oid * o_end ,
struct agentx_bulk_state * state , struct snmp_pdu_context * c )
{
if ( state - > index < = state - > getbulk . non_repeaters )
return snmp_get_next2 ( p , o_start , o_end , c ) ;
else
{
struct oid * o_curr = NULL ;
struct oid * o_predecessor = NULL ;
enum snmp_search_res r ;
uint i = 0 ;
do
{
o_predecessor = o_curr ;
o_curr = search_mib ( p , o_start , o_end , o_curr , c , & r ) ;
i + + ;
} while ( o_curr & & i < = state - > repetition ) ;
if ( ! o_curr & & i = = 1 )
{
o_predecessor = o_start ;
goto abnormal ;
}
2022-11-19 22:00:02 +00:00
2023-07-26 12:30:34 +00:00
if ( ! o_curr )
goto abnormal ;
return snmp_mib_fill2 ( p , o_curr , c ) ;
abnormal : ;
uint sz = snmp_varbind_hdr_size_from_oid ( o_predecessor ) ;
if ( c - > size < sz )
{
snmp_log ( " snmp_get_bulk2() insufficient amount of memory in TX buffer, returning GET_ERROR " ) ;
c - > error = AGENTX_RES_GEN_ERROR ;
return ;
}
struct agentx_varbind * vb = snmp_create_varbind ( c - > buffer , o_predecessor ) ;
vb - > type = AGENTX_END_OF_MIB_VIEW ;
ADVANCE ( c - > buffer , c - > size , snmp_varbind_size ( vb , c - > byte_ord ) ) ;
2022-11-19 22:00:02 +00:00
}
}
2023-07-26 12:30:34 +00:00
static uint UNUSED
parse_close_pdu ( struct snmp_proto UNUSED * p , byte UNUSED * req , uint UNUSED size )
2023-03-14 13:10:08 +00:00
{
/*
snmp_log ( " parse_close_pdu() " ) ;
// byte *pkt = req;
// sock *sk = p->sock;
if ( size < sizeof ( struct agentx_header ) )
{
snmp_log ( " p_close early return " ) ;
return 0 ;
}
// struct agentx_header *h = (void *) req;
ADVANCE ( req , size , AGENTX_HEADER_SIZE ) ;
//snmp_log("after header %p", req);
p - > state = SNMP_ERR ;
*/
return 0 ;
}
2023-07-26 12:30:34 +00:00
static inline void
update_packet_size ( struct snmp_proto * p , struct agentx_header * h , byte * start , byte * end )
{
uint size ;
if ( EMPTY_LIST ( p - > additional_buffers ) )
size = snmp_pkt_len ( start , end ) ;
else
size = p - > to_send ;
/* TODO add packet size limiting
* we couldn ' t overflow the size because we limit the maximum packet size
*/
struct additional_buffer * b ;
WALK_LIST ( b , p - > additional_buffers )
{
size + = b - > pos - b - > buf ;
}
STORE_U32 ( h - > payload , size ) ;
// if (p->additional_buffers)
// STORE_U32(h->payload, p->to_send + (end - start));
// else {}
//// STORE_U32(h->payload, snmp_pkt_len(start, end));
}
static inline void
response_err_ind ( struct agentx_response * res , uint err , uint ind )
{
STORE_U32 ( res - > error , err ) ;
if ( err ! = AGENTX_RES_NO_ERROR & & err ! = AGENTX_RES_PARSE_ERROR )
STORE_U32 ( res - > index , ind ) ;
else
STORE_U32 ( res - > index , 0 ) ;
}
static uint
parse_gets2_pdu ( struct snmp_proto * p , byte * const pkt_start , uint size , uint * skip )
{
snmp_log ( " parse_gets2_pdu() " ) ;
struct oid * o_start = NULL , * o_end = NULL ;
byte * pkt = pkt_start ;
struct agentx_header * h = ( void * ) pkt ;
ADVANCE ( pkt , size , AGENTX_HEADER_SIZE ) ;
uint pkt_size = LOAD ( h - > payload , h - > flags & AGENTX_NETWORK_BYTE_ORDER ) ;
sock * sk = p - > sock ;
struct snmp_pdu_context c = {
//.buffer = sk->tbuf,
//.size = sk->tbsize,
. buffer = sk - > tpos ,
. size = sk - > tbuf + sk - > tbsize - sk - > tpos ,
. byte_ord = h - > flags & AGENTX_NETWORK_BYTE_ORDER ,
. error = AGENTX_RES_NO_ERROR ,
. context = 0 ,
} ;
//snmp_dump_packet(sk->tbuf, 64);
uint clen ; /* count of characters in context (without last '\0') */
char * context ; /* newly allocated string of character */
/* alters pkt; assign context, clen */
SNMP_LOAD_CONTEXT ( p , h , pkt , context , clen ) ;
/*
* We need more data ; for valid response we need to know full
* header picture , including the context octet string
*/
if ( size < clen )
{
snmp_log ( " size %u < %u clen, returning 0 " , size , clen ) ;
goto wait ;
}
/*
* It is a malformed packet if the context octet string should be longer than
* whole packet .
*/
if ( pkt_size < clen )
{
/* for malformed packets consume full pkt_size [or size] */
c . error = AGENTX_RES_PARSE_ERROR ;
goto send ;
}
/* The RFC does not consider the context octet string as a part of a header */
ADVANCE ( pkt , pkt_size , clen ) ;
size - = clen ;
/* FIXME add support for c.context hashing
c . context = . . .
*/
struct agentx_bulk_state bulk_state = { 0 } ;
if ( c . size < sizeof ( struct agentx_response ) )
{
die ( " gets2: too small tx buffer " ) ;
snmp_manage_tbuf ( p , & c ) ;
}
struct agentx_response * response_header = prepare_response ( p , & c ) ;
uint ind = 1 ;
while ( c . error = = AGENTX_RES_NO_ERROR & & size > 0 & & pkt_size > 0 )
{
snmp_log ( " iter %u ``size'' %u " , ind , c . buffer - ( ( byte * ) response_header ) ) ;
if ( size < snmp_oid_sizeof ( 0 ) )
goto partial ;
/* We load search range start OID */
const struct oid * o_start_b = ( void * ) pkt ;
uint sz ;
if ( ( sz = snmp_oid_size ( o_start_b ) ) > pkt_size )
{
/* for malformed packets consume full pkt_size [or size] */
c . error = AGENTX_RES_PARSE_ERROR ; /* Packet error, inconsistent values */
goto send ;
}
/*
* If we already have written same relevant data to the tx - buffer then
* we send processed part , otherwise we don ' t have anything to send and
* need to wait for more data to be recieved .
*/
if ( sz > size & & ind > 1 )
{
snmp_log ( " sz %u > %u size && ind %u > 1 " , sz , size , ind ) ;
goto partial ; /* send already processed part */
}
else if ( sz > size )
{
snmp_log ( " sz %u > %u size; returning 0 " , sz , size ) ;
goto wait ;
}
/* update buffer pointer and remaining size counters */
ADVANCE ( pkt , pkt_size , sz ) ;
size - = sz ;
/* We load search range end OID
* The exactly same process of sanity checking is preformed while loading
* the SearchRange ' s end OID
*/
const struct oid * o_end_b = ( void * ) pkt ;
if ( ( sz = snmp_oid_size ( o_end_b ) ) > pkt_size )
{
c . error = AGENTX_RES_PARSE_ERROR ; /* Packet error, inconsistent values */
goto send ;
}
if ( sz > size & & ind > 1 )
{
snmp_log ( " sz2 %u > %u size && ind %u > 1 " , sz , size , ind ) ;
size + = snmp_oid_size ( o_start_b ) ;
goto partial ;
}
else if ( sz > size )
{
snmp_log ( " sz2 %u > %u size; returning 0 " , sz , size ) ;
goto wait ;
}
ADVANCE ( pkt , pkt_size , sz ) ;
size - = sz ;
/* We create copy of OIDs outside of rx-buffer and also prefixize them */
o_start = snmp_prefixize ( p , o_start_b , c . byte_ord ) ;
o_end = snmp_prefixize ( p , o_end_b , c . byte_ord ) ;
if ( ! snmp_is_oid_empty ( o_end ) & & snmp_oid_compare ( o_start , o_end ) > 0 )
{
snmp_log ( " snmp_gets2() o_start does not preceed o_end, returning GEN_ERROR " ) ;
c . error = AGENTX_RES_GEN_ERROR ;
goto send ;
}
/* TODO find mib_class, check if type is GET of GET_NEXT, act acordingly */
switch ( h - > type )
{
case AGENTX_GET_PDU :
snmp_mib_fill2 ( p , o_start , & c ) ;
break ;
case AGENTX_GET_NEXT_PDU :
snmp_get_next2 ( p , o_start , o_end , & c ) ;
break ;
case AGENTX_GET_BULK_PDU :
snmp_get_bulk2 ( p , o_start , o_end , & bulk_state , & c ) ;
break ;
default :
die ( " incorrect usage " ) ;
}
mb_free ( o_start ) ;
o_start = NULL ;
mb_free ( o_end ) ;
o_end = NULL ;
ind + + ;
} /* while (c.error == AGENTX_RES_NO_ERROR && size > 0) */
send :
snmp_log ( " gets2: sending response ... " ) ;
response_err_ind ( response_header , c . error , ind ) ;
// update_packet_size(&response_header->h, sk->tbuf, c.buffer);
update_packet_size ( p , & response_header - > h , ( byte * ) response_header , c . buffer ) ;
//snmp_dump_packet((byte *) response_header, AGENTX_HEADER_SIZE + LOAD(response_header->h.payload, c.byte_ord));
//snmp_dump_packet((byte *) response_header, AGENTX_HEADER_SIZE + 16 + 8);
//snmp_dump_packet(32 + ((byte *) response_header), 32);
//snmp_dump_packet((byte *) response_header, c.buffer - ((byte *) response_header));
/*
byte b , d ;
b = * ( ( byte * ) response_header ) ;
d = * ( c . buffer - 1 ) ;
snmp_log ( " diff %d start byte %u end byte %u " , c . buffer - ( ( byte * )
response_header ) , b , d ) ;
*/
/* number of bytes put into the tx-buffer */
//int ret = sk_send(sk, c.buffer - sk->tbuf);
snmp_log ( " sending response to Get-PDU, GetNext-PDU or GetBulk-PDU request ... " ) ;
snmp_send ( p , & c ) ;
/*
int ret = sk_send ( sk , c . buffer - sk - > tpos ) ;
if ( ret = = 0 )
snmp_log ( " sk_send sleep (gets2 " ) ;
else if ( ret < 0 )
snmp_log ( " sk_send err %d (gets2) " , ret ) ;
else
snmp_log ( " sk_send was successful (gets2) ! " ) ;
*/
mb_free ( context ) ;
mb_free ( o_start ) ;
mb_free ( o_end ) ;
/* number of bytes parsed form rx-buffer */
return pkt - pkt_start ;
partial :
snmp_log ( " partial packet " ) ;
/* The context octet is not added into response pdu */
* skip = AGENTX_HEADER_SIZE ;
goto send ;
wait :
mb_free ( context ) ;
mb_free ( o_start ) ;
mb_free ( o_end ) ;
return 0 ;
}
#if 0
2023-03-14 13:10:08 +00:00
// TODO FIXME retval
2022-09-20 12:28:57 +00:00
/* req is request */
2023-03-14 13:10:08 +00:00
/**
* parse_gets_pdu - handle Get - PDU , GetNext - PDU and GetBulk - PDU
* @ p :
* @ req : request packet buffer
* @ size : request length
*
* Returns lenght of created response packet .
*/
2023-07-26 12:30:34 +00:00
static uint UNUSED
parse_gets_pdu ( struct snmp_proto * p , byte * pkt_start , uint size , uint UNUSED * skip )
2022-09-20 12:28:57 +00:00
{
2022-12-10 12:22:37 +00:00
snmp_log ( " parse_gets_pdu " ) ;
2022-09-20 12:28:57 +00:00
sock * sk = p - > sock ;
2023-07-26 12:30:34 +00:00
//byte *res = sk->tbuf; /* res_pkt */
// uint rsize = sk->tbsize;
byte * res = sk - > tpos ;
2023-03-14 13:10:08 +00:00
/* req (request) points at the beginning of packet list */
// TODO is the pkt_start really needed ?!
2023-07-26 12:30:34 +00:00
struct agentx_header * h = ( void * ) pkt_start ;
2023-03-14 13:10:08 +00:00
ADVANCE ( pkt_start , size , AGENTX_HEADER_SIZE ) ;
snmp_log ( " advancing %p cause header " , pkt_start ) ;
2022-09-20 12:28:57 +00:00
2023-03-14 13:10:08 +00:00
byte * pkt = pkt_start ;
2022-09-20 12:28:57 +00:00
uint clen ;
char * context ;
2023-03-14 13:10:08 +00:00
SNMP_LOAD_CONTEXT ( p , h , pkt , context , clen ) ;
2022-09-20 12:28:57 +00:00
2023-07-26 12:30:34 +00:00
struct snmp_pdu_context c = {
//.buffer = sk->tbuf,
//.size = sk->tbsize,
. buffer = sk - > tpos ,
. size = sk - > tbuf + sk - > tbsize - sk - > tpos ,
. byte_ord = h - > flags & AGENTX_NETWORK_BYTE_ORDER ,
. context = 0 , // FIXME add context support
. error = AGENTX_RES_NO_ERROR ,
} ;
uint pkt_size = LOAD ( h - > payload , c . byte_ord ) ;
// NO! CHECKs: pkt_size + HEADER_SIZE == size
2022-11-15 15:29:03 +00:00
2023-07-26 12:30:34 +00:00
if ( c . size < sizeof ( struct agentx_response ) )
{
// FIXME alloc more mem
die ( " buffer too small " ) ;
}
struct agentx_response * response_header = prepare_response ( p , & c ) ;
2023-03-14 13:10:08 +00:00
2022-11-19 22:00:02 +00:00
/* used only for state AGENTX_GET_BULK_PDU */
struct agentx_bulk_state bulk_state ;
if ( h - > type = = AGENTX_GET_BULK_PDU )
{
2023-03-14 13:10:08 +00:00
snmp_log ( " gets creating get bulk context BEWARE " ) ;
2023-07-26 12:30:34 +00:00
struct agentx_getbulk * bulk = ( void * ) pkt ;
ADVANCE ( pkt , pkt_size , sizeof ( struct agentx_getbulk ) ) ;
bulk_state = ( struct agentx_bulk_state ) {
. getbulk . non_repeaters = LOAD ( bulk - > non_repeaters , c . byte_ord ) ,
. getbulk . max_repetitions = LOAD ( bulk - > max_repetitions , c . byte_ord ) ,
. index = 1 ,
. repetition = 1 ,
} ;
}
/*
if ( size < sizeof ( struct agentx_getbulk ) )
return 0 ;
if ( pkt_size < sizeof ( struct agentx_getbulk ) )
{
c . error = AGENTX_RES_PARSE_ERROR ;
goto send ;
}
struct agentx_bulk_state bulk_state ;
if ( h - > type = = AGENTX_GET_BULK_PDU )
{
struct agentx_getbulk * bulk = pkt ;
ADVANCE ( pkt , pkt_size , sizeof ( struct agentx_getbulk ) ) ;
size - = sizeof ( struct agentx_getbulk ) ;
2022-11-19 22:00:02 +00:00
bulk_state = ( struct agentx_bulk_state ) {
2023-07-26 12:30:34 +00:00
. getbulk . non_repeaters = LOAD16 ( bulk - > non_repeaters , c . byte_ord ) ;
. getbulk . max_repetitions = LOAD16 ( bulk - > max_repetitions , c . byte_ord ) ;
2022-11-19 22:00:02 +00:00
. index = 1 ,
. repetition = 1 ,
} ;
}
2023-07-26 12:30:34 +00:00
*/
byte * tmp ;
2022-11-19 22:00:02 +00:00
2022-09-20 12:28:57 +00:00
uint ind = 1 ;
2023-07-26 12:30:34 +00:00
while ( c . error = = AGENTX_RES_NO_ERROR & & size > 0 )
2022-09-20 12:28:57 +00:00
{
2023-07-26 12:30:34 +00:00
/* pkt_size is bigger that OID header */
if ( size < snmp_oid_sizeof ( 0 ) )
{
}
2022-11-15 15:29:03 +00:00
/* oids from message buffer */
2022-11-05 15:29:00 +00:00
struct oid * o_start_b , * o_end_b ;
o_start_b = ( struct oid * ) pkt ;
pkt + = snmp_oid_size ( o_start_b ) ;
o_end_b = ( struct oid * ) pkt ;
pkt + = snmp_oid_size ( o_end_b ) ;
2023-07-26 12:30:34 +00:00
snmp_log ( " HERE pkt after oids %p (end %p) " , pkt , pkt + size ) ;
2022-09-20 12:28:57 +00:00
/* advertised size of oid is greater then size of message */
2022-11-05 15:29:00 +00:00
if ( snmp_oid_size ( o_start_b ) > size | | snmp_oid_size ( o_end_b ) > size )
2022-09-20 12:28:57 +00:00
{
2022-12-10 12:22:37 +00:00
snmp_log ( " too big o_start or o_end " ) ;
2023-03-14 13:10:08 +00:00
snmp_log ( " o_start_b packet: %u o_end_b packet: %u packet size: %u " ,
2023-03-24 14:02:23 +00:00
snmp_oid_size ( o_start_b ) , snmp_oid_size ( o_end_b ) , size ) ;
2023-07-26 12:30:34 +00:00
//err = -1; /* parse error too big n_subid (greater than message) */
2022-09-20 12:28:57 +00:00
continue ;
}
2022-11-15 15:29:03 +00:00
snmp_oid_dump ( o_start_b ) ;
snmp_oid_dump ( o_end_b ) ;
2023-07-26 12:30:34 +00:00
/* object identifier (oid) normalization */
struct oid * o_start = snmp_prefixize ( p , o_start_b , c . byte_ord ) ;
struct oid * o_end = snmp_prefixize ( p , o_end_b , c . byte_ord ) ;
2022-11-15 15:29:03 +00:00
snmp_oid_dump ( o_start ) ;
snmp_oid_dump ( o_end ) ;
2022-11-05 15:29:00 +00:00
2023-03-14 13:10:08 +00:00
snmp_log ( " gets buffer start size %u, buffer end size %u, program start size %u, "
" program end size %u " , snmp_oid_size ( o_start_b ) , snmp_oid_size ( o_end_b ) ,
snmp_oid_size ( o_start ) , snmp_oid_size ( o_end ) ) ;
// TODO handle NULL o_start and o_end
2023-07-26 12:30:34 +00:00
u8 mib_class = snmp_get_mib_class ( o_start ) ;
2022-11-15 15:29:03 +00:00
2023-03-14 13:10:08 +00:00
snmp_log ( " get mib_class () %d -> next pdu parsing ... " , mib_class ) ;
2022-11-15 15:29:03 +00:00
2022-09-20 12:28:57 +00:00
switch ( h - > type )
{
case AGENTX_GET_PDU :
2022-12-10 12:22:37 +00:00
snmp_log ( " type Get-PDU " ) ;
2022-11-19 22:00:02 +00:00
2023-07-26 12:30:34 +00:00
/*
2022-11-19 22:00:02 +00:00
struct snmp_error error = ( struct snmp_error ) {
. oid = o_start ,
. type = AGENTX_NO_SUCH_OBJECT ,
} ;
2023-07-26 12:30:34 +00:00
*/
2022-11-19 22:00:02 +00:00
2023-07-26 12:30:34 +00:00
//snmp_dump_packet(pkt, size);
// TODO o_start NULL check
//res_pkt = snmp_mib_fill(p, o_start, mib_class, res_pkt, rsize, &error, 0, byte_ord);
tmp = snmp_mib_fill ( p , o_start , mib_class , & c ) ;
2022-11-05 15:29:00 +00:00
//res_pkt = find_n_fill(p, o_start, res_pkt, rsize, 0, byte_ord);
2023-07-26 12:30:34 +00:00
if ( tmp )
c . buffer = tmp ;
else
{ } // TODO
2022-09-20 12:28:57 +00:00
break ;
case AGENTX_GET_NEXT_PDU :
2023-07-26 12:30:34 +00:00
tmp = snmp_get_next ( p , o_start , o_end , mib_class , & c ) ;
//res_pkt = snmp_get_next(p, o_start, o_end, res_pkt, rsize, 0, mib_class, byte_ord);
if ( tmp )
c . buffer = tmp ;
else
{ } // TODO
2022-11-05 15:29:00 +00:00
2022-09-20 12:28:57 +00:00
break ;
2022-12-17 17:16:19 +00:00
case AGENTX_GET_BULK_PDU :
2023-07-26 12:30:34 +00:00
tmp = snmp_get_bulk ( p , o_start , o_end , & bulk_state , & c ) ;
if ( tmp )
c . buffer = tmp ;
else
{ } // TODO
2022-11-19 22:00:02 +00:00
break ;
2022-09-20 12:28:57 +00:00
}
2022-11-05 15:29:00 +00:00
mb_free ( o_start ) ;
mb_free ( o_end ) ;
2022-09-20 12:28:57 +00:00
ind + + ;
}
2022-12-10 12:22:37 +00:00
snmp_log ( " pasting size " ) ;
2023-07-26 12:30:34 +00:00
response_err_ind ( response_header , c . error , ind ) ;
update_packet_size ( p , & response_header - > h , res , c . buffer ) ;
2022-09-20 12:28:57 +00:00
2023-07-26 12:30:34 +00:00
snmp_log ( " ttx %p c.buffer - res %lu " , p - > sock - > ttx , c . buffer - res ) ;
snmp_log ( " c.buffer %p res %p " , c . buffer , res ) ;
2023-03-14 13:10:08 +00:00
snmp_log ( " dumping response packet (gets) " ) ;
2023-07-26 12:30:34 +00:00
//snmp_dump_packet(res, c.buffer - res);
2022-09-20 12:28:57 +00:00
2023-03-14 13:10:08 +00:00
// TODO need to send prepared packet here
2023-07-26 12:30:34 +00:00
int ret = sk_send ( sk , c . buffer - res ) ;
2023-03-14 13:10:08 +00:00
if ( ret = = 0 )
snmp_log ( " sk_send sleep (gets) " ) ;
else if ( ret < 0 )
snmp_log ( " sk_send err %d (gets) " , ret ) ;
else
snmp_log ( " sk_send ok ! (gets) " ) ;
2022-08-02 14:04:25 +00:00
2023-07-26 12:30:34 +00:00
return pkt - pkt_start - AGENTX_HEADER_SIZE ;
2022-08-02 14:04:25 +00:00
}
2023-07-26 12:30:34 +00:00
# endif
2022-08-02 14:04:25 +00:00
void
2022-08-10 15:31:32 +00:00
snmp_start_subagent ( struct snmp_proto * p )
2022-08-02 14:04:25 +00:00
{
2022-12-10 12:22:37 +00:00
snmp_log ( " snmp_start_subagent() starting subagent " ) ;
2023-03-14 13:10:08 +00:00
snmp_log ( " DEBUG p->local_as %u " , p - > local_as ) ;
2022-08-10 15:31:32 +00:00
/* blank oid means unsupported */
2022-12-10 17:08:00 +00:00
struct oid * blank = snmp_oid_blank ( p ) ;
open_pdu ( p , blank ) ;
mb_free ( blank ) ;
2022-08-02 14:04:25 +00:00
}
void
2022-08-10 15:31:32 +00:00
snmp_stop_subagent ( struct snmp_proto * p )
2022-08-02 14:04:25 +00:00
{
2022-12-10 17:08:00 +00:00
snmp_log ( " snmp_stop_subagent() state %s " , p - > state ) ;
2022-12-17 17:16:19 +00:00
// sock *sk = p->sock;
2022-08-10 15:31:32 +00:00
2022-12-17 17:16:19 +00:00
if ( p - > state = = SNMP_STOP )
2022-09-20 12:28:57 +00:00
close_pdu ( p , AGENTX_CLOSE_SHUTDOWN ) ;
2022-08-10 15:31:32 +00:00
}
2022-08-02 14:04:25 +00:00
2022-11-05 15:29:00 +00:00
static inline int
oid_prefix ( struct oid * o , u32 * prefix , uint len )
{
for ( uint i = 0 ; i < len ; i + + )
if ( o - > ids [ i ] ! = prefix [ i ] )
return 0 ; // false
return 1 ; // true
}
2023-03-14 13:10:08 +00:00
#if 0
2022-08-10 15:31:32 +00:00
int
snmp_rx ( sock * sk , uint size )
2022-09-30 07:36:09 +00:00
{
2022-12-10 12:22:37 +00:00
snmp_log ( " snmp_rx() " ) ;
2022-08-10 15:31:32 +00:00
struct snmp_proto * p = sk - > data ;
2023-07-26 12:30:34 +00:00
byte * pkt = sk - > rpos ;
2022-08-02 14:04:25 +00:00
2022-09-06 16:04:29 +00:00
// 1 means all done; 0 means to be continued
return parse_pkt ( p , pkt , size ) ;
2022-09-30 07:36:09 +00:00
/*
2022-09-06 16:04:29 +00:00
while ( end > = pkt + AGENTX_HEADER_SIZE )
2022-08-10 15:31:32 +00:00
{
parse_header ( p ) ;
parse_pkt ( p , ) ;
}
2022-09-30 07:36:09 +00:00
*/
2022-08-02 14:04:25 +00:00
}
2023-03-14 13:10:08 +00:00
# endif
int
snmp_rx ( sock * sk , uint size )
{
snmp_log ( " snmp_rx() size %u " , size ) ;
2023-07-26 12:30:34 +00:00
//snmp_dump_packet(sk->tbuf, 64);
2023-03-14 13:10:08 +00:00
struct snmp_proto * p = sk - > data ;
byte * pkt_start = sk - > rbuf ;
2023-07-26 12:30:34 +00:00
byte * end = pkt_start + size ;
/*
* In some cases we want to save the header for future parsing , skip is number
* of bytes that should not be overriden by memmove ( )
*/
uint skip = 0 ;
//snmp_dump_packet(pkt_start, size);
2023-03-14 13:10:08 +00:00
snmp_log ( " snmp_rx before loop " ) ;
while ( end > = pkt_start + AGENTX_HEADER_SIZE )
{
2023-07-26 12:30:34 +00:00
uint parsed_len = parse_pkt ( p , pkt_start , size , & skip ) ;
2023-03-14 13:10:08 +00:00
snmp_log ( " snmp_rx loop end %p parsed >>> %u <<< curr %p " , end , parsed_len ,
pkt_start + parsed_len ) ;
if ( parsed_len = = 0 )
break ;
pkt_start + = parsed_len ;
size - = parsed_len ;
}
snmp_log ( " snmp_rx loop finished " ) ;
if ( pkt_start ! = end )
{
2023-07-26 12:30:34 +00:00
snmp_log ( " snmp_rx memmove sk->rbuf + skip 0x%p (0x%p, %u), pkt_start 0x%p, length %u " , sk - > rbuf + skip , sk - > rbuf , skip , pkt_start , end - pkt_start ) ;
memmove ( sk - > rbuf + skip , pkt_start , end - pkt_start ) ;
//snmp_dump_packet(sk->tbuf, 64);
2023-03-14 13:10:08 +00:00
snmp_log ( " snmp_rx returning 0 " ) ;
return 0 ;
}
snmp_log ( " snmp_rx returning 1 " ) ;
return 1 ;
}
2022-08-02 14:04:25 +00:00
2022-09-06 16:04:29 +00:00
/* ping pdu */
void
snmp_ping ( struct snmp_proto * p )
2022-08-02 14:04:25 +00:00
{
2022-09-30 07:36:09 +00:00
/* this does not support non-default context */
2022-08-10 15:31:32 +00:00
sock * sk = p - > sock ;
2023-07-26 12:30:34 +00:00
struct snmp_pdu_context c = {
. buffer = sk - > tpos ,
. size = sk - > tbuf + sk - > tbsize - sk - > tpos ,
} ;
2022-09-06 16:04:29 +00:00
2023-07-26 12:30:34 +00:00
if ( c . size < AGENTX_HEADER_SIZE )
snmp_manage_tbuf ( p , & c ) ;
2022-09-30 07:36:09 +00:00
2023-07-26 12:30:34 +00:00
snmp_log ( " ping_pdu() " ) ;
struct agentx_header * h = ( struct agentx_header * ) c . buffer ;
ADVANCE ( c . buffer , c . size , AGENTX_HEADER_SIZE ) ;
SNMP_BLANK_HEADER ( h , AGENTX_PING_PDU ) ;
SNMP_SESSION ( h , p ) ;
2022-08-02 14:04:25 +00:00
2023-07-26 12:30:34 +00:00
/* sending only header => pkt - buf */
snmp_log ( " sending ping packet ... " ) ;
snmp_send ( p , & c ) ;
2022-08-02 14:04:25 +00:00
}
2022-08-10 15:31:32 +00:00
/*
2022-09-06 16:04:29 +00:00
void
snmp_agent_reconfigure ( void )
2022-08-10 15:31:32 +00:00
{
2022-09-06 16:04:29 +00:00
}
2022-09-20 12:28:57 +00:00
static int
compare ( struct oid * left , struct oid * right )
{
2022-09-30 07:36:09 +00:00
const u32 INTERNET_PREFIX [ ] = { 1 , 3 , 6 , 1 } ;
if ( left - > prefix = = 0 & & right - > prefix = = 0 )
goto test_ids ;
if ( right - > prefix = = 0 )
{
struct oid * temp = left ;
left = right ;
right = temp ;
}
if ( left - > prefix = = 0 )
{
for ( int i = 0 ; i < 4 ; i + + )
if ( left - > ids [ i ] < INTERNET_PREFIX [ i ] )
return - 1 ;
else if ( left - > ids [ i ] > INTERNET_PREFIX [ i ] )
return 1 ;
for ( int i = 0 ; i < MIN ( left - > n_subid - 4 , right - > n_subid ) ; i + + )
if ( left - > ids [ i + 4 ] < right - > ids [ i ] )
return - 1 ;
else if ( left - > ids [ i + 4 ] > right - > ids [ i ] )
return 1 ;
goto all_same ;
}
2022-09-20 12:28:57 +00:00
if ( left - > prefix < right - > prefix )
return - 1 ;
else if ( left - > prefix > right - > prefix )
return 1 ;
2022-09-30 07:36:09 +00:00
test_ids :
2022-09-20 12:28:57 +00:00
for ( int i = 0 ; i < MIN ( left - > n_subid , right - > n_subid ) ; i + + )
if ( left - > ids [ i ] < right - > ids [ i ] )
return - 1 ;
else if ( left - > ids [ i ] > right - > ids [ i ] )
return 1 ;
2022-09-30 07:36:09 +00:00
all_same :
/ * shorter sequence is before longer in lexicografical order * /
if ( left - > n_subid < right - > n_subid )
return - 1 ;
else if ( left - > n_subid > right - > n_subid )
return 1 ;
else
return 0 ;
2022-09-20 12:28:57 +00:00
}
2022-09-30 07:36:09 +00:00
*/
2022-09-20 12:28:57 +00:00
static inline int
is_bgp4_mib_prefix ( struct oid * o )
{
if ( o - > prefix = = 2 & & o - > ids [ 0 ] = = 15 )
2022-09-30 07:36:09 +00:00
return 1 ;
2022-09-20 12:28:57 +00:00
else
return 0 ;
}
2022-09-30 07:36:09 +00:00
static inline int
has_inet_prefix ( struct oid * o )
{
return ( o - > n_subid > 4 & & o - > ids [ 0 ] = = 1 & &
o - > ids [ 1 ] = = 3 & & o - > ids [ 2 ] = = 6 & &
o - > ids [ 3 ] = = 1 ) ;
}
2022-12-17 17:16:19 +00:00
/**
2023-07-26 12:30:34 +00:00
* snmp_search_check_end_oid - check if oid is before SearchRange end
2022-12-17 17:16:19 +00:00
*
* @ found : best oid found in MIB tree
* @ bound : upper bound specified in SearchRange
*
* check if found oid meet the SearchRange upper bound condition in
* lexicographical order , returns boolean value
*/
2023-07-26 12:30:34 +00:00
int snmp_search_check_end_oid ( const struct oid * found , const struct oid * bound )
2022-09-20 12:28:57 +00:00
{
2023-03-24 14:02:23 +00:00
snmp_log ( " upper_bound_check(*f, *b) %p %p is_empty() %d " , found , bound ,
snmp_is_oid_empty ( bound ) ) ;
2022-12-17 17:16:19 +00:00
if ( snmp_is_oid_empty ( bound ) )
return 1 ;
2023-07-26 12:30:34 +00:00
return ( snmp_oid_compare ( found , bound ) < 0 ) ;
2022-12-17 17:16:19 +00:00
}
2023-07-26 12:30:34 +00:00
/* tree is tree with "internet" prefix .1.3.6.1
working only with o_start , o_end allocated in heap ( not from buffer ) */
static struct oid *
search_mib ( struct snmp_proto * p , const struct oid * o_start , const struct oid * o_end ,
struct oid * o_curr , struct snmp_pdu_context * c ,
enum snmp_search_res * result )
2022-12-17 17:16:19 +00:00
{
2023-07-26 12:30:34 +00:00
snmp_log ( " search_mib() " ) ;
ASSUME ( o_start ! = NULL ) ;
2022-09-30 07:36:09 +00:00
2023-07-26 12:30:34 +00:00
if ( o_curr & & ( o_curr - > n_subid < 2 | | o_curr - > ids [ 0 ] ! = 1 ) )
return NULL ;
if ( ! o_curr & & ( o_start - > n_subid < 2 | | o_start - > ids [ 0 ] ! = 1 ) )
2022-11-05 15:29:00 +00:00
return NULL ;
2022-09-30 07:36:09 +00:00
2022-11-05 15:29:00 +00:00
if ( ! o_curr )
{
2023-07-26 12:30:34 +00:00
o_curr = snmp_oid_duplicate ( p - > p . pool , o_start ) ;
2022-11-05 15:29:00 +00:00
// XXX is it right time to free o_start right now (here) ?
2023-07-26 12:30:34 +00:00
// not for use in snmp_get_next2() the o_start comes and ends in _gets2_()
2022-11-05 15:29:00 +00:00
}
2022-09-30 07:36:09 +00:00
2023-07-26 12:30:34 +00:00
const struct oid * blank = NULL ;
if ( ! snmp_is_oid_empty ( o_end ) & &
snmp_get_mib_class ( o_curr ) < snmp_get_mib_class ( o_end ) )
2022-09-30 07:36:09 +00:00
{
2023-07-26 12:30:34 +00:00
o_end = blank = snmp_oid_blank ( p ) ;
snmp_log ( " search_mib() o_end points to blank oid now %p " , o_end ) ;
}
2022-11-19 22:00:02 +00:00
2023-07-26 12:30:34 +00:00
enum snmp_search_res r ;
switch ( o_curr - > ids [ 1 ] )
{
case SNMP_BGP4_MIB :
r = snmp_bgp_search2 ( p , & o_curr , o_end , c - > context ) ;
2022-12-17 17:16:19 +00:00
2023-07-26 12:30:34 +00:00
if ( r = = SNMP_SEARCH_OK )
{
* result = r ;
break ;
return o_curr ;
}
2022-11-19 22:00:02 +00:00
2023-07-26 12:30:34 +00:00
// TODO add early break for o_end less then thinkable maximum in each tree
2022-11-19 22:00:02 +00:00
2023-07-26 12:30:34 +00:00
/* fall through */
2022-12-17 17:16:19 +00:00
2023-07-26 12:30:34 +00:00
default :
o_curr = snmp_oid_duplicate ( p - > p . pool , o_start ) ;
* result = SNMP_SEARCH_END_OF_VIEW ;
break ;
2022-09-30 07:36:09 +00:00
}
2022-11-05 15:29:00 +00:00
2023-07-26 12:30:34 +00:00
//mb_free(blank);
return o_curr ;
2022-12-17 17:16:19 +00:00
}
2022-09-30 07:36:09 +00:00
/*
2022-09-06 16:04:29 +00:00
static byte *
find_ospf_record ( struct snmp_proto * p , struct oid * o , byte * buf , uint size )
2022-08-10 15:31:32 +00:00
{
2023-03-14 13:10:08 +00:00
// TO DO X XX
2022-09-06 16:04:29 +00:00
return NULL ;
}
2022-09-30 07:36:09 +00:00
*/
2022-08-10 15:31:32 +00:00
2022-12-17 17:24:05 +00:00
/**
2022-11-15 15:29:03 +00:00
* snmp_prefixize - return prefixed oid copy if possible
2022-11-05 15:29:00 +00:00
* @ proto : allocation pool holder
* @ oid : from packet loaded object identifier
2022-12-17 17:24:05 +00:00
* @ byte_ord : byte order of @ oid
2022-11-05 15:29:00 +00:00
*
* Returns prefixed ( meaning with nonzero prefix field ) oid copy of @ oid if
2022-12-10 17:08:00 +00:00
* possible , NULL otherwise . Returned pointer is always allocated from @ proto ' s
2022-11-05 15:29:00 +00:00
* pool not a pointer to recieve buffer ( from which is most likely @ oid ) .
*/
2022-11-15 15:29:03 +00:00
struct oid *
2023-07-26 12:30:34 +00:00
snmp_prefixize ( struct snmp_proto * proto , const struct oid * oid , int byte_ord )
2022-09-20 12:28:57 +00:00
{
2023-07-26 12:30:34 +00:00
ASSERT ( oid ! = NULL ) ;
2023-03-24 14:02:23 +00:00
snmp_log ( " snmp_prefixize() " ) ;
2022-09-20 12:28:57 +00:00
const u32 prefix [ ] = { 1 , 3 , 6 , 1 } ;
2022-11-15 15:29:03 +00:00
if ( snmp_is_oid_empty ( oid ) )
{
/* allocate new zeroed oid */
2023-03-24 14:02:23 +00:00
snmp_log ( " blank " ) ;
2022-12-10 17:08:00 +00:00
return snmp_oid_blank ( proto ) ;
2022-11-15 15:29:03 +00:00
}
2023-03-24 14:02:23 +00:00
/* already in prefixed form */
else if ( oid - > prefix ! = 0 ) {
2023-07-26 12:30:34 +00:00
struct oid * new = snmp_oid_duplicate ( proto - > p . pool , oid ) ;
2023-03-24 14:02:23 +00:00
snmp_log ( " already prefixed " ) ;
2022-11-15 15:29:03 +00:00
return new ;
}
2022-11-05 15:29:00 +00:00
if ( oid - > n_subid < 5 )
2023-03-24 14:02:23 +00:00
{ snmp_log ( " too small " ) ; return NULL ; }
2022-09-20 12:28:57 +00:00
for ( int i = 0 ; i < 4 ; i + + )
2022-11-05 15:29:00 +00:00
if ( LOAD ( oid - > ids [ i ] , byte_ord ) ! = prefix [ i ] )
2023-03-24 14:02:23 +00:00
{ snmp_log ( " different prefix " ) ; return NULL ; }
2022-09-20 12:28:57 +00:00
2023-03-24 14:02:23 +00:00
/* validity check here */
2022-11-05 15:29:00 +00:00
if ( oid - > ids [ 4 ] > = 256 )
2023-03-24 14:02:23 +00:00
{ snmp_log ( " outside byte first id " ) ; return NULL ; }
2022-11-05 15:29:00 +00:00
2022-12-17 17:24:05 +00:00
struct oid * new = mb_alloc ( proto - > p . pool ,
2022-11-05 15:29:00 +00:00
sizeof ( struct oid ) + MAX ( ( oid - > n_subid - 5 ) * sizeof ( u32 ) , 0 ) ) ;
2023-07-26 12:30:34 +00:00
/*
2023-03-24 14:02:23 +00:00
snmp_log ( " new %p new->ids %p &new->ids %p oid %p oid->ids %p oid->ids[5] %p "
" &oid->ids[5] %p &(oid->ids[5]) %p " , new , new - > ids , & new - > ids , oid , oid - > ids ,
oid - > ids [ 5 ] , & oid - > ids [ 5 ] , & ( oid - > ids [ 5 ] ) ) ;
2023-07-26 12:30:34 +00:00
*/
2022-09-20 12:28:57 +00:00
2022-11-05 15:29:00 +00:00
memcpy ( new , oid , sizeof ( struct oid ) ) ;
new - > n_subid = oid - > n_subid - 5 ;
2022-09-20 12:28:57 +00:00
2022-12-17 17:24:05 +00:00
/* validity check before allocation => ids[4] < 256
2022-11-05 15:29:00 +00:00
and can be copied to one byte new - > prefix */
new - > prefix = oid - > ids [ 4 ] ;
2022-09-20 12:28:57 +00:00
2022-11-05 15:29:00 +00:00
memcpy ( & new - > ids , & oid - > ids [ 5 ] , new - > n_subid * sizeof ( u32 ) ) ;
2022-09-20 12:28:57 +00:00
return new ;
}
2023-07-26 12:30:34 +00:00
static void
snmp_mib_fill2 ( struct snmp_proto * p , struct oid * oid ,
struct snmp_pdu_context * c )
2022-11-19 22:00:02 +00:00
{
2023-07-26 12:30:34 +00:00
ASSUME ( oid ! = NULL ) ;
2022-11-05 15:29:00 +00:00
2023-07-26 12:30:34 +00:00
if ( c - > size < snmp_varbind_hdr_size_from_oid ( oid ) )
{
// FIXME need more mem
snmp_log ( " snmp_mib_fill2() need more memory in TX buffer, returning with GEN_ERROR " ) ;
c - > error = AGENTX_RES_GEN_ERROR ;
return ;
}
2022-11-19 22:00:02 +00:00
2023-07-26 12:30:34 +00:00
struct agentx_varbind * vb = snmp_create_varbind ( c - > buffer , oid ) ;
2022-11-05 15:29:00 +00:00
if ( oid - > n_subid < 2 | | ( oid - > prefix ! = 2 & & oid - > ids [ 0 ] ! = 1 ) )
2022-11-19 22:00:02 +00:00
{
2022-12-17 17:24:05 +00:00
vb - > type = AGENTX_NO_SUCH_OBJECT ;
2023-07-26 12:30:34 +00:00
ADVANCE ( c - > buffer , c - > size , snmp_varbind_header_size ( vb ) ) ;
return ;
2022-11-19 22:00:02 +00:00
}
2022-11-05 15:29:00 +00:00
2023-07-26 12:30:34 +00:00
u8 mib_class = snmp_get_mib_class ( oid ) ;
2022-11-05 15:29:00 +00:00
switch ( mib_class )
{
case SNMP_CLASS_BGP :
2023-07-26 12:30:34 +00:00
snmp_bgp_fill ( p , vb , c ) ;
2022-11-15 15:29:03 +00:00
break ;
2023-07-26 12:30:34 +00:00
case SNMP_CLASS_INVALID :
case SNMP_CLASS_END :
default :
vb - > type = AGENTX_NO_SUCH_OBJECT ;
ADVANCE ( c - > buffer , c - > size , snmp_varbind_header_size ( vb ) ) ;
2022-11-05 15:29:00 +00:00
}
2023-07-26 12:30:34 +00:00
}
#if 0
/**
* snmp_mib_fill -
*/
static byte *
snmp_mib_fill ( struct snmp_proto UNUSED * p , struct oid * oid , u8 mib_class ,
struct snmp_pdu_context * c )
{
ASSERT ( oid ! = NULL ) ;
snmp_log ( " snmp_mib_fill() " ) ;
2022-12-17 17:24:05 +00:00
2023-07-26 12:30:34 +00:00
struct agentx_varbind * vb = snmp_create_varbind ( c - > buffer , oid ) ;
/* SNMPv2 mgmt mib-2 */
if ( oid - > n_subid < 2 | | ( oid - > prefix ! = 2 & & oid - > ids [ 0 ] ! = 1 ) )
2022-11-19 22:00:02 +00:00
{
2023-07-26 12:30:34 +00:00
vb - > type = AGENTX_NO_SUCH_OBJECT ;
return c - > buffer + snmp_varbind_header_size ( vb ) ;
2022-11-19 22:00:02 +00:00
}
2023-07-26 12:30:34 +00:00
//byte *last = c->buffer;
switch ( mib_class )
{
case SNMP_CLASS_BGP :
//return snmp_bgp_fill(p, vb, c);
return NULL ;
default :
return NULL ;
}
return NULL ;
2022-11-05 15:29:00 +00:00
}
2023-07-26 12:30:34 +00:00
# endif
2022-11-05 15:29:00 +00:00
2023-07-26 12:30:34 +00:00
/**
*
* Important note : After managing insufficient buffer size all in buffer pointers
* are invalidated !
*/
void
snmp_manage_tbuf ( struct snmp_proto * p , struct snmp_pdu_context * c )
2022-09-06 16:04:29 +00:00
{
2023-07-26 12:30:34 +00:00
snmp_log ( " snmp_manage_tbuf() " ) ;
2022-09-06 16:04:29 +00:00
2023-07-26 12:30:34 +00:00
struct additional_buffer * t = TAIL ( p - > additional_buffers ) ;
t - > pos = c - > buffer ;
2023-03-14 13:10:08 +00:00
2023-07-26 12:30:34 +00:00
struct additional_buffer * b = mb_alloc ( p - > p . pool , sizeof ( struct additional_buffer ) ) ;
b - > buf = b - > pos = mb_alloc ( p - > p . pool , SNMP_TX_BUFFER_SIZE ) ;
add_tail ( & p - > additional_buffers , & b - > n ) ;
2022-09-06 16:04:29 +00:00
2023-07-26 12:30:34 +00:00
c - > buffer = b - > buf ;
c - > size = SNMP_TX_BUFFER_SIZE ;
}
2022-09-06 16:04:29 +00:00
2023-07-26 12:30:34 +00:00
int
snmp_send ( struct snmp_proto * p , struct snmp_pdu_context * c )
{
sock * sk = p - > sock ;
2022-09-06 16:04:29 +00:00
2023-07-26 12:30:34 +00:00
if ( EMPTY_LIST ( p - > additional_buffers ) )
return sk_send ( sk , c - > buffer - sk - > tpos ) ;
return sk_send ( sk , p - > to_send ) ;
2022-08-10 15:31:32 +00:00
}
2023-07-26 12:30:34 +00:00
void
snmp_tx ( sock * sk )
2022-09-20 12:28:57 +00:00
{
2023-07-26 12:30:34 +00:00
snmp_log ( " snmp_tx() hook " ) ;
struct snmp_proto * p = sk - > data ;
2022-09-20 12:28:57 +00:00
2023-07-26 12:30:34 +00:00
while ( ! EMPTY_LIST ( p - > additional_buffers ) )
{
struct additional_buffer * b = HEAD ( p - > additional_buffers ) ;
rem_node ( & b - > n ) ;
memcpy ( sk - > tbuf , b - > buf , b - > pos - b - > buf ) ;
uint used = b - > pos - b - > buf ;
mb_free ( b - > buf ) ;
mb_free ( b ) ;
int ret = sk_send ( sk , used ) ;
/* we exit if and error occured or the data will be send in the future */
if ( ret < = 0 )
return ;
}
2022-09-20 12:28:57 +00:00
}
2023-07-26 12:30:34 +00:00
static struct agentx_response *
prepare_response ( struct snmp_proto * p , struct snmp_pdu_context * c )
{
snmp_log ( " prepare_response() " ) ;
struct agentx_response * r = ( void * ) c - > buffer ;
struct agentx_header * h = & r - > h ;
SNMP_BLANK_HEADER ( h , AGENTX_RESPONSE_PDU ) ;
SNMP_SESSION ( h , p ) ;
/* protocol doesn't care about subagent upTime */
STORE_U32 ( r - > uptime , 0 ) ;
STORE_U16 ( r - > error , AGENTX_RES_NO_ERROR ) ;
STORE_U16 ( r - > index , 0 ) ;
ADVANCE ( c - > buffer , c - > size , sizeof ( struct agentx_response ) ) ;
return r ;
}
2022-08-10 15:31:32 +00:00
# undef SNMP_ERR_SHIFT