net_util_md.c

来自「This is a resource based on j2me embedde」· C语言 代码 · 共 1,305 行 · 第 1/3 页

C
1,305
字号
/* * @(#)net_util_md.c	1.14 06/10/13 * * Copyright  1990-2008 Sun Microsystems, Inc. All Rights Reserved.   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER   *    * This program is free software; you can redistribute it and/or   * modify it under the terms of the GNU General Public License version   * 2 only, as published by the Free Software Foundation.    *    * 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 version 2 for more details (a copy is   * included at /legal/license.txt).    *    * You should have received a copy of the GNU General Public License   * version 2 along with this work; if not, write to the Free Software   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA   * 02110-1301 USA    *    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa   * Clara, CA 95054 or visit www.sun.com if you need additional   * information or have any questions.  * */#include <errno.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/tcp.h>	/* Defines TCP_NODELAY, needed for 2.6 */#include <netinet/in.h>#include <net/if.h>#include <netdb.h>#include <stdlib.h>#include <dlfcn.h>#ifdef __linux__#include <arpa/inet.h>#include <net/route.h>#include <sys/utsname.h>#ifndef IPV6_FLOWINFO_SEND#define IPV6_FLOWINFO_SEND      33#endif#endif#include "jni_util.h"#include "jvm.h"#include "net_util.h"#include "java_net_InetAddress.h"#include "java_net_Inet4Address.h"#include "java_net_Inet6Address.h"#include "java_net_SocketOptions.h"/* needed from libsocket on Solaris 8 */getaddrinfo_f getaddrinfo_ptr = NULL;freeaddrinfo_f freeaddrinfo_ptr = NULL;getnameinfo_f getnameinfo_ptr = NULL;/* * EXCLBIND socket options only on Solaris 8 & 9. */#if defined(__solaris__) && !defined(TCP_EXCLBIND)#define TCP_EXCLBIND            0x21#endif#if defined(__solaris__) && !defined(UDP_EXCLBIND)#define UDP_EXCLBIND            0x0101#endif#ifdef __solaris__static int init_max_buf;static int tcp_max_buf;static int udp_max_buf;/* * Get the specified parameter from the specified driver. The value * of the parameter is assumed to be an 'int'. If the parameter * cannot be obtained return the specified default value. */static int getParam(char *driver, char *param, int dflt){    struct strioctl stri;    char buf [64];    int s;    int value;    s = open (driver, O_RDWR);    if (s < 0) {	return dflt;    }    strncpy (buf, param, sizeof(buf));    stri.ic_cmd = ND_GET;    stri.ic_timout = 0;    stri.ic_dp = buf;    stri.ic_len = sizeof(buf);    if (ioctl (s, I_STR, &stri) < 0) {	value = dflt;    } else {	value = atoi(buf);    }    close (s);    return value;}#endif#ifdef __linux__static int kernelV22 = 0;static int vinit = 0;int kernelIsV22 () {    if (!vinit) {	struct utsname sysinfo;	if (uname(&sysinfo) == 0) {	    sysinfo.release[3] = '\0';	    if (strcmp(sysinfo.release, "2.2") == 0) {		kernelV22 = JNI_TRUE;	    }	}	vinit = 1;    }    return kernelV22;}static int kernelV24 = 0;static int vinit24 = 0;int kernelIsV24 () {    if (!vinit24) {	struct utsname sysinfo;	if (uname(&sysinfo) == 0) {	    sysinfo.release[3] = '\0';	    if (strcmp(sysinfo.release, "2.4") == 0) {		kernelV24 = JNI_TRUE;	    }	}	vinit24 = 1;    }    return kernelV24;}#endif#include "jni_statics.h"int initialized = 0;void init(JNIEnv *env) {    if (!initialized) {        Java_java_net_InetAddress_init(env, 0);        Java_java_net_Inet4Address_init(env, 0);        Java_java_net_Inet6Address_init(env, 0);	initialized = 1;    }}voidNET_ThrowByNameWithLastError(JNIEnv *env, const char *name,                   const char *defaultDetail) {    char errmsg[255];    sprintf(errmsg, "errno: %d, error: %s\n", errno, defaultDetail);     JNU_ThrowByNameWithLastError(env, name, errmsg); }void NET_ThrowCurrent(JNIEnv *env, char *msg) {    NET_ThrowNew(env, errno, msg);}voidNET_ThrowNew(JNIEnv *env, int errorNumber, char *msg) {    char fullMsg[512];    if (!msg) {	msg = "no further information";    }    switch(errorNumber) {    case EBADF: 	jio_snprintf(fullMsg, sizeof(fullMsg), "socket closed: %s", msg);	JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", fullMsg);	break;    case EINTR:	JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", msg);	break;    default:	errno = errorNumber;        JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", msg);	break;    }}jfieldIDNET_GetFileDescriptorID(JNIEnv *env){    jclass cls = (*env)->FindClass(env, "java/io/FileDescriptor");    CHECK_NULL_RETURN(cls, NULL);    return (*env)->GetFieldID(env, cls, "fd", "I");}jint  IPv6_supported(){#ifndef AF_INET6    return JNI_FALSE;#endif#ifdef AF_INET6    int fd;    void *ipv6_fn;    fd = JVM_Socket(AF_INET6, SOCK_STREAM, 0) ;    if (fd < 0) {	/* 	 *  TODO: We really cant tell since it may be an unrelated error 	 *  for now we will assume that AF_INET6 is not available 	 */	return JNI_FALSE;    }     /**     * Linux - check if any interface has an IPv6 address.     * Don't need to parse the line - we just need an indication.     */    {        FILE *fP = fopen("/proc/net/if_inet6", "r");        char buf[255];        char *bufP;        if (fP == NULL) {	    close(fd);            return JNI_FALSE;        }        bufP = fgets(buf, sizeof(buf), fP);        fclose(fP);        if (bufP == NULL) {	    close(fd);            return JNI_FALSE;        }    }    /**     * On Solaris 8 it's possible to create INET6 sockets even     * though IPv6 is not enabled on all interfaces. Thus we     * query the number of IPv6 addresses to verify that IPv6     * has been configured on at least one interface.     *     * On Linux it doesn't matter - if IPv6 is built-in the      * kernel then IPv6 addresses will be bound automatically     * to all interfaces.     */#endif /* AF_INET6 */    /*      *  OK we may have the stack available in the kernel,     *  we should also check if the APIs are available.     */    ipv6_fn = dlsym(RTLD_DEFAULT, "inet_pton");    if (ipv6_fn == NULL ) { 	close(fd);	return JNI_FALSE;    }    /*     * We've got the library, let's get the pointers to some     * IPV6 specific functions. We have to do that because, at least     * on Solaris we may build on a system without IPV6 networking     * libraries, therefore we can't have a hard link to these     * functions.     */    getaddrinfo_ptr = (getaddrinfo_f)        dlsym(RTLD_DEFAULT, "getaddrinfo");    freeaddrinfo_ptr = (freeaddrinfo_f)        dlsym(RTLD_DEFAULT, "freeaddrinfo");    getnameinfo_ptr = (getnameinfo_f)        dlsym(RTLD_DEFAULT, "getnameinfo");    if (freeaddrinfo_ptr == NULL || getnameinfo_ptr == NULL) {        /* We need all 3 of them */        getaddrinfo_ptr = NULL;    }    close(fd);    return JNI_TRUE; }void NET_AllocSockaddr(struct sockaddr **him, int *len) {#ifdef AF_INET6    if (ipv6_available()) {	struct sockaddr_in6 *him6 = (struct sockaddr_in6*)malloc(sizeof(struct sockaddr_in6));	*him = (struct sockaddr*)him6;	*len = sizeof(struct sockaddr_in6);    } else#endif /* AF_INET6 */  	{	    struct sockaddr_in *him4 = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));	    *him = (struct sockaddr*)him4;	    *len = sizeof(struct sockaddr_in);	}}#if defined(__linux__) && defined(AF_INET6)/* following code creates a list of addresses from the kernel * routing table that are routed via the loopback address. * We check all destination addresses against this table * and override the scope_id field to use the relevant value for "lo" * in order to work-around the Linux bug that prevents packets destined * for certain local addresses from being sent via a physical interface. */struct loopback_route {    struct in6_addr addr; /* destination address */    int plen; /* prefix length */};static struct loopback_route *loRoutes = 0;static int nRoutes = 0; /* number of routes */static int loRoutes_size = 16; /* initial size */static int lo_scope_id = 0;static void initLoopbackRoutes();void printAddr (struct in6_addr *addr) {    int i;    for (i=0; i<16; i++) {	printf ("%02x", addr->s6_addr[i]);    }    printf ("\n");}   static void initLoopbackRoutes() {    FILE *f;    char srcp[8][5];    char hopp[8][5];    int dest_plen, src_plen, use, refcnt, metric;    unsigned long flags;    char dest_str[40];    struct in6_addr dest_addr;    char device[16];        if (loRoutes != 0) {	free (loRoutes);    }    loRoutes = calloc (loRoutes_size, sizeof(struct loopback_route));    if (loRoutes == 0) {	return;    }    /*     * Scan /proc/net/ipv6_route looking for a matching     * route.     */    if ((f = fopen("/proc/net/ipv6_route", "r")) == NULL) {	return ;    }    while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x "                     "%4s%4s%4s%4s%4s%4s%4s%4s %02x "                     "%4s%4s%4s%4s%4s%4s%4s%4s "                     "%08x %08x %08x %08lx %8s",		     dest_str, &dest_str[5], &dest_str[10], &dest_str[15],		     &dest_str[20], &dest_str[25], &dest_str[30], &dest_str[35],		     &dest_plen,		     srcp[0], srcp[1], srcp[2], srcp[3],		     srcp[4], srcp[5], srcp[6], srcp[7],		     &src_plen,		     hopp[0], hopp[1], hopp[2], hopp[3],		     hopp[4], hopp[5], hopp[6], hopp[7],		     &metric, &use, &refcnt, &flags, device) == 31) {	/* 	 * Some routes should be ignored	 */	if ( (dest_plen < 0 || dest_plen > 128)  ||	     (src_plen != 0) ||				     (flags & (RTF_POLICY | RTF_FLOW)) ||	     ((flags & RTF_REJECT) && dest_plen == 0) ) {	    continue;	}	/*  	 * Convert the destination address	 */	dest_str[4] = ':';	dest_str[9] = ':';	dest_str[14] = ':';	dest_str[19] = ':';	dest_str[24] = ':';	dest_str[29] = ':';	dest_str[34] = ':';	dest_str[39] = '\0';	if (inet_pton(AF_INET6, dest_str, &dest_addr) < 0) {	    /* not an Ipv6 address */	    continue;	} 	if (strcmp(device, "lo") != 0) {	    /* Not a loopback route */	    continue;	} else {	    if (nRoutes == loRoutes_size) {		loRoutes = realloc (loRoutes, loRoutes_size * 				sizeof (struct loopback_route) * 2);		if (loRoutes == 0) {		    return ;		}		loRoutes_size *= 2;	    }	    memcpy (&loRoutes[nRoutes].addr,&dest_addr,sizeof(struct in6_addr));	    loRoutes[nRoutes].plen = dest_plen;	    nRoutes ++;	}    }    fclose (f);    {	/* now find the scope_id for "lo" */        char devname[20];        char addr6p[8][5];        int plen, scope, dad_status, if_idx;        if ((f = fopen("/proc/net/if_inet6", "r")) != NULL) {            while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",                      addr6p[0], addr6p[1], addr6p[2], addr6p[3],                      addr6p[4], addr6p[5], addr6p[6], addr6p[7],                  &if_idx, &plen, &scope, &dad_status, devname) == 13) {		if (strcmp(devname, "lo") == 0) {			    /*		     * Found - so just return the index

⌨️ 快捷键说明

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