/*
* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
* http://www.ntop.org
*
* Copyright (C) 2003 Abdelkader Lahmadi <Abdelkader.Lahmadi@loria.fr>
* Olivier Festor <Olivier.Festor@loria.fr>
* Copyright (C) 2003-04 Luca Deri <deri@ntop.org>
*
* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "ntop.h"
#ifdef INET6
#define ROUNDUP(a) \
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
#define SA(saddr) ((struct sockaddr *)saddr)
#define SA4(saddr) ((struct sockaddr_in *)saddr)
#define IN4(saddr) (&SA4(saddr)->sin_addr)
#define SA6(saddr) ((struct sockaddr_in6 *)saddr)
#define IN6(saddr) (&SA6(saddr)->sin6_addr)
static struct in6_addr *in6_cpy(struct in6_addr *dst, struct in6_addr *src) {
return memcpy(dst, src, sizeof(struct in6_addr));
}
static struct in_addr *in4_cpy(struct in_addr *dst, struct in_addr *src) {
return memcpy(dst, src, sizeof(struct in_addr));
}
static void str2in6_addr(char *str, struct in6_addr *addr) {
int i;
unsigned int x;
for (i=0; i < 16; i++){
sscanf(str + (i*2), "%02x",&x);
addr->s6_addr[i]= x & 0xff;
}
}
static int prefixlen(void *val, int size) {
unsigned char *name = (unsigned char *)val;
int byte, bit, plen = 0;
for (byte = 0; byte < size; byte++, plen += 8)
if (name[byte] != 0xff)
break;
if (byte == size)
return (plen);
for (bit = 7; bit != 0; bit--, plen++)
if (!(name[byte] & (1 << bit)))
break;
for (; bit != 0; bit--)
if (name[byte] & (1 << bit))
return(0);
byte++;
for (; byte < size; byte++)
if (name[byte])
return(0);
return (plen);
}
/* ************************************************* */
#if defined(HAVE_IFLIST_SYSCTL) && defined(HAVE_SYSCTL)
struct iface_handler *iface_new(void) {
int mib[6] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0 };
char *buf = NULL;
char *lim, *next;
size_t needed;
struct iface_handler *hdlr = NULL;
int i;
int if_pos = 0;
int addr_pos = 0;
struct iface_addr *ia;
/* Allocate memory for iface handler
*/
if (! (hdlr = (struct iface_handler *)calloc(1,sizeof(struct iface_handler)))) {
errno = ENOMEM;
goto failed;
}
/* Retrieve raw interface information buffer
*/
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
goto failed;
if (! (buf = malloc(needed))) {
errno = ENOMEM;
goto failed;
}
if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
goto failed;
/* Count interfaces and addresses
*/
lim = buf + needed;
next = buf;
while (next < lim) {
struct if_msghdr *ifm = (struct if_msghdr *)next;
if (ifm->ifm_type != RTM_IFINFO)
goto failed;
hdlr->if_count++;
next += ifm->ifm_msglen;
while (next < lim) {
struct if_msghdr *nextifm = (struct if_msghdr *)next;
if (nextifm->ifm_type != RTM_NEWADDR)
break;
next += nextifm->ifm_msglen;
hdlr->addr_count++;
}
}
/* Allocate memory for storing interfaces/addresses lists
*/
if ((! (hdlr->if_list = (struct iface_if *)calloc(hdlr->if_count,sizeof(struct iface_if)))) ||
(! (hdlr->addr_list = (struct iface_addr *)calloc(hdlr->addr_count,sizeof(struct iface_addr))))) {
errno = ENOMEM;
goto failed;
}
/* Parsing raw buffer
*/
lim = buf + needed;
next = buf;
while (next < lim) {
struct iface_if *ii = &hdlr->if_list[if_pos];
struct if_msghdr *ifm = (struct if_msghdr *)next;
struct sockaddr_dl *sdl = (struct sockaddr_dl *)(ifm + 1);
int acount = 0;
/* Sanity check
*/
if (ifm->ifm_type != RTM_IFINFO) {
errno = EACCES;
goto failed;
}
/* Interface name and index
*/
ii->next = &hdlr->if_list[if_pos+1];
ii->index = ifm->ifm_index;
strncpy(ii->name, sdl->sdl_data, sdl->sdl_nlen);
ii->name[sdl->sdl_nlen] = '\0';
/* Interface info
* UP / BROADCAST / MULTICAST / LOOPBACK / P2P / PROMISC / SIMPLEX
*/
if (ifm->ifm_flags & IFF_UP) /* interface is UP */
ii->info |= IFACE_INFO_UP;
if (ifm->ifm_flags & IFF_LOOPBACK) /* is a loopback net */
ii->info |= IFACE_INFO_LOOPBACK;
if (ifm->ifm_flags & IFF_POINTOPOINT) /* point to point link */
ii->info |= IFACE_INFO_P2P;
if (ifm->ifm_flags & IFF_BROADCAST) /* support broadcast */
ii->info |= IFACE_INFO_BROADCAST;
if (ifm->ifm_flags & IFF_MULTICAST) /* support multicast */
ii->info |= IFACE_INFO_MULTICAST;
if (ifm->ifm_flags & IFF_PROMISC) /* receive all packets */
ii->info |= IFACE_INFO_PROMISC;
/*if (ifm->ifm_flags & IFF_SIMPLEX)*/ /* can't hear own packets */
/* ii->info |= IFACE_INFO_SIMPLEX;*/
/* Information about physical interface
* type / physaddr / addrlen
*/
ii->type = sdl->sdl_type; // ::TODO:: type conversion
if (sdl->sdl_alen > 0) {
ii->phys.size = sdl->sdl_alen;
ii->phys.addr = malloc(ii->phys.size);
if (ii->phys.addr == NULL) {
errno = ENOMEM;
goto failed;
}
memcpy(ii->phys.addr, LLADDR(sdl), ii->phys.size);
}
/* Retrieve addresses
*/
ii->addrs = &hdlr->addr_list[addr_pos];
next += ifm->ifm_msglen;
while (next < lim) {
struct sockaddr *sa[RTAX_MAX];
struct if_msghdr *nextifm = (struct if_msghdr *)next;
struct ifa_msghdr *ifam = (struct ifa_msghdr *)nextifm;
char *cp = (char *)(ifam + 1);
/* Check for end
*/
if (nextifm->ifm_type != RTM_NEWADDR)
break;
/* Unpack address information
*/
memset(sa, 0, sizeof(sa));
for (i = 0; (i < RTAX_MAX) && (cp < lim); i++) {
if ((ifam->ifam_addrs & (1 << i)) == 0)
continue;
sa[i] = SA(cp);
cp += ROUNDUP(sa[i]->sa_len);
}
/* Basic information about interface
*/
ia = &hdlr->addr_list[addr_pos];
ia->family = -1;
ia->ifi = ii;
ia->next = &hdlr->addr_list[addr_pos+1];
/* Process accroding to address family
*/
if (sa[RTAX_IFA]) {
ia->family = sa[RTAX_IFA]->sa_family;
switch(ia->family) {
case AF_INET:
in4_cpy(&ia->af.inet.addr, IN4(sa[RTAX_IFA]));
in4_cpy(&ia->af.inet.bcast,
sa[RTAX_BRD]?IN4(sa[RTAX_BRD]):IN4(sa[RTAX_IFA]));
ia->af.inet.mask = sa[RTAX_NETMASK]
? prefixlen(IN4(sa[RTAX_NETMASK]),sizeof(struct in_addr))
: 8 * sizeof(struct in_addr);
break;
case AF_INET6:
in6_cpy(&ia->af.inet6.addr, IN6(sa[RTAX_IFA]));
ia->af.inet6.prefixlen = sa[RTAX_NETMASK]
? prefixlen(IN6(sa[RTAX_NETMASK]),sizeof(struct in6_addr))
: 8 * sizeof(struct in6_addr);
break;
default:
/* Don't know how to process it, so ignore it
*/
break;
}
}
next += nextifm->ifm_msglen;
acount++;
addr_pos++;
}
ia->next = NULL;
if (acount == 0)
ii->addrs = NULL;
if_pos++;
}
hdlr->if_list[hdlr->if_count-1].next = NULL;
free(buf);
return hdlr;
failed:
iface_destroy(hdlr);
free(buf);
return NULL;
}
#else
/* TODO: Using ioctl for getting interface addresses */
#ifdef LINUX
#define PATH_PROC_NET_IF_INET6 "/proc/net/if_inet6"
static int iface_getflags(struct iface_if *ii) {
int sock;
struct ifreq lifreq;
strncpy(lifreq.ifr_name, ii->name,IFNAMSIZ);
lifreq.ifr_addr.sa_family = AF_INET;
if ((sock = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
return -1;
/* Interface flags */
if (ioctl(sock, SIOCGIFFLAGS,&lifreq) < 0)
return -1;
if (lifreq.ifr_flags & IFF_UP) /* interface is UP */
ii->info |= IFACE_INFO_UP;
if (lifreq.ifr_flags & IFF_LOOPBACK) /* is a loopback net */
ii->info |= IFACE_INFO_LOOPBACK;
if (lifreq.ifr_flags & IFF_POINTOPOINT) /* point to point link */
ii->info |= IFACE_INFO_P2P;
if (lifreq.ifr_flags & IFF_BROADCAST) /* support broadcast */
ii->info |= IFACE_INFO_BROADCAST;
if (lifreq.ifr_flags & IFF_MULTICAST) /* support multicast */
ii->info |= IFACE_INFO_MULTICAST;
if (lifreq.ifr_flags & IFF_PROMISC) /* receive all packets */
ii->info |= IFACE_INFO_PROMISC;
close(sock);
return 1;
}
/* **************************************************** */
struct iface_handler *iface_new(void) {
char buf[1024];
char straddr[33];
char ifname[20];
int ifindex, plen, scope, status;
int found = 0;
struct iface_handler * hdlr;
FILE *fp;
int n;
struct iface_if *ii, *itf;
struct iface_addr *ia, *it;
struct in6_addr addr;
/* Allocate memory for iface handler
*/
if (! (hdlr = (struct iface_handler *)calloc(1,sizeof(struct iface_handler)))){
errno = ENOMEM;
goto failed;
}
fp = fopen(PATH_PROC_NET_IF_INET6,"r");
if (fp == NULL)
goto failed;
hdlr->if_list = ii = NULL;
hdlr->addr_list = ia = NULL;
while (fgets(buf, 1024, fp) != NULL){
n = sscanf(buf, "%32s %02x %02x %02x %02x %20s",
straddr, &ifindex,&plen, &scope, &status, ifname);
if (n != 6)
continue;
str2in6_addr(straddr, &addr);
/* search existing interface */
for (itf = hdlr->if_list;itf; itf= itf->next){
if (strncmp(itf->name, ifname,IFNAMSIZ) == 0){
/* update addresses*/
for (it = itf->addrs;it->next != NULL ; it = it->next);
ia = (struct iface_addr *) malloc(sizeof(struct iface_addr));
ia->family = AF_INET6;
ia->ifi = itf;
in6_cpy(&ia->af.inet6.addr, &addr);
ia->af.inet6.prefixlen = plen;
ia->next = NULL;
it->next = ia;
found = 1;
}
}
if (!found){
/* New interface/ address */
itf = (struct iface_if *)malloc(sizeof(struct iface_if));
itf->next = NULL;
memcpy(itf->name, ifname, IFNAMSIZ);
itf->index = ifindex;
iface_getflags(itf);
it = itf->addrs =(struct iface_addr *) malloc(sizeof(struct iface_addr));
it->family = AF_INET6;
it->ifi = itf;
in6_cpy(&it->af.inet6.addr, &addr);
it->af.inet6.prefixlen = plen;
it->next = NULL;
if (ii == NULL){
hdlr->if_list = itf;
hdlr->addr_list = it;
}else {
ii->next = itf;
}
ii = itf;
hdlr->if_count++;
}
}
return hdlr;
failed:
iface_destroy(hdlr);
return NULL;
}
#else
/* != LINUX */
struct iface_handler *iface_new(void) {
return NULL;
}
#endif
#endif
/* ******************************************************* */
void iface_destroy(struct iface_handler *hdlr) {
if (hdlr) {
if (hdlr->addr_list)
free(hdlr->addr_list);
if (hdlr->if_list) {
#if defined(HAVE_IFLIST_SYSCTL) && defined(HAVE_SYSCTL)
int i;
for (i = 0 ; i < hdlr->if_count ; i++)
if (hdlr->if_list[i].phys.addr)
free(hdlr->if_list[i].phys.addr);
#endif
free(hdlr->if_list);
}
free(hdlr);
}
}
int iface_addrcount(struct iface_handler *hdlr) {
return hdlr->addr_count;
}
int iface_ifcount(struct iface_handler *hdlr) {
return hdlr->if_count;
}
struct iface_if *iface_getif_first(struct iface_handler *hdlr) {
return hdlr->if_count ? &hdlr->if_list[0] : NULL;
}
struct iface_if *iface_getif_next(struct iface_if *ii) {
return ii ? ii->next : NULL;
}
int iface_if_addrcount(struct iface_if *ii, int family) {
struct iface_addr *ia;
int count = 0;
for (ia = ii->addrs ; ia ; ia = ia->next)
if (!family || (ia->family == family))
count++;
return count;
}
struct iface_if *iface_getif_byindex(struct iface_handler *hdlr, int idx) {
int i;
for (i = 0 ; i < hdlr->if_count ; i++)
if (hdlr->if_list[i].index == idx)
return &hdlr->if_list[i];
return NULL;
}
struct iface_if *iface_getif_byname(struct iface_handler *hdlr, char *name) {
int i;
for (i = 0 ; i < hdlr->if_count ; i++)
if (! strcmp(hdlr->if_list[i].name, name))
return &hdlr->if_list[i];
return NULL;
}
char *iface_if_getname(struct iface_if *ii, char *name, int size) {
if (name) {
name[size-1] = '\0';
strncpy(name, ii->name, size);
} else {
name = strdup(ii->name);
}
return name;
}
int iface_if_getindex(struct iface_if *ii) {
return ii->index;
}
int iface_if_getinfo(struct iface_if *ii) {
return ii->info;
}
int iface_if_gettype(struct iface_if *ii) {
return ii->type;
}
int iface_if_getphys(struct iface_if *ii,int *type,char *addr,int *addrsize) {
if (type)
*type = ii->type;
if (addr) {
*addrsize = *addrsize < ii->phys.size ? *addrsize : ii->phys.size;
if (ii->phys.addr)
memcpy(addr, ii->phys.addr, *addrsize);
}
return ii->phys.size;
}
struct iface_addr *iface_getaddr_first(struct iface_if *ii, int family) {
struct iface_addr *ia;
if (! (ia = ii->addrs))
return NULL;
if (family && (ia->family != family))
return iface_getaddr_next(ia, family);
return ia;
}
struct iface_addr *iface_getaddr_next(struct iface_addr *ia, int family) {
if (ia)
do {
ia = ia->next;
} while (ia && family && (ia->family != family));
return ia;
}
int iface_addr_getfamily(struct iface_addr *ia) {
return ia->family;
}
int iface_addr_ifindex(struct iface_addr *ia) {
return ia->ifi->index;
}
void *iface_addr_getinfo(struct iface_addr *ia, void *infobuf) {
switch(ia->family) {
case AF_INET:
memcpy(infobuf, &ia->af.inet, sizeof(struct iface_addr_inet));
return infobuf;
case AF_INET6:
memcpy(infobuf, &ia->af.inet6, sizeof(struct iface_addr_inet6));
return infobuf;
default:
return NULL;
}
}
/* *************************************************** */
int iface6(int *idx, int size) {
struct iface_if *ii;
struct iface_handler *ih;
int count = 0;
ih = iface_new();
if(ih == NULL)
return -1;
for (ii = iface_getif_first(ih) ; ii ; ii = iface_getif_next(ii))
if ((iface_if_getinfo(ii) & (IFACE_INFO_UP | IFACE_INFO_LOOPBACK)) ==
IFACE_INFO_UP)
if (iface_getaddr_first(ii, AF_INET6)) {
if (idx) {
if (count == size)
return count;
*idx++ = iface_if_getindex(ii);
}
count++;
}
iface_destroy(ih);
return count;
}
#if 0
// check for using only SIOCGIF* instead of sysctl, it seems more
// protable
#define ESTIMATED_LOCAL 20
/*@brief expand sockaddr's included in <code>ifam</code>
*
*@param ifam message containing information about interface
* addresses.
*@param ai structure where addresses will be expanded.
*/
void iface_unpackaddr(struct ifa_msghdr *ifam, struct rt_addrinfo *ai){
char *wp;
int rtax;
wp = (char *)(ifam + 1);
ai->rti_addrs = ifam->ifam_addrs;
for (rtax = 0; rtax < sizeof ai->rti_info / sizeof *ai->rti_info; rtax++)
if (ifam->ifam_addrs & (1 << rtax)) {
ai->rti_info[rtax] = (struct sockaddr *)wp;
wp += ROUNDUP(ai->rti_info[rtax]->sa_len);
} else
ai->rti_info[rtax] = NULL;
}
/*@ find all IP interfaces addreses
*
*@param type adresses family (AF_INET / AF_INET6)
*@param size number of addresses found
*@param addr buffer of list of adresses should be IPv4/IPv6
*/
int iface_getalladdr(int type, int *size, char **addr){
int mib[6], n, s, alloced;
size_t needed;
char *buf, *end, *ptr;
struct if_msghdr *ifm;
struct ifa_msghdr *ifam;
struct rt_addrinfo ai;
struct ifreq ifr;
struct sockaddr_dl *dl;
struct sockaddr_in6 *sin;
int num_local = -1;
struct in6_addr *saddr;
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[4] = NET_RT_IFLIST;
mib[2] = mib[3] = mib[5] = 0;
if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
return -1;
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
goto failed;
if ((buf = (char *)malloc(needed)) == NULL)
goto failed;
if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
goto failed;
num_local = 0;
alloced = 0;
end = buf + needed;
for (ptr = buf; ptr < end; ptr += ifm->ifm_msglen) {
ifm = (struct if_msghdr *)ptr;
dl = (struct sockaddr_dl *)(ifm + 1);
if (ifm->ifm_index != dl->sdl_index || dl->sdl_nlen == 0)
/* Skip over remaining ifa_msghdrs */
continue;
n = dl->sdl_nlen > sizeof(ifr.ifr_name) ?
sizeof(ifr.ifr_name) : dl->sdl_nlen;
strncpy(ifr.ifr_name, dl->sdl_data, n);
if (n < sizeof (ifr.ifr_name))
ifr.ifr_name[n] = '\0';
if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0)
return -1;
else if (ifr.ifr_flags & IFF_UP) {
ifam = (struct ifa_msghdr *)(ptr + ifm->ifm_msglen);
while ((char *)ifam < end && ifam->ifam_type == RTM_NEWADDR) {
iface_unpackaddr(ifam, &ai);
switch (type){
case AF_INET:
if (ai.rti_info[RTAX_IFA] != NULL &&
ai.rti_info[RTAX_IFA]->sa_family == AF_INET) {
if (alloced < num_local + 1) {
alloced += ESTIMATED_LOCAL;
saddr = (struct in_addr *)realloc(saddr, alloced * sizeof(struct in_addr));
if (saddr == NULL) {
num_local = 0;
goto failed;
break;
}
}
memcpy((struct in_addr *)&saddr[num_local++],
&(((struct sockaddr_in *)ai.rti_info[RTAX_IFA])->sin_addr),
sizeof(struct in_addr));
}
break;
case AF_INET6:
if (ai.rti_info[RTAX_IFA] != NULL &&
ai.rti_info[RTAX_IFA]->sa_family == AF_INET6) {
sin = (struct sockaddr_in6 *)ai.rti_info[RTAX_IFA];
if (!IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) &&
!IN6_IS_ADDR_LOOPBACK(&sin->sin6_addr)){
if (alloced < num_local + 1) {
alloced += ESTIMATED_LOCAL;
saddr = (struct in6_addr *)realloc(saddr, alloced * sizeof saddr[0]);
if (saddr == NULL) {
num_local = 0;
goto failed;
break;
}
}
}
memcpy(&saddr[num_local++],&sin->sin6_addr, sizeof(struct in6_addr));
}
break;
default:
goto failed;
}
ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen);
}
}
}
free(buf);
close(s);
*size = num_local;
*addr = (char *)saddr;
return 1;
failed:
free(buf);
close(s);
*size = num_local;
*addr = NULL;
return -1;
}
#endif
#endif /* INET6 */
/* ********************************************************************** */
void sanitizeIfName(char *deviceDescr) {
#ifdef WIN32
int i;
for(i=0; i<strlen(deviceDescr); i++)
switch(deviceDescr[i]) {
case ':':
case '/':
case '\\':
case '.':
case ' ':
deviceDescr[i] = '_';
}
#endif
}
/* ********************************************************************** */
void calculateUniqueInterfaceName(int deviceId) {
#ifdef WIN32
int i;
#endif
if(myGlobals.device[deviceId].uniqueIfName)
free(myGlobals.device[deviceId].uniqueIfName);
myGlobals.device[deviceId].uniqueIfName = strdup(myGlobals.device[deviceId].humanFriendlyName);
sanitizeIfName(myGlobals.device[deviceId].uniqueIfName);
}
/* ********************************************************************** */
#ifdef HAVE_SNMP
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <string.h>
#ifndef min
#define min(a,b) (a<b ? a : b)
#endif
char* getIfName(char *hostname, char *community, int ifIdx,
char *ifName_buf, u_short ifName_buflen) {
struct snmp_session session, *ss;
struct snmp_pdu *pdu;
struct snmp_pdu *response;
char buf[64];
oid anOID[MAX_OID_LEN];
size_t anOID_len = MAX_OID_LEN;
struct variable_list *vars;
int status;
int count=1;
ifName_buf[0] = '\0';
/*
* Initialize the SNMP library
*/
init_snmp("ntop");
/*
* Initialize a "session" that defines who we're going to talk to
*/
snmp_sess_init( &session ); /* set up defaults */
session.peername = strdup(hostname);
/* set up the authentication parameters for talking to the server */
/* set the SNMP version number */
session.version = SNMP_VERSION_1;
/* set the SNMPv1 community name used for authentication */
session.community = (u_char*)community;
session.community_len = strlen(community);
/*
* Open the session
*/
ss = snmp_open(&session); /* establish the session */
if (!ss)
return(ifName_buf);
pdu = snmp_pdu_create(SNMP_MSG_GET);
snprintf(buf, sizeof(buf), ".1.3.6.1.2.1.31.1.1.1.1.%d", ifIdx);
read_objid(buf, anOID, &anOID_len); snmp_add_null_var(pdu, anOID, anOID_len);
traceEvent(CONST_TRACE_NOISY,
"Reading SNMP interface name: [host=%s][community=%s][%s]",
hostname, community, buf);
/*
* Send the Request out.
*/
status = snmp_synch_response(ss, pdu, &response);
/*
* Process the response.
*/
if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) {
/* manipuate the information ourselves */
for(vars = response->variables; vars; vars = vars->next_variable) {
if (vars->type == ASN_OCTET_STR) {
int len = min(vars->val_len, ifName_buflen-1);
memcpy(ifName_buf, vars->val.string, len);
ifName_buf[len] = '\0';
}
}
}
/*
* Clean up:
* 1) free the response.
* 2) close the session.
*/
if (response) snmp_free_pdu(response);
snmp_close(ss);
return (ifName_buf);
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1