📄 snmp_core.c
字号:
leave_suid(); if (theInSnmpConnection < 0) fatal("Cannot open snmp Port"); commSetSelect(theInSnmpConnection, COMM_SELECT_READ, snmpHandleUdp, NULL, 0); debug(1, 1) ("Accepting SNMP messages on port %d, FD %d.\n", (int) port, theInSnmpConnection); if (Config.Addrs.snmp_outgoing.s_addr != no_addr.s_addr) { enter_suid(); theOutSnmpConnection = comm_open(SOCK_DGRAM, 0, Config.Addrs.snmp_outgoing, port, COMM_NONBLOCKING, "SNMP Port"); leave_suid(); if (theOutSnmpConnection < 0) fatal("Cannot open Outgoing SNMP Port"); commSetSelect(theOutSnmpConnection, COMM_SELECT_READ, snmpHandleUdp, NULL, 0); debug(1, 1) ("Outgoing SNMP messages on port %d, FD %d.\n", (int) port, theOutSnmpConnection); fd_note(theOutSnmpConnection, "Outgoing SNMP socket"); fd_note(theInSnmpConnection, "Incoming SNMP socket"); } else { theOutSnmpConnection = theInSnmpConnection; } memset(&theOutSNMPAddr, '\0', sizeof(struct in_addr)); len = sizeof(struct sockaddr_in); memset(&xaddr, '\0', len); x = getsockname(theOutSnmpConnection, (struct sockaddr *) &xaddr, &len); if (x < 0) debug(51, 1) ("theOutSnmpConnection FD %d: getsockname: %s\n", theOutSnmpConnection, xstrerror()); else theOutSNMPAddr = xaddr.sin_addr; }}voidsnmpConnectionShutdown(void){ if (theInSnmpConnection < 0) return; if (theInSnmpConnection != theOutSnmpConnection) { debug(49, 1) ("FD %d Closing SNMP socket\n", theInSnmpConnection); comm_close(theInSnmpConnection); } /* * Here we set 'theInSnmpConnection' to -1 even though the SNMP 'in' * and 'out' sockets might be just one FD. This prevents this * function from executing repeatedly. When we are really ready to * exit or restart, main will comm_close the 'out' descriptor. */ theInSnmpConnection = -1; /* * Normally we only write to the outgoing SNMP socket, but we * also have a read handler there to catch messages sent to that * specific interface. During shutdown, we must disable reading * on the outgoing socket. */ assert(theOutSnmpConnection > -1); commSetSelect(theOutSnmpConnection, COMM_SELECT_READ, NULL, NULL, 0);}voidsnmpConnectionClose(void){ snmpConnectionShutdown(); if (theOutSnmpConnection > -1) { debug(49, 1) ("FD %d Closing SNMP socket\n", theOutSnmpConnection); comm_close(theOutSnmpConnection); }}/* * Functions for handling the requests. *//* * Accept the UDP packet */voidsnmpHandleUdp(int sock, void *not_used){ LOCAL_ARRAY(char, buf, SNMP_REQUEST_SIZE); struct sockaddr_in from; socklen_t from_len; snmp_request_t *snmp_rq; int len; debug(49, 5) ("snmpHandleUdp: Called.\n"); commSetSelect(sock, COMM_SELECT_READ, snmpHandleUdp, NULL, 0); from_len = sizeof(struct sockaddr_in); memset(&from, '\0', from_len); memset(buf, '\0', SNMP_REQUEST_SIZE); Counter.syscalls.sock.recvfroms++; len = recvfrom(sock, buf, SNMP_REQUEST_SIZE, 0, (struct sockaddr *) &from, &from_len); if (len > 0) { buf[len] = '\0'; debug(49, 3) ("snmpHandleUdp: FD %d: received %d bytes from %s.\n", sock, len, inet_ntoa(from.sin_addr)); snmp_rq = xcalloc(1, sizeof(snmp_request_t)); snmp_rq->buf = (u_char *) buf; snmp_rq->len = len; snmp_rq->sock = sock; snmp_rq->outbuf = xmalloc(snmp_rq->outlen = SNMP_REQUEST_SIZE); xmemcpy(&snmp_rq->from, &from, sizeof(struct sockaddr_in)); snmpDecodePacket(snmp_rq); xfree(snmp_rq); } else { debug(49, 1) ("snmpHandleUdp: FD %d recvfrom: %s\n", sock, xstrerror()); }}/* * Turn SNMP packet into a PDU, check available ACL's */voidsnmpDecodePacket(snmp_request_t * rq){ struct snmp_pdu *PDU; struct snmp_session Session; aclCheck_t checklist; u_char *Community; u_char *buf = rq->buf; int len = rq->len; int allow = 0; debug(49, 5) ("snmpDecodePacket: Called.\n"); /* Now that we have the data, turn it into a PDU */ PDU = snmp_pdu_create(0); Session.Version = SNMP_VERSION_1; Community = snmp_parse(&Session, PDU, buf, len); checklist.src_addr = rq->from.sin_addr; checklist.snmp_community = (char *) Community; allow = aclCheckFast(Config.accessList.snmp, &checklist); if ((snmp_coexist_V2toV1(PDU)) && (Community) && (allow)) { rq->community = Community; rq->PDU = PDU; debug(49, 5) ("snmpAgentParse: reqid=[%d]\n", PDU->reqid); snmpConstructReponse(rq); } else { debug(49, 1) ("Failed SNMP agent query from : %s.\n", inet_ntoa(rq->from.sin_addr)); snmp_free_pdu(PDU); }}/* * Packet OK, ACL Check OK, Create reponse. */voidsnmpConstructReponse(snmp_request_t * rq){ struct snmp_session Session; struct snmp_pdu *RespPDU; int ret; debug(49, 5) ("snmpConstructReponse: Called.\n"); RespPDU = snmpAgentResponse(rq->PDU); snmp_free_pdu(rq->PDU); if (RespPDU != NULL) { Session.Version = SNMP_VERSION_1; Session.community = rq->community; Session.community_len = strlen((char *) rq->community); ret = snmp_build(&Session, RespPDU, rq->outbuf, &rq->outlen); sendto(rq->sock, rq->outbuf, rq->outlen, 0, (struct sockaddr *) &rq->from, sizeof(rq->from)); snmp_free_pdu(RespPDU); xfree(rq->outbuf); }}/* * Decide how to respond to the request, construct a response and * return the response to the requester. * * If configured forward any reponses which are not for this agent. */struct snmp_pdu *snmpAgentResponse(struct snmp_pdu *PDU){ struct snmp_pdu *Answer = NULL; oid_ParseFn *ParseFn = NULL; variable_list *VarPtr, *VarNew = NULL, **VarPtrP; int index = 0; debug(49, 5) ("snmpAgentResponse: Called.\n"); if ((Answer = snmp_pdu_create(SNMP_PDU_RESPONSE))) { Answer->reqid = PDU->reqid; Answer->errindex = 0; if (PDU->command == SNMP_PDU_GET) { variable_list **RespVars; RespVars = &(Answer->variables); /* Loop through all variables */ for (VarPtrP = &(PDU->variables); *VarPtrP; VarPtrP = &((*VarPtrP)->next_variable)) { VarPtr = *VarPtrP; index++; /* Find the parsing function for this variable */ ParseFn = snmpTreeGet(VarPtr->name, VarPtr->name_length); if (ParseFn == NULL) { Answer->errstat = SNMP_ERR_NOSUCHNAME; debug(49, 5) ("snmpAgentResponse: No such oid. "); } else VarNew = (*ParseFn) (VarPtr, (snint *) & (Answer->errstat)); /* Was there an error? */ if ((Answer->errstat != SNMP_ERR_NOERROR) || (VarNew == NULL)) { Answer->errindex = index; debug(49, 5) ("snmpAgentParse: successful.\n"); /* Just copy the rest of the variables. Quickly. */ *RespVars = VarPtr; *VarPtrP = NULL; return (Answer); } /* No error. Insert this var at the end, and move on to the next. */ *RespVars = VarNew; RespVars = &(VarNew->next_variable); } return (Answer); } else if (PDU->command == SNMP_PDU_GETNEXT) { oid *NextOidName = NULL; int NextOidNameLen = 0; ParseFn = snmpTreeNext(PDU->variables->name, PDU->variables->name_length, &(NextOidName), (snint *) & NextOidNameLen); if (ParseFn == NULL) { Answer->errstat = SNMP_ERR_NOSUCHNAME; debug(49, 5) ("snmpAgentResponse: No such oid: "); snmpDebugOid(5, PDU->variables->name, PDU->variables->name_length); } else { xfree(PDU->variables->name); PDU->variables->name = NextOidName; PDU->variables->name_length = NextOidNameLen; VarNew = (*ParseFn) (PDU->variables, (snint *) & Answer->errstat); } /* Was there an error? */ if (Answer->errstat != SNMP_ERR_NOERROR) { Answer->errindex = 1; Answer->variables = PDU->variables; PDU->variables = NULL; } else { Answer->variables = VarNew; } } else { snmp_free_pdu(Answer); Answer = NULL; } } return (Answer);}oid_ParseFn *snmpTreeGet(oid * Current, snint CurrentLen){ oid_ParseFn *Fn = NULL; mib_tree_entry *mibTreeEntry = NULL, *lastEntry = NULL; int count = 0; debug(49, 5) ("snmpTreeGet: Called\n"); debug(49, 6) ("snmpTreeGet: Current : \n"); snmpDebugOid(6, Current, CurrentLen); mibTreeEntry = mib_tree_head; if (Current[count] == mibTreeEntry->name[count]) { count++; while ((mibTreeEntry) && (count < CurrentLen) && (!mibTreeEntry->parsefunction)) { lastEntry = mibTreeEntry; mibTreeEntry = snmpTreeEntry(Current[count], count, mibTreeEntry); count++; } } if (mibTreeEntry && mibTreeEntry->parsefunction) Fn = mibTreeEntry->parsefunction; debug(49, 5) ("snmpTreeGet: return\n"); return (Fn);}oid_ParseFn *snmpTreeNext(oid * Current, snint CurrentLen, oid ** Next, snint * NextLen){ oid_ParseFn *Fn = NULL; mib_tree_entry *mibTreeEntry = NULL, *nextoid = NULL; int count = 0; debug(49, 5) ("snmpTreeNext: Called\n"); debug(49, 6) ("snmpTreeNext: Current : \n"); snmpDebugOid(6, Current, CurrentLen); mibTreeEntry = mib_tree_head; if (Current[count] == mibTreeEntry->name[count]) { count++; while ((mibTreeEntry) && (count < CurrentLen) && (!mibTreeEntry->parsefunction)) { mibTreeEntry = snmpTreeEntry(Current[count], count, mibTreeEntry); count++; } debug(49, 5) ("snmpTreeNext: Recursed down to requested object\n"); } else { return NULL; } if (mibTreeEntry == mib_tree_last) return (Fn); if ((mibTreeEntry) && (mibTreeEntry->parsefunction)) { *NextLen = CurrentLen; *Next = (*mibTreeEntry->instancefunction) (Current, NextLen, mibTreeEntry, &Fn); if (*Next) return (Fn); } if ((mibTreeEntry) && (mibTreeEntry->parsefunction)) { count--; nextoid = snmpTreeSiblingEntry(Current[count], count, mibTreeEntry->parent); if (nextoid) { debug(49, 5) ("snmpTreeNext: Next OID found for sibling\n"); mibTreeEntry = nextoid; count++; } else { debug(49, 5) ("snmpTreeNext: Attempting to recurse up for next object\n"); while (!nextoid) { count--; if (mibTreeEntry->parent->parent) { nextoid = mibTreeEntry->parent; mibTreeEntry = snmpTreeEntry(Current[count] + 1, count, nextoid->parent); if (!mibTreeEntry) { mibTreeEntry = nextoid;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -