* Renamed the proprietary SIOC_* ioctls to B_SOCKET_* - no reason to pollute

global name space, and have ugly identifiers for nothing :-)
* Added a flags field to struct ifaliasreq. Added flags to mark an alias that
  is currently being configured, or has been automatically configured.
  Those flags aren't used yet, but they will replace IFF_CONFIGURING and
  friends.
* Implemented deleting addresses only from interfaces via ifconfig.
* Added more command aliases for delete to ifconfig ("del", and "delete", for
  more consistency with route).
* Fixed control_routes() to only release a reference to an address if it
  actually got one before.
* If an interface address is deleted, its routes are now removed as well.
* InterfaceAddress now holds a reference to its interface as planned.
* Implemented removing interfaces. Works quite nicely.
* When downing an interface, all of its routes are now removed. When upping
  it again, at least the default routes are added.
* datalink.cpp's get_interface_name_or_index() leaked a reference to the
  interface found.
* SIOCAIFADDR would also leak a reference when new addresses were added.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37872 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2010-08-03 15:51:54 +00:00
parent a7faa05822
commit 2b1c0755dd
10 changed files with 303 additions and 174 deletions

View File

@ -61,6 +61,7 @@ struct ifaliasreq {
struct sockaddr_storage ifra_destination;
};
struct sockaddr_storage ifra_mask;
uint32_t ifra_flags;
};
/* interface flags */
@ -74,10 +75,15 @@ struct ifaliasreq {
#define IFF_ALLMULTI 0x0200 /* receive all multicast packets */
#define IFF_SIMPLEX 0x0800 /* doesn't receive own transmissions */
#define IFF_LINK 0x1000 /* has link */
#define IFF_AUTO_CONFIGURED 0x2000 /* has been automatically configured */
#define IFF_CONFIGURING 0x4000 /* auto configuration in progress */
#define IFF_AUTO_CONFIGURED 0x2000
#define IFF_CONFIGURING 0x4000
#define IFF_MULTICAST 0x8000 /* supports multicast */
/* interface alias flags */
#define IFAF_AUTO_CONFIGURED 0x0001 /* has been automatically configured */
#define IFAF_CONFIGURING 0x0002 /* auto configuration in progress */
/* used with SIOCGIFCOUNT, and SIOCGIFCONF */
struct ifconf {
int ifc_len; /* size of buffer */

View File

@ -6,7 +6,9 @@
#define _SYS_SOCKIO_H
/*! Socket I/O control codes, usually via struct ifreq */
/*! Socket I/O control codes, usually via struct ifreq, most of them should
be compatible with the BSDs.
*/
#define SIOCADDRT 8900 /* add route */
@ -66,11 +68,12 @@
#define SIOCSIFGENERIC 8945 /* generic IF set op */
#define SIOCGIFGENERIC 8946 /* generic IF get op */
#define SIOC_IF_ALIAS_REMOVE 8918 /* synonym for SIOCDIFADDR */
#define SIOC_IF_ALIAS_ADD 8919 /* synonym for SIOCAIFADDR */
#define SIOC_IF_ALIAS_SET 8947 /* set interface alias, ifaliasreq */
#define SIOC_IF_ALIAS_GET 8948 /* get interface alias, ifaliasreq */
#define SIOC_IF_ALIAS_COUNT 8959 /* count interface aliases */
/* Haiku specific extensions */
#define B_SOCKET_REMOVE_ALIAS 8918 /* synonym for SIOCDIFADDR */
#define B_SOCKET_ADD_ALIAS 8919 /* synonym for SIOCAIFADDR */
#define B_SOCKET_SET_ALIAS 8947 /* set interface alias, ifaliasreq */
#define B_SOCKET_GET_ALIAS 8948 /* get interface alias, ifaliasreq */
#define B_SOCKET_COUNT_ALIASES 8949 /* count interface aliases */
#define SIOCEND 9000 /* SIOCEND >= highest SIOC* */

View File

@ -38,6 +38,7 @@ typedef struct net_interface_address {
struct sockaddr* local;
struct sockaddr* destination;
struct sockaddr* mask;
uint32_t flags;
} net_interface_address;
typedef struct net_interface {

View File

@ -110,9 +110,9 @@ option_to_string(int32 option)
CODE(SIOCSIFGENERIC) /* generic IF set op */
CODE(SIOCGIFGENERIC) /* generic IF get op */
CODE(SIOC_IF_ALIAS_SET) /* set interface alias, ifaliasreq */
CODE(SIOC_IF_ALIAS_GET) /* get interface alias, ifaliasreq */
CODE(SIOC_IF_ALIAS_COUNT) /* count interface aliases */
CODE(B_SOCKET_SET_ALIAS) /* set interface alias, ifaliasreq */
CODE(B_SOCKET_GET_ALIAS) /* get interface alias, ifaliasreq */
CODE(B_SOCKET_COUNT_ALIASES) /* count interface aliases */
default:
static char buffer[24];
@ -142,7 +142,7 @@ get_interface_name_or_index(net_domain* domain, int32 option, void* value,
if (user_memcpy(&request, value, expected) < B_OK)
return B_BAD_ADDRESS;
net_interface* interface = NULL;
Interface* interface = NULL;
if (option == SIOCGIFINDEX)
interface = get_interface(domain, request.ifr_name);
else
@ -157,6 +157,7 @@ get_interface_name_or_index(net_domain* domain, int32 option, void* value,
strlcpy(request.ifr_name, interface->name, IF_NAMESIZE);
*_length = sizeof(ifreq);
interface->ReleaseReference();
return user_memcpy(value, &request, sizeof(ifreq));
}
@ -200,14 +201,14 @@ datalink_control(net_domain* _domain, int32 option, void* value,
case SIOCGIFNAME:
return get_interface_name_or_index(domain, option, value, _length);
case SIOCAIFADDR: /* same as SIOC_IF_ALIAS_ADD */
case SIOCAIFADDR: /* same as B_SOCKET_ADD_ALIAS */
{
// add new interface address
if (*_length < sizeof(struct ifaliasreq))
return B_BAD_VALUE;
struct ifaliasreq request;
if (user_memcpy(&request, value, sizeof(struct ifaliasreq)) < B_OK)
if (user_memcpy(&request, value, sizeof(struct ifaliasreq)) != B_OK)
return B_BAD_ADDRESS;
Interface* interface = get_interface(domain, request.ifra_name);
@ -216,6 +217,8 @@ datalink_control(net_domain* _domain, int32 option, void* value,
status_t status = add_interface_address(interface, domain,
request);
notify_interface_changed(interface);
interface->ReleaseReference();
return status;
}
@ -232,11 +235,11 @@ datalink_control(net_domain* _domain, int32 option, void* value,
return status;
}
case SIOCDIFADDR: /* same as SIOC_IF_ALIAS_REMOVE */
case SIOCDIFADDR: /* same as B_SOCKET_REMOVE_ALIAS */
{
// remove interface (address)
struct ifreq request;
if (user_memcpy(&request, value, sizeof(struct ifreq)) < B_OK)
if (user_memcpy(&request, value, sizeof(struct ifreq)) != B_OK)
return B_BAD_ADDRESS;
Interface* interface = get_interface(domain, request.ifr_name);
@ -246,8 +249,7 @@ datalink_control(net_domain* _domain, int32 option, void* value,
status_t status;
if (request.ifr_addr.sa_family != AF_UNSPEC
|| request.ifr_addr.sa_len != 0) {
// TODO: remove interface if this was the last address?
&& request.ifr_addr.sa_len != 0) {
status = interface->Control(domain, SIOCDIFADDR, request,
(ifreq*)value, *_length);
} else
@ -675,7 +677,7 @@ interface_protocol_down(net_datalink_protocol* _protocol)
deviceInterface->up_count--;
interface_went_down(interface);
interface->WentDown();
if (deviceInterface->up_count > 0)
return;
@ -745,7 +747,7 @@ interface_protocol_control(net_datalink_protocol* _protocol, int32 option,
&((struct ifreq*)argument)->ifr_addr, maxLength);
}
case SIOC_IF_ALIAS_COUNT:
case B_SOCKET_COUNT_ALIASES:
{
ifreq request;
request.ifr_count = interface->CountAddresses();
@ -754,7 +756,7 @@ interface_protocol_control(net_datalink_protocol* _protocol, int32 option,
&request.ifr_count, sizeof(request.ifr_count));
}
case SIOC_IF_ALIAS_GET:
case B_SOCKET_GET_ALIAS:
{
ifaliasreq request;
if (user_memcpy(&request, argument, sizeof(ifaliasreq)) != B_OK)

View File

@ -170,6 +170,10 @@ InterfaceAddress::InterfaceAddress(net_interface* netInterface,
InterfaceAddress::~InterfaceAddress()
{
TRACE("InterfaceAddress %p: destructor\n", this);
if (interface != NULL && (flags & IFAF_DIRECT_ADDRESS) == 0)
((Interface*)interface)->ReleaseReference();
}
@ -213,6 +217,7 @@ InterfaceAddress::AddressFor(int32 option)
switch (option) {
case SIOCSIFADDR:
case SIOCGIFADDR:
case SIOCDIFADDR:
return &local;
case SIOCSIFNETMASK:
@ -231,6 +236,54 @@ InterfaceAddress::AddressFor(int32 option)
}
/*! Adds the default routes that every interface address needs, ie. the local
host route, and one for the subnet (if set).
*/
void
InterfaceAddress::AddDefaultRoutes(int32 option)
{
net_route route;
route.destination = local;
route.gateway = NULL;
route.interface_address = this;
if (mask != NULL && (option == SIOCSIFNETMASK || option == SIOCSIFADDR)) {
route.mask = mask;
route.flags = 0;
add_route(domain, &route);
}
if (option == SIOCSIFADDR) {
route.mask = NULL;
route.flags = RTF_LOCAL | RTF_HOST;
add_route(domain, &route);
}
}
/*! Removes the default routes as set by AddDefaultRoutes() again. */
void
InterfaceAddress::RemoveDefaultRoutes(int32 option)
{
net_route route;
route.destination = local;
route.gateway = NULL;
route.interface_address = this;
if (mask != NULL && (option == SIOCSIFNETMASK || option == SIOCSIFADDR)) {
route.mask = mask;
route.flags = 0;
remove_route(domain, &route);
}
if (option == SIOCSIFADDR) {
route.mask = NULL;
route.flags = RTF_LOCAL | RTF_HOST;
remove_route(domain, &route);
}
}
#if ENABLE_DEBUGGER_COMMANDS
@ -331,11 +384,18 @@ InterfaceAddress::Prepare(sockaddr** _address, size_t size)
void
InterfaceAddress::_Init(net_interface* netInterface, net_domain* netDomain)
{
TRACE("InterfaceAddress %p: init interface %p, domain %p\n", this,
netInterface, netDomain);
interface = netInterface;
domain = netDomain;
local = NULL;
destination = NULL;
mask = NULL;
flags = 0;
if (interface != NULL)
((Interface*)interface)->AcquireReference();
}
@ -370,6 +430,27 @@ Interface::Interface(const char* interfaceName,
Interface::~Interface()
{
TRACE("Interface %p: destructor\n", this);
put_device_interface(fDeviceInterface);
// Uninitialize the domain datalink protocols
DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator();
while (domain_datalink* datalink = iterator.Next()) {
put_domain_datalink_protocols(this, datalink->domain);
}
// Free domain datalink objects
domain_datalink* next = fDatalinkTable.Clear(true);
while (next != NULL) {
domain_datalink* datalink = next;
next = next->hash_link;
delete datalink;
}
recursive_lock_destroy(&fLock);
// Release reference of the stack - at this point, our stack may be unloaded
@ -477,10 +558,6 @@ Interface::RemoveAddress(InterfaceAddress* address)
fAddresses.Remove(address);
address->GetDoublyLinkedListLink()->next = NULL;
// TODO!
// if (_FirstForFamily(domain->family) == NULL)
// put_domain_datalink_protocols(this, domain);
locker.Unlock();
MutexLocker hashLocker(sHashLock);
@ -541,6 +618,17 @@ Interface::CountAddresses()
}
void
Interface::RemoveAddresses()
{
RecursiveLocker locker(fLock);
while (InterfaceAddress* address = fAddresses.RemoveHead()) {
address->ReleaseReference();
}
}
/*! This is called in order to call the correct methods of the datalink
protocols, ie. it will translate address changes to
net_datalink_protocol::change_address(), and IFF_UP changes to
@ -565,7 +653,7 @@ Interface::Control(net_domain* domain, int32 option, ifreq& request,
if ((requestFlags & IFF_UP) != 0)
status = _SetUp();
else
_SetDown();
SetDown();
}
if (status == B_OK) {
@ -581,7 +669,7 @@ Interface::Control(net_domain* domain, int32 option, ifreq& request,
return status;
}
case SIOC_IF_ALIAS_SET:
case B_SOCKET_SET_ALIAS:
{
RecursiveLocker locker(fLock);
@ -681,6 +769,39 @@ Interface::Control(net_domain* domain, int32 option, ifreq& request,
}
void
Interface::SetDown()
{
if ((flags & IFF_UP) == 0)
return;
RecursiveLocker locker(fLock);
DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator();
while (domain_datalink* datalink = iterator.Next()) {
datalink->first_info->interface_down(datalink->first_protocol);
}
flags &= ~IFF_UP;
}
/*! Called when a device lost its IFF_UP status. We will invalidate all
interface routes here.
*/
void
Interface::WentDown()
{
RecursiveLocker locker(fLock);
AddressList::Iterator iterator = fAddresses.GetIterator();
while (InterfaceAddress* address = iterator.Next()) {
if (address->domain != NULL)
invalidate_routes(address->domain, this);
}
}
status_t
Interface::CreateDomainDatalinkIfNeeded(net_domain* domain)
{
@ -713,6 +834,7 @@ Interface::CreateDomainDatalinkIfNeeded(net_domain* domain)
datalink->direct_address.mask = NULL;
datalink->direct_address.domain = domain;
datalink->direct_address.interface = this;
datalink->direct_address.flags = IFAF_DIRECT_ADDRESS;
fDatalinkTable.Insert(datalink);
@ -785,7 +907,7 @@ Interface::_SetUp()
if (status != B_OK)
return status;
// propagate flag to all datalink protocols
// Propagate flag to all datalink protocols
RecursiveLocker locker(fLock);
@ -810,26 +932,15 @@ Interface::_SetUp()
}
}
flags |= IFF_UP;
return B_OK;
}
// Add default routes for the existing addresses
void
Interface::_SetDown()
{
if ((flags & IFF_UP) == 0)
return;
RecursiveLocker locker(fLock);
DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator();
while (domain_datalink* datalink = iterator.Next()) {
datalink->first_info->interface_down(datalink->first_protocol);
AddressList::Iterator addressIterator = fAddresses.GetIterator();
while (InterfaceAddress* address = addressIterator.Next()) {
address->AddDefaultRoutes(SIOCSIFADDR);
}
down_device_interface(fDeviceInterface);
flags &= ~IFF_UP;
flags |= IFF_UP;
return B_OK;
}
@ -912,56 +1023,6 @@ find_interface(uint32 index)
}
/*! Removes the default routes as set by add_default_routes() again. */
static void
remove_default_routes(InterfaceAddress* address, int32 option)
{
net_route route;
route.destination = address->local;
route.gateway = NULL;
route.interface_address = address;
if (address->mask != NULL
&& (option == SIOCSIFNETMASK || option == SIOCSIFADDR)) {
route.mask = address->mask;
route.flags = 0;
remove_route(address->domain, &route);
}
if (option == SIOCSIFADDR) {
route.mask = NULL;
route.flags = RTF_LOCAL | RTF_HOST;
remove_route(address->domain, &route);
}
}
/*! Adds the default routes that every interface address needs, ie. the local
host route, and one for the subnet (if set).
*/
static void
add_default_routes(InterfaceAddress* address, int32 option)
{
net_route route;
route.destination = address->local;
route.gateway = NULL;
route.interface_address = address;
if (address->mask != NULL
&& (option == SIOCSIFNETMASK || option == SIOCSIFADDR)) {
route.mask = address->mask;
route.flags = 0;
add_route(address->domain, &route);
}
if (option == SIOCSIFADDR) {
route.mask = NULL;
route.flags = RTF_LOCAL | RTF_HOST;
add_route(address->domain, &route);
}
}
// #pragma mark -
@ -1000,47 +1061,17 @@ add_interface(const char* name, net_domain_private* domain,
status_t
remove_interface(Interface* interface)
{
return B_ERROR;
#if 0
// deleting an interface is fairly complex as we need
// to clear all references to it throughout the stack
interface->SetDown();
interface->RemoveAddresses();
// this will possibly call (if IFF_UP):
// interface_protocol_down()
// domain_interface_went_down()
// invalidate_routes()
// remove_route()
// update_route_infos()
// get_route_internal()
// down_device_interface() -- if upcount reaches 0
interface_set_down(interface);
MutexLocker locker(sLock);
sInterfaces.Remove(interface);
locker.Unlock();
// This call requires the RX Lock to be a recursive
// lock since each uninit_protocol() call may call
// again into the stack to unregister a reader for
// instance, which tries to obtain the RX lock again.
put_domain_datalink_protocols(interface);
put_device_interface(interface->device_interface);
delete interface;
#endif
#if 0
invalidate_routes(domain, interface);
list_remove_item(&domain->interfaces, interface);
notify_interface_removed(interface);
delete_interface((net_interface_private*)interface);
#endif
}
void
interface_went_down(Interface* interface)
{
TRACE("interface_went_down(%s)\n", interface->name);
// TODO!
//invalidate_routes(domain, interface);
interface->ReleaseReference();
return B_OK;
}
@ -1100,7 +1131,22 @@ update_interface_address(InterfaceAddress* interfaceAddress, int32 option,
if (_address == NULL)
return B_BAD_VALUE;
remove_default_routes(interfaceAddress, option);
Interface* interface = (Interface*)interfaceAddress->interface;
interfaceAddress->RemoveDefaultRoutes(option);
if (option == SIOCDIFADDR) {
// Remove address, and release its reference (causing our caller to
// delete it)
locker.Unlock();
invalidate_routes(interfaceAddress);
interface->RemoveAddress(interfaceAddress);
interfaceAddress->ReleaseReference();
return B_OK;
}
sAddressTable.Remove(interfaceAddress);
// Copy new address over
@ -1135,8 +1181,8 @@ update_interface_address(InterfaceAddress* interfaceAddress, int32 option,
interfaceAddress->local, oldNetmask);
}
add_default_routes(interfaceAddress, option);
notify_interface_changed(interfaceAddress->interface);
interfaceAddress->AddDefaultRoutes(option);
notify_interface_changed(interface);
}
sAddressTable.Insert(interfaceAddress);

View File

@ -25,6 +25,10 @@
struct net_device_interface;
// Additional address flags
#define IFAF_DIRECT_ADDRESS 0x1000
struct InterfaceAddress : DoublyLinkedListLinkImpl<InterfaceAddress>,
net_interface_address, Referenceable {
InterfaceAddress();
@ -40,6 +44,9 @@ struct InterfaceAddress : DoublyLinkedListLinkImpl<InterfaceAddress>,
sockaddr** AddressFor(int32 option);
void AddDefaultRoutes(int32 option);
void RemoveDefaultRoutes(int32 option);
InterfaceAddress*& HashTableLink() { return fLink; }
#if ENABLE_DEBUGGER_COMMANDS
@ -121,11 +128,15 @@ public:
bool GetNextAddress(InterfaceAddress** _address);
InterfaceAddress* AddressAt(size_t index);
size_t CountAddresses();
void RemoveAddresses();
status_t Control(net_domain* domain, int32 option,
ifreq& request, ifreq* userRequest,
size_t length);
void SetDown();
void WentDown();
recursive_lock& Lock() { return fLock; }
net_device_interface* DeviceInterface() { return fDeviceInterface; }
@ -142,7 +153,6 @@ public:
private:
status_t _SetUp();
void _SetDown();
InterfaceAddress* _FirstForFamily(int family);
status_t _ChangeAddress(RecursiveLocker& locker,
InterfaceAddress* address, int32 option,

View File

@ -411,6 +411,8 @@ status_t
control_routes(struct net_interface* _interface, net_domain* domain,
int32 option, void* argument, size_t length)
{
TRACE("control_routes(interface %p, domain %p, option %" B_PRId32 ")\n",
_interface, domain, option);
Interface* interface = (Interface*)_interface;
switch (option) {
@ -447,7 +449,8 @@ control_routes(struct net_interface* _interface, net_domain* domain,
else
status = remove_route(domain, &route);
address->ReleaseReference();
if (address != NULL)
address->ReleaseReference();
return status;
}
}
@ -601,7 +604,7 @@ invalidate_routes(net_domain* _domain, net_interface* interface)
net_domain_private* domain = (net_domain_private*)_domain;
RecursiveLocker locker(domain->lock);
dprintf("invalidate_routes(%i, %s)\n", domain->family, interface->name);
TRACE("invalidate_routes(%i, %s)\n", domain->family, interface->name);
RouteList::Iterator iterator = domain->routes.GetIterator();
while (iterator.HasNext()) {
@ -613,6 +616,26 @@ invalidate_routes(net_domain* _domain, net_interface* interface)
}
void
invalidate_routes(InterfaceAddress* address)
{
net_domain_private* domain = (net_domain_private*)address->domain;
TRACE("invalidate_routes(%s)\n",
AddressString(domain, address->local).Data());
RecursiveLocker locker(domain->lock);
RouteList::Iterator iterator = domain->routes.GetIterator();
while (iterator.HasNext()) {
net_route* route = iterator.Next();
if (route->interface_address == address)
remove_route(domain, route);
}
}
struct net_route*
get_route(struct net_domain* _domain, const struct sockaddr* address)
{

View File

@ -15,6 +15,9 @@
#include <util/DoublyLinkedList.h>
class InterfaceAddress;
struct net_route_private
: net_route, DoublyLinkedListLinkImpl<net_route_private> {
int32 ref_count;
@ -41,6 +44,7 @@ status_t remove_route(struct net_domain* domain,
status_t get_route_information(struct net_domain* domain, void* buffer,
size_t length);
void invalidate_routes(net_domain* domain, net_interface* interface);
void invalidate_routes(InterfaceAddress* address);
struct net_route* get_route(struct net_domain* domain,
const struct sockaddr* address);
status_t get_device_route(struct net_domain* domain, uint32 index,

View File

@ -106,9 +106,9 @@ static const ioctl_info kIOCtls[] = {
IOCTL_INFO_ENTRY(SIOCATMARK),
IOCTL_INFO_ENTRY(SIOCSPGRP),
IOCTL_INFO_ENTRY_TYPE(SIOC_IF_ALIAS_SET, struct ifaliasreq *),
IOCTL_INFO_ENTRY_TYPE(SIOC_IF_ALIAS_GET, struct ifaliasreq *),
IOCTL_INFO_ENTRY_TYPE(SIOC_IF_ALIAS_COUNT, struct ifaliasreq *),
IOCTL_INFO_ENTRY_TYPE(B_SOCKET_SET_ALIAS, struct ifaliasreq *),
IOCTL_INFO_ENTRY_TYPE(B_SOCKET_GET_ALIAS, struct ifaliasreq *),
IOCTL_INFO_ENTRY_TYPE(B_SOCKET_COUNT_ALIASES, struct ifreq *),
// termios ioctls
IOCTL_INFO_ENTRY(TCGETA),

View File

@ -393,6 +393,7 @@ prepare_request(struct ifreq& request, const char* name)
return false;
}
memset(&request, 0, sizeof(ifreq));
strcpy(request.ifr_name, name);
return true;
}
@ -723,20 +724,56 @@ list_interfaces(const char* name)
}
/*! If there are any arguments given, this will remove only the specified
addresses from the interface named \a name.
If there are no arguments, it will remove the complete interface with all
of its addresses.
*/
void
delete_interface(const char* name)
delete_interface(const char* name, char* const* args, int32 argCount)
{
ifreq request;
if (!prepare_request(request, name))
return;
int socket = find_socket(request, -1);
if (socket == -1)
return;
for (int32 i = 0; i < argCount; i++) {
int32 familyIndex;
if (get_address_family(args[i], familyIndex))
i++;
if (ioctl(socket, SIOCDIFADDR, &request, sizeof(request)) < 0) {
fprintf(stderr, "%s: Could not delete interface %s: %s\n",
kProgramName, name, strerror(errno));
// TODO: be smart enough to detect the family by the 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",
kProgramName, args[i]);
exit(1);
}
if (ioctl(socket, SIOCDIFADDR, &request, sizeof(request)) < 0) {
fprintf(stderr, "%s: Could not delete address %s from interface %s:"
" %s\n", kProgramName, args[i], name, strerror(errno));
}
}
if (argCount == 0) {
// Delete interface
int socket = find_socket(request, -1);
if (socket < 0)
exit(1);
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",
kProgramName, name, strerror(errno));
}
}
}
@ -776,12 +813,9 @@ configure_interface(const char* name, char* const* args,
if (index == 0) {
// the interface does not exist yet, we have to add it first
ifaliasreq request;
memset(&request, 0, sizeof(ifaliasreq));
strlcpy(request.ifra_name, name, IF_NAMESIZE);
request.ifra_addr.ss_family = AF_UNSPEC;
request.ifra_mask.ss_family = AF_UNSPEC;
request.ifra_broadaddr.ss_family = AF_UNSPEC;
if (ioctl(socket, SIOCAIFADDR, &request, sizeof(request)) < 0) {
fprintf(stderr, "%s: Could not add interface: %s\n", kProgramName,
strerror(errno));
@ -1052,32 +1086,32 @@ main(int argc, char** argv)
if (argc > 1 && (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")))
usage(0);
bool deleteInterfaces = false;
if (argc > 1
&& (!strcmp(argv[1], "--delete")
|| !strcmp(argv[1], "--del")
|| !strcmp(argv[1], "-d"))) {
// delete interfaces
if (argc < 3)
usage(1);
deleteInterfaces = true;
}
if (initialize_address_families() == false) {
if (!initialize_address_families()) {
fprintf(stderr, "%s: The networking stack doesn't seem to be "
"available.\n", kProgramName);
return 1;
}
if (deleteInterfaces) {
for (int i = 2; i < argc; i++) {
delete_interface(argv[i]);
}
if (argc > 1
&& (!strcmp(argv[1], "--delete")
|| !strcmp(argv[1], "--del")
|| !strcmp(argv[1], "-d")
|| !strcmp(argv[1], "del")
|| !strcmp(argv[1], "delete"))) {
// Delete interface (addresses)
if (argc < 3)
usage(1);
const char* name = argv[2];
delete_interface(name, argv + 3, argc - 3);
return 0;
} else if (argc > 1 && !strcmp(argv[1], "-a")) {
// accept -a option for those that are used to it from other platforms
}
if (argc > 1 && !strcmp(argv[1], "-a")) {
// Accept an optional "-a" option to list all interfaces for those
// that are used to it from other platforms.
if (argc > 2)
usage(1);
@ -1087,7 +1121,7 @@ main(int argc, char** argv)
const char* name = argv[1];
if (argc > 2) {
// add or configure an interface
// Add or configure an interface
configure_interface(name, argv + 2, argc - 2);
return 0;