📄 snmp.c
字号:
/* * ifstat - InterFace STATistics * Copyright (c) 2001, Ga雔 Roualland <gael.roualland@dial.oleane.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id: snmp.c,v 1.26 2003/05/06 23:30:02 gael Exp $ */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdlib.h>#include <stdio.h>#include "ifstat.h"#ifdef USE_SNMP#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <string.h>#ifdef HAVE_NET_SNMP#include <net-snmp/net-snmp-config.h>#include <net-snmp/net-snmp-includes.h>#else#include <ucd-snmp/ucd-snmp-config.h>#include <ucd-snmp/ucd-snmp-includes.h>#endif#include "snmp.h"/* define this to use ifcount as a hint to discover interfaces does not work well with routers that do not number interfaces sequentially, but is faster that the ifIndex walk used otherwise */#undef USE_SNMP_IFCOUNTstatic char *snmp_sess_errstring(struct snmp_session *ss) { char *res; snmp_error(ss, NULL, NULL, &res); return res;}#ifdef USE_SNMP_IFCOUNT/* report the value interfaces.ifNumber.0, actually the number of interfaces */static int snmp_get_ifcount(struct snmp_session *ss) { int nifaces = -1; oid ifcount[] = { 1, 3, 6, 1, 2, 1, 2, 1, 0 }; struct snmp_pdu *pdu; struct snmp_pdu *response = NULL; int status; if ((pdu = snmp_pdu_create(SNMP_MSG_GET)) == NULL) { ifstat_error("snmp_pdu_create: %s", snmp_api_errstring(snmp_errno)); return -1; } snmp_add_null_var(pdu, ifcount, sizeof(ifcount) / sizeof(oid)); if ((status = snmp_synch_response(ss, pdu, &response)) != STAT_SUCCESS || response->errstat != SNMP_ERR_NOERROR || response->variables == NULL || response->variables->type != ASN_INTEGER) { if (status == STAT_SUCCESS) ifstat_error("snmp: Error: %s", snmp_errstring(response->errstat)); else ifstat_error("snmpget(interfaces.ifNumber.0): %s", snmp_sess_errstring(ss)); if (response) snmp_free_pdu(response); return -1; } nifaces = *(response->variables->val.integer); snmp_free_pdu(response); if (nifaces < 0) return -1; return nifaces;}#endifstatic int snmp_get_nextif(struct snmp_session *ss, int index) { oid ifindex[] = { 1, 3, 6, 1, 2, 1, 2, 2, 1, 1, 0 }; int len = sizeof(ifindex) / sizeof(oid); struct snmp_pdu *pdu; struct snmp_pdu *response = NULL; struct variable_list *vars; int status; if (index >= 0) ifindex[len - 1] = index; if ((pdu = snmp_pdu_create(SNMP_MSG_GETNEXT)) == NULL) { ifstat_error("snmp_pdu_create: %s", snmp_api_errstring(snmp_errno)); return -1; } snmp_add_null_var(pdu, ifindex, (index < 0) ? len - 1 : len); if ((status = snmp_synch_response(ss, pdu, &response)) != STAT_SUCCESS || response->errstat != SNMP_ERR_NOERROR || response->variables == NULL) { if (status == STAT_SUCCESS) ifstat_error("snmp: Error: %s", snmp_errstring(response->errstat)); else ifstat_error("snmpgetnext(interfaces.ifTable.ifEntry.ifIndex...): %s", snmp_sess_errstring(ss)); if (response != NULL) snmp_free_pdu(response); return -1; } for(vars = response->variables; vars; vars = vars->next_variable) { /* check that the variable is under the base oid */ if (vars->name_length != len) continue; if (memcmp(ifindex, vars->name, sizeof(ifindex) - sizeof(oid)) != 0) continue; index = vars->name[vars->name_length - 1]; snmp_free_pdu(response); return index; } snmp_free_pdu(response); return -1;}#define S_IFNAMEMAX 64struct ifsnmp { char name[S_IFNAMEMAX]; unsigned long bout, bin; int flags, index;};#define S_UP 1#define S_BIN 2#define S_BOUT 4#define S_LOOP 8#define S_INVALID 16#define S_NUMNAME 32#define S_IFNAME 64 /* fill a struct ifsnmp buffer of selected information (flags) for interface index to (index + nifaces - 1). ifsnmp must be large enough, and nifaces shouldb'nt too large since some devices have limited capability for large responses... In case we get a unknown name answer and we're polling several interfaces at once, interfaces will be polled again individually to try to solve the problem.*/static int snmp_get_ifinfos(struct snmp_session *ss, int nifaces, int flags, struct ifsnmp * ifsnmp, int *toobig) { struct snmp_pdu *pdu, *response = NULL; oid ifinfo[] = { 1, 3, 6, 1, 2, 1, 2, 2, 1, 0, 0 }; /* interfaces.ifTable.ifEntry.x.n */#define ifDescr 2#define ifType 3 #define ifOperStatus 8 #define ifInOctets 10#define ifOutOctets 16 struct variable_list *vars; int i, status; if (nifaces <= 0) return 0; if ((pdu = snmp_pdu_create(SNMP_MSG_GET)) == NULL) { ifstat_error("snmp_pdu_create: %s", snmp_api_errstring(snmp_errno)); return 0; } for (i = 0; i < nifaces; i++) { ifsnmp[i].flags = 0; ifsnmp[i].name[0] = 0; /* set interface index */ ifinfo[10] = ifsnmp[i].index; if (flags & S_NUMNAME) { sprintf(ifsnmp[i].name, "if%d", ifsnmp[i].index); } else if (flags & S_IFNAME) { /* require descr */ ifinfo[9] = ifDescr; snmp_add_null_var(pdu, ifinfo, sizeof(ifinfo) / sizeof(oid)); } /* then optional data */ if (flags & S_UP) { ifinfo[9] = ifOperStatus; snmp_add_null_var(pdu, ifinfo, sizeof(ifinfo) / sizeof(oid)); } if (flags & S_BOUT) { ifinfo[9] = ifOutOctets; snmp_add_null_var(pdu, ifinfo, sizeof(ifinfo) / sizeof(oid)); } if (flags & S_BIN) { ifinfo[9] = ifInOctets; snmp_add_null_var(pdu, ifinfo, sizeof(ifinfo) / sizeof(oid)); } if (flags & S_LOOP) { ifinfo[9] = ifType; snmp_add_null_var(pdu, ifinfo, sizeof(ifinfo) / sizeof(oid)); } } if ((status = snmp_synch_response(ss, pdu, &response)) != STAT_SUCCESS || response->errstat != SNMP_ERR_NOERROR || response->variables == NULL) { if (status == STAT_SUCCESS) { if (response->errstat != SNMP_ERR_NOSUCHNAME && response->errstat != SNMP_ERR_TOOBIG) ifstat_error("snmp: Error: %s", snmp_errstring(response->errstat)); else if (nifaces > 1) { /* maybe only one of the interface is broken or too many interfaces polled at once -- repoll inetrface per interface */ if (response->errstat == SNMP_ERR_TOOBIG && toobig != NULL) (*toobig)++; if (response != NULL) snmp_free_pdu(response); status = 0; for (i = 0; i < nifaces; i++) { if (!snmp_get_ifinfos(ss, 1, flags, ifsnmp + i, NULL)) ifsnmp[i].flags |= S_INVALID; else status = 1; } return status; } } else ifstat_error("snmpget(interfaces.ifTable.ifEntry...): %s", snmp_sess_errstring(ss)); if (response != NULL) snmp_free_pdu(response); return 0; } for(vars = response->variables; vars; vars = vars->next_variable) { /* check that the variable is under the base oid */ if (memcmp(ifinfo, vars->name, sizeof(ifinfo) - 2 * sizeof(oid)) != 0) continue; for(i = 0; i < nifaces; i++) { if (ifsnmp[i].index == vars->name[10]) break; } if (i == nifaces) /* not found */ continue; switch (vars->name[9]) { case ifDescr: if (vars->type == ASN_OCTET_STR) { int count = vars->val_len; if (count >= sizeof(ifsnmp[i].name)) count = sizeof(ifsnmp[i].name) - 1; strncpy(ifsnmp[i].name, vars->val.string, count); ifsnmp[i].name[count] = '\0'; } break; case ifOperStatus: if (vars->type == ASN_INTEGER) { if (*(vars->val.integer) == 1) /* up */ ifsnmp[i].flags |= S_UP; } break; case ifType: if (vars->type == ASN_INTEGER) { if (*(vars->val.integer) == 24) /* softwareLoopback */ ifsnmp[i].flags |= S_LOOP; } break; case ifInOctets:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -