* ifconfig is no longer using any ioctl()s, but the new C++ classes only. Seems
to work fine so far. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38061 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -9,16 +9,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <errno.h>
|
||||||
#include <net/if.h>
|
|
||||||
#include <net/if_dl.h>
|
|
||||||
#include <net/if_media.h>
|
#include <net/if_media.h>
|
||||||
#include <net/if_types.h>
|
#include <net/if_types.h>
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/sockio.h>
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -41,107 +34,13 @@ enum preferred_output_format {
|
|||||||
PREFER_OUTPUT_PREFIX_LENGTH,
|
PREFER_OUTPUT_PREFIX_LENGTH,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct address_family {
|
struct address_family {
|
||||||
int family;
|
int family;
|
||||||
const char* name;
|
const char* name;
|
||||||
const char* identifiers[4];
|
const char* identifiers[4];
|
||||||
preferred_output_format preferred_format;
|
preferred_output_format preferred_format;
|
||||||
bool (*parse_address)(const char* string, sockaddr* _address);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
bool initialize_address_families();
|
|
||||||
|
|
||||||
// AF_INET family
|
|
||||||
static bool inet_parse_address(const char* string, sockaddr* address);
|
|
||||||
|
|
||||||
// AF_INET6 family
|
|
||||||
static bool inet6_parse_address(const char* string, sockaddr* address);
|
|
||||||
|
|
||||||
static const address_family kFamilies[] = {
|
|
||||||
{
|
|
||||||
AF_INET,
|
|
||||||
"inet",
|
|
||||||
{"AF_INET", "inet", "ipv4", NULL},
|
|
||||||
PREFER_OUTPUT_MASK,
|
|
||||||
inet_parse_address,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
AF_INET6,
|
|
||||||
"inet6",
|
|
||||||
{"AF_INET6", "inet6", "ipv6", NULL},
|
|
||||||
PREFER_OUTPUT_PREFIX_LENGTH,
|
|
||||||
inet6_parse_address,
|
|
||||||
},
|
|
||||||
{ -1, NULL, {NULL}, PREFER_OUTPUT_MASK, 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - IPv4
|
|
||||||
|
|
||||||
|
|
||||||
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(sockaddr_in);
|
|
||||||
address.sin_port = 0;
|
|
||||||
address.sin_addr = inetAddress;
|
|
||||||
memset(&address.sin_zero[0], 0, sizeof(address.sin_zero));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - IPv6
|
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
|
|
||||||
struct media_type {
|
struct media_type {
|
||||||
int type;
|
int type;
|
||||||
const char* name;
|
const char* name;
|
||||||
@@ -160,6 +59,22 @@ struct media_type {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static const address_family kFamilies[] = {
|
||||||
|
{
|
||||||
|
AF_INET,
|
||||||
|
"inet",
|
||||||
|
{"AF_INET", "inet", "ipv4", NULL},
|
||||||
|
PREFER_OUTPUT_MASK
|
||||||
|
},
|
||||||
|
{
|
||||||
|
AF_INET6,
|
||||||
|
"inet6",
|
||||||
|
{"AF_INET6", "inet6", "ipv6", NULL},
|
||||||
|
PREFER_OUTPUT_PREFIX_LENGTH
|
||||||
|
},
|
||||||
|
{ -1, NULL, {NULL}, PREFER_OUTPUT_MASK }
|
||||||
|
};
|
||||||
|
|
||||||
static const media_type kMediaTypes[] = {
|
static const media_type kMediaTypes[] = {
|
||||||
{
|
{
|
||||||
0, // for generic options
|
0, // for generic options
|
||||||
@@ -199,30 +114,7 @@ static const media_type kMediaTypes[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static bool
|
static void
|
||||||
media_parse_subtype(const char* string, int media, int* type)
|
|
||||||
{
|
|
||||||
for (int32 i = 0; kMediaTypes[i].type >= 0; i++) {
|
|
||||||
// only check for generic or correct subtypes
|
|
||||||
if (kMediaTypes[i].type &&
|
|
||||||
kMediaTypes[i].type != media)
|
|
||||||
continue;
|
|
||||||
for (int32 j = 0; kMediaTypes[i].subtypes[j].subtype >= 0; j++) {
|
|
||||||
if (strcmp(kMediaTypes[i].subtypes[j].name, string) == 0) {
|
|
||||||
// found a match
|
|
||||||
*type = kMediaTypes[i].subtypes[j].subtype;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
usage(int status)
|
usage(int status)
|
||||||
{
|
{
|
||||||
printf("usage: %s [<interface> [<address family>] [<address> [<mask>] | "
|
printf("usage: %s [<interface> [<address family>] [<address> [<mask>] | "
|
||||||
@@ -255,42 +147,46 @@ usage(int status)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
static bool
|
||||||
prepare_request(struct ifreq& request, const char* name)
|
media_parse_subtype(const char* string, int media, int* type)
|
||||||
{
|
{
|
||||||
if (strlen(name) >= IF_NAMESIZE) {
|
for (int32 i = 0; kMediaTypes[i].type >= 0; i++) {
|
||||||
fprintf(stderr, "%s: interface name \"%s\" is too long.\n",
|
// only check for generic or correct subtypes
|
||||||
kProgramName, name);
|
if (kMediaTypes[i].type &&
|
||||||
return false;
|
kMediaTypes[i].type != media)
|
||||||
|
continue;
|
||||||
|
for (int32 j = 0; kMediaTypes[i].subtypes[j].subtype >= 0; j++) {
|
||||||
|
if (strcmp(kMediaTypes[i].subtypes[j].name, string) == 0) {
|
||||||
|
// found a match
|
||||||
|
*type = kMediaTypes[i].subtypes[j].subtype;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
memset(&request, 0, sizeof(ifreq));
|
|
||||||
strcpy(request.ifr_name, name);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
static bool
|
||||||
get_address_family(const char* argument, int32& familyIndex)
|
get_address_family(const char* argument, int& family)
|
||||||
{
|
{
|
||||||
for (int32 i = 0; kFamilies[i].family >= 0; i++) {
|
for (int32 i = 0; kFamilies[i].family >= 0; i++) {
|
||||||
for (int32 j = 0; kFamilies[i].identifiers[j]; j++) {
|
for (int32 j = 0; kFamilies[i].identifiers[j]; j++) {
|
||||||
if (!strcmp(argument, kFamilies[i].identifiers[j])) {
|
if (!strcmp(argument, kFamilies[i].identifiers[j])) {
|
||||||
// found a match
|
// found a match
|
||||||
familyIndex = i;
|
family = kFamilies[i].family;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaults to AF_INET
|
family = AF_UNSPEC;
|
||||||
familyIndex = 0;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const address_family*
|
static const address_family*
|
||||||
get_address_family(int32 family)
|
address_family_for(int family)
|
||||||
{
|
{
|
||||||
for (int32 i = 0; kFamilies[i].family >= 0; i++) {
|
for (int32 i = 0; kFamilies[i].family >= 0; i++) {
|
||||||
if (kFamilies[i].family == family)
|
if (kFamilies[i].family == family)
|
||||||
@@ -302,70 +198,57 @@ get_address_family(int32 family)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Parses the \a argument as network \a address for the specified \a family.
|
||||||
|
If \a family is \c AF_UNSPEC, \a family will be overwritten with the family
|
||||||
|
of the successfully parsed address.
|
||||||
|
*/
|
||||||
bool
|
bool
|
||||||
parse_address(int32 familyIndex, const char* argument, struct sockaddr& address)
|
parse_address(int& family, const char* argument, BNetworkAddress& address)
|
||||||
{
|
{
|
||||||
if (argument == NULL)
|
if (argument == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return kFamilies[familyIndex].parse_address(argument, &address);
|
status_t status = address.SetTo(family, argument, (uint16)0,
|
||||||
|
B_NO_ADDRESS_RESOLUTION);
|
||||||
|
if (status != B_OK)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (family == AF_UNSPEC) {
|
||||||
|
// Test if we support the resulting address family
|
||||||
|
bool supported = false;
|
||||||
|
|
||||||
|
for (int32 i = 0; kFamilies[i].family >= 0; i++) {
|
||||||
|
if (kFamilies[i].family == address.Family()) {
|
||||||
|
supported = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!supported)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Take over family from address
|
||||||
|
family = address.Family();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
prefix_length_to_mask(int32 familyIndex, const char* argument,
|
prefix_length_to_mask(int family, const char* argument, BNetworkAddress& mask)
|
||||||
struct sockaddr& mask)
|
|
||||||
{
|
{
|
||||||
char *end;
|
char *end;
|
||||||
uint32 prefixLength = strtoul(argument, &end, 10);
|
uint32 prefixLength = strtoul(argument, &end, 10);
|
||||||
if (end == argument)
|
if (end == argument)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
BNetworkAddress address;
|
return mask.SetToMask(family, prefixLength) == B_OK;
|
||||||
if (address.SetToMask(kFamilies[familyIndex].family, prefixLength) != B_OK)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
memcpy(&mask, &address.SockAddr(), address.Length());
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #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
|
void
|
||||||
list_interface_addresses(BNetworkInterface& interface, uint32 flags)
|
list_interface_addresses(BNetworkInterface& interface, uint32 flags)
|
||||||
{
|
{
|
||||||
@@ -376,7 +259,7 @@ list_interface_addresses(BNetworkInterface& interface, uint32 flags)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
const address_family* family
|
const address_family* family
|
||||||
= get_address_family(address.Address().Family());
|
= address_family_for(address.Address().Family());
|
||||||
|
|
||||||
printf("\t%s addr: %s", family->name,
|
printf("\t%s addr: %s", family->name,
|
||||||
address.Address().ToString().String());
|
address.Address().ToString().String());
|
||||||
@@ -415,22 +298,10 @@ list_interface(const char* name)
|
|||||||
status_t status = interface.GetHardwareAddress(linkAddress);
|
status_t status = interface.GetHardwareAddress(linkAddress);
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
const char *type = "unknown";
|
const char *type = "unknown";
|
||||||
char address[256];
|
|
||||||
strcpy(address, "none");
|
|
||||||
|
|
||||||
switch (linkAddress.LinkLevelType()) {
|
switch (linkAddress.LinkLevelType()) {
|
||||||
case IFT_ETHER:
|
case IFT_ETHER:
|
||||||
{
|
|
||||||
type = "Ethernet";
|
type = "Ethernet";
|
||||||
|
|
||||||
if (linkAddress.LinkLevelAddressLength() > 0) {
|
|
||||||
uint8 *mac = linkAddress.LinkLevelAddress();
|
|
||||||
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;
|
break;
|
||||||
}
|
|
||||||
case IFT_LOOP:
|
case IFT_LOOP:
|
||||||
type = "Local Loopback";
|
type = "Local Loopback";
|
||||||
break;
|
break;
|
||||||
@@ -439,7 +310,11 @@ list_interface(const char* name)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Hardware Type: %s, Address: %s\n", type, address);
|
BString address = linkAddress.ToString();
|
||||||
|
if (address.Length() == 0)
|
||||||
|
address = "none";
|
||||||
|
|
||||||
|
printf("Hardware Type: %s, Address: %s\n", type, address.String());
|
||||||
} else
|
} else
|
||||||
printf("No link level: %s\n", strerror(status));
|
printf("No link level: %s\n", strerror(status));
|
||||||
|
|
||||||
@@ -562,45 +437,33 @@ list_interfaces(const char* name)
|
|||||||
void
|
void
|
||||||
delete_interface(const char* name, char* const* args, int32 argCount)
|
delete_interface(const char* name, char* const* args, int32 argCount)
|
||||||
{
|
{
|
||||||
ifreq request;
|
BNetworkInterface interface(name);
|
||||||
if (!prepare_request(request, name))
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (int32 i = 0; i < argCount; i++) {
|
for (int32 i = 0; i < argCount; i++) {
|
||||||
int32 familyIndex;
|
int family;
|
||||||
if (get_address_family(args[i], familyIndex))
|
if (get_address_family(args[i], family))
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
// TODO: be smart enough to detect the family by the address
|
BNetworkAddress address;
|
||||||
|
if (!parse_address(family, args[i], address)) {
|
||||||
int socket = find_socket(request, kFamilies[familyIndex].family);
|
|
||||||
if (socket == -1) {
|
|
||||||
fprintf(stderr, "%s: Address family \"%s\" is not available.\n",
|
|
||||||
kProgramName, kFamilies[familyIndex].name);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!parse_address(familyIndex, args[i], request.ifr_addr)) {
|
|
||||||
fprintf(stderr, "%s: Could not parse address \"%s\".\n",
|
fprintf(stderr, "%s: Could not parse address \"%s\".\n",
|
||||||
kProgramName, args[i]);
|
kProgramName, args[i]);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ioctl(socket, SIOCDIFADDR, &request, sizeof(request)) < 0) {
|
status_t status = interface.RemoveAddress(address);
|
||||||
|
if (status != B_OK) {
|
||||||
fprintf(stderr, "%s: Could not delete address %s from interface %s:"
|
fprintf(stderr, "%s: Could not delete address %s from interface %s:"
|
||||||
" %s\n", kProgramName, args[i], name, strerror(errno));
|
" %s\n", kProgramName, args[i], name, strerror(status));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argCount == 0) {
|
if (argCount == 0) {
|
||||||
// Delete interface
|
// Delete interface
|
||||||
int socket = find_socket(request, -1);
|
BNetworkRoster& roster = BNetworkRoster::Default();
|
||||||
if (socket < 0)
|
|
||||||
exit(1);
|
status_t status = roster.RemoveInterface(interface);
|
||||||
|
if (status != B_OK) {
|
||||||
request.ifr_addr.sa_family = AF_UNSPEC;
|
|
||||||
|
|
||||||
if (ioctl(socket, SIOCDIFADDR, &request, sizeof(request)) < 0) {
|
|
||||||
fprintf(stderr, "%s: Could not delete interface %s: %s\n",
|
fprintf(stderr, "%s: Could not delete interface %s: %s\n",
|
||||||
kProgramName, name, strerror(errno));
|
kProgramName, name, strerror(errno));
|
||||||
}
|
}
|
||||||
@@ -612,109 +475,95 @@ void
|
|||||||
configure_interface(const char* name, char* const* args,
|
configure_interface(const char* name, char* const* args,
|
||||||
int32 argCount)
|
int32 argCount)
|
||||||
{
|
{
|
||||||
ifreq request;
|
|
||||||
if (!prepare_request(request, name))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// try to parse address family
|
// try to parse address family
|
||||||
|
|
||||||
int32 familyIndex;
|
int family;
|
||||||
int32 i = 0;
|
int32 i = 0;
|
||||||
if (get_address_family(args[i], familyIndex))
|
if (get_address_family(args[i], family))
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
int socket = sAddressFamilySockets[familyIndex];
|
// try to parse address
|
||||||
if (socket < 0) {
|
|
||||||
fprintf(stderr, "%s: Address family \"%s\" is not available.\n",
|
BNetworkAddress address;
|
||||||
kProgramName, kFamilies[familyIndex].name);
|
BNetworkAddress mask;
|
||||||
exit(1);
|
|
||||||
|
if (parse_address(family, args[i], address)) {
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (parse_address(family, args[i], mask))
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 index = 0;
|
BNetworkInterface interface(name);
|
||||||
if (ioctl(socket, SIOCGIFINDEX, &request, sizeof(request)) >= 0)
|
if (!interface.Exists()) {
|
||||||
index = request.ifr_index;
|
|
||||||
|
|
||||||
bool hasAddress = false, hasMask = false, hasPeer = false;
|
|
||||||
bool hasBroadcast = false, doAutoConfig = false;
|
|
||||||
struct sockaddr address, mask, peer, broadcast;
|
|
||||||
int mtu = -1, metric = -1, media = -1;
|
|
||||||
int addFlags = 0, currentFlags = 0, removeFlags = 0;
|
|
||||||
|
|
||||||
if (index == 0) {
|
|
||||||
// the interface does not exist yet, we have to add it first
|
// the interface does not exist yet, we have to add it first
|
||||||
ifaliasreq request;
|
BNetworkRoster& roster = BNetworkRoster::Default();
|
||||||
memset(&request, 0, sizeof(ifaliasreq));
|
|
||||||
strlcpy(request.ifra_name, name, IF_NAMESIZE);
|
status_t status = roster.AddInterface(interface);
|
||||||
|
if (status != B_OK) {
|
||||||
if (ioctl(socket, SIOCAIFADDR, &request, sizeof(request)) < 0) {
|
|
||||||
fprintf(stderr, "%s: Could not add interface: %s\n", kProgramName,
|
fprintf(stderr, "%s: Could not add interface: %s\n", kProgramName,
|
||||||
strerror(errno));
|
strerror(status));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to parse address
|
BNetworkAddress broadcast;
|
||||||
|
BNetworkAddress peer;
|
||||||
if (parse_address(familyIndex, args[i], address)) {
|
int mtu = -1, metric = -1, media = -1;
|
||||||
hasAddress = true;
|
int addFlags = 0, currentFlags = 0, removeFlags = 0;
|
||||||
i++;
|
bool doAutoConfig = false;
|
||||||
|
|
||||||
if (parse_address(familyIndex, args[i], mask)) {
|
|
||||||
hasMask = true;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse parameters and flags
|
// parse parameters and flags
|
||||||
|
|
||||||
while (i < argCount) {
|
while (i < argCount) {
|
||||||
if (!strcmp(args[i], "peer")) {
|
if (!strcmp(args[i], "peer")) {
|
||||||
if (!parse_address(familyIndex, args[i + 1], peer)) {
|
if (!parse_address(family, args[i + 1], peer)) {
|
||||||
fprintf(stderr, "%s: Option 'peer' needs valid address "
|
fprintf(stderr, "%s: Option 'peer' needs valid address "
|
||||||
"parameter\n", kProgramName);
|
"parameter\n", kProgramName);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
hasPeer = true;
|
|
||||||
i++;
|
i++;
|
||||||
} else if (!strcmp(args[i], "nm") || !strcmp(args[i], "netmask")) {
|
} else if (!strcmp(args[i], "nm") || !strcmp(args[i], "netmask")) {
|
||||||
if (hasMask) {
|
if (!mask.IsEmpty()) {
|
||||||
fprintf(stderr, "%s: Netmask or prefix length is specified "
|
fprintf(stderr, "%s: Netmask or prefix length is specified "
|
||||||
"twice\n", kProgramName);
|
"twice\n", kProgramName);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (!parse_address(familyIndex, args[i + 1], mask)) {
|
if (!parse_address(family, args[i + 1], mask)) {
|
||||||
fprintf(stderr, "%s: Option 'netmask' needs valid address "
|
fprintf(stderr, "%s: Option 'netmask' needs valid address "
|
||||||
"parameter\n", kProgramName);
|
"parameter\n", kProgramName);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
hasMask = true;
|
|
||||||
i++;
|
i++;
|
||||||
} else if (!strcmp(args[i], "prefixlen")
|
} else if (!strcmp(args[i], "prefixlen") || !strcmp(args[i], "plen")
|
||||||
|| !strcmp(args[i], "plen")) {
|
|| !strcmp(args[i], "prefix-length")) {
|
||||||
if (hasMask) {
|
if (!mask.IsEmpty()) {
|
||||||
fprintf(stderr, "%s: Netmask or prefix length is specified "
|
fprintf(stderr, "%s: Netmask or prefix length is specified "
|
||||||
"twice\n", kProgramName);
|
"twice\n", kProgramName);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (!prefix_length_to_mask(familyIndex, args[i + 1], mask)) {
|
|
||||||
fprintf(stderr, "%s: Option 'prefixlen' is invalid for this "
|
// default to AF_INET if no address family has been specified yet
|
||||||
"address family\n", kProgramName);
|
if (family == AF_UNSPEC)
|
||||||
|
family = AF_INET;
|
||||||
|
|
||||||
|
if (!prefix_length_to_mask(family, args[i + 1], mask)) {
|
||||||
|
fprintf(stderr, "%s: Option 'prefix-length %s' is invalid for "
|
||||||
|
"this address family\n", kProgramName, args[i + 1]);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
hasMask = true;
|
|
||||||
i++;
|
i++;
|
||||||
} else if (!strcmp(args[i], "bc") || !strcmp(args[i], "broadcast")) {
|
} else if (!strcmp(args[i], "bc") || !strcmp(args[i], "broadcast")) {
|
||||||
if (hasBroadcast) {
|
if (!broadcast.IsEmpty()) {
|
||||||
fprintf(stderr, "%s: broadcast address is specified twice\n",
|
fprintf(stderr, "%s: broadcast address is specified twice\n",
|
||||||
kProgramName);
|
kProgramName);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (!parse_address(familyIndex, args[i + 1], broadcast)) {
|
if (!parse_address(family, args[i + 1], broadcast)) {
|
||||||
fprintf(stderr, "%s: Option 'broadcast' needs valid address "
|
fprintf(stderr, "%s: Option 'broadcast' needs valid address "
|
||||||
"parameter\n", kProgramName);
|
"parameter\n", kProgramName);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
hasBroadcast = true;
|
|
||||||
addFlags |= IFF_BROADCAST;
|
addFlags |= IFF_BROADCAST;
|
||||||
i++;
|
i++;
|
||||||
} else if (!strcmp(args[i], "mtu")) {
|
} else if (!strcmp(args[i], "mtu")) {
|
||||||
@@ -734,8 +583,8 @@ configure_interface(const char* name, char* const* args,
|
|||||||
metric = strtol(args[i + 1], NULL, 0);
|
metric = strtol(args[i + 1], NULL, 0);
|
||||||
i++;
|
i++;
|
||||||
} else if (!strcmp(args[i], "media")) {
|
} else if (!strcmp(args[i], "media")) {
|
||||||
if (ioctl(socket, SIOCGIFMEDIA, &request,
|
media = interface.Media();
|
||||||
sizeof(struct ifreq)) < 0) {
|
if (media < 0) {
|
||||||
fprintf(stderr, "%s: Unable to detect media type\n",
|
fprintf(stderr, "%s: Unable to detect media type\n",
|
||||||
kProgramName);
|
kProgramName);
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -745,8 +594,7 @@ configure_interface(const char* name, char* const* args,
|
|||||||
kProgramName);
|
kProgramName);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (!media_parse_subtype(args[i + 1], IFM_TYPE(request.ifr_media),
|
if (!media_parse_subtype(args[i + 1], IFM_TYPE(media), &media)) {
|
||||||
&media)) {
|
|
||||||
fprintf(stderr, "%s: Invalid parameter for option 'media': "
|
fprintf(stderr, "%s: Invalid parameter for option 'media': "
|
||||||
"'%s'\n", kProgramName, args[i + 1]);
|
"'%s'\n", kProgramName, args[i + 1]);
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -783,96 +631,71 @@ configure_interface(const char* name, char* const* args,
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doAutoConfig && (hasAddress || hasMask || hasBroadcast || hasPeer)) {
|
if (doAutoConfig && (!address.IsEmpty() || !mask.IsEmpty()
|
||||||
|
|| !broadcast.IsEmpty() || !peer.IsEmpty())) {
|
||||||
fprintf(stderr, "%s: Contradicting changes specified\n", kProgramName);
|
fprintf(stderr, "%s: Contradicting changes specified\n", kProgramName);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// set address/mask/broadcast/peer
|
// set address/mask/broadcast/peer
|
||||||
|
|
||||||
if (hasAddress) {
|
if (!address.IsEmpty() || !mask.IsEmpty() || !broadcast.IsEmpty()) {
|
||||||
memcpy(&request.ifr_addr, &address, address.sa_len);
|
BNetworkInterfaceAddress interfaceAddress;
|
||||||
|
interfaceAddress.SetAddress(address);
|
||||||
|
interfaceAddress.SetMask(mask);
|
||||||
|
if (!broadcast.IsEmpty())
|
||||||
|
interfaceAddress.SetBroadcast(broadcast);
|
||||||
|
else if (!peer.IsEmpty())
|
||||||
|
interfaceAddress.SetDestination(peer);
|
||||||
|
|
||||||
if (ioctl(socket, SIOCSIFADDR, &request, sizeof(struct ifreq)) < 0) {
|
status_t status = interface.SetAddress(interfaceAddress);
|
||||||
|
if (status != B_OK) {
|
||||||
fprintf(stderr, "%s: Setting address failed: %s\n", kProgramName,
|
fprintf(stderr, "%s: Setting address failed: %s\n", kProgramName,
|
||||||
strerror(errno));
|
strerror(status));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ioctl(socket, SIOCGIFFLAGS, &request, sizeof(struct ifreq)) < 0) {
|
currentFlags = interface.Flags();
|
||||||
fprintf(stderr, "%s: Getting flags failed: %s\n", kProgramName,
|
|
||||||
strerror(errno));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
currentFlags = request.ifr_flags;
|
|
||||||
|
|
||||||
if (hasMask) {
|
|
||||||
memcpy(&request.ifr_mask, &mask, mask.sa_len);
|
|
||||||
|
|
||||||
if (ioctl(socket, SIOCSIFNETMASK, &request, sizeof(struct ifreq)) < 0) {
|
|
||||||
fprintf(stderr, "%s: Setting subnet mask failed: %s\n",
|
|
||||||
kProgramName, strerror(errno));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasBroadcast) {
|
|
||||||
memcpy(&request.ifr_broadaddr, &broadcast, broadcast.sa_len);
|
|
||||||
|
|
||||||
if (ioctl(socket, SIOCSIFBRDADDR, &request, sizeof(struct ifreq)) < 0) {
|
|
||||||
fprintf(stderr, "%s: Setting broadcast address failed: %s\n",
|
|
||||||
kProgramName, strerror(errno));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasPeer) {
|
|
||||||
memcpy(&request.ifr_dstaddr, &peer, peer.sa_len);
|
|
||||||
|
|
||||||
if (ioctl(socket, SIOCSIFDSTADDR, &request, sizeof(struct ifreq)) < 0) {
|
|
||||||
fprintf(stderr, "%s: Setting peer address failed: %s\n",
|
|
||||||
kProgramName, strerror(errno));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// set flags
|
// set flags
|
||||||
|
|
||||||
if (hasAddress || hasMask || hasBroadcast || hasPeer)
|
if (!address.IsEmpty() || !mask.IsEmpty() || !broadcast.IsEmpty()
|
||||||
|
|| !peer.IsEmpty())
|
||||||
removeFlags = IFF_AUTO_CONFIGURED | IFF_CONFIGURING;
|
removeFlags = IFF_AUTO_CONFIGURED | IFF_CONFIGURING;
|
||||||
|
|
||||||
if (addFlags || removeFlags) {
|
if (addFlags || removeFlags) {
|
||||||
request.ifr_flags = (currentFlags & ~removeFlags) | addFlags;
|
status_t status
|
||||||
if (ioctl(socket, SIOCSIFFLAGS, &request, sizeof(struct ifreq)) < 0) {
|
= interface.SetFlags((currentFlags & ~removeFlags) | addFlags);
|
||||||
|
if (status != B_OK) {
|
||||||
fprintf(stderr, "%s: Setting flags failed: %s\n", kProgramName,
|
fprintf(stderr, "%s: Setting flags failed: %s\n", kProgramName,
|
||||||
strerror(errno));
|
strerror(status));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// set options
|
// set options
|
||||||
|
|
||||||
if (mtu != -1) {
|
if (mtu != -1) {
|
||||||
request.ifr_mtu = mtu;
|
status_t status = interface.SetMTU(mtu);
|
||||||
if (ioctl(socket, SIOCSIFMTU, &request, sizeof(struct ifreq)) < 0) {
|
if (status != B_OK) {
|
||||||
fprintf(stderr, "%s: Setting MTU failed: %s\n", kProgramName,
|
fprintf(stderr, "%s: Setting MTU failed: %s\n", kProgramName,
|
||||||
strerror(errno));
|
strerror(status));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (metric != -1) {
|
if (metric != -1) {
|
||||||
request.ifr_metric = metric;
|
status_t status = interface.SetMetric(metric);
|
||||||
if (ioctl(socket, SIOCSIFMETRIC, &request, sizeof(struct ifreq)) < 0) {
|
if (status != B_OK) {
|
||||||
fprintf(stderr, "%s: Setting metric failed: %s\n", kProgramName,
|
fprintf(stderr, "%s: Setting metric failed: %s\n", kProgramName,
|
||||||
strerror(errno));
|
strerror(status));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (media != -1) {
|
if (media != -1) {
|
||||||
request.ifr_media = media;
|
status_t status = interface.SetMedia(media);
|
||||||
if (ioctl(socket, SIOCSIFMEDIA, &request, sizeof(struct ifreq)) < 0) {
|
if (status != B_OK) {
|
||||||
fprintf(stderr, "%s: Setting media failed: %s\n", kProgramName,
|
fprintf(stderr, "%s: Setting media failed: %s\n", kProgramName,
|
||||||
strerror(errno));
|
strerror(status));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -882,7 +705,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;
|
||||||
address.AddString("family", kFamilies[familyIndex].name);
|
address.AddString("family", address_family_for(family)->name);
|
||||||
address.AddBool("auto_config", true);
|
address.AddBool("auto_config", true);
|
||||||
message.AddMessage("address", &address);
|
message.AddMessage("address", &address);
|
||||||
|
|
||||||
@@ -915,11 +738,13 @@ main(int argc, char** argv)
|
|||||||
if (argc > 1 && (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")))
|
if (argc > 1 && (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")))
|
||||||
usage(0);
|
usage(0);
|
||||||
|
|
||||||
if (!initialize_address_families()) {
|
int socket = ::socket(AF_LINK, SOCK_DGRAM, 0);
|
||||||
|
if (socket < 0) {
|
||||||
fprintf(stderr, "%s: The networking stack doesn't seem to be "
|
fprintf(stderr, "%s: The networking stack doesn't seem to be "
|
||||||
"available.\n", kProgramName);
|
"available.\n", kProgramName);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
close(socket);
|
||||||
|
|
||||||
if (argc > 1
|
if (argc > 1
|
||||||
&& (!strcmp(argv[1], "--delete")
|
&& (!strcmp(argv[1], "--delete")
|
||||||
|
|||||||
Reference in New Issue
Block a user