* Reimplemented listing interfaces completely via the new C++ API. Only when

configuring or deleting interfaces, the ioctl()s are used directly for now;
  but this should be changed as well.
* Applied patch by Atis partially that fixes mask creation by prefix length,
  and changes a few other minor things.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38025 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2010-08-11 13:25:36 +00:00
parent 9de96be375
commit b2a400e53a
2 changed files with 93 additions and 154 deletions
+1 -23
View File
@@ -1,30 +1,8 @@
SubDir HAIKU_TOP src bin network ifconfig ; SubDir HAIKU_TOP src bin network ifconfig ;
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.
}
UseHeaders [ FDirName $(HAIKU_TOP) src servers net ] : true ; UseHeaders [ FDirName $(HAIKU_TOP) src servers net ] : true ;
BinCommand ifconfig : BinCommand ifconfig :
ifconfig.cpp ifconfig.cpp
: be network : be network bnetapi
; ;
# Installation -- in the test directory for the time being
HaikuInstall install-networking
: [ FDirName $(HAIKU_TEST_DIR) kits net ]
: ifconfig ;
HaikuInstall install-userland-networking
: [ FDirName $(HAIKU_TEST_DIR) kits net userland ]
: ifconfig
: installed-userland-networking
;
Package haiku-networkingkit-cvs :
ifconfig :
# boot home config bin ;
boot home Desktop haiku-networkingkit ;
+92 -131
View File
@@ -9,9 +9,6 @@
*/ */
#include <Message.h>
#include <Messenger.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <net/if.h> #include <net/if.h>
#include <net/if_dl.h> #include <net/if_dl.h>
@@ -27,6 +24,11 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <Message.h>
#include <Messenger.h>
#include <NetworkInterface.h>
#include <NetworkRoster.h>
#include <NetServer.h> #include <NetServer.h>
@@ -109,7 +111,6 @@ initialize_address_families()
} }
static bool static bool
inet_parse_address(const char* string, sockaddr* _address) inet_parse_address(const char* string, sockaddr* _address)
{ {
@@ -160,7 +161,7 @@ inet_mask_to_prefix_length(sockaddr* _mask)
uint8 result = 0; uint8 result = 0;
uint32 hostMask = ntohl(mask.sin_addr.s_addr); uint32 hostMask = ntohl(mask.sin_addr.s_addr);
for (uint8 i = 32; i > 0; i--) { for (uint8 i = 32; i > 0; i--) {
if (hostMask & (1 << (i - 1)) == 0) if ((hostMask & (1 << (i - 1))) == 0)
break; break;
result++; result++;
} }
@@ -215,7 +216,7 @@ inet6_prefix_length_to_mask(uint8 prefixLength, sockaddr* _mask)
for (uint8 i = 0; i < sizeof(in6_addr); i++, prefixLength -= 8) { for (uint8 i = 0; i < sizeof(in6_addr); i++, prefixLength -= 8) {
if (prefixLength < 8) { if (prefixLength < 8) {
const uint8 masks[] = { static const uint8 masks[] = {
0x00, 0x80, 0xc0, 0xe0, 0x00, 0x80, 0xc0, 0xe0,
0xf0, 0xf8, 0xfc, 0xfe 0xf0, 0xf8, 0xfc, 0xfe
}; };
@@ -418,6 +419,19 @@ get_address_family(const char* argument, int32& familyIndex)
} }
const address_family*
get_address_family(int32 family)
{
for (int32 i = 0; kFamilies[i].family >= 0; i++) {
if (kFamilies[i].family == family)
return &kFamilies[i];
}
// defaults to AF_INET
return &kFamilies[0];
}
bool bool
parse_address(int32 familyIndex, const char* argument, struct sockaddr& address) parse_address(int32 familyIndex, const char* argument, struct sockaddr& address)
{ {
@@ -482,49 +496,43 @@ find_socket(struct ifreq& request, int addressFamily)
void void
list_interface_address(int socket, const address_family* family, list_interface_addresses(BNetworkInterface& interface, uint32 flags)
uint32 flags, ifreq* request)
{ {
if (ioctl(socket, SIOCGIFADDR, request, sizeof(struct ifreq)) < 0) int32 count = interface.CountAddresses();
return; for (int32 i = 0; i < count; i++) {
BNetworkInterfaceAddress address;
if (interface.GetAddressAt(i, address) != B_OK)
break;
printf("\t%s addr: ", family->name); const address_family* family
family->print_address(&request->ifr_addr); = get_address_family(address.Address().Family());
if ((flags & IFF_BROADCAST) != 0 printf("\t%s addr: ", family->name);
&& ioctl(socket, SIOCGIFBRDADDR, request, sizeof(struct ifreq)) == 0 family->print_address(address.Address());
&& request->ifr_broadaddr.sa_family == family->family) {
printf(", Bcast: "); if ((flags & IFF_BROADCAST) != 0) {
family->print_address(&request->ifr_broadaddr); printf(", Bcast: ");
} family->print_address(address.Broadcast());
if (ioctl(socket, SIOCGIFNETMASK, request, sizeof(struct ifreq)) == 0 }
&& request->ifr_mask.sa_family == family->family) {
switch (family->preferred_format) { switch (family->preferred_format) {
case PREFER_OUTPUT_MASK: case PREFER_OUTPUT_MASK:
printf(", Mask: "); printf(", Mask: ");
family->print_address(&request->ifr_mask); family->print_address(address.Mask());
break; break;
case PREFER_OUTPUT_PREFIX_LENGTH: case PREFER_OUTPUT_PREFIX_LENGTH:
printf(", Prefix Length: %u", printf(", Prefix Length: %u",
family->mask_to_prefix_length(&request->ifr_mask)); family->mask_to_prefix_length(address.Mask()));
break; break;
} }
putchar('\n');
} }
putchar('\n');
} }
bool bool
list_interface(const char* name, int addressFamily) list_interface(const char* name)
{ {
ifreq request;
if (!prepare_request(request, name))
return true;
int socket = find_socket(request, addressFamily);
if (socket == -1)
return false;
printf("%s", name); printf("%s", name);
size_t length = strlen(name); size_t length = strlen(name);
if (length < 8) if (length < 8)
@@ -534,60 +542,57 @@ list_interface(const char* name, int addressFamily)
// get link level interface for this interface // get link level interface for this interface
int linkSocket = ::socket(AF_LINK, SOCK_DGRAM, 0); BNetworkInterface interface(name);
if (linkSocket < 0) { BNetworkAddress linkAddress;
printf("No link level: %s\n", strerror(errno)); status_t status = interface.GetHardwareAddress(linkAddress);
} else { if (status == B_OK) {
const char *type = "unknown"; const char *type = "unknown";
char address[256]; char address[256];
strcpy(address, "none"); strcpy(address, "none");
if (ioctl(linkSocket, SIOCGIFADDR, &request, sizeof(struct ifreq)) switch (linkAddress.LinkLevelType()) {
== 0) { case IFT_ETHER:
sockaddr_dl &link = *(sockaddr_dl*)&request.ifr_addr; {
type = "Ethernet";
switch (link.sdl_type) { if (linkAddress.LinkLevelAddressLength() > 0) {
case IFT_ETHER: uint8 *mac = linkAddress.LinkLevelAddress();
{ sprintf(address, "%02x:%02x:%02x:%02x:%02x:%02x",
type = "Ethernet"; mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
} else
if (link.sdl_alen > 0) { strcpy(address, "not available");
uint8 *mac = (uint8*)LLADDR(&link); break;
sprintf(address, "%02x:%02x:%02x:%02x:%02x:%02x",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
} else
strcpy(address, "not available");
break;
}
case IFT_LOOP:
type = "Local Loopback";
break;
case IFT_MODEM:
type = "Modem";
break;
} }
case IFT_LOOP:
type = "Local Loopback";
break;
case IFT_MODEM:
type = "Modem";
break;
} }
printf("Hardware Type: %s, Address: %s\n", type, address); printf("Hardware Type: %s, Address: %s\n", type, address);
close(linkSocket); } else
} printf("No link level: %s\n", strerror(status));
if (ioctl(socket, SIOCGIFMEDIA, &request, sizeof(struct ifreq)) == 0 int media = interface.Media();
&& (request.ifr_media & IFM_ACTIVE) != 0) { if ((media & IFM_ACTIVE) != 0) {
// dump media state in case we're linked // dump media state in case we're linked
const char* type = "unknown"; const char* type = "unknown";
bool show = false; bool show = false;
for (int32 i = 0; kMediaTypes[i].type >= 0; i++) { for (int32 i = 0; kMediaTypes[i].type >= 0; i++) {
// loopback don't really have a media anyway // loopback don't really have a media anyway
if (IFM_TYPE(request.ifr_media) == 0/*IFT_LOOP*/) if (IFM_TYPE(media) == 0/*IFT_LOOP*/)
break; break;
// only check for generic or correct subtypes // only check for generic or correct subtypes
if (kMediaTypes[i].type && if (kMediaTypes[i].type
kMediaTypes[i].type != IFM_TYPE(request.ifr_media)) && kMediaTypes[i].type != IFM_TYPE(media))
continue; continue;
for (int32 j = 0; kMediaTypes[i].subtypes[j].subtype >= 0; j++) { for (int32 j = 0; kMediaTypes[i].subtypes[j].subtype >= 0; j++) {
if (kMediaTypes[i].subtypes[j].subtype == IFM_SUBTYPE(request.ifr_media)) { if (kMediaTypes[i].subtypes[j].subtype == IFM_SUBTYPE(media)) {
// found a match // found a match
type = kMediaTypes[i].subtypes[j].pretty; type = kMediaTypes[i].subtypes[j].pretty;
show = true; show = true;
@@ -600,31 +605,14 @@ list_interface(const char* name, int addressFamily)
printf("\tMedia Type: %s\n", type); printf("\tMedia Type: %s\n", type);
} }
uint32 flags = 0; uint32 flags = interface.Flags();
if (ioctl(socket, SIOCGIFFLAGS, &request, sizeof(struct ifreq)) == 0)
flags = request.ifr_flags;
for (int32 i = 0; kFamilies[i].family >= 0; i++) { list_interface_addresses(interface, flags);
int familySocket = sAddressFamilySockets[i];
if (familySocket != -1) {
list_interface_address(familySocket, &kFamilies[i],
flags, &request);
}
}
// Print MTU, metric, flags // Print MTU, metric, flags
printf("\tMTU: "); printf("\tMTU: %" B_PRId32 ", Metric: %" B_PRId32, interface.MTU(),
if (ioctl(socket, SIOCGIFMTU, &request, sizeof(struct ifreq)) == 0) interface.Metric());
printf("%d", request.ifr_mtu);
else
printf("-");
printf(", Metric: ");
if (ioctl(socket, SIOCGIFMETRIC, &request, sizeof(struct ifreq)) == 0)
printf("%d", request.ifr_metric);
else
printf("-");
if (flags != 0) { if (flags != 0) {
const struct { const struct {
@@ -660,16 +648,16 @@ list_interface(const char* name, int addressFamily)
// Print statistics // Print statistics
if (ioctl(socket, SIOCGIFSTATS, &request, sizeof(struct ifreq)) == 0) { ifreq_stats stats;
printf("\tReceive: %d packets, %d errors, %Ld bytes, %d mcasts, %d dropped\n", if (interface.GetStats(stats) == B_OK) {
request.ifr_stats.receive.packets, request.ifr_stats.receive.errors, printf("\tReceive: %d packets, %d errors, %Ld bytes, %d mcasts, %d "
request.ifr_stats.receive.bytes, request.ifr_stats.receive.multicast_packets, "dropped\n", stats.receive.packets, stats.receive.errors,
request.ifr_stats.receive.dropped); stats.receive.bytes, stats.receive.multicast_packets,
printf("\tTransmit: %d packets, %d errors, %Ld bytes, %d mcasts, %d dropped\n", stats.receive.dropped);
request.ifr_stats.send.packets, request.ifr_stats.send.errors, printf("\tTransmit: %d packets, %d errors, %Ld bytes, %d mcasts, %d "
request.ifr_stats.send.bytes, request.ifr_stats.send.multicast_packets, "dropped\n", stats.send.packets, stats.send.errors,
request.ifr_stats.send.dropped); stats.send.bytes, stats.send.multicast_packets, stats.send.dropped);
printf("\tCollisions: %d\n", request.ifr_stats.collisions); printf("\tCollisions: %d\n", stats.collisions);
} }
putchar('\n'); putchar('\n');
@@ -681,46 +669,20 @@ void
list_interfaces(const char* name) list_interfaces(const char* name)
{ {
if (name != NULL) { if (name != NULL) {
list_interface(name, -1); list_interface(name);
return; return;
} }
// get a list of all interfaces // get a list of all interfaces
int socket = sAddressFamilySockets[0]; BNetworkRoster& roster = BNetworkRoster::Default();
ifconf config; BNetworkInterface interface;
config.ifc_len = sizeof(config.ifc_value); uint32 cookie = 0;
if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0)
return;
uint32 count = (uint32)config.ifc_value; while (roster.GetNextInterface(&cookie, interface) == B_OK) {
if (count == 0) { list_interface(interface.Name());
fprintf(stderr, "%s: There are no interfaces yet!\n", kProgramName);
return;
} }
void *buffer = malloc(count * sizeof(struct ifreq));
if (buffer == NULL) {
fprintf(stderr, "%s: Out of memory.\n", kProgramName);
return;
}
config.ifc_len = count * sizeof(struct ifreq);
config.ifc_buf = buffer;
if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0)
return;
ifreq* interface = (ifreq*)buffer;
for (uint32 i = 0; i < count; i++) {
list_interface(interface->ifr_name, interface->ifr_addr.sa_family);
interface = (ifreq*)((uint8*)interface
+ _SIZEOF_ADDR_IFREQ(interface[0]));
}
free(buffer);
} }
@@ -1052,8 +1014,7 @@ configure_interface(const char* name, char* const* args,
BMessage message(kMsgConfigureInterface); BMessage message(kMsgConfigureInterface);
message.AddString("device", name); message.AddString("device", name);
BMessage address; BMessage address;
// TODO: this is not working for ipv6 yet address.AddString("family", kFamilies[familyIndex].name);
address.AddString("family", "inet");
address.AddBool("auto_config", true); address.AddBool("auto_config", true);
message.AddMessage("address", &address); message.AddMessage("address", &address);