[haiku-commits] r37600 - in haiku/trunk/src/bin/network: . ifconfig ping6 route tcpdump

  • From: axeld@xxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Mon, 19 Jul 2010 17:24:36 +0200 (CEST)

Author: axeld
Date: 2010-07-19 17:24:36 +0200 (Mon, 19 Jul 2010)
New Revision: 37600
Changeset: http://dev.haiku-os.org/changeset/37600

Added:
   haiku/trunk/src/bin/network/ping6/
   haiku/trunk/src/bin/network/ping6/Jamfile
   haiku/trunk/src/bin/network/ping6/ping6.c
Modified:
   haiku/trunk/src/bin/network/Jamfile
   haiku/trunk/src/bin/network/ifconfig/ifconfig.cpp
   haiku/trunk/src/bin/network/route/route.cpp
   haiku/trunk/src/bin/network/tcpdump/Jamfile
Log:
Another patch by Atis Elsts:
* Added ping6 command from FreeBSD.
* tcpdump is now built with IPv6 supprt.
* added IPv6 support to route, and ifconfig (the family stuff should eventually
  be factored out).


Modified: haiku/trunk/src/bin/network/Jamfile
===================================================================
--- haiku/trunk/src/bin/network/Jamfile 2010-07-19 15:03:37 UTC (rev 37599)
+++ haiku/trunk/src/bin/network/Jamfile 2010-07-19 15:24:36 UTC (rev 37600)
@@ -15,6 +15,7 @@
 #SubInclude HAIKU_TOP src bin network pppconfig ;
 #SubInclude HAIKU_TOP src bin network ppp_up ;
 SubInclude HAIKU_TOP src bin network ping ;
+SubInclude HAIKU_TOP src bin network ping6 ;
 SubInclude HAIKU_TOP src bin network route ;
 SubInclude HAIKU_TOP src bin network setwep ;
 SubInclude HAIKU_TOP src bin network tcpdump ;

Modified: haiku/trunk/src/bin/network/ifconfig/ifconfig.cpp
===================================================================
--- haiku/trunk/src/bin/network/ifconfig/ifconfig.cpp   2010-07-19 15:03:37 UTC 
(rev 37599)
+++ haiku/trunk/src/bin/network/ifconfig/ifconfig.cpp   2010-07-19 15:24:36 UTC 
(rev 37600)
@@ -1,10 +1,11 @@
 /*
- * Copyright 2006-2008, Haiku, Inc. All Rights Reserved.
+ * Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
  * Distributed under the terms of the MIT License.
  *
  * Authors:
  *             Axel Dörfler, axeld@xxxxxxxxxxxxxxxx
  *             Oliver Tappe, zooey@xxxxxxxxxxxxxxx
+ *             Atis Elsts, the.kfx@xxxxxxxxx
  */
 
 
@@ -33,30 +34,82 @@
 const char* kProgramName = __progname;
 
 
+enum preferred_output_format {
+       PREFER_OUTPUT_MASK,
+       PREFER_OUTPUT_PREFIX_LENGTH,
+};
+
+
 struct address_family {
        int                     family;
        const char*     name;
        const char*     identifiers[4];
+       preferred_output_format preferred_format;
        bool            (*parse_address)(const char* string, sockaddr* 
_address);
+       bool            (*prefix_length_to_mask)(uint8 prefixLength, sockaddr* 
mask);
+       uint8           (*mask_to_prefix_length)(sockaddr* mask);
        void            (*print_address)(sockaddr* address);
 };
 
+
+bool initialize_address_families();
+
 // AF_INET family
 static bool inet_parse_address(const char* string, sockaddr* address);
+static bool inet_prefix_length_to_mask(uint8 prefixLength, sockaddr* mask);
+static uint8 inet_mask_to_prefix_length(sockaddr* mask);
 static void inet_print_address(sockaddr* address);
 
+// AF_INET6 family
+static bool inet6_parse_address(const char* string, sockaddr* address);
+static bool inet6_prefix_length_to_mask(uint8 prefixLength, sockaddr* mask);
+static uint8 inet6_mask_to_prefix_length(sockaddr* mask);
+static void inet6_print_address(sockaddr* address);
+
 static const address_family kFamilies[] = {
        {
                AF_INET,
                "inet",
                {"AF_INET", "inet", "ipv4", NULL},
+               PREFER_OUTPUT_MASK,
                inet_parse_address,
+               inet_prefix_length_to_mask,
+               inet_mask_to_prefix_length,
                inet_print_address
        },
-       { -1, NULL, {NULL}, NULL, NULL }
+       {
+               AF_INET6,
+               "inet6",
+               {"AF_INET6", "inet6", "ipv6", NULL},
+               PREFER_OUTPUT_PREFIX_LENGTH,
+               inet6_parse_address,
+               inet6_prefix_length_to_mask,
+               inet6_mask_to_prefix_length,
+               inet6_print_address
+       },
+       { -1, NULL, {NULL}, PREFER_OUTPUT_MASK, NULL, NULL, NULL, NULL }
 };
 
 
+static int sAddressFamilySockets[sizeof(kFamilies) / sizeof(kFamilies[0])];
+
+
+bool
+initialize_address_families()
+{
+       bool ok = false;
+       for (int32 i = 0; kFamilies[i].family >= 0; i++) {
+               int fd = socket(kFamilies[i].family, SOCK_DGRAM, 0);
+               if (fd != -1) {
+                       sAddressFamilySockets[i] = fd;
+                       ok = true;
+               }
+       }
+       return ok;
+}
+
+
+
 static bool
 inet_parse_address(const char* string, sockaddr* _address)
 {
@@ -65,9 +118,9 @@
        if (inet_aton(string, &inetAddress) != 1)
                return false;
 
-       sockaddr_in& address = *(sockaddr_in *)_address;
+       sockaddr_in& address = *(sockaddr_in*)_address;
        address.sin_family = AF_INET;
-       address.sin_len = sizeof(struct sockaddr_in);
+       address.sin_len = sizeof(sockaddr_in);
        address.sin_port = 0;
        address.sin_addr = inetAddress;
        memset(&address.sin_zero[0], 0, sizeof(address.sin_zero));
@@ -76,10 +129,50 @@
 }
 
 
+static bool
+inet_prefix_length_to_mask(uint8 prefixLength, sockaddr* _mask)
+{
+       if (prefixLength > 32)
+               return false;
+
+       sockaddr_in& mask = *(sockaddr_in*)_mask;
+       mask.sin_family = AF_INET;
+       mask.sin_len = sizeof(sockaddr_in);
+       mask.sin_port = 0;
+       memset(&mask.sin_zero[0], 0, sizeof(mask.sin_zero));
+
+       uint32 hostMask = 0;
+       for (uint8 i = 32; i > 32 - prefixLength; i--)
+               hostMask |= 1 << (i - 1);
+       mask.sin_addr.s_addr = htonl(hostMask);
+
+       return true;
+}
+
+
+static uint8
+inet_mask_to_prefix_length(sockaddr* _mask)
+{
+       sockaddr_in& mask = *(sockaddr_in*)_mask;
+       if (mask.sin_family != AF_INET)
+               return (uint8)-1;
+
+       uint8 result = 0;
+       uint32 hostMask = ntohl(mask.sin_addr.s_addr);
+       for (uint8 i = 32; i > 0; i--) {
+               if (hostMask & (1 << (i - 1)) == 0)
+                       break;
+               result++;
+       }
+
+       return result;
+}
+
+
 static void
 inet_print_address(sockaddr* _address)
 {
-       sockaddr_in& address = *(sockaddr_in *)_address;
+       sockaddr_in& address = *(sockaddr_in*)_address;
 
        if (address.sin_family != AF_INET)
                return;
@@ -88,6 +181,90 @@
 }
 
 
+static bool
+inet6_parse_address(const char* string, sockaddr* _address)
+{
+       sockaddr_in6& address = *(sockaddr_in6*)_address;
+
+       if (inet_pton(AF_INET6, string, &address.sin6_addr) != 1)
+               return false;
+
+       address.sin6_family = AF_INET6;
+       address.sin6_len = sizeof(sockaddr_in6);
+       address.sin6_port = 0;
+       address.sin6_flowinfo = 0;
+       address.sin6_scope_id = 0;
+
+       return true;
+}
+
+
+static bool
+inet6_prefix_length_to_mask(uint8 prefixLength, sockaddr* _mask)
+{
+       if (prefixLength > 128)
+               return false;
+
+       sockaddr_in6& mask = *(sockaddr_in6*)_mask;
+       mask.sin6_family = AF_INET6;
+       mask.sin6_len = sizeof(sockaddr_in6);
+       mask.sin6_port = 0;
+       mask.sin6_flowinfo = 0;
+       mask.sin6_scope_id = 0;
+       memset(mask.sin6_addr.s6_addr, 0, sizeof(in6_addr));
+
+       for (uint8 i = 0; i < sizeof(in6_addr); i++, prefixLength -= 8) {
+               if (prefixLength < 8) {
+                       const uint8 masks[] = {
+                               0x00, 0x80, 0xc0, 0xe0,
+                               0xf0, 0xf8, 0xfc, 0xfe
+                       };
+                       mask.sin6_addr.s6_addr[i] = masks[prefixLength];
+                       break;
+               }
+
+               mask.sin6_addr.s6_addr[i] = 0xff;
+       }
+
+       return true;
+}
+
+
+static uint8
+inet6_mask_to_prefix_length(sockaddr* _mask)
+{
+       sockaddr_in6& mask = *(sockaddr_in6*)_mask;
+       if (mask.sin6_family != AF_INET6)
+               return (uint8)~0;
+
+       uint8 result = 0;
+       for (uint8 i = 0; i < sizeof(in6_addr); i++) {
+               for (uint8 j = 0; j < 8; j++) {
+                       if (!(mask.sin6_addr.s6_addr[i] & (1 << j)))
+                               return result;
+                       result++;
+               }
+       }
+
+       return 128;
+}
+
+
+static void
+inet6_print_address(sockaddr* _address)
+{
+       sockaddr_in6& address = *(sockaddr_in6*)_address;
+
+       if (address.sin6_family != AF_INET6)
+               return;
+
+       char buffer[INET6_ADDRSTRLEN];
+
+       printf("%s",
+               inet_ntop(AF_INET6, &address.sin6_addr, buffer, 
sizeof(buffer)));
+}
+
+
 //     #pragma mark -
 
 
@@ -181,12 +358,13 @@
                        "auto-config] [<option/flags>...]]\n"
                "\t%s --delete interface [...]\n\n"
                "Where <option> can be the following:\n"
-               "  netmask <addr>   - networking subnet mask\n"
-               "  broadcast <addr> - set broadcast address\n"
-               "  peer <addr>      - ppp-peer address\n"
-               "  mtu <bytes>      - maximal transfer unit\n"
-               "  metric <number>  - metric number to use (defaults to 0)\n"
-               "  media <media>    - media type to use (defaults to auto)\n",
+               "  netmask <addr>     - networking subnet mask\n"
+               "  prefixlen <number> - subnet mask length in bits\n"
+               "  broadcast <addr>   - set broadcast address\n"
+               "  peer <addr>        - ppp-peer address\n"
+               "  mtu <bytes>        - maximal transfer unit\n"
+               "  metric <number>    - metric number to use (defaults to 0)\n"
+               "  media <media>      - media type to use (defaults to auto)\n",
                kProgramName, kProgramName);
        for (int32 i = 0; kMediaTypes[i].type >= 0; i++) {
                printf("For %s <media> can be one of: ", kMediaTypes[i].pretty);
@@ -210,8 +388,8 @@
 prepare_request(struct ifreq& request, const char* name)
 {
        if (strlen(name) > IF_NAMESIZE) {
-               fprintf(stderr, "%s: interface name \"%s\" is too long.\n", 
kProgramName,
-                       name);
+               fprintf(stderr, "%s: interface name \"%s\" is too long.\n",
+                       kProgramName, name);
                return false;
        }
 
@@ -249,22 +427,103 @@
 }
 
 
+bool
+prefix_length_to_mask(int32 familyIndex, const char* argument,
+       struct sockaddr& mask)
+{
+       if (argument == NULL)
+               return false;
+
+       char *end;
+       uint32 prefixLength = strtoul(argument, &end, 10);
+       if (end == argument)
+               return false;
+
+       return kFamilies[familyIndex].prefix_length_to_mask(
+               (uint8)prefixLength, &mask);
+}
+
+
 //     #pragma mark -
 
 
+int
+find_socket(struct ifreq& request, int addressFamily)
+{
+       int socket = -1;
+       bool socketExists = false;
+       bool ok = false;
+
+       for (int32 i = 0; kFamilies[i].family >= 0; i++) {
+               if (addressFamily != -1 && addressFamily != kFamilies[i].family)
+                       continue;
+
+               socket = sAddressFamilySockets[i];
+               if (socket == -1)
+                       continue;
+
+               socketExists = true;
+
+               if (ioctl(socket, SIOCGIFINDEX, &request, sizeof(request)) >= 
0) {
+                       ok = true;
+                       break;
+               }
+       }
+
+       if (socketExists && !ok) {
+               fprintf(stderr, "%s: Interface \"%s\" does not exist.\n",
+                       kProgramName, request.ifr_name);
+               return -1;
+       }
+
+       return socket;
+}
+
+
 void
-list_interface(int socket, const char* name)
+list_interface_address(int socket, const address_family* family,
+       uint32 flags, ifreq* request)
 {
-       ifreq request;
-       if (!prepare_request(request, name))
+       if (ioctl(socket, SIOCGIFADDR, request, sizeof(struct ifreq)) < 0)
                return;
 
-       if (ioctl(socket, SIOCGIFINDEX, &request, sizeof(request)) < 0) {
-               fprintf(stderr, "%s: Interface \"%s\" does not exist.\n", 
kProgramName,
-                       name);
-               return;
+       printf("\t%s addr: ", family->name);
+       family->print_address(&request->ifr_addr);
+
+       if ((flags & IFF_BROADCAST) != 0
+               && ioctl(socket, SIOCGIFBRDADDR, request, sizeof(struct ifreq)) 
== 0
+               && request->ifr_broadaddr.sa_family == family->family) {
+               printf(", Bcast: ");
+               family->print_address(&request->ifr_broadaddr);
        }
+       if (ioctl(socket, SIOCGIFNETMASK, request, sizeof(struct ifreq)) == 0
+               && request->ifr_mask.sa_family == family->family) {
+               switch (family->preferred_format) {
+                       case PREFER_OUTPUT_MASK:
+                               printf(", Mask: ");
+                               family->print_address(&request->ifr_mask);
+                               break;
+                       case PREFER_OUTPUT_PREFIX_LENGTH:
+                               printf(", Prefix Length: %u",
+                                       
family->mask_to_prefix_length(&request->ifr_mask));
+                               break;
+               }
+       }
+       putchar('\n');
+}
 
+
+bool
+list_interface(const char* name, int addressFamily)
+{
+       ifreq request;
+       if (!prepare_request(request, name))
+               return true;
+
+       int socket = find_socket(request, addressFamily);
+       if (socket == -1)
+               return false;
+
        printf("%s", name);
        size_t length = strlen(name);
        if (length < 8)
@@ -286,7 +545,7 @@
                        prepare_request(request, request.ifr_parameter.device);
                        if (ioctl(linkSocket, SIOCGIFADDR, &request, 
sizeof(struct ifreq))
                                        == 0) {
-                               sockaddr_dl &link = *(sockaddr_dl 
*)&request.ifr_addr;
+                               sockaddr_dl &link = 
*(sockaddr_dl*)&request.ifr_addr;
 
                                switch (link.sdl_type) {
                                        case IFT_ETHER:
@@ -294,7 +553,7 @@
                                                type = "Ethernet";
 
                                                if (link.sdl_alen > 0) {
-                                                       uint8 *mac = (uint8 
*)LLADDR(&link);
+                                                       uint8 *mac = 
(uint8*)LLADDR(&link);
                                                        sprintf(address, 
"%02x:%02x:%02x:%02x:%02x:%02x",
                                                                mac[0], mac[1], 
mac[2], mac[3], mac[4], mac[5]);
                                                } else
@@ -348,29 +607,11 @@
                flags = request.ifr_flags;
 
        for (int32 i = 0; kFamilies[i].family >= 0; i++) {
-               int familySocket = ::socket(kFamilies[i].family, SOCK_DGRAM, 0);
-               if (familySocket < 0)
-                       continue;
-
-               if (ioctl(familySocket, SIOCGIFADDR, &request, sizeof(struct 
ifreq)) == 0) {
-                       printf("\t%s addr: ", kFamilies[i].name);
-                       kFamilies[i].print_address(&request.ifr_addr);
-
-                       if ((flags & IFF_BROADCAST) != 0
-                               && ioctl(familySocket, SIOCGIFBRDADDR, 
&request, sizeof(struct ifreq)) == 0
-                               && request.ifr_broadaddr.sa_family == 
kFamilies[i].family) {
-                               printf(", Bcast: ");
-                               
kFamilies[i].print_address(&request.ifr_broadaddr);
-                       }
-                       if (ioctl(familySocket, SIOCGIFNETMASK, &request, 
sizeof(struct ifreq)) == 0
-                               && request.ifr_mask.sa_family == 
kFamilies[i].family) {
-                               printf(", Mask: ");
-                               kFamilies[i].print_address(&request.ifr_mask);
-                       }
-                       putchar('\n');
+               int familySocket = sAddressFamilySockets[i];
+               if (familySocket != -1) {
+                       list_interface_address(familySocket, &kFamilies[i],
+                               flags, &request);
                }
-
-               close(familySocket);
        }
 
        // Print MTU, metric, flags
@@ -434,19 +675,22 @@
        }
 
        putchar('\n');
+       return true;
 }
 
 
 void
-list_interfaces(int socket, const char* name)
+list_interfaces(const char* name)
 {
        if (name != NULL) {
-               list_interface(socket, name);
+               list_interface(name, -1);
                return;
        }
 
        // get a list of all interfaces
 
+       int socket = sAddressFamilySockets[0];
+
        ifconf config;
        config.ifc_len = sizeof(config.ifc_value);
        if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0)
@@ -469,12 +713,13 @@
        if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0)
                return;
 
-       ifreq *interface = (ifreq *)buffer;
+       ifreq* interface = (ifreq*)buffer;
 
        for (uint32 i = 0; i < count; i++) {
-               list_interface(socket, interface->ifr_name);
+               list_interface(interface->ifr_name, 
interface->ifr_addr.sa_family);
 
-               interface = (ifreq *)((addr_t)interface + IF_NAMESIZE + 
interface->ifr_addr.sa_len);
+               interface = (ifreq*)((addr_t)interface + IF_NAMESIZE
+                       + interface->ifr_addr.sa_len);
        }
 
        free(buffer);
@@ -482,12 +727,16 @@
 
 
 void
-delete_interface(int socket, const char* name)
+delete_interface(const char* name)
 {
        ifreq request;
        if (!prepare_request(request, name))
                return;
 
+       int socket = find_socket(request, -1);
+       if (socket == -1)
+               return;
+
        if (ioctl(socket, SIOCDIFADDR, &request, sizeof(request)) < 0) {
                fprintf(stderr, "%s: Could not delete interface %s: %s\n",
                        kProgramName, name, strerror(errno));
@@ -496,13 +745,27 @@
 
 
 void
-configure_interface(int socket, const char* name, char* const* args,
+configure_interface(const char* name, char* const* args,
        int32 argCount)
 {
        ifreq request;
        if (!prepare_request(request, name))
                return;
 
+       // try to parse address family
+
+       int32 familyIndex;
+       int32 i = 0;
+       if (get_address_family(args[i], familyIndex))
+               i++;
+
+       int socket = sAddressFamilySockets[familyIndex];
+       if (socket < 0) {
+               fprintf(stderr, "%s: Address family \"%s\" is not available.\n",
+                       kProgramName, kFamilies[familyIndex].name);
+               exit(1);
+       }
+
        uint32 index = 0;
        if (ioctl(socket, SIOCGIFINDEX, &request, sizeof(request)) >= 0)
                index = request.ifr_index;
@@ -513,25 +776,6 @@
        int mtu = -1, metric = -1, media = -1;
        int addFlags = 0, currentFlags = 0, removeFlags = 0;
 
-       // try to parse address family
-
-       int32 familyIndex;
-       int32 i = 0;
-       if (get_address_family(args[i], familyIndex))
-               i++;
-
-       if (kFamilies[familyIndex].family != AF_INET) {
-               close(socket);
-
-               // replace socket with one of the correct address family
-               socket = ::socket(kFamilies[familyIndex].family, SOCK_DGRAM, 0);
-               if (socket < 0) {
-                       fprintf(stderr, "%s: Address family \"%s\" is not 
available.\n",
-                               kProgramName, kFamilies[familyIndex].name);
-                       exit(1);
-               }
-       }
-
        if (index == 0) {
                // the interface does not exist yet, we have to add it first
                request.ifr_parameter.base_name[0] = '\0';
@@ -571,8 +815,8 @@
                        i++;
                } else if (!strcmp(args[i], "nm") || !strcmp(args[i], 
"netmask")) {
                        if (hasMask) {
-                               fprintf(stderr, "%s: Netmask is specified 
twice\n",
-                                       kProgramName);
+                               fprintf(stderr, "%s: Netmask or prefix length 
is specified "
+                                       "twice\n", kProgramName);
                                exit(1);
                        }
                        if (!parse_address(familyIndex, args[i + 1], mask)) {
@@ -582,6 +826,20 @@
                        }
                        hasMask = true;
                        i++;
+               } else if (!strcmp(args[i], "prefixlen") 
+                               || !strcmp(args[i], "plen")) {
+                       if (hasMask) {
+                               fprintf(stderr, "%s: Netmask or prefix length 
is specified "
+                                       "twice\n", kProgramName);
+                               exit(1);
+                       }
+                       if (!prefix_length_to_mask(familyIndex, args[i + 1], 
mask)) {
+                               fprintf(stderr, "%s: Option 'prefixlen' is 
invalid for this "
+                                       "address family\n", kProgramName);
+                               exit(1);
+                       }
+                       hasMask = true;
+                       i++;
                } else if (!strcmp(args[i], "bc") || !strcmp(args[i], 
"broadcast")) {
                        if (hasBroadcast) {
                                fprintf(stderr, "%s: broadcast address is 
specified twice\n",
@@ -761,6 +1019,7 @@
                BMessage message(kMsgConfigureInterface);
                message.AddString("device", name);
                BMessage address;
+               // TODO: this is not working for ipv6 yet
                address.AddString("family", "inet");
                address.AddBool("auto_config", true);
                message.AddMessage("address", &address);
@@ -807,9 +1066,7 @@
                deleteInterfaces = true;
        }
 
-       // we need a socket to talk to the networking stack
-       int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
-       if (socket < 0) {
+       if (initialize_address_families() == false) {
                fprintf(stderr, "%s: The networking stack doesn't seem to be "
                        "available.\n", kProgramName);
                return 1;
@@ -817,7 +1074,7 @@
 
        if (deleteInterfaces) {
                for (int i = 2; i < argc; i++) {
-                       delete_interface(socket, argv[i]);
+                       delete_interface(argv[i]);
                }
                return 0;
        } else if (argc > 1 && !strcmp(argv[1], "-a")) {
@@ -825,7 +1082,7 @@
                if (argc > 2)
                        usage(1);
 
-               list_interfaces(socket, NULL);
+               list_interfaces(NULL);
                return 0;
        }
 
@@ -833,13 +1090,13 @@
        if (argc > 2) {
                // add or configure an interface
 
-               configure_interface(socket, name, argv + 2, argc - 2);
+               configure_interface(name, argv + 2, argc - 2);
                return 0;
        }
 
        // list interfaces
 
-       list_interfaces(socket, name);
+       list_interfaces(name);
        return 0;
 }
 

Added: haiku/trunk/src/bin/network/ping6/Jamfile
===================================================================
--- haiku/trunk/src/bin/network/ping6/Jamfile                           (rev 0)
+++ haiku/trunk/src/bin/network/ping6/Jamfile   2010-07-19 15:24:36 UTC (rev 
37600)
@@ -0,0 +1,29 @@
+SubDir HAIKU_TOP src bin network ping6 ;
+
+SetSubDirSupportedPlatforms $(HAIKU_BONE_COMPATIBLE_PLATFORMS) ;
+
+if ! $(TARGET_PLATFORM_HAIKU_COMPATIBLE) {
+       UseHeaders [ FDirName $(HAIKU_TOP) headers posix ] : true ;
+               # We need the public network headers also when not compiling 
for Haiku.
+               # Unfortunately we get more than we want, namely all POSIX 
headers.
+}
+
+BinCommand ping6 :
+       ping6.c
+       : $(TARGET_NETWORK_LIBS) $(TARGET_SELECT_UNAME_ETC_LIB) ;
+
+# Installation -- in the test directory for the time being
+HaikuInstall install-networking
+       : [ FDirName $(HAIKU_TEST_DIR) kits net ]
+       : ping6 ;
+
+HaikuInstall install-userland-networking 
+       : [ FDirName $(HAIKU_TEST_DIR) kits net userland ]
+       : ping6
+       : installed-userland-networking
+;
+
+Package haiku-networkingkit-cvs :
+       ping6 :
+       boot home Desktop haiku-networkingkit ;
+

Added: haiku/trunk/src/bin/network/ping6/ping6.c
===================================================================
--- haiku/trunk/src/bin/network/ping6/ping6.c                           (rev 0)
+++ haiku/trunk/src/bin/network/ping6/ping6.c   2010-07-19 15:24:36 UTC (rev 
37600)
@@ -0,0 +1,2712 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Muuss.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Using the InterNet Control Message Protocol (ICMP) "ECHO" facility,
+ * measure round-trip-delays and packet loss across network paths.
+ *
+ * Author -
+ *     Mike Muuss
+ *     U. S. Army Ballistic Research Laboratory
+ *     December, 1983
+ *
+ * Status -
+ *     Public Domain.  Distribution Unlimited.
+ * Bugs -
+ *     More statistics could always be gathered.
+ *     This program has to run SUID to ROOT to access the ICMP socket.
+ */
+
+/*
+ * NOTE:
+ * USE_SIN6_SCOPE_ID assumes that sin6_scope_id has the same semantics
+ * as IPV6_PKTINFO.  Some people object it (sin6_scope_id specifies *link*
+ * while IPV6_PKTINFO specifies *interface*.  Link is defined as collection of
+ * network attached to 1 or more interfaces)
+ */
+#define USE_SIN6_SCOPE_ID 1
+
+#define USE_RFC2292BIS 1
+#define HAVE_POLL_H 1
+#define CMSG_SENDING_UNSUPPORTED 1
+#undef IPSEC
+#undef IPV6_OPTIONS
+
+#include <sys/param.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <net/if.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <math.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
+
+#ifdef IPSEC
+#include <netipsec/ah.h>
+#include <netipsec/ipsec.h>
+#endif
+
+struct tv32 {
+       u_int32_t tv32_sec;
+       u_int32_t tv32_usec;
+};
+
+#define        IP6LEN                  40
+#define MAXPACKETLEN   (IPV6_MAXPACKET - IP6LEN) 
+#define ICMP6ECHOLEN   8       /* icmp echo header len excluding time */
+#define ICMP6ECHOTMLEN sizeof(struct tv32)
+#define ICMP6_NIQLEN   (ICMP6ECHOLEN + 8)
+# define CONTROLLEN            10240   /* ancillary data buffer size RFC3542 
20.1 */
+/* FQDN case, 64 bits of nonce + 32 bits ttl */
+#define ICMP6_NIRLEN   (ICMP6ECHOLEN + 12)
+#define        EXTRA           256     /* for AH and various other headers. 
weird. */
+#define        DEFDATALEN      ICMP6ECHOTMLEN
+#define MAXDATALEN     MAXPACKETLEN - IP6LEN - ICMP6ECHOLEN
+#define        NROUTES         9               /* number of record route slots 
*/
+
+#define        A(bit)          rcvd_tbl[(bit)>>3]      /* identify byte in 
array */
+#define        B(bit)          (1 << ((bit) & 0x07))   /* identify bit in byte 
*/
+#define        SET(bit)        (A(bit) |= B(bit))
+#define        CLR(bit)        (A(bit) &= (~B(bit)))
+#define        TST(bit)        (A(bit) & B(bit))
+
+#define        F_FLOOD         0x0001
+#define        F_INTERVAL      0x0002
+#define        F_PINGFILLED    0x0008
+#define        F_QUIET         0x0010
+#define        F_RROUTE        0x0020
+#define        F_SO_DEBUG      0x0040
+#define        F_VERBOSE       0x0100
+#ifdef IPSEC
+#ifdef IPSEC_POLICY_IPSEC
+#define        F_POLICY        0x0400
+#else
+#define F_AUTHHDR      0x0200
+#define F_ENCRYPT      0x0400
+#endif /*IPSEC_POLICY_IPSEC*/
+#endif /*IPSEC*/
+#define F_NODEADDR     0x0800
+#define F_FQDN         0x1000
+#define F_INTERFACE    0x2000
+#define F_SRCADDR      0x4000
+#define F_HOSTNAME     0x10000
+#define F_FQDNOLD      0x20000
+#define F_NIGROUP      0x40000
+#define F_SUPTYPES     0x80000
+#define F_NOMINMTU     0x100000
+#define F_ONCE         0x200000
+#define F_AUDIBLE      0x400000
+#define F_MISSED       0x800000
+#define F_NOUSERDATA   (F_NODEADDR | F_FQDN | F_FQDNOLD | F_SUPTYPES)
+u_int options;
+
+#define IN6LEN         sizeof(struct in6_addr)
+#define SA6LEN         sizeof(struct sockaddr_in6)
+#define DUMMY_PORT     10101
+
+#define SIN6(s)        ((struct sockaddr_in6 *)(s))
+
+/*
+ * MAX_DUP_CHK is the number of bits in received table, i.e. the maximum
+ * number of received sequence numbers we can keep track of.  Change 128
+ * to 8192 for complete accuracy...
+ */
+#define        MAX_DUP_CHK     (8 * 8192)
+int mx_dup_ck = MAX_DUP_CHK;
+char rcvd_tbl[MAX_DUP_CHK / 8];
+
+struct addrinfo *res;
+struct sockaddr_in6 dst;       /* who to ping6 */
+struct sockaddr_in6 src;       /* src addr of this packet */
+socklen_t srclen;
+int datalen = DEFDATALEN;
+int s;                         /* socket file descriptor */
+u_char outpack[MAXPACKETLEN];
+char BSPACE = '\b';            /* characters written for flood */
+char BBELL = '\a';             /* characters written for AUDIBLE */
+char DOT = '.';
+char *hostname;
+int ident;                     /* process id to identify our packets */
+u_int8_t nonce[8];             /* nonce field for node information */
+int hoplimit = -1;             /* hoplimit */
+int pathmtu = 0;               /* path MTU for the destination.  0 = unspec. */
+
+/* counters */
+long nmissedmax;               /* max value of ntransmitted - nreceived - 1 */
+long npackets;                 /* max packets to transmit */
+long nreceived;                        /* # of packets we got back */
+long nrepeats;                 /* number of duplicates */
+long ntransmitted;             /* sequence # for outbound packets = #sent */
+struct timeval interval = {1, 0}; /* interval between packets */
+
+/* timing */
+int timing;                    /* flag to do timing */
+double tmin = 999999999.0;     /* minimum round trip time */
+double tmax = 0.0;             /* maximum round trip time */
+double tsum = 0.0;             /* sum of all times, for doing average */
+double tsumsq = 0.0;           /* sum of all times squared, for std. dev. */
+
+/* for node addresses */
+u_short naflags;
+
+/* for ancillary data(advanced API) */
+struct msghdr smsghdr;
+struct iovec smsgiov;
+char *scmsg = 0;
+
+volatile sig_atomic_t seenalrm;
+volatile sig_atomic_t seenint;
+#ifdef SIGINFO
+volatile sig_atomic_t seeninfo;
+#endif
+
+int     main(int, char *[]);
+void    fill(char *, char *);
+int     get_hoplim(struct msghdr *);
+int     get_pathmtu(struct msghdr *);
+struct in6_pktinfo *get_rcvpktinfo(struct msghdr *);
+void    onsignal(int);
+void    retransmit(void);
+void    onint(int);
+size_t  pingerlen(void);
+int     pinger(void);
+const char *pr_addr(struct sockaddr *, int);
+void    pr_icmph(struct icmp6_hdr *, u_char *);
+void    pr_iph(struct ip6_hdr *);
+void    pr_suptypes(struct icmp6_nodeinfo *, size_t);
+void    pr_nodeaddr(struct icmp6_nodeinfo *, int);
+int     myechoreply(const struct icmp6_hdr *);
+int     mynireply(const struct icmp6_nodeinfo *);
+char *dnsdecode(const u_char **, const u_char *, const u_char *,
+       char *, size_t);
+void    pr_pack(u_char *, int, struct msghdr *);
+void    pr_exthdrs(struct msghdr *);
+void    pr_ip6opt(void *, size_t);
+void    pr_rthdr(void *, size_t);
+int     pr_bitrange(u_int32_t, int, int);
+void    pr_retip(struct ip6_hdr *, u_char *);
+void    summary(void);
+void    tvsub(struct timeval *, struct timeval *);
+int     setpolicy(int, char *);
+char   *nigroup(char *);
+void    usage(void);
+
+
+static void err(int exitval, char *where)
+{
+       printf("error: %s: error %d [%s]\n", where, errno, strerror(errno));
+       exit(exitval);
+}
+
+static void errx(int exitval, char *fmt_string, ...)
+{
+       va_list list;
+       va_start(list, fmt_string);
+       printf("error: ");
+       vprintf(fmt_string, list);
+       printf("\n");
+       va_end(list);
+       exit(exitval);
+}
+
+static void warn(char *where)
+{
+       printf("warning: %s: error %d [%s]\n", where, errno, strerror(errno));
+}

[... truncated: 2928 lines follow ...]

Other related posts:

  • » [haiku-commits] r37600 - in haiku/trunk/src/bin/network: . ifconfig ping6 route tcpdump - axeld