📄 snmp_api.c
字号:
#endif
}
#endif /* AF_UNIX */
}
addr_size = snmp_socket_length(isp->me.sa_family);
/* Set up connections */
if ( session->flags & SNMP_FLAGS_STREAM_SOCKET ) {
if ( session->local_port != 0 )
session->flags |= SNMP_FLAGS_LISTENING;
sd = socket(isp->me.sa_family, SOCK_STREAM, 0);
}
else
sd = socket(isp->me.sa_family, SOCK_DGRAM, 0);
if (sd < 0){
in_session->s_snmp_errno = SNMPERR_NO_SOCKET;
in_session->s_errno = errno;
snmp_set_detail(strerror(errno));
snmp_sess_close(slp);
return 0;
}
isp->sd = sd;
#ifdef SO_BSDCOMPAT
/* Patch for Linux. Without this, UDP packets that fail get an ICMP
* response. Linux turns the failed ICMP response into an error message
* and return value, unlike all other OS's.
*/
{
int one=1;
setsockopt(sd, SOL_SOCKET, SO_BSDCOMPAT, &one, sizeof(one));
}
#endif /* SO_BSDCOMPAT */
//#ifndef __ECOS
#ifndef SERVER_REQUIRES_CLIENT_SOCKET
if (!(( session->flags & SNMP_FLAGS_STREAM_SOCKET ) &&
#ifdef AF_UNIX
( isp->me.sa_family == AF_UNIX ) &&
#endif /* AF_UNIX */
( session->local_port == 0 ))) {
/* Client Unix-domain stream sockets don't need to 'bind' */
#endif
if (bind(sd, (struct sockaddr *)&isp->me, addr_size) != 0){
in_session->s_snmp_errno = SNMPERR_BAD_LOCPORT;
in_session->s_errno = errno;
snmp_set_detail(strerror(errno));
snmp_sess_close(slp);
return 0;
}
#ifndef SERVER_REQUIRES_CLIENT_SOCKET
}
#endif
//#endif // not __ECOS
if ( session->flags & SNMP_FLAGS_STREAM_SOCKET ) {
if ( session->local_port == 0 ) { /* Client session */
if ( connect( sd, (struct sockaddr *)&(isp->addr),
snmp_socket_length(isp->addr.sa_family)) != 0 ) {
in_session->s_snmp_errno = SNMPERR_BAD_LOCPORT;
in_session->s_errno = errno;
snmp_set_detail(strerror(errno));
snmp_sess_close(slp);
return 0;
}
} else { /* Server session */
if ( listen( sd, SNMP_STREAM_QUEUE_LEN ) != 0 ) {
in_session->s_snmp_errno = SNMPERR_BAD_LOCPORT;
in_session->s_errno = errno;
snmp_set_detail(strerror(errno));
snmp_sess_close(slp);
return 0;
}
}
}
/* if we are opening a V3 session and we don't know engineID
we must probe it - this must be done after the session is
created and inserted in the list so that the response can
handled correctly */
#ifdef CYGPKG_SNMPAGENT_V3_SUPPORT
if (session->version == SNMP_VERSION_3) {
if (session->securityEngineIDLen == 0 &&
(session->securityEngineIDLen & SNMP_FLAGS_DONT_PROBE) !=
SNMP_FLAGS_DONT_PROBE) {
snmpv3_build_probe_pdu(&pdu);
DEBUGMSGTL(("snmp_api","probing for engineID...\n"));
status = snmp_sess_synch_response(slp, pdu, &response);
if ((response == NULL) && (status == STAT_SUCCESS)) status = STAT_ERROR;
switch (status) {
case STAT_SUCCESS:
in_session->s_snmp_errno = SNMPERR_INVALID_MSG; /* XX?? */
DEBUGMSGTL(("snmp_sess_open",
"error: expected Report as response to probe: %s (%d)\n",
snmp_errstring(response->errstat), response->errstat));
break;
case STAT_ERROR: /* this is what we expected -> Report == STAT_ERROR */
in_session->s_snmp_errno = SNMPERR_UNKNOWN_ENG_ID;
break;
case STAT_TIMEOUT:
in_session->s_snmp_errno = SNMPERR_TIMEOUT;
default:
DEBUGMSGTL(("snmp_sess_open",
"unable to connect with remote engine: %s (%d)\n",
snmp_api_errstring(session->s_snmp_errno),
session->s_snmp_errno));
break;
}
if (slp->session->securityEngineIDLen == 0) {
DEBUGMSGTL(("snmp_api","unable to determine remote engine ID\n"));
snmp_sess_close(slp);
return NULL;
}
in_session->s_snmp_errno = SNMPERR_SUCCESS;
if (snmp_get_do_debugging()) {
DEBUGMSGTL(("snmp_sess_open", " probe found engineID: "));
for(i = 0; i < slp->session->securityEngineIDLen; i++)
DEBUGMSG(("snmp_sess_open", "%02x",
slp->session->securityEngineID[i]));
DEBUGMSG(("snmp_sess_open","\n"));
}
}
/* if boot/time supplied set it for this engineID */
if (session->engineBoots || session->engineTime) {
set_enginetime(session->securityEngineID, session->securityEngineIDLen,
session->engineBoots, session->engineTime, TRUE);
}
if (create_user_from_session(slp->session) != SNMPERR_SUCCESS) {
in_session->s_snmp_errno = SNMPERR_UNKNOWN_USER_NAME; /* XX?? */
DEBUGMSGTL(("snmp_api","snmp_sess_open(): failed(2) to create a new user from session\n"));
snmp_sess_close(slp);
return NULL;
}
}
#endif /* CYGPKG_SNMPAGENT_V3_SUPPORT */
return (void *)slp;
} /* end snmp_sess_open() */
void *
snmp_sess_open(struct snmp_session *pss)
{
void * pvoid;
pvoid = _sess_open(pss);
if ( !pvoid) {
SET_SNMP_ERROR(pss->s_snmp_errno);
}
return pvoid;
}
#ifdef CYGPKG_SNMPAGENT_V3_SUPPORT
/* create_user_from_session(struct snmp_session *session):
creates a user in the usm table from the information in a session
Parameters:
session -- IN: pointer to the session to use when creating the user.
Returns:
SNMPERR_SUCCESS
SNMPERR_GENERR
*/
int
create_user_from_session(struct snmp_session *session)
{
struct usmUser *user;
/* now that we have the engineID, create an entry in the USM list
for this user using the information in the session */
user = usm_get_user_from_list(session->securityEngineID,
session->securityEngineIDLen,
session->securityName,
usm_get_userList(), 0);
if (user == NULL) {
DEBUGMSGTL(("snmp_api","Building user %s...\n",session->securityName));
/* user doesn't exist so we create and add it */
user = (struct usmUser *) calloc(1,sizeof(struct usmUser));
if (user == NULL)
return SNMPERR_GENERR;
/* copy in the securityName */
if (session->securityName) {
user->name = strdup(session->securityName);
user->secName = strdup(session->securityName);
if (user->name == NULL || user->secName == NULL) {
usm_free_user(user);
return SNMPERR_GENERR;
}
}
/* copy in the engineID */
if (memdup(&user->engineID, session->securityEngineID,
session->securityEngineIDLen) != SNMPERR_SUCCESS) {
usm_free_user(user);
return SNMPERR_GENERR;
}
user->engineIDLen = session->securityEngineIDLen;
/* copy the auth protocol */
if (session->securityAuthProto != NULL) {
user->authProtocol =
snmp_duplicate_objid(session->securityAuthProto,
session->securityAuthProtoLen);
if (user->authProtocol == NULL) {
usm_free_user(user);
return SNMPERR_GENERR;
}
user->authProtocolLen = session->securityAuthProtoLen;
}
/* copy the priv protocol */
if (session->securityPrivProto != NULL) {
user->privProtocol =
snmp_duplicate_objid(session->securityPrivProto,
session->securityPrivProtoLen);
if (user->privProtocol == NULL) {
usm_free_user(user);
return SNMPERR_GENERR;
}
user->privProtocolLen = session->securityPrivProtoLen;
}
/* copy in the authentication Key, and convert to the localized version */
if (session->securityAuthKey != NULL && session->securityAuthKeyLen != 0) {
user->authKey = (u_char *)malloc (USM_LENGTH_KU_HASHBLOCK);
user->authKeyLen = USM_LENGTH_KU_HASHBLOCK;
if (generate_kul( user->authProtocol, user->authProtocolLen,
session->securityEngineID, session->securityEngineIDLen,
session->securityAuthKey, session->securityAuthKeyLen,
user->authKey, &user->authKeyLen ) != SNMPERR_SUCCESS) {
usm_free_user(user);
return SNMPERR_GENERR;
}
}
/* copy in the privacy Key, and convert to the localized version */
if (session->securityPrivKey != NULL && session->securityPrivKeyLen != 0) {
user->privKey = (u_char *)malloc (USM_LENGTH_KU_HASHBLOCK);
user->privKeyLen = USM_LENGTH_KU_HASHBLOCK;
if (generate_kul( user->authProtocol, user->authProtocolLen,
session->securityEngineID, session->securityEngineIDLen,
session->securityPrivKey, session->securityPrivKeyLen,
user->privKey, &user->privKeyLen ) != SNMPERR_SUCCESS) {
usm_free_user(user);
return SNMPERR_GENERR;
}
}
/* add the user into the database */
usm_add_user(user);
}
return SNMPERR_SUCCESS;
} /* end create_user_from_session() */
#endif /* CYGPKG_SNMPAGENT_V3_SUPPORT */
/*
* Close the input session. Frees all data allocated for the session,
* dequeues any pending requests, and closes any sockets allocated for
* the session. Returns 0 on error, 1 otherwise.
*/
int
snmp_sess_close(void *sessp)
{
struct session_list *slp = (struct session_list *)sessp;
struct snmp_internal_session *isp;
struct snmp_session *sesp;
if (slp == NULL)
return 0;
isp = slp->internal; slp->internal = 0;
if (isp) {
struct request_list *rp, *orp;
SNMP_FREE(isp->packet);
if (isp->sd != -1)
{
#ifndef HAVE_CLOSESOCKET
close(isp->sd);
#else
closesocket(isp->sd);
#endif
#ifdef AF_UNIX
if ( isp->me.sa_family == AF_UNIX )
unlink( isp->me.sa_data );
#endif /* AF_UNIX */
}
/* Free each element in the input request list. */
rp = isp->requests;
while(rp){
orp = rp;
rp = rp->next_request;
snmp_free_pdu(orp->pdu);
free((char *)orp);
}
free((char *)isp);
}
sesp = slp->session; slp->session = 0;
if (sesp) {
SNMP_FREE(sesp->peername);
SNMP_FREE(sesp->community);
SNMP_FREE(sesp->contextEngineID);
SNMP_FREE(sesp->contextName);
SNMP_FREE(sesp->securityEngineID);
SNMP_FREE(sesp->securityName);
SNMP_FREE(sesp->securityAuthProto);
SNMP_FREE(sesp->securityPrivProto);
free((char *)sesp);
}
free((char *)slp);
return 1;
}
int
snmp_close(struct snmp_session *session)
{
struct session_list *slp = NULL, *oslp = NULL;
{ /*MTCRITICAL_RESOURCE*/
snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
if (Sessions && Sessions->session == session){ /* If first entry */
slp = Sessions;
Sessions = slp->next;
} else {
for(slp = Sessions; slp; slp = slp->next){
if (slp->session == session){
if (oslp) /* if we found entry that points here */
oslp->next = slp->next; /* link around this entry */
break;
}
oslp = slp;
}
}
snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
} /*END MTCRITICAL_RESOURCE*/
if (slp == NULL){
return 0;
}
return snmp_sess_close((void *)slp);
}
int
snmp_close_sessions( void )
{
struct session_list *slp;
snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
while ( Sessions ) {
slp = Sessions;
Sessions = Sessions->next;
snmp_sess_close((void *)slp);
}
snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
return 1;
}
#ifdef CYGPKG_SNMPAGENT_V3_SUPPORT
static int
snmpv3_build_probe_pdu (struct snmp_pdu **pdu)
{
struct usmUser *user;
/* create the pdu */
if (!pdu) return -1;
*pdu = snmp_pdu_create(SNMP_MSG_GET);
(*pdu)->version = SNMP_VERSION_3;
(*pdu)->securityName = strdup("");
(*pdu)->securityNameLen = strlen((*pdu)->securityName);
(*pdu)->securityLevel = SNMP_SEC_LEVEL_NOAUTH;
(*pdu)->securityModel = SNMP_SEC_MODEL_USM;
/* create the empty user */
user = usm_get_user(NULL, 0, (*pdu)->securityName);
if (user == NULL) {
user = (struct usmUser *) calloc(1,sizeof(struct usmUser));
user->name = strdup((*pdu)->securityName);
user->secName = strdup((*pdu)->securityName);
user->authProtocolLen = sizeof(usmNoAuthProtocol)/sizeof(oid);
user->authProtocol =
snmp_duplicate_objid(usmNoAuthProtocol, user->authProtocolLen);
user->privProtocolLen = sizeof(usmNoPrivProtocol)/sizeof(oid);
user->privProtocol =
snmp_duplicate_objid(usmNoPrivProtocol, user->privProtocolLen);
usm_add_user(user);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -