[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r4268 - GNUnet/src/util/network
From: |
grothoff |
Subject: |
[GNUnet-SVN] r4268 - GNUnet/src/util/network |
Date: |
Mon, 8 Jan 2007 20:38:05 -0800 (PST) |
Author: grothoff
Date: 2007-01-08 20:38:03 -0800 (Mon, 08 Jan 2007)
New Revision: 4268
Added:
GNUnet/src/util/network/ip.c
Log:
missing
Added: GNUnet/src/util/network/ip.c
===================================================================
--- GNUnet/src/util/network/ip.c 2007-01-09 04:36:00 UTC (rev 4267)
+++ GNUnet/src/util/network/ip.c 2007-01-09 04:38:03 UTC (rev 4268)
@@ -0,0 +1,408 @@
+/*
+ This file is part of GNUnet.
+ (C) 2001, 2002, 2004, 2005, 2006, 2007 Christian Grothoff (and other
contributing authors)
+
+ GNUnet 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, or (at your
+ option) any later version.
+
+ GNUnet 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 GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file util/network/ip.c
+ * @brief code to determine the IP of the local machine
+ *
+ *
+ * Determine the IP of the local machine. We have many
+ * ways to get that IP:
+ * a) from the interface (ifconfig)
+ * b) via DNS from our HOSTNAME (environment)
+ * c) from the configuration (HOSTNAME specification or static IP)
+ *
+ * Which way applies depends on the OS, the configuration
+ * (dynDNS? static IP? NAT?) and at the end what the user
+ * needs.
+ *
+ * @author Christian Grothoff
+ * @author Tzvetan Horozov
+ */
+
+#include <stdlib.h>
+#include "platform.h"
+#include "gnunet_util_network.h"
+
+/* maximum length of hostname */
+#define MAX_HOSTNAME 1024
+
+/**
+ * Obtain the identity information for the current node
+ * (connection information), conInfo.
+ * @return SYSERR on failure, OK on success
+ */
+static int getAddressFromHostname(struct GE_Context * ectx,
+ IPaddr * identity) {
+ char hostname[MAX_HOSTNAME];
+ int ret;
+
+ if (0 != gethostname(hostname, MAX_HOSTNAME)) {
+ GE_LOG_STRERROR(ectx,
+ GE_ERROR | GE_ADMIN | GE_USER | GE_BULK,
+ "gethostname");
+ return SYSERR;
+ }
+ ret = get_host_by_name(ectx,
+ hostname,
+ identity);
+ return ret;
+}
+
+#if HAVE_GETIFADDRS && HAVE_FREEIFADDRS
+static int getAddressFromGetIfAddrs(struct GC_Configuration * cfg,
+ struct GE_Context * ectx,
+ IPaddr * identity) {
+ char * interfaces;
+ struct ifaddrs *ifa_first;
+
+ if (-1 == GC_get_configuration_value_string(cfg,
+ "NETWORK",
+ "INTERFACE",
+ "eth0",
+ &interfaces)) {
+ GE_LOG(ectx,
+ GE_ERROR | GE_BULK | GE_USER,
+ _("No interface specified in section `%s' under `%s'!\n"),
+ "NETWORK",
+ "INTERFACE");
+ return SYSERR; /* that won't work! */
+ }
+
+ if (getifaddrs(&ifa_first) == 0) {
+ struct ifaddrs *ifa_ptr;
+
+ ifa_ptr = ifa_first;
+ for (ifa_ptr = ifa_first; ifa_ptr != NULL; ifa_ptr = ifa_ptr->ifa_next) {
+ if (ifa_ptr->ifa_name != NULL &&
+ ifa_ptr->ifa_addr != NULL &&
+ (ifa_ptr->ifa_flags & IFF_UP) != 0) {
+ if (strcmp(interfaces, (char *)ifa_ptr->ifa_name) != 0)
+ continue;
+ if (ifa_ptr->ifa_addr->sa_family != AF_INET)
+ continue;
+ memcpy(identity,
+ &(((struct sockaddr_in *)ifa_ptr->ifa_addr)->sin_addr),
+ sizeof(struct in_addr));
+ freeifaddrs(ifa_first);
+ FREE(interfaces);
+ return OK;
+ }
+ }
+ freeifaddrs(ifa_first);
+ }
+ GE_LOG(ectx,
+ GE_WARNING | GE_USER | GE_BULK,
+ _("Could not obtain IP for interface `%s' using `%s'.\n"),
+ interfaces,
+ "getifaddrs");
+ FREE(interfaces);
+ return SYSERR;
+}
+#endif
+
+
+#if LINUX || SOMEBSD || MINGW
+#define MAX_INTERFACES 16
+static int getAddressFromIOCTL(struct GC_Configuration * cfg,
+ struct GE_Context * ectx,
+ IPaddr * identity) {
+ char * interfaces;
+#ifndef MINGW
+ struct ifreq ifr[MAX_INTERFACES];
+ struct ifconf ifc;
+ int sockfd,ifCount;
+#else
+ DWORD dwIP;
+#endif
+ int i;
+
+ if (-1 == GC_get_configuration_value_string(cfg,
+ "NETWORK",
+ "INTERFACE",
+ "eth0",
+ &interfaces)) {
+ GE_LOG(ectx,
+ GE_ERROR | GE_BULK | GE_USER,
+ _("No interface specified in section `%s' under `%s'!\n"),
+ "NETWORK",
+ "INTERFACE");
+ return SYSERR; /* that won't work! */
+ }
+#ifndef MINGW
+ sockfd = SOCKET(PF_INET, SOCK_DGRAM, 0);
+ if (sockfd == -1) {
+ FREE(interfaces);
+ GE_LOG_STRERROR(ectx,
+ GE_ERROR | GE_ADMIN | GE_USER | GE_BULK,
+ "socket");
+ return SYSERR;
+ }
+ memset(&ifc,
+ 0,
+ sizeof(struct ifconf));
+ ifc.ifc_len = sizeof(ifr);
+ ifc.ifc_buf = (char*)𝔦
+
+ if (ioctl(sockfd,
+ SIOCGIFCONF,
+ &ifc) == -1) {
+ GE_LOG_STRERROR(ectx,
+ GE_WARNING | GE_ADMIN | GE_USER | GE_BULK,
+ "ioctl");
+ if (0 != CLOSE(sockfd))
+ GE_LOG_STRERROR(ectx,
+ GE_WARNING | GE_ADMIN | GE_BULK,
+ "close");
+ FREE(interfaces);
+ return SYSERR;
+ }
+ ifCount = ifc.ifc_len / sizeof(struct ifreq);
+
+ /* first, try to find exatly matching interface */
+ for (i=0;i<ifCount;i++){
+ if (ioctl(sockfd, SIOCGIFADDR, &ifr[i]) != 0)
+ continue;
+ if (ioctl(sockfd, SIOCGIFFLAGS, &ifr[i]) != 0)
+ continue;
+ if (!(ifr[i].ifr_flags & IFF_UP))
+ continue;
+ if (strcmp((char*) interfaces,
+ (char*) ifr[i].ifr_name) != 0)
+ continue;
+ memcpy(identity,
+ &(((struct sockaddr_in *)&ifr[i].ifr_addr)->sin_addr),
+ sizeof(struct in_addr));
+ if (0 != CLOSE(sockfd))
+ GE_LOG_STRERROR(ectx,
+ GE_WARNING | GE_ADMIN | GE_BULK,
+ "close");
+ FREE(interfaces);
+ return OK;
+ }
+ GE_LOG(ectx,
+ GE_WARNING | GE_ADMIN | GE_USER | GE_BULK,
+ _("Could not find interface `%s' using `%s', "
+ "trying to find another interface.\n"),
+ interfaces,
+ "ioctl");
+ /* if no such interface exists, take any interface but loopback */
+ for (i=0;i<ifCount;i++){
+ if (ioctl(sockfd, SIOCGIFADDR, &ifr[i]) != 0)
+ continue;
+ if (ioctl(sockfd, SIOCGIFFLAGS, &ifr[i]) != 0)
+ continue;
+ if (!(ifr[i].ifr_flags & IFF_UP))
+ continue;
+ if (strncmp("lo",
+ (char*) ifr[i].ifr_name, 2) == 0)
+ continue;
+ memcpy(identity,
+ &(((struct sockaddr_in *)&ifr[i].ifr_addr)->sin_addr),
+ sizeof(struct in_addr));
+ if (0 != CLOSE(sockfd))
+ GE_LOG_STRERROR(ectx,
+ GE_WARNING | GE_ADMIN | GE_BULK,
+ "close");
+ FREE(interfaces);
+ return OK;
+ }
+
+ if (0 != CLOSE(sockfd))
+ GE_LOG_STRERROR(ectx,
+ GE_WARNING | GE_ADMIN | GE_BULK,
+ "close");
+ GE_LOG(ectx,
+ GE_WARNING | GE_USER | GE_BULK,
+ _("Could not obtain IP for interface `%s' using `%s'.\n"),
+ interfaces,
+ "ioctl");
+ FREE(interfaces);
+ return SYSERR;
+#else /* MinGW */
+
+ /* Win 98 or Win NT SP 4 */
+ if (GNGetIpAddrTable)
+ {
+ PMIB_IFTABLE pTable;
+ PMIB_IPADDRTABLE pAddrTable;
+ DWORD dwIfIdx;
+ unsigned int iAddrCount = 0;
+
+ dwIP = 0;
+
+ EnumNICs(&pTable, &pAddrTable);
+
+ for(dwIfIdx=0; dwIfIdx < pTable->dwNumEntries; dwIfIdx++) {
+ unsigned long long l;
+ BYTE bPhysAddr[MAXLEN_PHYSADDR];
+
+ l = _atoi64(interfaces);
+
+ memset(bPhysAddr, 0, MAXLEN_PHYSADDR);
+ memcpy(bPhysAddr,
+ pTable->table[dwIfIdx].bPhysAddr,
+ pTable->table[dwIfIdx].dwPhysAddrLen);
+
+ if (memcmp(bPhysAddr, &l, sizeof(l)) == 0) {
+ for(i = 0; i < pAddrTable->dwNumEntries; i++) {
+ if (pAddrTable->table[i].dwIndex
+ == pTable->table[dwIfIdx].dwIndex) {
+ iAddrCount++;
+ dwIP = pAddrTable->table[i].dwAddr;
+ }
+ }
+ }
+ }
+
+ if (! iAddrCount)
+ {
+ GE_LOG(ectx, GE_WARNING | GE_BULK | GE_USER,
+ _("Could not find an IP address for "
+ "interface `%s'.\n"),
+ interfaces);
+
+ GlobalFree(pTable);
+ GlobalFree(pAddrTable);
+ return SYSERR;
+ }
+ else if (iAddrCount > 1)
+ GE_LOG(ectx, GE_WARNING | GE_BULK | GE_USER,
+ _("There is more than one IP address specified"
+ " for interface `%s'.\nGNUnet will "
+ "use %u.%u.%u.%u.\n"),
+ interfaces,
+ PRIP(ntohl(dwIP)));
+
+ identity->addr = dwIP;
+
+ GlobalFree(pTable);
+ GlobalFree(pAddrTable);
+ }
+ else /* Win 95 */
+ {
+ SOCKET s;
+ HOSTENT *pHost;
+ SOCKADDR_IN theHost;
+
+ s = SOCKET(PF_INET, SOCK_STREAM, 0);
+ pHost = GETHOSTBYNAME("www.example.com");
+ if (! pHost) {
+ GE_LOG(ectx, GE_ERROR | GE_BULK | GE_USER,
+ _("Could not resolve `%s' to "
+ "determine our IP address: %s\n"),
+ "www.example.com",
+ STRERROR(errno));
+ return SYSERR;
+ }
+
+ theHost.sin_family = AF_INET;
+ theHost.sin_port = htons(80);
+ theHost.sin_addr.S_un.S_addr
+ = *((unsigned long *) pHost->h_addr_list[0]);
+ if (CONNECT(s,
+ (SOCKADDR *) &theHost,
+ sizeof(theHost)) == SOCKET_ERROR) {
+ GE_LOG_STRERROR(ectx, GE_ERROR | GE_BULK | GE_USER,
+ "connect");
+ return SYSERR;
+ }
+
+ i = sizeof(theHost);
+ if (GETSOCKNAME(s,
+ (SOCKADDR *) &theHost,
+ &i) == SOCKET_ERROR) {
+ GE_LOG_STRERROR(ectx, GE_ERROR | GE_BULK | GE_USER,
+ "getsockname");
+ return SYSERR;
+ }
+ closesocket(s);
+ identity->addr = theHost.sin_addr.S_un.S_addr;
+ }
+
+ GE_LOG(ectx, GE_DEBUG | GE_REQUEST | GE_USER,
+ _("GNUnet now uses the IP address %u.%u.%u.%u.\n"),
+ PRIP(ntohl(identity->addr)));
+
+ return OK;
+#endif
+}
+
+#endif
+
+/**
+ * Get the IP address for the local machine.
+ * @return NULL on error, IP as string otherwise
+ */
+char * network_get_local_ip(struct GC_Configuration * cfg,
+ struct GE_Context * ectx,
+ IPaddr * addr) {
+ IPaddr address;
+ char * ipString;
+ int retval;
+ char buf[65];
+
+ retval = SYSERR;
+ if (GC_have_configuration_value(cfg,
+ "NETWORK",
+ "IP-LOCAL")) {
+ ipString = NULL;
+ GC_get_configuration_value_string(cfg,
+ "NETWORK",
+ "IP-LOCAL",
+ "",
+ &ipString);
+ if (strlen(ipString) > 0) {
+ retval = get_host_by_name(ectx,
+ ipString,
+ &address);
+ }
+ FREE(ipString);
+ }
+#if LINUX || SOMEBSD || MINGW
+ if (retval == SYSERR)
+ if (OK == getAddressFromIOCTL(cfg,
+ ectx,
+ &address))
+ retval = OK;
+#endif
+#if HAVE_GETIFADDRS && HAVE_FREEIFADDRS
+ if (retval == SYSERR)
+ if (OK == getAddressFromGetIfAddrs(cfg,
+ ectx,
+ &address))
+ retval = OK;
+#endif
+ if (retval == SYSERR)
+ retval = getAddressFromHostname(ectx,
+ &address);
+ if (retval == SYSERR)
+ return NULL;
+ SNPRINTF(buf,
+ 64,
+ "%u.%u.%u.%u",
+ PRIP(ntohl(*(int*)&address)));
+ if (addr != NULL)
+ *addr = address;
+ return STRDUP(buf);
+}
+
+
+/* end of ip.c */
Property changes on: GNUnet/src/util/network/ip.c
___________________________________________________________________
Name: svn:eol-style
+ native
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r4268 - GNUnet/src/util/network,
grothoff <=