diff --git a/proto/snmp/config.Y b/proto/snmp/config.Y index 1d7c421d..e7fe5364 100644 --- a/proto/snmp/config.Y +++ b/proto/snmp/config.Y @@ -31,7 +31,6 @@ snmp_proto: snmp_proto_item: proto_item | snmp_bgp_bond - /* | INTERFACE snmp_interface TODO */ | LOCAL PORT expr { if (($3 < 1) || ($3 > 65535)) cf_error("Invalid port number"); SNMP_CFG->local_port = $3; @@ -42,12 +41,31 @@ snmp_proto_item: } | LOCAL ID IP4 { SNMP_CFG->bgp_local_id = $3; } | LOCAL ADDRESS IP4 { SNMP_CFG->local_ip = $3; } + | REMOTE ADDRESS DEFAULT { + if (SNMP_CFG->trans_type != SNMP_TRANS_DEFAULT) + cf_error("Duplicit option remote address"); + } | REMOTE ADDRESS IP4 { - if (ip4_zero($3)) cf_error("Invalid remote ip address"); + if (SNMP_CFG->trans_type != SNMP_TRANS_DEFAULT) + cf_error("Duplicit option remote address"); + + // TODO + //if (ip4_zero($3)) cf_error("Invalid remote ip address"); + SNMP_CFG->remote_ip = $3; + SNMP_CFG->trans_type = SNMP_TRANS_TCP; + } + | REMOTE ADDRESS text { + if (SNMP_CFG->trans_type != SNMP_TRANS_DEFAULT) + cf_error("Duplicit option remote address"); + + if (strcmp($3, agentx_master_addr)) { + SNMP_CFG->remote_path = $3; + SNMP_CFG->trans_type = SNMP_TRANS_UNIX; + } } | LOCAL AS expr { - if ($3 < 1 || $3 > 65535) cf_error("Invalid local AS"); + if ($3 < 1 || $3 > UINT16_MAX) cf_error("Invalid local AS"); SNMP_CFG->bgp_local_as = $3; } | SNMP DESCRIPTION text { @@ -87,7 +105,9 @@ snmp_proto_start: proto_start SNMP SNMP_CFG->bonds = 0; SNMP_CFG->local_ip = IP4_NONE; - SNMP_CFG->remote_ip = ip4_build(127,0,0,1); + SNMP_CFG->remote_ip = IP4_NONE; + SNMP_CFG->remote_path = agentx_master_addr; + SNMP_CFG->trans_type = SNMP_TRANS_DEFAULT; SNMP_CFG->bgp_local_id = IP4_NONE; SNMP_CFG->local_port = 0; SNMP_CFG->remote_port = 705; diff --git a/proto/snmp/snmp.c b/proto/snmp/snmp.c index f08386fb..2d81a297 100644 --- a/proto/snmp/snmp.c +++ b/proto/snmp/snmp.c @@ -122,6 +122,7 @@ // TODO: remove me #include "proto/bgp/bgp.h" +const char agentx_master_addr[] = AGENTX_MASTER_ADDR; static void snmp_start_locked(struct object_lock *lock); static void snmp_sock_err(sock *sk, int err); @@ -170,6 +171,7 @@ int snmp_set_state(struct snmp_proto *p, enum snmp_proto_state state) { enum snmp_proto_state last = p->state; + const struct snmp_config *cf = (struct snmp_config *) p->p.cf; TRACE(D_EVENTS, "SNMP changing state to %u", state); @@ -193,31 +195,50 @@ snmp_set_state(struct snmp_proto *p, enum snmp_proto_state state) case SNMP_INIT: DBG("snmp -> SNMP_INIT\n"); ASSERT(last == SNMP_DOWN); - struct object_lock *lock; - lock = p->lock = olock_new(p->pool); - /* - * lock->addr - * lock->port - * lock->iface - * lock->vrf - */ - lock->type = OBJLOCK_TCP; - lock->hook = snmp_start_locked; - lock->data = p; - olock_acquire(lock); - return PS_START; + if (cf->trans_type == SNMP_TRANS_TCP) + { + /* We need to lock the IP address */ + struct object_lock *lock; + lock = p->lock = olock_new(p->pool); + + /* + * lock->iface + * lock->vrf + */ + lock->addr = ipa_from_ip4(cf->remote_ip); + lock->port = cf->remote_port; + lock->type = OBJLOCK_TCP; + lock->hook = snmp_start_locked; + lock->data = p; + olock_acquire(lock); + return PS_START; + } + + p->state = state = SNMP_LOCKED; + /* Fall thru */ case SNMP_LOCKED: DBG("snmp -> SNMP_LOCKED\n"); ASSERT(last == SNMP_INIT || SNMP_RESET); sock *s = sk_new(p->pool); - s->type = SK_TCP_ACTIVE; - s->saddr = ipa_from_ip4(p->local_ip); - s->daddr = ipa_from_ip4(p->remote_ip); - s->dport = p->remote_port; - s->rbsize = SNMP_RX_BUFFER_SIZE; - s->tbsize = SNMP_TX_BUFFER_SIZE; + + if (cf->trans_type == SNMP_TRANS_TCP) + { + s->type = SK_TCP_ACTIVE; + s->saddr = ipa_from_ip4(p->local_ip); + s->daddr = ipa_from_ip4(p->remote_ip); + s->dport = p->remote_port; + s->rbsize = SNMP_RX_BUFFER_SIZE; + s->tbsize = SNMP_TX_BUFFER_SIZE; + } + else + { + s->type = SK_UNIX_ACTIVE; + s->host = cf->remote_path; /* daddr */ + s->rbsize = SNMP_RX_BUFFER_SIZE; + s->tbsize = SNMP_TX_BUFFER_SIZE; + } /* s->tos = IP_PREC_INTERNET_CONTROL */ s->tx_hook = snmp_connected; @@ -241,12 +262,14 @@ snmp_set_state(struct snmp_proto *p, enum snmp_proto_state state) p->sock->rx_hook = snmp_rx; p->sock->tx_hook = NULL; snmp_start_subagent(p); - // handle no response (for long time) + p->startup_timer->hook = snmp_stop_timeout; + tm_start(p->startup_timer, 1 S); return PS_START; case SNMP_REGISTER: DBG("snmp -> SNMP_REGISTER\n"); ASSERT(last == SNMP_OPEN); + tm_stop(p->startup_timer); /* stop timeout */ snmp_register_mibs(p); return PS_START; @@ -276,6 +299,7 @@ snmp_set_state(struct snmp_proto *p, enum snmp_proto_state state) DBG("snmp -> SNMP_RESET\n"); ASSUME(last == SNMP_REGISTER || last == SNMP_CONN); ASSUME(p->sock); + snmp_stop_subagent(p); p->sock->rx_hook = snmp_rx_skip; p->sock->tx_hook = snmp_tx_skip; return PS_STOP; @@ -612,8 +636,10 @@ snmp_show_proto_info(struct proto *P) static void snmp_postconfig(struct proto_config *CF) { + const struct snmp_config *cf = (struct snmp_config *) CF; + /* Walk the BGP protocols and cache their references. */ - if (((struct snmp_config *) CF)->bgp_local_as == 0) + if (cf->bgp_local_as == 0) cf_error("local as not specified"); } diff --git a/proto/snmp/snmp.h b/proto/snmp/snmp.h index 1f2552a5..e5f126c6 100644 --- a/proto/snmp/snmp.h +++ b/proto/snmp/snmp.h @@ -29,6 +29,8 @@ #define SNMP_TX_BUFFER_SIZE 8192 #define SNMP_PKT_SIZE_MAX 4098 +#define AGENTX_MASTER_ADDR "/var/agentx/master" + enum snmp_proto_state { SNMP_DOWN = 0, SNMP_INIT = 1, @@ -46,12 +48,20 @@ struct snmp_bond { u8 type; }; +enum snmp_transport_type { + SNMP_TRANS_DEFAULT, + SNMP_TRANS_UNIX, + SNMP_TRANS_TCP, +}; + struct snmp_config { struct proto_config cf; + enum snmp_transport_type trans_type; ip4_addr local_ip; - ip4_addr remote_ip; u16 local_port; + ip4_addr remote_ip; /* master agentx IP address for TCP transport */ u16 remote_port; + const char *remote_path; /* master agentx UNIX socket name */ ip4_addr bgp_local_id; /* BGP4-MIB related fields */ u32 bgp_local_as; @@ -67,7 +77,7 @@ struct snmp_config { * We use this fact to check differences of * nonallocated parts of configs with memcpy */ - //const struct oid *oid_identifier; TODO + //const struct oid *oid_identifier; TODO }; #define SNMP_BGP_P_REGISTERING 0x01 @@ -84,6 +94,7 @@ struct snmp_registered_oid { struct oid *oid; }; + struct snmp_proto { struct proto p; struct object_lock *lock; @@ -153,4 +164,6 @@ int snmp_set_state(struct snmp_proto *p, enum snmp_proto_state state); void snmp_reset(struct snmp_proto *p); +extern const char agentx_master_addr[sizeof(AGENTX_MASTER_ADDR)]; + #endif