* 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:
@@ -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 ;
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user