⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tunnel.c

📁 开发snmp的开发包有两个开放的SNMP开发库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * tunnel.c -- *  *      An implementation of the TUNNEL-MIB for the UCD-SNMP 4.2 *      agent running on Linux 2.2.x. *       * Copyright (c) 2000 Frank Strauss <strauss@ibr.cs.tu-bs.de> * *                          All Rights Reserved *  * Permission to use, copy, modify and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appears in all copies and * that both that copyright notice and this permission notice appear in * supporting documentation, and that the name of the author and CMU and * The Regents of the University of California not be used in advertising * or publicity pertaining to distribution of the software without * specific written permission. *  * THE AUTHOR AND CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA * DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL * THE AUTHOR OR CMU OR THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY * DAMAGES WHATSOEVER RESULTING FROM THE LOSS OF USE, DATA OR PROFITS, * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. * *//* * NOTE: This TUNNEL-MIB implementation * *       (a) DOES NOT implement write access on the tunnelConfigTable, *           i.e. no new tunnels can be created and no existing tunnels *           can be removed through SET operations. * *       (b) DOES implement write access on some tunnelIfTable objects *           to allow reconfiguring established tunnels. This violates *           RFC 2667! However, the author thinks it makes sense. ;-) */#include <string.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/time.h>#include <sys/ioctl.h>#include <signal.h>#include <netinet/in.h>#include <arpa/inet.h>#include <linux/if.h>#include <linux/ip.h>#include <linux/sockios.h>#include <linux/if_tunnel.h>#include <linux/if_arp.h>#include <net-snmp/net-snmp-config.h>#include <net-snmp/net-snmp-includes.h>#include <net-snmp/agent/net-snmp-agent-includes.h>#include "util_funcs.h"#include "tunnel.h"#ifndef MIN#define MIN(a, b) (((a) < (b)) ? (a) : (b))#endif#ifndef MAX#define MAX(a, b) (((a) > (b)) ? (a) : (b))#endif#ifdef USING_IF_MIB_IFTABLE_IFTABLE_MODULE#include "if-mib/ifTable/ifTable.h"#include "if-mib/ifTable/ifTable_defs.h"#else/* * This is used, because the TUNNEL-MIB augments ifTable.  */extern unsigned char *var_ifEntry(struct variable *,                                  oid *, size_t *,                                  int, size_t *, WriteMethod **);#endif/* * tunnel_variables_oid: *   this is the top level oid that we want to register under.  This *   is essentially a prefix, with the suffix appearing in the *   variable below. */oid             tunnel_variables_oid[] =    { 1, 3, 6, 1, 2, 1, 10, 131, 1, 1 };const int       tunnel_len = 10;oid             tunnel_ifEntry_oid[] =    { 1, 3, 6, 1, 2, 1, 10, 131, 1, 1, 1, 1 };const int       tunnel_ifEntry_len = 12;oid             tunnel_configEntry_oid[] =    { 1, 3, 6, 1, 2, 1, 10, 131, 1, 1, 2, 1 };const int       tunnel_configEntry_len = 12;struct tunnel {    oid             ifindex;    int             id;    char           *ifname;    int             active;    unsigned long   local;    unsigned long   remote;    int             encaps;    int             hoplimit;    int             security;    int             tos;    oid             config_name[MAX_OID_LEN];    size_t          config_length;    struct tunnel  *next;};/* * variable4 tunnel_variables: *   this variable defines function callbacks and type return information  *   for the tunnel mib section  */struct variable4 tunnel_variables[] = {    /*     * magic number        , variable type , ro/rw , callback fn  , L, oidsuffix      */#define   LOCALADDRESS          1    {LOCALADDRESS, ASN_IPADDRESS, RWRITE, var_tunnelIfEntry, 3, {1, 1, 1}},#define   REMOTEADDRESS         2    {REMOTEADDRESS, ASN_IPADDRESS, RWRITE, var_tunnelIfEntry, 3,     {1, 1, 2}},#define   ENCAPSMETHOD          3    {ENCAPSMETHOD, ASN_INTEGER, RONLY, var_tunnelIfEntry, 3, {1, 1, 3}},#define   HOPLIMIT              4    {HOPLIMIT, ASN_INTEGER, RWRITE, var_tunnelIfEntry, 3, {1, 1, 4}},#define   SECURITY              5    {SECURITY, ASN_INTEGER, RONLY, var_tunnelIfEntry, 3, {1, 1, 5}},#define   TOS                   6    {TOS, ASN_INTEGER, RWRITE, var_tunnelIfEntry, 3, {1, 1, 6}},#define   IFINDEX               7    {IFINDEX, ASN_INTEGER, RONLY, var_tunnelConfigEntry, 3, {2, 1, 5}},#define   ROWSTATUS             8    {ROWSTATUS, ASN_INTEGER, RWRITE, var_tunnelConfigEntry, 3, {2, 1, 6}},};extern int      register_sysORTable(oid *, size_t, const char *);extern int      unregister_sysORTable(oid *, size_t);static oid      sysORTable_reg[] = { 1, 3, 6, 1, 2, 1, 10, 131 };static size_t   sysORTable_reglen = 8;static struct tunnel *tunnels;voiddeinit_tunnel(void){    unregister_sysORTable(sysORTable_reg, sysORTable_reglen);}intterm_tunnel(int majorID, int minorID, void *serverarg, void *clientarg){    deinit_tunnel();    return 0;}voidinit_tunnel(void){    register_sysORTable(sysORTable_reg, sysORTable_reglen,                        "RFC 2667 TUNNEL-MIB implementation for "                        "Linux 2.2.x kernels.");    /*     * register ourselves with the agent to handle our mib tree      */    REGISTER_MIB("tunnel", tunnel_variables, variable4,                 tunnel_variables_oid);    snmp_register_callback(SNMP_CALLBACK_LIBRARY,                           SNMP_CALLBACK_SHUTDOWN, term_tunnel, NULL);    tunnels = NULL;}static intgetType(int index){#ifndef USING_IF_MIB_IFTABLE_IFTABLE_MODULE    oid             name[MAX_OID_LEN] = { 1, 3, 6, 1, 2, 1, 2, 2, 1, 3 };    size_t          length = 10;    struct variable ifType_variable =        { 3, ASN_INTEGER, RONLY, var_ifEntry, 10,        {1, 3, 6, 1, 2, 1, 2, 2, 1, 3}    };    unsigned char  *p;    size_t          var_len;    WriteMethod    *write_method;    name[length] = index;    length++;    p = var_ifEntry(&ifType_variable,                    name, &length,                    1 /* exact */ , &var_len, &write_method);    if (!p)        return 0;    return *(int *) p;#else    ifTable_mib_index imi;    ifTable_rowreq_ctx *rr;    imi.ifIndex = index;    rr = ifTable_row_find_by_mib_index(&imi);    if (NULL == rr)        return 0;    return rr->data.ifType;#endif}static char    *getName(int index){#ifndef USING_IF_MIB_IFTABLE_IFTABLE_MODULE    oid             name[MAX_OID_LEN] = { 1, 3, 6, 1, 2, 1, 2, 2, 1, 2 };    size_t          length = 10;    struct variable ifName_variable =        { 2, ASN_INTEGER, RONLY, var_ifEntry, 10,        {1, 3, 6, 1, 2, 1, 2, 2, 1, 2}    };    unsigned char  *p;    size_t          var_len;    WriteMethod    *write_method;    name[length] = index;    length++;    p = var_ifEntry(&ifName_variable,                    name, &length,                    1 /* exact */ , &var_len, &write_method);    if (!p)        return NULL;    return p;#else    return netsnmp_access_interface_name_find(index);#endif}static struct ip_tunnel_parm *getTunnelParm(char *ifname){    struct ifreq    ifrq;    int             fd;    static struct ip_tunnel_parm parm;    if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {        return NULL;    }    memset(&parm, 0, sizeof(struct ip_tunnel_parm));    strcpy(ifrq.ifr_name, ifname);    ifrq.ifr_ifru.ifru_data = (void *) &parm;    if (ioctl(fd, SIOCGETTUNNEL, &ifrq) < 0) {        /*         * try again with the last char of the device name cut off.         * it might have been a zero digit appended by the agent.         */        ifrq.ifr_name[strlen(ifrq.ifr_name) - 1] = 0;        if (ioctl(fd, SIOCGETTUNNEL, &ifrq) < 0) {            close(fd);            return NULL;        }        ifname[strlen(ifname) - 1] = 0;    }    close(fd);    return &parm;}intsetTunnelParm(char *ifname, struct ip_tunnel_parm *parm){    struct ifreq    ifrq;    int             fd;    int             err;    if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {        return -1;    }    strcpy(ifrq.ifr_name, ifname);    ifrq.ifr_ifru.ifru_data = (void *) parm;    err = ioctl(fd, SIOCCHGTUNNEL, &ifrq);    close(fd);    return err;}/* * update a struct tunnel. its index and ifname elements have to be set. */static struct tunnel *updateTunnel(struct tunnel *tunnel){    struct ip_tunnel_parm *parm;    int             fd;    struct ifreq    ifrq;    /*     * NOTE: getTunnelParm() may adjust the passed ifname.      */    parm = getTunnelParm(tunnel->ifname);    if (!parm) {	DEBUGMSGTL(("tunnel",		    "updateTunnel(): getTunnelParm(\"%s\") returned NULL\n",		    tunnel->ifname));        tunnel->active = 0;        return NULL;    }    tunnel->active = 1;    tunnel->local = parm->iph.saddr;    tunnel->remote = parm->iph.daddr;    if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {        DEBUGMSGTL(("snmpd", "socket open failure in updateTunnels()\n"));        return NULL;    } else {        /*         * NOTE: this ioctl does not guarantee 6 bytes of a physaddr.         * In particular, a 'sit0' interface only appears to get back         * 4 bytes of sa_data. We don't use sa_data here, or we'd         * need to memset it to 0 before the ioct.         */        strcpy(ifrq.ifr_name, tunnel->ifname);        if (ioctl(fd, SIOCGIFHWADDR, &ifrq) == 0)            switch (ifrq.ifr_hwaddr.sa_family) {            case ARPHRD_TUNNEL:                tunnel->encaps = 2;                break;;         /* direct */            case ARPHRD_TUNNEL6:                tunnel->encaps = 2;                break;;         /* direct */            case ARPHRD_IPGRE:                tunnel->encaps = 3;                break;;         /* gre */            case ARPHRD_SIT:                tunnel->encaps = 2;                break;;         /* direct */            default:                tunnel->encaps = 1;     /* other */            }        close(fd);    }    tunnel->hoplimit = parm->iph.ttl;    tunnel->security = 1;    tunnel->tos = (parm->iph.tos & 1) ? -1 : parm->iph.tos;    /*     * XXX: adjust tos mapping (kernel <-> TUNNEL-MIB::tunnelIfTOS)      */    return tunnel;}static voidupdateTunnels(void){    static int      max_index = 1;    static struct tunnel *last_tunnel = NULL;    struct tunnel  *tunnel;    char           *ifname;    int             type;    /*     * uptime the tunnels we have so far      */    for (tunnel = tunnels; tunnel; tunnel = tunnel->next) {        DEBUGMSG(("tunnel",                  "updateTunnels(): updating %s (index=%d)\n",                  tunnel->ifname, tunnel->ifindex));        updateTunnel(tunnel);    }    /*     * look for new tunnels      */    for (; max_index < 256; max_index++) {        DEBUGMSG(("tunnel",                  "updateTunnels(): looking for new index=%d\n",                  max_index));        type = getType(max_index);        if (type == 131) {            tunnel = (struct tunnel *) malloc(sizeof(struct tunnel));            if (!tunnel)                continue;            tunnel->ifindex = max_index;            tunnel->id = 1;            ifname = getName(max_index);            if (!ifname) {                free(tunnel);                continue;            }            tunnel->ifname = strdup(ifname);            if (!tunnel->ifname) {                free(tunnel);                continue;            }            if (!updateTunnel(tunnel)) {                free(tunnel);                continue;            }            if (last_tunnel)                last_tunnel->next = tunnel;            if (!tunnels)                tunnels = last_tunnel = tunnel;            tunnel->next = NULL;            last_tunnel = tunnel;            DEBUGMSG(("tunnel",                      "updateTunnels(): added %s (index=%d state=%d)\n",                      tunnel->ifname, tunnel->ifindex, tunnel->active));        }        if (type == 0)            break;    }}static struct tunnel *getTunnelByIfIndex(int index){    struct tunnel  *tunnel;    DEBUGMSG(("tunnel", "getTunnelByIfIndex(%d): ", index));    for (tunnel = tunnels; tunnel; tunnel = tunnel->next) {        if (tunnel->ifindex == index) {            if (!tunnel->active)                break;            DEBUGMSG(("tunnel",                      "%s (index=%d)\n", tunnel->ifname, tunnel->ifindex));            return tunnel;        }    }    DEBUGMSG(("tunnel", "NONE\n"));    return NULL;}static struct tunnel *getNextTunnelByIfIndex(int index){    struct tunnel  *tunnel;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -