* The "route" command now uses BNetworkAddress instead of its home brewn

solution, too.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38233 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2010-08-18 13:04:50 +00:00
parent c141a31f83
commit f072d0a87a
2 changed files with 55 additions and 260 deletions

View File

@ -1,30 +1,8 @@
SubDir HAIKU_TOP src bin network route ;
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.
}
UsePrivateHeaders net ;
BinCommand route :
route.cpp
: libnetwork.so
: be libnetwork.so libbnetapi.so
;
# Installation -- in the test directory for the time being
HaikuInstall install-networking
: [ FDirName $(HAIKU_TEST_DIR) kits net ]
: route ;
HaikuInstall install-userland-networking
: [ FDirName $(HAIKU_TEST_DIR) kits net userland ]
: route
: installed-userland-networking
;
Package haiku-networkingkit-cvs :
route :
# boot home config bin ;
boot home Desktop haiku-networkingkit ;

View File

@ -7,8 +7,6 @@
*/
#include <SupportDefs.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <net/if_dl.h>
@ -23,6 +21,8 @@
#include <string.h>
#include <unistd.h>
#include <NetworkAddress.h>
extern const char* __progname;
const char* kProgramName = __progname;
@ -55,17 +55,6 @@ struct address_family {
const char* (*address_to_string)(sockaddr* address);
};
// 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 const char* inet_address_to_string(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 const char* inet6_address_to_string(sockaddr* address);
static const address_family kFamilies[] = {
{
@ -73,187 +62,17 @@ static const address_family kFamilies[] = {
"inet",
{"AF_INET", "inet", "ipv4", NULL},
PREFER_OUTPUT_MASK,
inet_parse_address,
inet_prefix_length_to_mask,
inet_mask_to_prefix_length,
inet_address_to_string,
},
{
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_address_to_string,
},
{ -1, NULL, {NULL}, PREFER_OUTPUT_MASK, NULL, NULL, NULL, NULL }
};
static bool
inet_parse_address(const char* string, sockaddr* _address)
{
in_addr inetAddress;
if (inet_aton(string, &inetAddress) != 1)
return false;
sockaddr_in& address = *(sockaddr_in*)_address;
address.sin_family = AF_INET;
address.sin_len = sizeof(struct sockaddr_in);
address.sin_port = 0;
address.sin_addr = inetAddress;
memset(&address.sin_zero[0], 0, sizeof(address.sin_zero));
return true;
}
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)
{
if (_mask == NULL)
return 32;
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 const char*
inet_address_to_string(sockaddr* address)
{
if (address == NULL || address->sa_family != AF_INET)
return "-";
return inet_ntoa(((sockaddr_in*)address)->sin_addr);
}
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)
{
if (_mask == NULL)
return 128;
sockaddr_in6& mask = *(sockaddr_in6*)_mask;
if (mask.sin6_family != AF_INET6)
return (uint8)-1;
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 const char*
inet6_address_to_string(sockaddr* address)
{
if (address == NULL || address->sa_family != AF_INET6)
return "-";
static char buffer[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &((sockaddr_in6*)address)->sin6_addr,
buffer, sizeof(buffer));
return buffer;
}
// #pragma mark -
void
usage(int status)
{
@ -311,30 +130,29 @@ get_address_family(const char* argument, int32& familyIndex)
bool
parse_address(int32 familyIndex, const char* argument,
struct sockaddr_storage& address)
parse_address(int32 familyIndex, const char* argument, BNetworkAddress& address)
{
if (argument == NULL)
return false;
return kFamilies[familyIndex].parse_address(argument, (sockaddr*)&address);
return address.SetTo(kFamilies[familyIndex].family, argument,
(uint16)0, B_NO_ADDRESS_RESOLUTION) == B_OK;
}
bool
prefix_length_to_mask(int32 familyIndex, const char* argument,
struct sockaddr_storage& mask)
BNetworkAddress& mask)
{
if (argument == NULL)
return false;
char *end;
char* end;
uint32 prefixLength = strtoul(argument, &end, 10);
if (end == argument)
return false;
return kFamilies[familyIndex].prefix_length_to_mask(
(uint8)prefixLength, (sockaddr*)&mask);
return mask.SetToMask(kFamilies[familyIndex].family, prefixLength) == B_OK;
}
@ -385,25 +203,29 @@ list_routes(int socket, const char *interfaceName, route_entry &route)
}
if (family != NULL) {
BNetworkAddress destination(*route.destination);
BNetworkAddress mask;
if (route.mask != NULL)
mask.SetTo(*route.mask);
// TODO: is the %15s format OK for IPv6?
printf("%15s", family->address_to_string(route.destination));
printf("%15s", destination.ToString().String());
switch (family->preferred_format) {
case PREFER_OUTPUT_MASK:
printf(" mask %-15s ",
family->address_to_string(route.mask));
printf(" mask %-15s ", mask.ToString().String());
break;
case PREFER_OUTPUT_PREFIX_LENGTH:
printf("/%u ",
family->mask_to_prefix_length(route.mask));
printf("/%zd ", mask.PrefixLength());
break;
}
if ((route.flags & RTF_GATEWAY) != 0) {
printf("gateway %-15s ",
family->address_to_string(route.gateway));
BNetworkAddress gateway;
if (route.gateway != NULL)
gateway.SetTo(*route.gateway);
printf("gateway %-15s ", gateway.ToString().String());
}
} else {
} else
printf("unknown family ");
}
printf("%s", interface->ifr_name);
@ -421,7 +243,8 @@ list_routes(int socket, const char *interfaceName, route_entry &route)
};
bool first = true;
for (uint32 i = 0; i < sizeof(kFlags) / sizeof(kFlags[0]); i++) {
for (uint32 i = 0; i < sizeof(kFlags) / sizeof(kFlags[0]);
i++) {
if ((route.flags & kFlags[i].value) != 0) {
if (first) {
printf(", ");
@ -444,8 +267,8 @@ list_routes(int socket, const char *interfaceName, route_entry &route)
if (route.gateway != NULL)
addressSize += route.gateway->sa_len;
interface = (ifreq*)((addr_t)interface + IF_NAMESIZE + sizeof(route_entry)
+ addressSize);
interface = (ifreq*)((addr_t)interface + IF_NAMESIZE
+ sizeof(route_entry) + addressSize);
}
free(buffer);
@ -574,10 +397,9 @@ main(int argc, char** argv)
bool familySpecified = false;
int32 familyIndex = 0;
const char *interface = NULL;
sockaddr_storage destination;
sockaddr_storage mask;
sockaddr_storage gateway;
bool hasDestination = false, hasGateway = false, hasMask = false;
BNetworkAddress destination;
BNetworkAddress mask;
BNetworkAddress gateway;
bool defaultRoute = false;
route_entry route;
@ -598,7 +420,6 @@ main(int argc, char** argv)
i++;
break;
} else if (parse_address(familyIndex, argv[i], destination)) {
hasDestination = true;
i++;
break;
}
@ -606,7 +427,7 @@ main(int argc, char** argv)
i++;
}
if (!defaultRoute && !hasDestination && mode != RTM_LIST)
if (!defaultRoute && destination.IsEmpty() && mode != RTM_LIST)
usage(1);
if (i == 3)
@ -614,39 +435,36 @@ main(int argc, char** argv)
if (interfaceIndex != -1 && interfaceIndex < argc)
interface = argv[interfaceIndex];
if (i < argc && parse_address(familyIndex, argv[i], mask)) {
hasMask = true;
if (i < argc && parse_address(familyIndex, argv[i], mask))
i++;
}
// parse options and flags
while (i < argc) {
if (!strcmp(argv[i], "gw") || !strcmp(argv[i], "gateway")) {
if (!parse_address(familyIndex, argv[i + 1], gateway)) {
fprintf(stderr, "%s: Option 'gw' needs valid address parameter\n",
kProgramName);
fprintf(stderr, "%s: Option 'gw' needs valid address "
"parameter\n", kProgramName);
exit(1);
}
hasGateway = true;
i++;
} else if (!strcmp(argv[i], "nm") || !strcmp(argv[i], "netmask")) {
if (hasMask) {
fprintf(stderr, "%s: Netmask or prefix length is specified twice\n",
kProgramName);
if (!mask.IsEmpty()) {
fprintf(stderr, "%s: Netmask or prefix length is specified "
"twice\n", kProgramName);
exit(1);
}
if (!parse_address(familyIndex, argv[i + 1], mask)) {
fprintf(stderr, "%s: Option 'netmask' needs valid address parameter\n",
kProgramName);
fprintf(stderr, "%s: Option 'netmask' needs valid address "
"parameter\n", kProgramName);
exit(1);
}
hasMask = true;
i++;
} else if (!strcmp(argv[i], "plen") || !strcmp(argv[i], "prefixlen")) {
if (hasMask) {
fprintf(stderr, "%s: Netmask or prefix length is specified twice\n",
kProgramName);
} else if (!strcmp(argv[i], "plen") || !strcmp(argv[i], "prefixlen")
|| !strcmp(argv[i], "prefix-length")) {
if (!mask.IsEmpty()) {
fprintf(stderr, "%s: Netmask or prefix length is specified "
"twice\n", kProgramName);
exit(1);
}
if (!prefix_length_to_mask(familyIndex, argv[i + 1], mask)) {
@ -654,13 +472,12 @@ main(int argc, char** argv)
"address family\n", kProgramName);
exit(1);
}
hasMask = true;
i++;
} else if (!strcmp(argv[i], "mtu")) {
route.mtu = argv[i + 1] ? strtol(argv[i + 1], NULL, 0) : 0;
if (route.mtu <= 500) {
fprintf(stderr, "%s: Option 'mtu' exptected valid max transfer unit size\n",
kProgramName);
fprintf(stderr, "%s: Option 'mtu' exptected valid max transfer "
"unit size\n", kProgramName);
exit(1);
}
i++;
@ -676,12 +493,12 @@ main(int argc, char** argv)
i++;
}
if (hasDestination)
route.destination = (sockaddr*)&destination;
if (hasMask)
route.mask = (sockaddr*)&mask;
if (hasGateway) {
route.gateway = (sockaddr*)&gateway;
if (!destination.IsEmpty())
route.destination = (sockaddr*)destination;
if (!mask.IsEmpty())
route.mask = (sockaddr*)mask;
if (!gateway.IsEmpty()) {
route.gateway = (sockaddr*)gateway;
route.flags |= RTF_GATEWAY;
}
@ -696,8 +513,8 @@ main(int argc, char** argv)
switch (mode) {
case RTM_ADD:
if (interface == NULL) {
fprintf(stderr, "%s: You need to specify an interface when adding a route.\n",
kProgramName);
fprintf(stderr, "%s: You need to specify an interface when "
"adding a route.\n", kProgramName);
usage(1);
}
@ -705,8 +522,8 @@ main(int argc, char** argv)
break;
case RTM_DELETE:
if (interface == NULL) {
fprintf(stderr, "%s: You need to specify an interface when removing a route.\n",
kProgramName);
fprintf(stderr, "%s: You need to specify an interface when "
"removing a route.\n", kProgramName);
usage(1);
}