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

📄 snmpudpipv6domain.c

📁 snmp up 2
💻 C
📖 第 1 页 / 共 3 页
字号:
#include <net-snmp/net-snmp-config.h>#include <stdio.h>#include <sys/types.h>#include <ctype.h>#include <errno.h>#if HAVE_STRING_H#include <string.h>#else#include <strings.h>#endif#if HAVE_STDLIB_H#include <stdlib.h>#endif#if HAVE_UNISTD_H#include <unistd.h>#endif#if HAVE_SYS_SOCKET_H#include <sys/socket.h>#endif#if HAVE_NETINET_IN_H#include <netinet/in.h>#endif#if HAVE_ARPA_INET_H#include <arpa/inet.h>#endif#if HAVE_NETDB_H#include <netdb.h>#endif#if HAVE_NET_IF_H#include <net/if.h>#endif#if HAVE_DMALLOC_H#include <dmalloc.h>#endif#include <net-snmp/types.h>#include <net-snmp/output_api.h>#include <net-snmp/config_api.h>#include <net-snmp/library/snmp_transport.h>#include <net-snmp/library/snmpUDPIPv6Domain.h>oid netsnmp_UDPIPv6Domain[10] = { ENTERPRISE_MIB, 3, 3, 4 };static netsnmp_tdomain udp6Domain;/* * Return a string representing the address in data, or else the "far end" * address if data is NULL.   */static char *netsnmp_udp6_fmtaddr(netsnmp_transport *t, void *data, int len){    struct sockaddr_in6 *to = NULL;    DEBUGMSGTL(("netsnmp_udp6", "fmtaddr: t = %p, data = %p, len = %d\n", t,                data, len));    if (data != NULL && len == sizeof(struct sockaddr_in6)) {        to = (struct sockaddr_in6 *) data;    } else if (t != NULL && t->data != NULL) {        to = (struct sockaddr_in6 *) t->data;    }    if (to == NULL) {        return strdup("UDP/IPv6: unknown");    } else {        char addr[INET6_ADDRSTRLEN];        char tmp[INET6_ADDRSTRLEN + 8];        sprintf(tmp, "[%s]:%hd",                inet_ntop(AF_INET6, (void *) &(to->sin6_addr), addr,                          INET6_ADDRSTRLEN), ntohs(to->sin6_port));        return strdup(tmp);    }}/* * You can write something into opaque that will subsequently get passed back  * to your send function if you like.  For instance, you might want to * remember where a PDU came from, so that you can send a reply there...   */static intnetsnmp_udp6_recv(netsnmp_transport *t, void *buf, int size,		  void **opaque, int *olength){    int             rc = -1;    socklen_t       fromlen = sizeof(struct sockaddr_in6);    struct sockaddr *from;    if (t != NULL && t->sock >= 0) {        from = (struct sockaddr *) malloc(sizeof(struct sockaddr_in6));        if (from == NULL) {            *opaque = NULL;            *olength = 0;            return -1;        } else {            memset(from, 0, fromlen);        }	while (rc < 0) {	  rc = recvfrom(t->sock, buf, size, 0, from, &fromlen);	  if (rc < 0 && errno != EINTR) {	    break;	  }	}        if (rc >= 0) {	    char *string = netsnmp_udp6_fmtaddr(NULL, from, fromlen);            DEBUGMSGTL(("netsnmp_udp6",			"recvfrom fd %d got %d bytes (from %s)\n", t->sock,                        rc, string));            free(string);        } else {            DEBUGMSGTL(("netsnmp_udp6", "recvfrom fd %d err %d (\"%s\")\n",			t->sock, errno, strerror(errno)));        }        *opaque = (void *) from;        *olength = sizeof(struct sockaddr_in6);    }    return rc;}static intnetsnmp_udp6_send(netsnmp_transport *t, void *buf, int size,		  void **opaque, int *olength){    int rc = -1;    struct sockaddr *to = NULL;    if (opaque != NULL && *opaque != NULL &&        *olength == sizeof(struct sockaddr_in6)) {        to = (struct sockaddr *) (*opaque);    } else if (t != NULL && t->data != NULL &&               t->data_length == sizeof(struct sockaddr_in6)) {        to = (struct sockaddr *) (t->data);    }    if (to != NULL && t != NULL && t->sock >= 0) {        char *string = netsnmp_udp6_fmtaddr(NULL, (void *)to,					    sizeof(struct sockaddr_in6));        DEBUGMSGTL(("netsnmp_udp6", "send %d bytes from %p to %s on fd %d\n",                    size, buf, string, t->sock));        free(string);	while (rc < 0) {	    rc = sendto(t->sock, buf, size, 0, to,sizeof(struct sockaddr_in6));	    if (rc < 0 && errno != EINTR) {		break;	    }	}    }    return rc;}static intnetsnmp_udp6_close(netsnmp_transport *t){    int rc = -1;    if (t != NULL && t->sock >= 0) {        DEBUGMSGTL(("netsnmp_udp6", "close fd %d\n", t->sock));#ifndef HAVE_CLOSESOCKET        rc = close(t->sock);#else        rc = closesocket(t->sock);#endif        t->sock = -1;    }    return rc;}/* * Open a UDP/IPv6-based transport for SNMP.  Local is TRUE if addr is the * local address to bind to (i.e. this is a server-type session); otherwise * addr is the remote address to send things to.   */netsnmp_transport *netsnmp_udp6_transport(struct sockaddr_in6 *addr, int local){    netsnmp_transport *t = NULL;    int             rc = 0, udpbuf = (1 << 17);    char           *string = NULL;    if (addr == NULL || addr->sin6_family != AF_INET6) {        return NULL;    }    t = (netsnmp_transport *) malloc(sizeof(netsnmp_transport));    if (t == NULL) {        return NULL;    }    string = netsnmp_udp6_fmtaddr(NULL, (void *) addr,				  sizeof(struct sockaddr_in6));    DEBUGMSGTL(("netsnmp_udp6", "open %s %s\n", local ? "local" : "remote",                string));    free(string);    memset(t, 0, sizeof(netsnmp_transport));    t->domain = netsnmp_UDPIPv6Domain;    t->domain_length =        sizeof(netsnmp_UDPIPv6Domain) / sizeof(netsnmp_UDPIPv6Domain[0]);    t->sock = socket(PF_INET6, SOCK_DGRAM, 0);    if (t->sock < 0) {        netsnmp_transport_free(t);        return NULL;    }#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(t->sock, SOL_SOCKET, SO_BSDCOMPAT, &one, sizeof(one));    }#endif                          /*SO_BSDCOMPAT */    /*     * Try to set the send and receive buffers to a reasonably large value, so     * that we can send and receive big PDUs (defaults to 8192 bytes (!) on     * Solaris, for instance).  Don't worry too much about errors -- just     * plough on regardless.       */#ifdef  SO_SNDBUF    if (setsockopt(t->sock, SOL_SOCKET, SO_SNDBUF, &udpbuf, sizeof(int)) != 0){        DEBUGMSGTL(("netsnmp_udp6", "couldn't set SO_SNDBUF to %d bytes: %s\n",		    udpbuf, strerror(errno)));    }#endif                          /*SO_SNDBUF */#ifdef  SO_RCVBUF    if (setsockopt(t->sock, SOL_SOCKET, SO_RCVBUF, &udpbuf, sizeof(int)) != 0){        DEBUGMSGTL(("netsnmp_udp6", "couldn't set SO_RCVBUF to %d bytes: %s\n",		    udpbuf, strerror(errno)));    }#endif                          /*SO_RCVBUF */    if (local) {        /*         * This session is inteneded as a server, so we must bind on to the         * given IP address, which may include an interface address, or could         * be INADDR_ANY, but certainly includes a port number.         */#ifdef IPV6_V6ONLY        /* Try to restrict PF_INET6 socket to IPv6 communications only. */        {	  int one=1;	  if (setsockopt(t->sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&one, sizeof(one)) != 0) {	    DEBUGMSGTL(("netsnmp_udp6", "couldn't set IPV6_V6ONLY to %d bytes: %s\n", one, strerror(errno)));	  } 	}#endif        rc = bind(t->sock, (struct sockaddr *) addr,		  sizeof(struct sockaddr_in6));        if (rc != 0) {            netsnmp_udp6_close(t);            netsnmp_transport_free(t);            return NULL;        }        t->local = malloc(18);        if (t->local == NULL) {            netsnmp_udp6_close(t);            netsnmp_transport_free(t);        }        memcpy(t->local, addr->sin6_addr.s6_addr, 16);        t->local[16] = (addr->sin6_port & 0xff00) >> 8;        t->local[17] = (addr->sin6_port & 0x00ff) >> 0;        t->local_length = 18;        t->data = NULL;        t->data_length = 0;    } else {        /*         * This is a client session.  Save the address in the         * transport-specific data pointer for later use by netsnmp_udp6_send.         */        t->data = malloc(sizeof(struct sockaddr_in6));        if (t->data == NULL) {            netsnmp_transport_free(t);            return NULL;        }        memcpy(t->data, addr, sizeof(struct sockaddr_in6));        t->data_length = sizeof(struct sockaddr_in6);        t->remote = malloc(18);        if (t->remote == NULL) {            netsnmp_udp6_close(t);            netsnmp_transport_free(t);            return NULL;        }        memcpy(t->remote, addr->sin6_addr.s6_addr, 16);        t->remote[16] = (addr->sin6_port & 0xff00) >> 8;        t->remote[17] = (addr->sin6_port & 0x00ff) >> 0;        t->remote_length = 18;    }    /*     * 16-bit length field, 8 byte UDP header, 40 byte IPv6 header.       */    t->msgMaxSize = 0xffff - 8 - 40;    t->f_recv     = netsnmp_udp6_recv;    t->f_send     = netsnmp_udp6_send;    t->f_close    = netsnmp_udp6_close;    t->f_accept   = NULL;    t->f_fmtaddr  = netsnmp_udp6_fmtaddr;    return t;}intnetsnmp_sockaddr_in6(struct sockaddr_in6 *addr,                     const char *inpeername, int remote_port){    char           *cp = NULL, *peername = NULL;    char            debug_addr[INET6_ADDRSTRLEN];#if HAVE_GETADDRINFO    struct addrinfo *addrs = NULL;    struct addrinfo hint;    int             err;#elif HAVE_GETIPNODEBYNAME    struct hostent *hp = NULL;    int             err;#elif HAVE_GETHOSTBYNAME    struct hostent *hp = NULL;#endif    if (addr == NULL) {        return 0;    }    DEBUGMSGTL(("netsnmp_sockaddr_in6", "addr %p, peername \"%s\"\n",                addr, inpeername ? inpeername : "[NIL]"));    memset(addr, 0, sizeof(struct sockaddr_in6));    addr->sin6_family = AF_INET6;    addr->sin6_addr = in6addr_any;    if (remote_port > 0) {        addr->sin6_port = htons(remote_port);    } else if (netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 				  NETSNMP_DS_LIB_DEFAULT_PORT) > 0) {        addr->sin6_port = htons(netsnmp_ds_get_int(NETSNMP_DS_LIBRARY_ID, 						 NETSNMP_DS_LIB_DEFAULT_PORT));    } else {        addr->sin6_port = htons(SNMP_PORT);    }    if (inpeername != NULL) {        /*         * Duplicate the peername because we might want to mank around with         * it.           */        peername = strdup(inpeername);        if (peername == NULL) {            return 0;        }        for (cp = peername; *cp && isdigit((int) *cp); cp++);        if (!*cp && atoi(peername) != 0) {            /*             * Okay, it looks like JUST a port number.               */            DEBUGMSGTL(("netsnmp_sockaddr_in6", "totally numeric: %d\n",                        atoi(peername)));            addr->sin6_port = htons(atoi(peername));            goto resolved;        }        /*         * See if it is an IPv6 address, which covered with square brankets         * with an appended :port.           */        if (*peername == '[') {            cp = strchr(peername, ']');            if (cp != NULL) {	      /*	       * See if it is an IPv6 link-local address with interface	       * name as <zone_id>, like fe80::1234%eth0.	       * Please refer to the internet draft, IPv6 Scoped Address Architecture	       * http://www.ietf.org/internet-drafts/draft-ietf-ipngwg-scoping-arch-04.txt	       *	       */	        char *scope_id;		unsigned int if_index = 0;                *cp = '\0';		scope_id = strchr(peername + 1, '%');		if (scope_id != NULL) {		    *scope_id = '\0';		    if_index = if_nametoindex(scope_id + 1);		}                if (*(cp + 1) == ':') {                    if (atoi(cp + 2) != 0 &&                        inet_pton(AF_INET6, peername + 1,                                  (void *) &(addr->sin6_addr))) {                        DEBUGMSGTL(("netsnmp_sockaddr_in6",                                    "IPv6 address with port suffix :%d\n",                                    atoi(cp + 2)));                        addr->sin6_port = htons(atoi(cp + 2));			addr->sin6_scope_id = if_index;                        goto resolved;                    }                } else {

⌨️ 快捷键说明

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