* Reworked the complete stack to allow more than one address per network

interface - this caused quite a number of changes.
* Network interfaces, and its addresses are now reference counted (not yet
  complete, though, InterfaceAddresses need to hold references to their
  interface as well).
* There are two known regressions of this commit that I will fix later:
  - you cannot remove interfaces anymore
  - IPv4 multicast was broken anyway, but now it's disabled, too.
* Moved a device_interfaces.cpp|h out of interfaces.cpp.
* The datalink layer chain is now instantiated per domain per interface,
  not just per interface anymore.
* When a buffer reaches the network layer, it has no known interface yet, ie.
  the ipv4|6|whatever modules need to set this manually.
* Added more debug output, and some new debugger commands, the control option
  is now printed in clear text.
* Added hash_address() function to the address modules. Added "const" to
  set_to_defaults() where needed.
* Fixed net_buffer's restore header functions offset use as reported by Atis.
* Improved buffer dump output, use the domain module to print the address if
  available.
* Moved net_buffer::type into the union, as it's not needed by the upper layers
  anymore.
* Moved IPv6 specific code from {add|remove}_default_route() to where it
  belongs, but disabled it for the time being.
* Completely discarded useless ipv4_datagram module.
* Added ping6 to the build.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37794 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2010-07-28 17:38:23 +00:00
parent b216fbd077
commit 61729d9323
44 changed files with 3469 additions and 2378 deletions

View File

@ -46,8 +46,8 @@ SYSTEM_BIN = "[" addattr alert arp base64 basename bash bc beep bootman bzip2
mkfifo mkfs mkindex mktemp modifiers mount mount_nfs mountvolume mv
netcat netstat nl nohup notify nproc
od open
passwd paste patch pathchk pc ping play playfile playsound playwav pr prio
printenv printf profile ps ptx pwd
passwd paste patch pathchk pc ping ping6 play playfile playsound playwav
pr prio printenv printf profile ps ptx pwd
query quit
rc readlink ReadOnlyBootPrompt reindex release renice rlog rm rmattr
rmindex rmdir roster route
@ -105,10 +105,10 @@ SYSTEM_SERVERS = app_server cddb_daemon debug_server input_server mail_daemon
;
SYSTEM_NETWORK_DEVICES = ethernet loopback ;
SYSTEM_NETWORK_DATALINK_PROTOCOLS = ethernet_frame <module>arp loopback_frame
ipv4_datagram ;
SYSTEM_NETWORK_DATALINK_PROTOCOLS = ethernet_frame <module>arp loopback_frame ;
#ipv6_datagram ;
#SYSTEM_NETWORK_PPP = ipcp modem pap pppoe ;
SYSTEM_NETWORK_PROTOCOLS = ipv4 tcp udp icmp unix ;
SYSTEM_NETWORK_PROTOCOLS = ipv4 tcp udp icmp unix ; # icmp6 ipv6 ;
SYSTEM_ADD_ONS_ACCELERANTS = $(X86_ONLY)radeon.accelerant
$(X86_ONLY)nvidia.accelerant $(X86_ONLY)matrox.accelerant

View File

@ -1,5 +1,5 @@
/*
* Copyright 2006-2007, Haiku, Inc. All Rights Reserved.
* Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _NET_IF_H
@ -16,12 +16,6 @@
#define IFNAMSIZ IF_NAMESIZE
struct ifreq_parameter {
char base_name[IF_NAMESIZE];
char device[128];
uint8_t sub_type;
};
struct ifreq_stream_stats {
uint32_t packets;
uint32_t errors;
@ -43,7 +37,6 @@ struct ifreq {
struct sockaddr ifr_dstaddr;
struct sockaddr ifr_broadaddr;
struct sockaddr ifr_mask;
struct ifreq_parameter ifr_parameter;
struct ifreq_stats ifr_stats;
struct route_entry ifr_route;
int ifr_flags;
@ -56,6 +49,14 @@ struct ifreq {
};
};
/* used with SIOCAIFADDR */
struct ifaliasreq {
char ifra_name[IF_NAMESIZE];
struct sockaddr_storage ifra_addr;
struct sockaddr_storage ifra_broadaddr;
struct sockaddr_storage ifra_mask;
};
/* interface flags */
#define IFF_UP 0x0001
#define IFF_BROADCAST 0x0002 /* valid broadcast address */

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2007, Haiku Inc. All Rights Reserved.
* Copyright 2002-2010, Haiku Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _SYS_SOCKIO_H
@ -38,7 +38,6 @@
#define SIOCGETRT 8928 /* get route information for destination */
#define SIOCGIFSTATS 8929 /* get interface stats */
#define SIOCGIFPARAM 8930 /* get interface parameter */
#define SIOCGIFTYPE 8931 /* get interface type */
#define SIOCSPACKETCAP 8932 /* Start capturing packets on an interface */

View File

@ -18,14 +18,9 @@
typedef struct net_buffer {
struct list_link link;
// TODO: we should think about moving the address fields into the buffer
// data itself via associated data or something like this. Or this
// structure as a whole, too...
struct sockaddr* source;
struct sockaddr* destination;
struct net_interface* interface;
int32 type;
struct net_interface_address* interface_address;
union {
struct {
uint16 start;
@ -33,6 +28,7 @@ typedef struct net_buffer {
} fragment;
uint32 sequence;
uint32 offset;
int32 type;
};
uint32 flags;
uint32 size;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2006-2008, Haiku, Inc. All Rights Reserved.
* Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef NET_DATALINK_H
@ -18,84 +18,98 @@
typedef struct net_datalink_protocol net_datalink_protocol;
typedef struct net_domain {
const char *name;
int family;
struct list interfaces;
struct net_protocol_module_info *module;
struct net_address_module_info *address_module;
typedef struct net_domain {
const char* name;
int family;
struct net_protocol_module_info* module;
struct net_address_module_info* address_module;
} net_domain;
struct net_interface {
struct list_link link;
struct net_domain *domain;
struct net_device *device;
struct net_datalink_protocol *first_protocol;
struct net_datalink_protocol_module_info *first_info;
typedef struct net_interface_address {
struct net_domain* domain;
struct net_interface* interface;
struct sockaddr* local;
struct sockaddr* destination;
struct sockaddr* mask;
} net_interface_address;
typedef struct net_interface {
struct net_device* device;
char name[IF_NAMESIZE];
struct sockaddr *address;
struct sockaddr *destination;
struct sockaddr *mask;
uint32 index;
uint32 flags;
uint8 type;
uint32 mtu;
uint32 metric;
};
} net_interface;
struct net_route {
struct sockaddr *destination;
struct sockaddr *mask;
struct sockaddr *gateway;
typedef struct net_route {
struct sockaddr* destination;
struct sockaddr* mask;
struct sockaddr* gateway;
uint32 flags;
uint32 mtu;
struct net_interface *interface;
};
struct net_interface_address* interface_address;
} net_route;
struct net_route_info {
typedef struct net_route_info {
struct list_link link;
struct net_route *route;
struct net_route* route;
struct sockaddr address;
};
} net_route_info;
struct net_datalink_module_info {
module_info info;
status_t (*control)(struct net_domain *domain, int32 option, void *value,
size_t *_length);
status_t (*send_data)(struct net_route *route, struct net_buffer *buffer);
status_t (*send_datagram)(struct net_protocol *protocol,
struct net_domain *domain, struct net_buffer *buffer);
status_t (*control)(net_domain* domain, int32 option, void* value,
size_t* _length);
status_t (*send_data)(net_route* route, net_buffer* buffer);
status_t (*send_datagram)(struct net_protocol* protocol,
net_domain* domain, net_buffer* buffer);
bool (*is_local_address)(struct net_domain *domain,
const struct sockaddr *address, net_interface **_interface,
uint32 *_matchedType);
bool (*is_local_link_address)(struct net_domain *domain, bool unconfigured,
const struct sockaddr *address, net_interface **_interface);
bool (*is_local_address)(net_domain* domain,
const struct sockaddr* address,
net_interface_address** _interfaceAddress,
uint32* _matchedType);
bool (*is_local_link_address)(net_domain* domain,
bool unconfigured, const struct sockaddr* address,
net_interface_address** _interfaceAddress);
net_interface *(*get_interface)(struct net_domain *domain, uint32 index);
net_interface *(*get_interface_with_address)(struct net_domain *domain,
const struct sockaddr *address);
net_interface* (*get_interface)(net_domain* domain, uint32 index);
net_interface* (*get_interface_with_address)(
const struct sockaddr* address);
void (*put_interface)(net_interface* interface);
net_interface_address* (*get_interface_address)(
const struct sockaddr* address);
bool (*get_next_interface_address)(net_interface* interface,
net_interface_address** _address);
void (*put_interface_address)(net_interface_address* address);
status_t (*join_multicast)(net_interface* interface,
net_domain* domain, const struct sockaddr* address);
status_t (*leave_multicast)(net_interface* interface,
net_domain* domain, const struct sockaddr* address);
// routes
status_t (*add_route)(struct net_domain *domain,
const struct net_route *route);
status_t (*remove_route)(struct net_domain *domain,
const struct net_route *route);
struct net_route *(*get_route)(struct net_domain *domain,
const struct sockaddr *address);
status_t (*get_buffer_route)(struct net_domain *domain,
struct net_buffer *buffer, struct net_route **_route);
void (*put_route)(struct net_domain *domain, struct net_route *route);
status_t (*add_route)(net_domain* domain, const net_route* route);
status_t (*remove_route)(net_domain* domain, const net_route* route);
net_route* (*get_route)(net_domain* domain,
const struct sockaddr* address);
status_t (*get_buffer_route)(net_domain* domain,
struct net_buffer* buffer, net_route** _route);
void (*put_route)(net_domain* domain, net_route* route);
status_t (*register_route_info)(struct net_domain *domain,
struct net_route_info *info);
status_t (*unregister_route_info)(struct net_domain *domain,
struct net_route_info *info);
status_t (*update_route_info)(struct net_domain *domain,
struct net_route_info *info);
status_t (*register_route_info)(net_domain* domain,
net_route_info* info);
status_t (*unregister_route_info)(net_domain* domain,
net_route_info* info);
status_t (*update_route_info)(net_domain* domain,
net_route_info* info);
};
#define NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS 0x01
@ -104,47 +118,58 @@ struct net_address_module_info {
module_info info;
uint32 flags;
status_t (*copy_address)(const sockaddr *from, sockaddr **to,
bool replaceWithZeros, const sockaddr *mask);
status_t (*copy_address)(const struct sockaddr* from,
struct sockaddr** to, bool replaceWithZeros,
const struct sockaddr* mask);
status_t (*mask_address)(const sockaddr *address, const sockaddr *mask,
sockaddr *result);
status_t (*mask_address)(const struct sockaddr* address,
const struct sockaddr* mask, struct sockaddr* result);
bool (*equal_addresses)(const sockaddr *a, const sockaddr *b);
bool (*equal_ports)(const sockaddr *a, const sockaddr *b);
bool (*equal_addresses_and_ports)(const sockaddr *a, const sockaddr *b);
bool (*equal_masked_addresses)(const sockaddr *a, const sockaddr *b,
const sockaddr *mask);
bool (*is_empty_address)(const sockaddr *address, bool checkPort);
bool (*is_same_family)(const sockaddr *address);
bool (*equal_addresses)(const struct sockaddr* a,
const struct sockaddr* b);
bool (*equal_ports)(const struct sockaddr* a,
const struct sockaddr* b);
bool (*equal_addresses_and_ports)(const struct sockaddr* a,
const struct sockaddr* b);
bool (*equal_masked_addresses)(const struct sockaddr* a,
const struct sockaddr* b, const struct sockaddr* mask);
bool (*is_empty_address)(const struct sockaddr* address,
bool checkPort);
bool (*is_same_family)(const struct sockaddr* address);
int32 (*first_mask_bit)(const sockaddr *mask);
int32 (*first_mask_bit)(const struct sockaddr* mask);
bool (*check_mask)(const sockaddr *address);
bool (*check_mask)(const struct sockaddr* address);
status_t (*print_address)(const sockaddr *address, char **buffer,
bool printPort);
status_t (*print_address_buffer)(const sockaddr *address, char *buffer,
size_t bufferSize, bool printPort);
status_t (*print_address)(const struct sockaddr* address,
char** buffer, bool printPort);
status_t (*print_address_buffer)(const struct sockaddr* address,
char* buffer, size_t bufferSize, bool printPort);
uint16 (*get_port)(const sockaddr *address);
status_t (*set_port)(sockaddr *address, uint16 port);
uint16 (*get_port)(const struct sockaddr* address);
status_t (*set_port)(struct sockaddr* address, uint16 port);
status_t (*set_to)(sockaddr *address, const sockaddr *from);
status_t (*set_to_empty_address)(sockaddr *address);
status_t (*set_to_defaults)(sockaddr *defaultMask,
sockaddr *defaultBroadcast, sockaddr *address,
sockaddr *netmask);
status_t (*set_to)(struct sockaddr* address,
const struct sockaddr* from);
status_t (*set_to_empty_address)(struct sockaddr* address);
status_t (*set_to_defaults)(struct sockaddr* defaultMask,
struct sockaddr* defaultBroadcast,
const struct sockaddr* address,
const struct sockaddr* netmask);
status_t (*update_to)(sockaddr *address, const sockaddr *from);
status_t (*update_to)(struct sockaddr* address,
const struct sockaddr* from);
uint32 (*hash_address_pair)(const sockaddr *ourAddress,
const sockaddr *peerAddress);
uint32 (*hash_address)(const struct sockaddr* address,
bool includePort);
uint32 (*hash_address_pair)(const struct sockaddr* ourAddress,
const struct sockaddr* peerAddress);
status_t (*checksum_address)(struct Checksum *checksum,
const sockaddr *address);
status_t (*checksum_address)(struct Checksum* checksum,
const struct sockaddr* address);
void (*get_loopback_address)(sockaddr *result);
void (*get_loopback_address)(struct sockaddr* result);
};
#endif // NET_DATALINK_H

View File

@ -1,5 +1,5 @@
/*
* Copyright 2006, Haiku, Inc. All Rights Reserved.
* Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef NET_DATALINK_PROTOCOL_H
@ -10,31 +10,37 @@
typedef struct net_datalink_protocol {
struct net_datalink_protocol *next;
struct net_datalink_protocol_module_info *module;
struct net_interface *interface;
struct net_datalink_protocol* next;
struct net_datalink_protocol_module_info* module;
struct net_interface* interface;
struct net_domain* domain;
} net_datalink_protocol;
struct net_datalink_protocol_module_info {
module_info info;
status_t (*init_protocol)(struct net_interface *interface,
net_datalink_protocol **_protocol);
status_t (*uninit_protocol)(net_datalink_protocol *self);
status_t (*init_protocol)(net_interface* interface, net_domain* domain,
net_datalink_protocol** _protocol);
status_t (*uninit_protocol)(net_datalink_protocol* self);
status_t (*send_data)(net_datalink_protocol *self,
net_buffer *buffer);
status_t (*send_data)(net_datalink_protocol* self, net_buffer* buffer);
status_t (*interface_up)(net_datalink_protocol *self);
void (*interface_down)(net_datalink_protocol *self);
status_t (*interface_up)(net_datalink_protocol* self);
void (*interface_down)(net_datalink_protocol* self);
status_t (*control)(net_datalink_protocol *self,
int32 op, void *argument, size_t length);
status_t (*change_address)(net_datalink_protocol* self,
net_interface_address* address, int32 option,
const struct sockaddr* oldAddress,
const struct sockaddr* newAddress);
status_t (*join_multicast)(net_datalink_protocol *self,
const sockaddr *address);
status_t (*leave_multicast)(net_datalink_protocol *self,
const sockaddr *address);
status_t (*control)(net_datalink_protocol* self, int32 option,
void* argument, size_t length);
status_t (*join_multicast)(net_datalink_protocol* self,
const struct sockaddr* address);
status_t (*leave_multicast)(net_datalink_protocol* self,
const struct sockaddr* address);
};
#endif // NET_DATALINK_PROTOCOL_H

View File

@ -1,7 +1,6 @@
SubDir HAIKU_TOP src add-ons kernel network datalink_protocols ;
SubInclude HAIKU_TOP src add-ons kernel network datalink_protocols arp ;
SubInclude HAIKU_TOP src add-ons kernel network datalink_protocols ethernet_frame ;
SubInclude HAIKU_TOP src add-ons kernel network datalink_protocols ipv4_datagram ;
SubInclude HAIKU_TOP src add-ons kernel network datalink_protocols ipv6_datagram ;
SubInclude HAIKU_TOP src add-ons kernel network datalink_protocols loopback_frame ;
HaikuSubInclude arp ;
HaikuSubInclude ethernet_frame ;
HaikuSubInclude ipv6_datagram ;
HaikuSubInclude loopback_frame ;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
* Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -7,6 +7,7 @@
* Hugo Santos, hugosantos@gmail.com
*/
//! Ethernet Address Resolution Protocol, see RFC 826.
@ -110,6 +111,7 @@ struct arp_entry {
struct arp_protocol : net_datalink_protocol {
sockaddr_dl hardware_address;
in_addr_t local_address;
};
@ -117,9 +119,10 @@ static const net_buffer* kDeletedBuffer = (net_buffer*)~0;
static void arp_timer(struct net_timer *timer, void *data);
net_buffer_module_info *gBufferModule;
static net_stack_module_info *sStackModule;
static hash_table *sCache;
net_buffer_module_info* gBufferModule;
static net_stack_module_info* sStackModule;
static net_datalink_module_info* sDatalinkModule;
static hash_table* sCache;
static mutex sCacheLock;
static bool sIgnoreReplies;
@ -283,7 +286,7 @@ void
arp_entry::MarkValid()
{
TRACE(("ARP entry %p Marked as VALID, have %li packets queued.\n", this,
queue.Size()));
queue.Count()));
flags = (flags & ~ARP_FLAG_REJECT) | ARP_FLAG_VALID;
@ -316,9 +319,6 @@ arp_entry::ScheduleRemoval()
static void
ipv4_to_ether_multicast(sockaddr_dl *destination, const sockaddr_in *source)
{
// TODO: this is ethernet specific, and doesn't belong here
// (should be moved to the ethernet_frame module)
// RFC 1112 - Host extensions for IP multicasting
//
// ``An IP host group address is mapped to an Ethernet multicast
@ -352,7 +352,7 @@ ipv4_to_ether_multicast(sockaddr_dl *destination, const sockaddr_in *source)
This function does not lock the cache - you have to do it yourself
before calling it.
*/
status_t
static status_t
arp_update_entry(in_addr_t protocolAddress, sockaddr_dl *hardwareAddress,
uint32 flags, arp_entry **_entry = NULL)
{
@ -405,22 +405,73 @@ arp_update_entry(in_addr_t protocolAddress, sockaddr_dl *hardwareAddress,
}
/*! Creates a permanent local entry for the interface belonging to this protocol.
You need to hold the cache lock when calling this function.
*/
static status_t
arp_update_local(arp_protocol *protocol)
static void
arp_remove_local_entry(arp_protocol* protocol, const sockaddr* local,
bool updateLocalAddress)
{
ASSERT_LOCKED_MUTEX(&sCacheLock);
in_addr_t inetAddress = ((sockaddr_in*)local)->sin_addr.s_addr;
net_interface *interface = protocol->interface;
MutexLocker locker(sCacheLock);
arp_entry* entry = arp_entry::Lookup(inetAddress);
if (entry != NULL) {
hash_remove(sCache, entry);
entry->flags |= ARP_FLAG_REMOVED;
}
if (updateLocalAddress && protocol->local_address == inetAddress) {
// find new local sender address
protocol->local_address = 0;
net_interface_address* address = NULL;
while (sDatalinkModule->get_next_interface_address(protocol->interface,
&address)) {
if (address->local == NULL || address->local->sa_family != AF_INET)
continue;
protocol->local_address
= ((sockaddr_in*)address->local)->sin_addr.s_addr;
}
}
locker.Unlock();
delete entry;
}
/*! Removes all entries belonging to the local interface of the \a procotol
given.
*/
static void
arp_remove_local(arp_protocol* protocol)
{
net_interface_address* address = NULL;
while (sDatalinkModule->get_next_interface_address(protocol->interface,
&address)) {
if (address->local == NULL || address->local->sa_family != AF_INET)
continue;
arp_remove_local_entry(protocol, address->local, false);
}
}
static status_t
arp_set_local_entry(arp_protocol* protocol, const sockaddr* local)
{
MutexLocker locker(sCacheLock);
net_interface* interface = protocol->interface;
in_addr_t inetAddress;
if (interface->address == NULL) {
if (local == NULL) {
// interface has not yet been set
inetAddress = INADDR_ANY;
} else
inetAddress = ((sockaddr_in *)interface->address)->sin_addr.s_addr;
inetAddress = ((sockaddr_in*)local)->sin_addr.s_addr;
if (protocol->local_address == 0)
protocol->local_address = inetAddress;
sockaddr_dl address;
address.sdl_len = sizeof(sockaddr_dl);
@ -435,7 +486,7 @@ arp_update_local(arp_protocol *protocol)
memcpy(&protocol->hardware_address, &address, sizeof(sockaddr_dl));
// cache the address in our protocol
arp_entry *entry;
arp_entry* entry;
status_t status = arp_update_entry(inetAddress, &address,
ARP_FLAG_LOCAL | ARP_FLAG_PERMANENT, &entry);
if (status == B_OK)
@ -445,6 +496,37 @@ arp_update_local(arp_protocol *protocol)
}
/*! Creates permanent local entries for all addresses of the interface belonging
to this protocol.
Returns an error if no entry could be added.
*/
static status_t
arp_update_local(arp_protocol* protocol)
{
protocol->local_address = 0;
// TODO: test if this actually works - maybe we should use
// INADDR_BROADCAST instead
ssize_t count = 0;
net_interface_address* address = NULL;
while (sDatalinkModule->get_next_interface_address(protocol->interface,
&address)) {
if (address->local == NULL || address->local->sa_family != AF_INET)
continue;
if (arp_set_local_entry(protocol, address->local) == B_OK) {
count++;
}
}
if (count == 0)
return arp_set_local_entry(protocol, NULL);
return B_OK;
}
static status_t
handle_arp_request(net_buffer *buffer, arp_header &header)
{
@ -518,15 +600,19 @@ arp_receive(void *cookie, net_device *device, net_buffer *buffer)
#ifdef TRACE_ARP
dprintf(" hw sender: %02x:%02x:%02x:%02x:%02x:%02x\n",
header.hardware_sender[0], header.hardware_sender[1], header.hardware_sender[2],
header.hardware_sender[3], header.hardware_sender[4], header.hardware_sender[5]);
dprintf(" proto sender: %ld.%ld.%ld.%ld\n", header.protocol_sender >> 24, (header.protocol_sender >> 16) & 0xff,
(header.protocol_sender >> 8) & 0xff, header.protocol_sender & 0xff);
header.hardware_sender[0], header.hardware_sender[1],
header.hardware_sender[2], header.hardware_sender[3],
header.hardware_sender[4], header.hardware_sender[5]);
unsigned int addr = ntohl(header.protocol_sender);
dprintf(" proto sender: %d.%d.%d.%d\n", addr >> 24, (addr >> 16) & 0xff,
(addr >> 8) & 0xff, addr & 0xff);
dprintf(" hw target: %02x:%02x:%02x:%02x:%02x:%02x\n",
header.hardware_target[0], header.hardware_target[1], header.hardware_target[2],
header.hardware_target[3], header.hardware_target[4], header.hardware_target[5]);
dprintf(" proto target: %ld.%ld.%ld.%ld\n", header.protocol_target >> 24, (header.protocol_target >> 16) & 0xff,
(header.protocol_target >> 8) & 0xff, header.protocol_target & 0xff);
header.hardware_target[0], header.hardware_target[1],
header.hardware_target[2], header.hardware_target[3],
header.hardware_target[4], header.hardware_target[5]);
addr = ntohl(header.protocol_target);
dprintf(" proto target: %d.%d.%d.%d\n", addr >> 24, (addr >> 16) & 0xff,
(addr >> 8) & 0xff, addr & 0xff);
#endif
if (ntohs(header.protocol_type) != ETHER_TYPE_IP
@ -588,21 +674,23 @@ arp_timer(struct net_timer *timer, void *data)
case ARP_STATE_REMOVE_FAILED:
case ARP_STATE_STALE:
{
// the entry has aged so much that we're going to remove it
TRACE((" remove ARP entry %p!\n", entry));
mutex_lock(&sCacheLock);
MutexLocker locker(sCacheLock);
if ((entry->flags & ARP_FLAG_REMOVED) != 0) {
// The entry has already been removed, and is about to be deleted
mutex_unlock(&sCacheLock);
// The entry has already been removed, and is about to be
// deleted
break;
}
hash_remove(sCache, entry);
mutex_unlock(&sCacheLock);
locker.Unlock();
delete entry;
break;
}
default:
{
@ -649,8 +737,7 @@ arp_timer(struct net_timer *timer, void *data)
You need to have the sCacheLock held when calling this function.
*/
static status_t
arp_start_resolve(net_datalink_protocol *protocol, in_addr_t address,
arp_entry **_entry)
arp_start_resolve(arp_protocol* protocol, in_addr_t address, arp_entry** _entry)
{
ASSERT_LOCKED_MUTEX(&sCacheLock);
@ -686,16 +773,8 @@ arp_start_resolve(net_datalink_protocol *protocol, in_addr_t address,
header.opcode = htons(ARP_OPCODE_REQUEST);
memcpy(header.hardware_sender, device->address.data, ETHER_ADDRESS_LENGTH);
if (protocol->interface->address != NULL) {
header.protocol_sender
= ((sockaddr_in *)protocol->interface->address)->sin_addr.s_addr;
} else {
header.protocol_sender = 0;
// TODO: test if this actually works - maybe we should use
// INADDR_BROADCAST instead
}
memset(header.hardware_target, 0, ETHER_ADDRESS_LENGTH);
header.protocol_sender = protocol->local_address;
header.protocol_target = address;
// prepare source and target addresses
@ -867,21 +946,25 @@ arp_uninit()
status_t
arp_init_protocol(struct net_interface *interface,
net_datalink_protocol **_protocol)
arp_init_protocol(net_interface* interface, net_domain* domain,
net_datalink_protocol** _protocol)
{
// We currently only support a single family and type!
if (interface->domain->family != AF_INET
|| interface->device->type != IFT_ETHER)
if (interface->device->type != IFT_ETHER
|| domain->family != AF_INET)
return B_BAD_TYPE;
status_t status = sStackModule->register_device_handler(interface->device,
ETHER_FRAME_TYPE | ETHER_TYPE_ARP, &arp_receive, NULL);
if (status < B_OK)
if (status != B_OK)
return status;
arp_protocol *protocol = new (std::nothrow) arp_protocol;
status = sStackModule->register_domain_device_handler(
interface->device, ETHER_FRAME_TYPE | ETHER_TYPE_IP, domain);
if (status != B_OK)
return status;
arp_protocol* protocol = new(std::nothrow) arp_protocol;
if (protocol == NULL)
return B_NO_MEMORY;
@ -896,6 +979,8 @@ arp_uninit_protocol(net_datalink_protocol *protocol)
{
sStackModule->unregister_device_handler(protocol->interface->device,
ETHER_FRAME_TYPE | ETHER_TYPE_ARP);
sStackModule->unregister_device_handler(protocol->interface->device,
ETHER_FRAME_TYPE | ETHER_TYPE_IP);
delete protocol;
return B_OK;
@ -914,7 +999,7 @@ arp_send_data(net_datalink_protocol *_protocol, net_buffer *buffer)
memcpy(buffer->source, &protocol->hardware_address,
protocol->hardware_address.sdl_len);
if (buffer->flags & MSG_MCAST) {
if ((buffer->flags & MSG_MCAST) != 0) {
sockaddr_dl multicastDestination;
ipv4_to_ether_multicast(&multicastDestination,
(sockaddr_in *)buffer->destination);
@ -926,14 +1011,16 @@ arp_send_data(net_datalink_protocol *_protocol, net_buffer *buffer)
((struct sockaddr_in *)buffer->destination)->sin_addr.s_addr);
if (entry == NULL) {
status_t status = arp_start_resolve(protocol,
((struct sockaddr_in *)buffer->destination)->sin_addr.s_addr, &entry);
if (status < B_OK)
((struct sockaddr_in*)buffer->destination)->sin_addr.s_addr,
&entry);
if (status != B_OK)
return status;
}
if (entry->flags & ARP_FLAG_REJECT)
if ((entry->flags & ARP_FLAG_REJECT) != 0)
return EHOSTUNREACH;
else if (!(entry->flags & ARP_FLAG_VALID)) {
if ((entry->flags & ARP_FLAG_VALID) == 0) {
// entry is still being resolved.
TRACE(("ARP Queuing packet %p, entry still being resolved.\n",
buffer));
@ -951,20 +1038,17 @@ arp_send_data(net_datalink_protocol *_protocol, net_buffer *buffer)
status_t
arp_up(net_datalink_protocol *_protocol)
arp_up(net_datalink_protocol* _protocol)
{
arp_protocol *protocol = (arp_protocol *)_protocol;
arp_protocol* protocol = (arp_protocol*)_protocol;
status_t status = protocol->next->module->interface_up(protocol->next);
if (status < B_OK)
if (status != B_OK)
return status;
// cache this device's address for later use
mutex_lock(&sCacheLock);
status = arp_update_local(protocol);
mutex_unlock(&sCacheLock);
if (status < B_OK) {
if (status != B_OK) {
protocol->next->module->interface_down(protocol->next);
return status;
}
@ -976,70 +1060,55 @@ arp_up(net_datalink_protocol *_protocol)
void
arp_down(net_datalink_protocol *protocol)
{
// remove local ARP entry from the cache
if (protocol->interface->address != NULL) {
MutexLocker locker(sCacheLock);
arp_entry *entry = arp_entry::Lookup(
((sockaddr_in *)protocol->interface->address)->sin_addr.s_addr);
if (entry != NULL) {
hash_remove(sCache, entry);
entry->flags |= ARP_FLAG_REMOVED;
locker.Unlock();
delete entry;
}
}
// remove local ARP entries from the cache
arp_remove_local((arp_protocol*)protocol);
protocol->next->module->interface_down(protocol->next);
}
status_t
arp_change_address(net_datalink_protocol* _protocol,
net_interface_address* address, int32 option,
const struct sockaddr* oldAddress, const struct sockaddr* newAddress)
{
arp_protocol* protocol = (arp_protocol*)_protocol;
switch (option) {
case SIOCSIFADDR:
case SIOCAIFADDR:
case SIOCDIFADDR:
// Those are the options we handle
if ((protocol->interface->flags & IFF_UP) != 0) {
// Update ARP entry for the local address
if (newAddress != NULL && newAddress->sa_family == AF_INET) {
status_t status = arp_set_local_entry(protocol, newAddress);
if (status != B_OK)
return status;
}
if (oldAddress != NULL && oldAddress->sa_family == AF_INET)
arp_remove_local_entry(protocol, oldAddress, true);
}
break;
default:
break;
}
return protocol->next->module->change_address(protocol->next, address,
option, oldAddress, newAddress);
}
status_t
arp_control(net_datalink_protocol *_protocol, int32 op, void *argument,
size_t length)
{
arp_protocol *protocol = (arp_protocol *)_protocol;
if (op == SIOCSIFADDR && (protocol->interface->flags & IFF_UP) != 0) {
// The interface may get a new address, so we need to update our
// local entries.
in_addr_t oldAddress = 0;
if (protocol->interface->address != NULL) {
oldAddress
= ((sockaddr_in *)protocol->interface->address)->sin_addr.s_addr;
}
status_t status = protocol->next->module->control(protocol->next,
SIOCSIFADDR, argument, length);
if (status < B_OK)
return status;
MutexLocker locker(sCacheLock);
arp_update_local(protocol);
if (oldAddress == ((sockaddr_in *)
protocol->interface->address)->sin_addr.s_addr)
return B_OK;
// remove previous address from cache
arp_entry *entry = arp_entry::Lookup(oldAddress);
if (entry != NULL) {
hash_remove(sCache, entry);
entry->flags |= ARP_FLAG_REMOVED;
locker.Unlock();
delete entry;
}
return B_OK;
}
return protocol->next->module->control(protocol->next,
op, argument, length);
arp_protocol* protocol = (arp_protocol*)_protocol;
return protocol->next->module->control(protocol->next, op, argument,
length);
}
@ -1097,6 +1166,7 @@ static net_datalink_protocol_module_info sARPModule = {
arp_send_data,
arp_up,
arp_down,
arp_change_address,
arp_control,
arp_join_multicast,
arp_leave_multicast,
@ -1104,12 +1174,13 @@ static net_datalink_protocol_module_info sARPModule = {
module_dependency module_dependencies[] = {
{NET_STACK_MODULE_NAME, (module_info **)&sStackModule},
{NET_BUFFER_MODULE_NAME, (module_info **)&gBufferModule},
{NET_STACK_MODULE_NAME, (module_info**)&sStackModule},
{NET_DATALINK_MODULE_NAME, (module_info**)&sDatalinkModule},
{NET_BUFFER_MODULE_NAME, (module_info**)&gBufferModule},
{}
};
module_info *modules[] = {
(module_info *)&sARPModule,
module_info* modules[] = {
(module_info*)&sARPModule,
NULL
};

View File

@ -1,5 +1,5 @@
/*
* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
* Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -30,23 +30,23 @@ struct ethernet_frame_protocol : net_datalink_protocol {
static const uint8 kBroadcastAddress[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
struct net_buffer_module_info *gBufferModule;
struct net_buffer_module_info* gBufferModule;
int32
ethernet_deframe(net_device *device, net_buffer *buffer)
ethernet_deframe(net_device* device, net_buffer* buffer)
{
//dprintf("asked to deframe buffer for device %s\n", device->name);
NetBufferHeaderRemover<ether_header> bufferHeader(buffer);
if (bufferHeader.Status() < B_OK)
if (bufferHeader.Status() != B_OK)
return bufferHeader.Status();
ether_header &header = bufferHeader.Data();
ether_header& header = bufferHeader.Data();
uint16 type = ntohs(header.type);
struct sockaddr_dl &source = *(struct sockaddr_dl *)buffer->source;
struct sockaddr_dl &destination = *(struct sockaddr_dl *)buffer->destination;
struct sockaddr_dl& source = *(struct sockaddr_dl*)buffer->source;
struct sockaddr_dl& destination = *(struct sockaddr_dl*)buffer->destination;
source.sdl_len = sizeof(sockaddr_dl);
source.sdl_family = AF_LINK;
@ -68,7 +68,7 @@ ethernet_deframe(net_device *device, net_buffer *buffer)
// mark buffer if it was a broadcast/multicast packet
if (!memcmp(header.destination, kBroadcastAddress, ETHER_ADDRESS_LENGTH))
buffer->flags |= MSG_BCAST;
else if (header.destination[0] & 0x01)
else if ((header.destination[0] & 0x01) != 0)
buffer->flags |= MSG_MCAST;
return ETHER_FRAME_TYPE | type;
@ -79,20 +79,24 @@ ethernet_deframe(net_device *device, net_buffer *buffer)
status_t
ethernet_frame_init(struct net_interface *interface, net_datalink_protocol **_protocol)
ethernet_frame_init(struct net_interface* interface, net_domain* domain,
net_datalink_protocol** _protocol)
{
net_stack_module_info *stack;
status_t status = get_module(NET_STACK_MODULE_NAME, (module_info **)&stack);
net_stack_module_info* stack;
status_t status = get_module(NET_STACK_MODULE_NAME, (module_info**)&stack);
if (status < B_OK)
return status;
status = stack->register_device_deframer(interface->device, &ethernet_deframe);
status = stack->register_device_deframer(interface->device,
&ethernet_deframe);
put_module(NET_STACK_MODULE_NAME);
if (status < B_OK)
if (status != B_OK)
return status;
ethernet_frame_protocol *protocol = new (std::nothrow) ethernet_frame_protocol;
ethernet_frame_protocol* protocol
= new(std::nothrow) ethernet_frame_protocol;
if (protocol == NULL)
return B_NO_MEMORY;
@ -102,10 +106,10 @@ ethernet_frame_init(struct net_interface *interface, net_datalink_protocol **_pr
status_t
ethernet_frame_uninit(net_datalink_protocol *protocol)
ethernet_frame_uninit(net_datalink_protocol* protocol)
{
net_stack_module_info *stack;
if (get_module(NET_STACK_MODULE_NAME, (module_info **)&stack) == B_OK) {
net_stack_module_info* stack;
if (get_module(NET_STACK_MODULE_NAME, (module_info**)&stack) == B_OK) {
stack->unregister_device_deframer(protocol->interface->device);
put_module(NET_STACK_MODULE_NAME);
}
@ -116,24 +120,23 @@ ethernet_frame_uninit(net_datalink_protocol *protocol)
status_t
ethernet_frame_send_data(net_datalink_protocol *protocol,
net_buffer *buffer)
ethernet_frame_send_data(net_datalink_protocol* protocol, net_buffer* buffer)
{
struct sockaddr_dl &source = *(struct sockaddr_dl *)buffer->source;
struct sockaddr_dl &destination = *(struct sockaddr_dl *)buffer->destination;
struct sockaddr_dl& source = *(struct sockaddr_dl*)buffer->source;
struct sockaddr_dl& destination = *(struct sockaddr_dl*)buffer->destination;
if (source.sdl_family != AF_LINK || source.sdl_type != IFT_ETHER)
return B_ERROR;
NetBufferPrepend<ether_header> bufferHeader(buffer);
if (bufferHeader.Status() < B_OK)
if (bufferHeader.Status() != B_OK)
return bufferHeader.Status();
ether_header &header = bufferHeader.Data();
header.type = htons(source.sdl_e_type);
memcpy(header.source, source.sdl_data, ETHER_ADDRESS_LENGTH);
if (buffer->flags & MSG_BCAST)
if ((buffer->flags & MSG_BCAST) != 0)
memcpy(header.destination, kBroadcastAddress, ETHER_ADDRESS_LENGTH);
else
memcpy(header.destination, destination.sdl_data, ETHER_ADDRESS_LENGTH);
@ -146,40 +149,49 @@ ethernet_frame_send_data(net_datalink_protocol *protocol,
status_t
ethernet_frame_up(net_datalink_protocol *_protocol)
ethernet_frame_up(net_datalink_protocol* protocol)
{
ethernet_frame_protocol *protocol = (ethernet_frame_protocol *)_protocol;
return protocol->next->module->interface_up(protocol->next);
}
void
ethernet_frame_down(net_datalink_protocol *protocol)
ethernet_frame_down(net_datalink_protocol* protocol)
{
return protocol->next->module->interface_down(protocol->next);
}
status_t
ethernet_frame_control(net_datalink_protocol *protocol,
int32 op, void *argument, size_t length)
ethernet_frame_change_address(net_datalink_protocol* protocol,
net_interface_address* address, int32 option,
const struct sockaddr* oldAddress, const struct sockaddr* newAddress)
{
return protocol->next->module->control(protocol->next, op, argument, length);
return protocol->next->module->change_address(protocol->next, address,
option, oldAddress, newAddress);
}
status_t
ethernet_frame_control(net_datalink_protocol* protocol, int32 option,
void* argument, size_t length)
{
return protocol->next->module->control(protocol->next, option, argument,
length);
}
static status_t
ethernet_frame_join_multicast(net_datalink_protocol *protocol,
const sockaddr *address)
ethernet_frame_join_multicast(net_datalink_protocol* protocol,
const sockaddr* address)
{
return protocol->next->module->join_multicast(protocol->next, address);
}
static status_t
ethernet_frame_leave_multicast(net_datalink_protocol *protocol,
const sockaddr *address)
ethernet_frame_leave_multicast(net_datalink_protocol* protocol,
const sockaddr* address)
{
return protocol->next->module->leave_multicast(protocol->next, address);
}
@ -190,7 +202,8 @@ ethernet_frame_std_ops(int32 op, ...)
{
switch (op) {
case B_MODULE_INIT:
return get_module(NET_BUFFER_MODULE_NAME, (module_info **)&gBufferModule);
return get_module(NET_BUFFER_MODULE_NAME,
(module_info**)&gBufferModule);
case B_MODULE_UNINIT:
put_module(NET_BUFFER_MODULE_NAME);
return B_OK;
@ -212,12 +225,13 @@ static net_datalink_protocol_module_info sEthernetFrameModule = {
ethernet_frame_send_data,
ethernet_frame_up,
ethernet_frame_down,
ethernet_frame_change_address,
ethernet_frame_control,
ethernet_frame_join_multicast,
ethernet_frame_leave_multicast,
};
module_info *modules[] = {
(module_info *)&sEthernetFrameModule,
module_info* modules[] = {
(module_info*)&sEthernetFrameModule,
NULL
};

View File

@ -1,25 +0,0 @@
SubDir HAIKU_TOP src add-ons kernel network datalink_protocols ipv4_datagram ;
SetSubDirSupportedPlatformsBeOSCompatible ;
if $(TARGET_PLATFORM) != haiku {
UseHeaders [ FStandardOSHeaders ] : true ;
# Needed for <support/Errors.h> and maybe other stuff.
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 kernel net ;
KernelAddon ipv4_datagram :
ipv4_datagram.cpp
;
# Installation
HaikuInstall install-networking : /boot/home/config/add-ons/kernel/haiku_network/datalink_protocols
: ipv4_datagram ;
Package haiku-networkingkit-cvs :
haiku :
boot home config add-ons kernel haiku_network datalink_protocols ;

View File

@ -1,150 +0,0 @@
/*
* Copyright 2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Hugo Santos, hugosantos@gmail.com
*/
#include <net_datalink.h>
#include <net_datalink_protocol.h>
#include <net_device.h>
#include <net_stack.h>
#include <KernelExport.h>
#include <net/ethernet.h> // for ETHER_TYPE_IP
#include <net/if_types.h>
#include <new>
static net_stack_module_info *sStackModule;
// TODO ETHER_FRAME_TYPE doesn't belong there, we need Layer 2
// independence.
static const int32 kIPv4FrameType = ETHER_FRAME_TYPE | ETHER_TYPE_IP;
static status_t
ipv4_datalink_init(net_interface *interface, net_datalink_protocol **_protocol)
{
dprintf("ipv4_datalink_init(%s)\n", interface->name);
if (interface->domain->family != AF_INET)
return B_BAD_TYPE;
// While the loopback doesn't get a header to mux protocols,
// we let it do all of the registration work.
if (interface->device->type == IFT_LOOP)
return B_BAD_TYPE;
net_datalink_protocol *protocol = new (std::nothrow) net_datalink_protocol;
if (protocol == NULL)
return B_NO_MEMORY;
// We register ETHER_TYPE_IP as most datalink protocols use it
// to identify IP datagrams. In the future we may limit this.
status_t status = sStackModule->register_domain_device_handler(
interface->device, kIPv4FrameType, interface->domain);
if (status < B_OK)
delete protocol;
else
*_protocol = protocol;
return status;
}
static status_t
ipv4_datalink_uninit(net_datalink_protocol *protocol)
{
sStackModule->unregister_device_handler(protocol->interface->device,
kIPv4FrameType);
delete protocol;
return B_OK;
}
static status_t
ipv4_datalink_send_data(net_datalink_protocol *protocol, net_buffer *buffer)
{
return protocol->next->module->send_data(protocol->next, buffer);
}
static status_t
ipv4_datalink_up(net_datalink_protocol *protocol)
{
return protocol->next->module->interface_up(protocol->next);
}
static void
ipv4_datalink_down(net_datalink_protocol *protocol)
{
// TODO Clear routes here instead?
protocol->next->module->interface_down(protocol->next);
}
static status_t
ipv4_datalink_control(net_datalink_protocol *protocol, int32 op,
void *argument, size_t length)
{
return protocol->next->module->control(protocol->next, op, argument, length);
}
static status_t
ipv4_datalink_join_multicast(net_datalink_protocol *protocol,
const sockaddr *address)
{
return protocol->next->module->join_multicast(protocol->next, address);
}
static status_t
ipv4_datalink_leave_multicast(net_datalink_protocol *protocol,
const sockaddr *address)
{
return protocol->next->module->leave_multicast(protocol->next, address);
}
static status_t
ipv4_datalink_std_ops(int32 op, ...)
{
switch (op) {
case B_MODULE_INIT:
return get_module(NET_STACK_MODULE_NAME, (module_info **)&sStackModule);
case B_MODULE_UNINIT:
return put_module(NET_STACK_MODULE_NAME);
}
return B_ERROR;
}
net_datalink_protocol_module_info gIPv4DataLinkModule = {
{
"network/datalink_protocols/ipv4_datagram/v1",
0,
ipv4_datalink_std_ops
},
ipv4_datalink_init,
ipv4_datalink_uninit,
ipv4_datalink_send_data,
ipv4_datalink_up,
ipv4_datalink_down,
ipv4_datalink_control,
ipv4_datalink_join_multicast,
ipv4_datalink_leave_multicast,
};
module_info *modules[] = {
(module_info *)&gIPv4DataLinkModule,
NULL
};

View File

@ -1040,6 +1040,66 @@ ipv6_datalink_down(net_datalink_protocol* protocol)
}
status_t
ipv6_datalink_change_address(net_datalink_protocol* protocol,
net_interface_address* address, int32 option,
const struct sockaddr* oldAddress, const struct sockaddr* newAddress)
{
#if 0
switch (option) {
case SIOCSIFADDR:
case SIOCAIFADDR:
case SIOCDIFADDR:
// Those are the options we handle
if ((protocol->interface->flags & IFF_UP) != 0) {
// Update ARP entry for the local address
if (newAddress != NULL && newAddress->sa_family == AF_INET6) {
status_t status = arp_set_local_entry(protocol, newAddress);
if (status != B_OK)
return status;
// add IPv6 remove multicast route (ff00::/8)
sockaddr_in6 address;
memset(&address, 0, sizeof(sockaddr_in6));
address.sin6_family = AF_INET6;
address.sin6_len = sizeof(sockaddr_in6);
address.sin6_addr.s6_addr[0] = 0xff;
route.destination = (sockaddr*)&address;
route.mask = (sockaddr*)&address;
route.flags = 0;
add_route(interface->domain, &route);
}
if (oldAddress != NULL && oldAddress->sa_family == AF_INET6) {
arp_remove_local_entry(protocol, oldAddress, true);
// remove IPv6 remove multicast route (ff00::/8)
sockaddr_in6 address;
memset(&address, 0, sizeof(sockaddr_in6));
address.sin6_family = AF_INET6;
address.sin6_len = sizeof(sockaddr_in6);
address.sin6_addr.s6_addr[0] = 0xff;
route.destination = (sockaddr*)&address;
route.mask = (sockaddr*)&address;
route.flags = 0;
remove_route(interface->domain, &route);
}
}
break;
default:
break;
}
#endif
return protocol->next->module->change_address(protocol->next, address,
option, oldAddress, newAddress);
}
static status_t
ipv6_datalink_control(net_datalink_protocol* protocol, int32 op, void* argument,
size_t length)
@ -1105,6 +1165,7 @@ net_datalink_protocol_module_info gIPv6DataLinkModule = {
ipv6_datalink_send_data,
ipv6_datalink_up,
ipv6_datalink_down,
ipv6_datalink_change_address,
ipv6_datalink_control,
ipv6_datalink_join_multicast,
ipv6_datalink_leave_multicast,

View File

@ -1,5 +1,5 @@
/*
* Copyright 2006, Haiku, Inc. All Rights Reserved.
* Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -28,11 +28,11 @@ struct loopback_frame_protocol : net_datalink_protocol {
};
struct net_buffer_module_info *gBufferModule;
struct net_buffer_module_info* gBufferModule;
int32
loopback_deframe(net_device *device, net_buffer *buffer)
loopback_deframe(net_device* device, net_buffer* buffer)
{
// there is not that much to do...
return 0;
@ -43,32 +43,34 @@ loopback_deframe(net_device *device, net_buffer *buffer)
status_t
loopback_frame_init(struct net_interface *interface, net_datalink_protocol **_protocol)
loopback_frame_init(struct net_interface*interface, net_domain* domain,
net_datalink_protocol** _protocol)
{
// We currently only support a single family and type!
if (interface->device->type != IFT_LOOP)
return B_BAD_TYPE;
loopback_frame_protocol *protocol;
loopback_frame_protocol* protocol;
net_stack_module_info *stack;
status_t status = get_module(NET_STACK_MODULE_NAME, (module_info **)&stack);
if (status < B_OK)
net_stack_module_info* stack;
status_t status = get_module(NET_STACK_MODULE_NAME, (module_info**)&stack);
if (status != B_OK)
return status;
status = stack->register_device_deframer(interface->device, &loopback_deframe);
if (status < B_OK)
status = stack->register_device_deframer(interface->device,
&loopback_deframe);
if (status != B_OK)
goto err1;
// We also register the domain as a handler for our packets
status = stack->register_domain_device_handler(interface->device,
0, interface->domain);
if (status < B_OK)
status = stack->register_domain_device_handler(interface->device, 0,
domain);
if (status != B_OK)
goto err2;
put_module(NET_STACK_MODULE_NAME);
protocol = new (std::nothrow) loopback_frame_protocol;
protocol = new(std::nothrow) loopback_frame_protocol;
if (protocol == NULL)
return B_NO_MEMORY;
@ -84,10 +86,10 @@ err1:
status_t
loopback_frame_uninit(net_datalink_protocol *protocol)
loopback_frame_uninit(net_datalink_protocol* protocol)
{
net_stack_module_info *stack;
if (get_module(NET_STACK_MODULE_NAME, (module_info **)&stack) == B_OK) {
net_stack_module_info* stack;
if (get_module(NET_STACK_MODULE_NAME, (module_info**)&stack) == B_OK) {
stack->unregister_device_deframer(protocol->interface->device);
stack->unregister_device_handler(protocol->interface->device, 0);
put_module(NET_STACK_MODULE_NAME);
@ -99,48 +101,56 @@ loopback_frame_uninit(net_datalink_protocol *protocol)
status_t
loopback_frame_send_data(net_datalink_protocol *protocol,
net_buffer *buffer)
loopback_frame_send_data(net_datalink_protocol* protocol, net_buffer* buffer)
{
return protocol->next->module->send_data(protocol->next, buffer);
}
status_t
loopback_frame_up(net_datalink_protocol *_protocol)
loopback_frame_up(net_datalink_protocol* protocol)
{
loopback_frame_protocol *protocol = (loopback_frame_protocol *)_protocol;
return protocol->next->module->interface_up(protocol->next);
}
void
loopback_frame_down(net_datalink_protocol *protocol)
loopback_frame_down(net_datalink_protocol* protocol)
{
return protocol->next->module->interface_down(protocol->next);
}
status_t
loopback_frame_control(net_datalink_protocol *protocol,
int32 op, void *argument, size_t length)
loopback_frame_change_address(net_datalink_protocol* protocol,
net_interface_address* address, int32 option,
const struct sockaddr* oldAddress, const struct sockaddr* newAddress)
{
return protocol->next->module->control(protocol->next, op, argument, length);
return protocol->next->module->change_address(protocol->next, address,
option, oldAddress, newAddress);
}
status_t
loopback_frame_control(net_datalink_protocol* protocol, int32 option,
void* argument, size_t length)
{
return protocol->next->module->control(protocol->next, option, argument,
length);
}
static status_t
loopback_frame_join_multicast(net_datalink_protocol *protocol,
const sockaddr *address)
loopback_frame_join_multicast(net_datalink_protocol* protocol,
const sockaddr* address)
{
return protocol->next->module->join_multicast(protocol->next, address);
}
static status_t
loopback_frame_leave_multicast(net_datalink_protocol *protocol,
const sockaddr *address)
loopback_frame_leave_multicast(net_datalink_protocol* protocol,
const sockaddr* address)
{
return protocol->next->module->leave_multicast(protocol->next, address);
}
@ -151,7 +161,8 @@ loopback_frame_std_ops(int32 op, ...)
{
switch (op) {
case B_MODULE_INIT:
return get_module(NET_BUFFER_MODULE_NAME, (module_info **)&gBufferModule);
return get_module(NET_BUFFER_MODULE_NAME,
(module_info**)&gBufferModule);
case B_MODULE_UNINIT:
put_module(NET_BUFFER_MODULE_NAME);
return B_OK;
@ -173,12 +184,13 @@ static net_datalink_protocol_module_info sLoopbackFrameModule = {
loopback_frame_send_data,
loopback_frame_up,
loopback_frame_down,
loopback_frame_change_address,
loopback_frame_control,
loopback_frame_join_multicast,
loopback_frame_leave_multicast,
};
module_info *modules[] = {
(module_info *)&sLoopbackFrameModule,
module_info* modules[] = {
(module_info*)&sLoopbackFrameModule,
NULL
};

View File

@ -86,8 +86,8 @@ static net_domain*
get_domain(struct net_buffer* buffer)
{
net_domain* domain;
if (buffer->interface != NULL)
domain = buffer->interface->domain;
if (buffer->interface_address != NULL)
domain = buffer->interface_address->domain;
else
domain = sStackModule->get_domain(buffer->source->sa_family);
@ -288,13 +288,8 @@ icmp_receive_data(net_buffer* buffer)
{
TRACE("ICMP received some data, buffer length %lu\n", buffer->size);
net_domain* domain;
if (buffer->interface != NULL)
domain = buffer->interface->domain;
else
domain = sStackModule->get_domain(buffer->source->sa_family);
if (domain == NULL || domain->module == NULL)
net_domain* domain = get_domain(buffer);
if (domain == NULL)
return B_ERROR;
NetBufferHeaderReader<icmp_header> bufferHeader(buffer);
@ -322,11 +317,11 @@ icmp_receive_data(net_buffer* buffer)
if (domain == NULL)
break;
if (buffer->interface != NULL) {
if (buffer->interface_address != NULL) {
// We only reply to echo requests of our local interface; we
// don't reply to broadcast requests
if (!domain->address_module->equal_addresses(
buffer->interface->address, buffer->destination))
buffer->interface_address->local, buffer->destination))
break;
}

View File

@ -141,7 +141,7 @@ struct ipv4_protocol : net_protocol {
uint8 time_to_live;
uint8 multicast_time_to_live;
uint32 flags;
struct sockaddr* interface_address; // for IP_MULTICAST_IF
struct sockaddr* multicast_address; // for IP_MULTICAST_IF
IPv4MulticastFilter multicast_filter;
};
@ -673,12 +673,14 @@ deliver_multicast(net_protocol_module_info* module, net_buffer* buffer,
if (module->deliver_data == NULL)
return false;
// TODO: fix multicast!
return false;
MutexLocker _(sMulticastGroupsLock);
sockaddr_in* multicastAddr = (sockaddr_in*)buffer->destination;
MulticastState::ValueIterator it = sMulticastState->Lookup(std::make_pair(
&multicastAddr->sin_addr, buffer->interface->index));
&multicastAddr->sin_addr, buffer->interface_address->interface->index));
size_t count = 0;
@ -687,7 +689,7 @@ deliver_multicast(net_protocol_module_info* module, net_buffer* buffer,
ipv4_protocol* ipProtocol = state->Parent()->Socket();
if (deliverToRaw && (ipProtocol->raw == NULL
|| ipProtocol->socket->protocol != buffer->protocol))
|| ipProtocol->socket->protocol != buffer->protocol))
continue;
if (state->FilterAccepts(buffer)) {
@ -819,11 +821,8 @@ IPv4Multicast::JoinGroup(IPv4GroupInterface* state)
MutexLocker _(sMulticastGroupsLock);
sockaddr_in groupAddr;
net_interface* interface = state->Interface();
status_t status = interface->first_info->join_multicast(
interface->first_protocol,
fill_sockaddr_in(&groupAddr, state->Address().s_addr));
status_t status = sDatalinkModule->join_multicast(state->Interface(),
sDomain, fill_sockaddr_in(&groupAddr, state->Address().s_addr));
if (status != B_OK)
return status;
@ -840,10 +839,7 @@ IPv4Multicast::LeaveGroup(IPv4GroupInterface* state)
sMulticastState->Remove(state);
sockaddr_in groupAddr;
net_interface* interface = state->Interface();
return interface->first_protocol->module->join_multicast(
interface->first_protocol,
return sDatalinkModule->leave_multicast(state->Interface(), sDomain,
fill_sockaddr_in(&groupAddr, state->Address().s_addr));
}
@ -876,7 +872,7 @@ ipv4_delta_membership(ipv4_protocol* protocol, int option,
net_interface* interface, const in_addr* groupAddr,
const in_addr* sourceAddr)
{
IPv4MulticastFilter &filter = protocol->multicast_filter;
IPv4MulticastFilter& filter = protocol->multicast_filter;
IPv4GroupInterface* state = NULL;
status_t status = B_OK;
@ -935,13 +931,14 @@ generic_to_ipv4(int option)
static net_interface*
get_multicast_interface(ipv4_protocol* protocol, const in_addr* address)
{
// TODO: this is broken and leaks references
sockaddr_in groupAddr;
net_route* route = sDatalinkModule->get_route(sDomain,
fill_sockaddr_in(&groupAddr, address ? address->s_addr : INADDR_ANY));
if (route == NULL)
return NULL;
return route->interface;
return route->interface_address->interface;
}
@ -955,7 +952,7 @@ ipv4_delta_membership(ipv4_protocol* protocol, int option,
interface = get_multicast_interface(protocol, groupAddr);
} else {
sockaddr_in address;
interface = sDatalinkModule->get_interface_with_address(sDomain,
interface = sDatalinkModule->get_interface_with_address(
fill_sockaddr_in(&address, interfaceAddr->s_addr));
}
@ -972,14 +969,13 @@ ipv4_generic_delta_membership(ipv4_protocol* protocol, int option,
uint32 index, const sockaddr_storage* _groupAddr,
const sockaddr_storage* _sourceAddr)
{
if (_groupAddr->ss_family != AF_INET)
return B_BAD_VALUE;
if (_sourceAddr && _sourceAddr->ss_family != AF_INET)
if (_groupAddr->ss_family != AF_INET
|| _sourceAddr != NULL && _sourceAddr->ss_family != AF_INET)
return B_BAD_VALUE;
const in_addr* groupAddr = &((const sockaddr_in*)_groupAddr)->sin_addr;
// TODO: this is broken and leaks references
net_interface* interface;
if (index == 0)
interface = get_multicast_interface(protocol, groupAddr);
@ -990,7 +986,7 @@ ipv4_generic_delta_membership(ipv4_protocol* protocol, int option,
return ENODEV;
const in_addr* sourceAddr = NULL;
if (_sourceAddr)
if (_sourceAddr != NULL)
sourceAddr = &((const sockaddr_in*)_sourceAddr)->sin_addr;
return ipv4_delta_membership(protocol, generic_to_ipv4(option), interface,
@ -1013,7 +1009,7 @@ ipv4_init_protocol(net_socket* socket)
protocol->time_to_live = kDefaultTTL;
protocol->multicast_time_to_live = kDefaultMulticastTTL;
protocol->flags = 0;
protocol->interface_address = NULL;
protocol->multicast_address = NULL;
return protocol;
}
@ -1024,7 +1020,7 @@ ipv4_uninit_protocol(net_protocol* _protocol)
ipv4_protocol* protocol = (ipv4_protocol*)_protocol;
delete protocol->raw;
delete protocol->interface_address;
delete protocol->multicast_address;
delete protocol;
return B_OK;
}
@ -1217,21 +1213,23 @@ ipv4_setsockopt(net_protocol* _protocol, int level, int option,
// Using INADDR_ANY to remove the previous setting.
if (address->sin_addr.s_addr == htonl(INADDR_ANY)) {
delete address;
delete protocol->interface_address;
protocol->interface_address = NULL;
delete protocol->multicast_address;
protocol->multicast_address = NULL;
return B_OK;
}
struct net_interface* interface
= sDatalinkModule->get_interface_with_address(sDomain,
(struct sockaddr*)address);
= sDatalinkModule->get_interface_with_address(
(sockaddr*)address);
if (interface == NULL) {
delete address;
return EADDRNOTAVAIL;
}
delete protocol->interface_address;
protocol->interface_address = (struct sockaddr*)address;
delete protocol->multicast_address;
protocol->multicast_address = (struct sockaddr*)address;
sDatalinkModule->put_interface(interface);
return B_OK;
}
if (option == IP_MULTICAST_TTL) {
@ -1346,16 +1344,18 @@ ipv4_send_routed_data(net_protocol* _protocol, struct net_route* route,
return B_BAD_VALUE;
ipv4_protocol* protocol = (ipv4_protocol*)_protocol;
net_interface* interface = route->interface;
net_interface_address* interfaceAddress = route->interface_address;
net_interface* interface = interfaceAddress->interface;
TRACE_SK(protocol, "SendRoutedData(%p, %p [%ld bytes])", route, buffer,
buffer->size);
sockaddr_in& source = *(sockaddr_in*)buffer->source;
sockaddr_in& destination = *(sockaddr_in*)buffer->destination;
sockaddr_in& broadcastAddress = *(sockaddr_in*)interface->destination;
sockaddr_in* broadcastAddress = (sockaddr_in*)interfaceAddress->destination;
bool headerIncluded = false, checksumNeeded = true;
bool checksumNeeded = true;
bool headerIncluded = false;
if (protocol != NULL)
headerIncluded = (protocol->flags & IP_FLAG_HEADER_INCLUDED) != 0;
@ -1366,8 +1366,8 @@ ipv4_send_routed_data(net_protocol* _protocol, struct net_route* route,
if ((interface->device->flags & IFF_BROADCAST) != 0
&& (destination.sin_addr.s_addr == INADDR_BROADCAST
|| destination.sin_addr.s_addr
== broadcastAddress.sin_addr.s_addr)) {
|| (broadcastAddress != NULL && destination.sin_addr.s_addr
== broadcastAddress->sin_addr.s_addr))) {
if (protocol && !(protocol->socket->options & SO_BROADCAST))
return B_BAD_VALUE;
buffer->flags |= MSG_BCAST;
@ -1466,18 +1466,21 @@ ipv4_send_data(net_protocol* _protocol, net_buffer* buffer)
}
// handle IP_MULTICAST_IF
if (IN_MULTICAST(ntohl(((sockaddr_in*)buffer->destination)->
sin_addr.s_addr)) && protocol->interface_address != NULL) {
net_interface* interface
= sDatalinkModule->get_interface_with_address(sDomain,
protocol->interface_address);
if (interface == NULL || (interface->flags & IFF_UP) == 0)
if (IN_MULTICAST(ntohl(
((sockaddr_in*)buffer->destination)->sin_addr.s_addr))
&& protocol->multicast_address != NULL) {
net_interface_address* address = sDatalinkModule->get_interface_address(
protocol->multicast_address);
if (address == NULL || (address->interface->flags & IFF_UP) == 0) {
sDatalinkModule->put_interface_address(address);
return EADDRNOTAVAIL;
}
buffer->interface = interface;
sDatalinkModule->put_interface_address(buffer->interface_address);
buffer->interface_address = address;
// the buffer takes over ownership of the address
net_route* route = sDatalinkModule->get_route(sDomain,
interface->address);
net_route* route = sDatalinkModule->get_route(sDomain, address->local);
if (route == NULL)
return ENETUNREACH;
@ -1540,7 +1543,7 @@ ipv4_get_mtu(net_protocol* protocol, const struct sockaddr* address)
if (route->mtu != 0)
mtu = route->mtu;
else
mtu = route->interface->mtu;
mtu = route->interface_address->interface->mtu;
sDatalinkModule->put_route(sDomain, route);
return mtu - sizeof(ipv4_header);
@ -1588,9 +1591,9 @@ ipv4_receive_data(net_buffer* buffer)
// test if the packet is really for us
if (!sDatalinkModule->is_local_address(sDomain, (sockaddr*)&destination,
&buffer->interface, &matchedAddressType)
&buffer->interface_address, &matchedAddressType)
&& !sDatalinkModule->is_local_link_address(sDomain, true,
buffer->destination, &buffer->interface)) {
buffer->destination, &buffer->interface_address)) {
TRACE(" ipv4_receive_data(): packet was not for us %x -> %x",
ntohl(header.source), ntohl(header.destination));

View File

@ -1,5 +1,5 @@
/*
* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
* Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -107,6 +107,7 @@ ipv4_is_empty_address(const sockaddr *address, bool checkPort)
&& (!checkPort || ((sockaddr_in *)address)->sin_port == 0);
}
/*! Checks if the given \a address is an IPv4 address.
\return false if \a address is NULL, or with family different from AF_INET
true if it has AF_INET address family
@ -120,6 +121,7 @@ ipv4_is_same_family(const sockaddr *address)
return address->sa_family == AF_INET;
}
/*! Compares the IP-addresses of the two given address structures \a a and \a b.
\return true if IP-addresses of \a a and \a b are equal, false if not
*/
@ -407,12 +409,12 @@ ipv4_set_to_empty_address(sockaddr *address)
static status_t
ipv4_set_to_defaults(sockaddr *_defaultMask, sockaddr *_defaultBroadcast,
sockaddr *_address, sockaddr *_mask)
const sockaddr *_address, const sockaddr *_mask)
{
sockaddr_in *defaultMask = (sockaddr_in *)_defaultMask;
sockaddr_in *defaultBroadcast = (sockaddr_in *)_defaultBroadcast;
sockaddr_in *address = (sockaddr_in *)_address;
sockaddr_in *mask = (sockaddr_in *)_mask;
const sockaddr_in *address = (const sockaddr_in *)_address;
const sockaddr_in *mask = (const sockaddr_in *)_mask;
if (address == NULL || (defaultMask == NULL && defaultBroadcast == NULL))
return B_BAD_VALUE;
@ -453,6 +455,23 @@ ipv4_set_to_defaults(sockaddr *_defaultMask, sockaddr *_defaultBroadcast,
}
/*! Computes a hash value of the given \a address.
\return uint32 representing the hash value
*/
static uint32
ipv4_hash_address(const struct sockaddr* _address, bool includePort)
{
const sockaddr_in* address = (const sockaddr_in*)_address;
if (address == NULL || address->sin_len == 0)
return 0;
if (includePort)
return address->sin_port ^ address->sin_addr.s_addr;
return address->sin_addr.s_addr;
}
/*! Computes a hash-value of the given addresses \a ourAddress
and \a peerAddress.
\return uint32 representing the hash-value
@ -526,6 +545,7 @@ net_address_module_info gIPv4AddressModule = {
ipv4_set_to_empty_address,
ipv4_set_to_defaults,
ipv4_update_to,
ipv4_hash_address,
ipv4_hash_address_pair,
ipv4_checksum_address,
ipv4_get_loopback_address

View File

@ -1,5 +1,5 @@
/*
* Copyright 2007, Haiku, Inc. All Rights Reserved.
* Copyright 2007-2010, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -14,19 +14,27 @@
#include <new>
static inline bool
operator==(const in_addr &a1, const in_addr &a2)
{
return a1.s_addr == a2.s_addr;
}
using std::nothrow;
static inline bool
operator==(const in_addr& a, const in_addr& b)
{
return a.s_addr == b.s_addr;
}
// #pragma mark -
template<typename Addressing>
MulticastGroupInterface<Addressing>::MulticastGroupInterface(Filter *parent,
const AddressType &address, net_interface *interface)
: fParent(parent), fMulticastAddress(address), fInterface(interface)
:
fParent(parent),
fMulticastAddress(address),
fInterface(interface)
{
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
* Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -478,6 +478,25 @@ ipv6_set_to_defaults(sockaddr *_defaultMask, sockaddr *_defaultBroadcast,
}
/*! Computes a hash value of the given \a address.
\return uint32 representing the hash value
*/
static uint32
ipv6_hash_address(const struct sockaddr* _address, bool includePort)
{
const sockaddr_in6* address = (const sockaddr_in6*)_address;
if (address == NULL || address->sin6_len == 0)
return 0;
// TODO: also use sin6_flowinfo and sin6_scope_id?
uint32 port = includePort ? address->sin6_port : 0;
uint32 result = jenkins_hashword((const uint32*)&address->sin6_addr,
sizeof(in6_addr) / sizeof(uint32), 0);
return jenkins_hashword(&port, 1, result);
}
/*! Computes a hash-value of the given addresses \a ourAddress
and \a peerAddress.
\return uint32 representing the hash-value
@ -485,26 +504,8 @@ ipv6_set_to_defaults(sockaddr *_defaultMask, sockaddr *_defaultBroadcast,
static uint32
ipv6_hash_address_pair(const sockaddr *ourAddress, const sockaddr *peerAddress)
{
uint32 result = 0;
if (ourAddress) {
const sockaddr_in6 *our = (const sockaddr_in6 *)ourAddress;
uint32 port = our->sin6_port;
result = jenkins_hashword((const uint32*)&our->sin6_addr,
sizeof(in6_addr) / sizeof(uint32), result);
result = jenkins_hashword(&port, 1, result);
}
if (peerAddress) {
const sockaddr_in6 *peer = (const sockaddr_in6 *)peerAddress;
uint32 port = peer->sin6_port;
result = jenkins_hashword((const uint32*)&peer->sin6_addr,
sizeof(in6_addr) / sizeof(uint32), result);
result = jenkins_hashword(&port, 1, result);
}
// TODO: also use sin6_flowinfo and sin6_scope_id?
return result;
uint32 result = ipv6_hash_address(peerAddress, true);
return jenkins_hashword(&result, 1, ipv6_hash_address(ourAddress, true));
}
@ -563,6 +564,7 @@ net_address_module_info gIPv6AddressModule = {
ipv6_set_to_empty_address,
ipv6_set_to_defaults,
ipv6_update_to,
ipv6_hash_address,
ipv6_hash_address_pair,
ipv6_checksum_address,
ipv6_get_loopback_address

View File

@ -1,11 +1,12 @@
/*
* Copyright 2006-2008, Haiku, Inc. All Rights Reserved.
* Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
*/
#include <net_datalink.h>
#include <ByteOrder.h>
@ -20,15 +21,13 @@
#include <bluetooth/bdaddrUtils.h>
#include <bluetooth/L2CAP/btL2CAP.h>
#define L2CAP_CHECKSUM(address) (address.b[0]+\
address.b[1]+\
address.b[2]+\
address.b[3]+\
address.b[4]+\
address.b[5])
/*!
Routing utility function: copies address \a from into a new address
#define L2CAP_CHECKSUM(address) \
(address.b[0] + address.b[1] + address.b[2] + address.b[3] \
+ address.b[4] + address.b[5])
/*! Routing utility function: copies address \a from into a new address
that is put into \a to.
If \a replaceWithZeros is set \a from will be replaced by an empty
address.
@ -67,8 +66,7 @@ l2cap_copy_address(const sockaddr *from, sockaddr **to,
}
/*!
Routing utility function: applies \a mask to given \a address and puts
/*! Routing utility function: applies \a mask to given \a address and puts
the resulting address into \a result.
\return B_OK if the mask has been applied
\return B_BAD_VALUE if \a address or \a mask is NULL
@ -84,8 +82,7 @@ l2cap_mask_address(const sockaddr *address, const sockaddr *mask,
}
/*!
Checks if the given \a address is the empty address. By default, the port
/*! Checks if the given \a address is the empty address. By default, the port
is checked, too, but you can avoid that by passing \a checkPort = false.
\return true if \a address is NULL, uninitialized or the empty address,
false if not
@ -103,8 +100,8 @@ l2cap_is_empty_address(const sockaddr *address, bool checkPort)
/*! Checks if the given \a address is L2CAP address.
\return false if \a address is NULL, or with family different from AF_BLUETOOTH
true if it has AF_BLUETOOTH address family
\return false if \a address is NULL, or with family different from
AF_BLUETOOTH true if it has AF_BLUETOOTH address family
*/
static bool
l2cap_is_same_family(const sockaddr *address)
@ -115,8 +112,8 @@ l2cap_is_same_family(const sockaddr *address)
return address->sa_family == AF_BLUETOOTH;
}
/*!
Compares the IP-addresses of the two given address structures \a a and \a b.
/*! Compares the IP-addresses of the two given address structures \a a and \a b.
\return true if IP-addresses of \a a and \a b are equal, false if not
*/
static bool
@ -134,8 +131,7 @@ l2cap_equal_addresses(const sockaddr *a, const sockaddr *b)
}
/*!
Compares the ports of the two given address structures \a a and \a b.
/*! Compares the ports of the two given address structures \a a and \a b.
\return true if ports of \a a and \a b are equal, false if not
*/
static bool
@ -147,10 +143,10 @@ l2cap_equal_ports(const sockaddr *a, const sockaddr *b)
}
/*!
Compares the IP-addresses and ports of the two given address structures
/*! Compares the IP-addresses and ports of the two given address structures
\a a and \a b.
\return true if IP-addresses and ports of \a a and \a b are equal, false if not
\return true if IP-addresses and ports of \a a and \a b are equal, false if
not.
*/
static bool
l2cap_equal_addresses_and_ports(const sockaddr *a, const sockaddr *b)
@ -168,8 +164,7 @@ l2cap_equal_addresses_and_ports(const sockaddr *a, const sockaddr *b)
}
/*!
Applies the given \a mask two \a a and \a b and then checks whether
/*! Applies the given \a mask two \a a and \a b and then checks whether
the masked addresses match.
\return true if \a a matches \a b after masking both, false if not
*/
@ -184,8 +179,7 @@ l2cap_equal_masked_addresses(const sockaddr *a, const sockaddr *b,
}
/*!
Routing utility function: determines the least significant bit that is set
/*! Routing utility function: determines the least significant bit that is set
in the given \a mask.
\return the number of the first bit that is set (0-32, where 32 means
that there's no bit set in the mask).
@ -200,8 +194,7 @@ l2cap_first_mask_bit(const sockaddr *_mask)
}
/*!
Routing utility function: checks the given \a mask for correctness (which
/*! Routing utility function: checks the given \a mask for correctness (which
means that (starting with LSB) consists zero or more unset bits, followed
by bits that are all set).
\return true if \a mask is ok, false if not
@ -214,8 +207,7 @@ l2cap_check_mask(const sockaddr *_mask)
}
/*!
Creates a buffer for the given \a address and prints the address into
/*! Creates a buffer for the given \a address and prints the address into
it (hexadecimal representation in host byte order or '<none>').
If \a printPort is set, the port is printed, too.
\return B_OK if the address could be printed, \a buffer will point to
@ -270,8 +262,7 @@ l2cap_print_address(const sockaddr *_address, char **_buffer, bool printPort)
}
/*!
Determines the port of the given \a address.
/*! Determines the port of the given \a address.
\return uint16 representing the port-nr
*/
static uint16
@ -284,8 +275,7 @@ l2cap_get_port(const sockaddr *address)
}
/*!
Sets the port of the given \a address to \a port.
/*! Sets the port of the given \a address to \a port.
\return B_OK if the port has been set
\return B_BAD_VALUE if \a address is NULL
*/
@ -300,8 +290,7 @@ l2cap_set_port(sockaddr *address, uint16 port)
}
/*!
Sets \a address to \a from.
/*! Sets \a address to \a from.
\return B_OK if \a from has been copied into \a address
\return B_BAD_VALUE if either \a address or \a from is NULL
\return B_MISMATCHED_VALUES if from is not of family AF_BLUETOOTH
@ -346,8 +335,7 @@ l2cap_update_to(sockaddr *_address, const sockaddr *_from)
}
/*!
Sets \a address to the empty address (0.0.0.0).
/*! Sets \a address to the empty address.
\return B_OK if \a address has been set
\return B_BAD_VALUE if \a address is NULL
*/
@ -366,14 +354,28 @@ l2cap_set_to_empty_address(sockaddr *address)
static status_t
l2cap_set_to_defaults(sockaddr *_defaultMask, sockaddr *_defaultBroadcast,
sockaddr *_address, sockaddr *_mask)
const sockaddr *_address, const sockaddr *_mask)
{
return B_OK;
// TODO: not implemented
return B_ERROR;
}
/*!
Computes a hash-value of the given addresses \a ourAddress
/*! Computes a hash value of the given \a address.
\return uint32 representing the hash value
*/
static uint32
l2cap_hash_address(const struct sockaddr* _address, bool includePort)
{
const sockaddr_l2cap* address = (const sockaddr_l2cap*)_address;
if (address == NULL || address->l2cap_len == 0)
return 0;
return address->l2cap_psm ^ L2CAP_CHECKSUM(address->l2cap_bdaddr);
}
/*! Computes a hash-value of the given addresses \a ourAddress
and \a peerAddress.
\return uint32 representing the hash-value
*/
@ -389,8 +391,7 @@ l2cap_hash_address_pair(const sockaddr *ourAddress, const sockaddr *peerAddress)
}
/*!
Adds the given \a address to the IP-checksum \a checksum.
/*! Adds the given \a address to the IP-checksum \a checksum.
\return B_OK if \a address has been added to the checksum
\return B_BAD_VALUE if either \a address or \a checksum is NULL
*/
@ -432,6 +433,7 @@ net_address_module_info gL2cap4AddressModule = {
l2cap_set_to_empty_address,
l2cap_set_to_defaults,
l2cap_update_to,
l2cap_hash_address,
l2cap_hash_address_pair,
l2cap_checksum_address,
NULL // get_loopback_address

View File

@ -2127,7 +2127,7 @@ TCPEndpoint::_PrepareSendPath(const sockaddr* peer)
// make sure connection does not already exist
status_t status = fManager->SetConnection(this, *LocalAddress(), peer,
fRoute->interface->address);
fRoute->interface_address->local);
if (status < B_OK)
return status;

View File

@ -660,10 +660,11 @@ tcp_receive_data(net_buffer* buffer)
{
TRACE(("TCP: Received buffer %p\n", buffer));
if (buffer->interface == NULL || buffer->interface->domain == NULL)
if (buffer->interface_address == NULL
|| buffer->interface_address->domain == NULL)
return B_ERROR;
net_domain* domain = buffer->interface->domain;
net_domain* domain = buffer->interface_address->domain;
net_address_module_info* addressModule = domain->address_module;
NetBufferHeaderReader<tcp_header> bufferHeader(buffer);

View File

@ -367,7 +367,7 @@ UdpDomainSupport::ConnectEndpoint(UdpEndpoint *endpoint,
= gDatalinkModule->get_route(fDomain, address);
if (routeToDestination) {
status = endpoint->LocalAddress().SetTo(
routeToDestination->interface->address);
routeToDestination->interface_address->local);
gDatalinkModule->put_route(fDomain, routeToDestination);
if (status < B_OK)
return status;
@ -516,8 +516,8 @@ UdpDomainSupport::_DemuxBroadcast(net_buffer *buffer)
sockaddr *peerAddr = buffer->source;
sockaddr *broadcastAddr = buffer->destination;
sockaddr *mask = NULL;
if (buffer->interface)
mask = (sockaddr *)buffer->interface->mask;
if (buffer->interface_address != NULL)
mask = (sockaddr *)buffer->interface_address->mask;
TRACE_DOMAIN("_DemuxBroadcast(%p)", buffer);
@ -731,7 +731,7 @@ UdpEndpointManager::ReceiveError(status_t error, net_buffer* buffer)
std::min(buffer->size, sizeof(udp_header))) != B_OK)
return B_BAD_VALUE;
net_domain* domain = buffer->interface->domain;
net_domain* domain = buffer->interface_address->domain;
net_address_module_info* addressModule = domain->address_module;
SocketAddress source(addressModule, buffer->source);
@ -760,13 +760,14 @@ UdpEndpointManager::Deframe(net_buffer *buffer)
udp_header &header = bufferHeader.Data();
if (buffer->interface == NULL || buffer->interface->domain == NULL) {
if (buffer->interface_address == NULL
|| buffer->interface_address->domain == NULL) {
TRACE_EPM(" Deframe(): UDP packed dropped as there was no domain "
"specified (interface %p).", buffer->interface);
"specified (interface address %p).", buffer->interface_address);
return B_BAD_VALUE;
}
net_domain *domain = buffer->interface->domain;
net_domain *domain = buffer->interface_address->domain;
net_address_module_info *addressModule = domain->address_module;
SocketAddress source(addressModule, buffer->source);
@ -869,11 +870,11 @@ UdpEndpointManager::_GetDomain(net_domain *domain, bool create)
UdpDomainSupport*
UdpEndpointManager::_GetDomain(net_buffer* buffer)
{
if (buffer->interface == NULL)
if (buffer->interface_address == NULL)
return NULL;
MutexLocker _(fLock);
return _GetDomain(buffer->interface->domain, false);
return _GetDomain(buffer->interface_address->domain, false);
// TODO: we don't want to hold to the manager's lock during the
// whole RX path, we may not hold an endpoint's lock with the
// manager lock held.
@ -1313,38 +1314,42 @@ init_udp()
if (status != B_OK)
goto err1;
status = gStackModule->register_domain_protocols(AF_INET, SOCK_DGRAM, IPPROTO_IP,
status = gStackModule->register_domain_protocols(AF_INET, SOCK_DGRAM,
IPPROTO_IP,
"network/protocols/udp/v1",
"network/protocols/ipv4/v1",
NULL);
if (status < B_OK)
goto err1;
status = gStackModule->register_domain_protocols(AF_INET6, SOCK_DGRAM, IPPROTO_IP,
status = gStackModule->register_domain_protocols(AF_INET6, SOCK_DGRAM,
IPPROTO_IP,
"network/protocols/udp/v1",
"network/protocols/ipv6/v1",
NULL);
if (status < B_OK)
goto err1;
status = gStackModule->register_domain_protocols(AF_INET, SOCK_DGRAM, IPPROTO_UDP,
status = gStackModule->register_domain_protocols(AF_INET, SOCK_DGRAM,
IPPROTO_UDP,
"network/protocols/udp/v1",
"network/protocols/ipv4/v1",
NULL);
if (status < B_OK)
goto err1;
status = gStackModule->register_domain_protocols(AF_INET6, SOCK_DGRAM, IPPROTO_UDP,
status = gStackModule->register_domain_protocols(AF_INET6, SOCK_DGRAM,
IPPROTO_UDP,
"network/protocols/udp/v1",
"network/protocols/ipv6/v1",
NULL);
if (status < B_OK)
goto err1;
status = gStackModule->register_domain_receiving_protocol(AF_INET, IPPROTO_UDP,
"network/protocols/udp/v1");
status = gStackModule->register_domain_receiving_protocol(AF_INET,
IPPROTO_UDP, "network/protocols/udp/v1");
if (status < B_OK)
goto err1;
status = gStackModule->register_domain_receiving_protocol(AF_INET6, IPPROTO_UDP,
"network/protocols/udp/v1");
status = gStackModule->register_domain_receiving_protocol(AF_INET6,
IPPROTO_UDP, "network/protocols/udp/v1");
if (status < B_OK)
goto err1;

View File

@ -217,7 +217,7 @@ unix_mask_address(const sockaddr *address, const sockaddr *mask,
static status_t
unix_set_to_defaults(sockaddr *defaultMask, sockaddr *defaultBroadcast,
sockaddr *address, sockaddr *netmask)
const sockaddr *address, const sockaddr *netmask)
{
if (address == NULL)
return B_BAD_VALUE;
@ -246,8 +246,9 @@ unix_update_to(sockaddr *address, const sockaddr *from)
static uint32
hash_address(const sockaddr_un* address)
unix_hash_address(const sockaddr* _address, bool includePort)
{
sockaddr_un* address = (sockaddr_un*)_address;
if (address == NULL)
return 0;
@ -264,8 +265,8 @@ hash_address(const sockaddr_un* address)
static uint32
unix_hash_address_pair(const sockaddr *ourAddress, const sockaddr *peerAddress)
{
return hash_address((sockaddr_un*)ourAddress) * 17
+ hash_address((sockaddr_un*)peerAddress);
return unix_hash_address(ourAddress, false) * 17
+ unix_hash_address(peerAddress, false);
}
@ -309,6 +310,7 @@ net_address_module_info gAddressModule = {
unix_set_to_empty_address,
unix_set_to_defaults,
unix_update_to,
unix_hash_address,
unix_hash_address_pair,
unix_checksum_address,
NULL // get_loopback_address

View File

@ -17,6 +17,7 @@ UsePrivateHeaders net shared ;
KernelAddon stack :
ancillary_data.cpp
datalink.cpp
device_interfaces.cpp
domains.cpp
interfaces.cpp
net_buffer.cpp

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,797 @@
/*
* Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, axeld@pinc-software.de
*/
#include "device_interfaces.h"
#include "domains.h"
#include "interfaces.h"
#include "stack_private.h"
#include "utility.h"
#include <net_device.h>
#include <lock.h>
#include <util/AutoLock.h>
#include <KernelExport.h>
#include <net/if_dl.h>
#include <new>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#define TRACE_DEVICE_INTERFACES
#ifdef TRACE_DEVICE_INTERFACES
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
static mutex sLock;
static DeviceInterfaceList sInterfaces;
static uint32 sDeviceIndex;
/*! A service thread for each device interface. It just reads as many packets
as availabe, deframes them, and puts them into the receive queue of the
device interface.
*/
static status_t
device_reader_thread(void* _interface)
{
net_device_interface* interface = (net_device_interface*)_interface;
net_device* device = interface->device;
status_t status = B_OK;
RecursiveLocker locker(interface->receive_lock);
while ((device->flags & IFF_UP) != 0) {
locker.Unlock();
net_buffer* buffer;
status = device->module->receive_data(device, &buffer);
locker.Lock();
if (status == B_OK) {
// feed device monitors
DeviceMonitorList::Iterator iterator =
interface->monitor_funcs.GetIterator();
while (net_device_monitor* monitor = iterator.Next()) {
monitor->receive(monitor, buffer);
}
buffer->interface_address = NULL;
buffer->type = interface->deframe_func(interface->device, buffer);
if (buffer->type < 0) {
gNetBufferModule.free(buffer);
continue;
}
fifo_enqueue_buffer(&interface->receive_queue, buffer);
} else {
// In case of error, give the other threads some
// time to run since this is a high priority time thread.
snooze(10000);
}
}
return status;
}
static status_t
device_consumer_thread(void* _interface)
{
net_device_interface* interface = (net_device_interface*)_interface;
net_device* device = interface->device;
net_buffer* buffer;
while (true) {
ssize_t status = fifo_dequeue_buffer(&interface->receive_queue, 0,
B_INFINITE_TIMEOUT, &buffer);
if (status != B_OK) {
if (status == B_INTERRUPTED)
continue;
break;
}
if (buffer->interface_address != NULL) {
// if the interface is already specified, this buffer was
// delivered locally.
if (buffer->interface_address->domain->module->receive_data(buffer)
== B_OK)
buffer = NULL;
} else {
// find handler for this packet
DeviceHandlerList::Iterator iterator =
interface->receive_funcs.GetIterator();
while (buffer && iterator.HasNext()) {
net_device_handler* handler = iterator.Next();
// if the handler returns B_OK, it consumed the buffer
if (handler->type == buffer->type
&& handler->func(handler->cookie, device, buffer) == B_OK)
buffer = NULL;
}
}
if (buffer != NULL)
gNetBufferModule.free(buffer);
}
return B_OK;
}
/*! The domain's device receive handler - this will inject the net_buffers into
the protocol layer (the domain's registered receive handler).
*/
static status_t
domain_receive_adapter(void* cookie, net_device* device, net_buffer* buffer)
{
net_domain_private* domain = (net_domain_private*)cookie;
return domain->module->receive_data(buffer);
}
static net_device_interface*
find_device_interface(const char* name)
{
DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator();
while (net_device_interface* interface = iterator.Next()) {
if (!strcmp(interface->device->name, name))
return interface;
}
return NULL;
}
static net_device_interface*
allocate_device_interface(net_device* device, net_device_module_info* module)
{
net_device_interface* interface = new(std::nothrow) net_device_interface;
if (interface == NULL)
return NULL;
recursive_lock_init(&interface->receive_lock, "interface receive lock");
char name[128];
snprintf(name, sizeof(name), "%s receive queue", device->name);
if (init_fifo(&interface->receive_queue, name, 16 * 1024 * 1024) < B_OK)
goto error1;
interface->device = device;
interface->up_count = 0;
interface->ref_count = 1;
interface->deframe_func = NULL;
interface->deframe_ref_count = 0;
snprintf(name, sizeof(name), "%s consumer", device->name);
interface->reader_thread = -1;
interface->consumer_thread = spawn_kernel_thread(device_consumer_thread,
name, B_DISPLAY_PRIORITY, interface);
if (interface->consumer_thread < B_OK)
goto error2;
resume_thread(interface->consumer_thread);
// TODO: proper interface index allocation
device->index = ++sDeviceIndex;
device->module = module;
sInterfaces.Add(interface);
return interface;
error2:
uninit_fifo(&interface->receive_queue);
error1:
recursive_lock_destroy(&interface->receive_lock);
delete interface;
return NULL;
}
static void
notify_device_monitors(net_device_interface* interface, int32 event)
{
RecursiveLocker _(interface->receive_lock);
DeviceMonitorList::Iterator iterator
= interface->monitor_funcs.GetIterator();
while (net_device_monitor* monitor = iterator.Next()) {
// it's safe for the "current" item to remove itself.
monitor->event(monitor, event);
}
}
#if ENABLE_DEBUGGER_COMMANDS
static int
dump_device_interface(int argc, char** argv)
{
if (argc != 2) {
kprintf("usage: %s [address]\n", argv[0]);
return 0;
}
net_device_interface* interface
= (net_device_interface*)parse_expression(argv[1]);
kprintf("device: %p\n", interface->device);
kprintf("reader_thread: %ld\n", interface->reader_thread);
kprintf("up_count: %" B_PRIu32 "\n", interface->up_count);
kprintf("ref_count: %" B_PRId32 "\n", interface->ref_count);
kprintf("deframe_func: %p\n", interface->deframe_func);
kprintf("deframe_ref_count: %" B_PRId32 "\n", interface->ref_count);
kprintf("monitor_funcs:\n");
kprintf("receive_funcs:\n");
kprintf("consumer_thread: %ld\n", interface->consumer_thread);
kprintf("receive_lock: %p\n", &interface->receive_lock);
kprintf("receive_queue: %p\n", &interface->receive_queue);
DeviceMonitorList::Iterator monitorIterator
= interface->monitor_funcs.GetIterator();
while (monitorIterator.HasNext())
kprintf(" %p\n", monitorIterator.Next());
DeviceHandlerList::Iterator handlerIterator
= interface->receive_funcs.GetIterator();
while (handlerIterator.HasNext())
kprintf(" %p\n", handlerIterator.Next());
return 0;
}
static int
dump_device_interfaces(int argc, char** argv)
{
DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator();
while (net_device_interface* interface = iterator.Next()) {
kprintf(" %p %s\n", interface, interface->device->name);
}
return 0;
}
#endif // ENABLE_DEBUGGER_COMMANDS
// #pragma mark - device interfaces
net_device_interface*
acquire_device_interface(net_device_interface* interface)
{
if (interface == NULL || atomic_add(&interface->ref_count, 1) == 0)
return NULL;
return interface;
}
void
get_device_interface_address(net_device_interface* interface, sockaddr* _address)
{
sockaddr_dl &address = *(sockaddr_dl*)_address;
address.sdl_family = AF_LINK;
address.sdl_index = interface->device->index;
address.sdl_type = interface->device->type;
address.sdl_nlen = strlen(interface->device->name);
address.sdl_slen = 0;
memcpy(address.sdl_data, interface->device->name, address.sdl_nlen);
address.sdl_alen = interface->device->address.length;
memcpy(LLADDR(&address), interface->device->address.data, address.sdl_alen);
address.sdl_len = sizeof(sockaddr_dl) - sizeof(address.sdl_data)
+ address.sdl_nlen + address.sdl_alen;
}
uint32
count_device_interfaces()
{
MutexLocker locker(sLock);
DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator();
uint32 count = 0;
while (iterator.HasNext()) {
iterator.Next();
count++;
}
return count;
}
/*! Dumps a list of all interfaces into the supplied userland buffer.
If the interfaces don't fit into the buffer, an error (\c ENOBUFS) is
returned.
*/
status_t
list_device_interfaces(void* _buffer, size_t* bufferSize)
{
MutexLocker locker(sLock);
DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator();
UserBuffer buffer(_buffer, *bufferSize);
while (net_device_interface* interface = iterator.Next()) {
ifreq request;
strlcpy(request.ifr_name, interface->device->name, IF_NAMESIZE);
get_device_interface_address(interface, &request.ifr_addr);
if (buffer.Copy(&request, IF_NAMESIZE + request.ifr_addr.sa_len) == NULL)
return buffer.Status();
}
*bufferSize = buffer.ConsumedAmount();
return B_OK;
}
/*! Releases the reference for the interface. When all references are
released, the interface is removed.
*/
void
put_device_interface(struct net_device_interface* interface)
{
if (atomic_add(&interface->ref_count, -1) != 1)
return;
{
MutexLocker locker(sLock);
sInterfaces.Remove(interface);
}
uninit_fifo(&interface->receive_queue);
status_t status;
wait_for_thread(interface->consumer_thread, &status);
net_device* device = interface->device;
const char* moduleName = device->module->info.name;
device->module->uninit_device(device);
put_module(moduleName);
recursive_lock_destroy(&interface->receive_lock);
delete interface;
}
/*! Finds an interface by the specified index and acquires a reference to it.
*/
struct net_device_interface*
get_device_interface(uint32 index)
{
MutexLocker locker(sLock);
// TODO: maintain an array of all device interfaces instead
DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator();
while (net_device_interface* interface = iterator.Next()) {
if (interface->device->index == index) {
if (atomic_add(&interface->ref_count, 1) != 0)
return interface;
}
}
return NULL;
}
/*! Finds an interface by the specified name and grabs a reference to it.
If the interface does not yet exist, a new one is created.
*/
struct net_device_interface*
get_device_interface(const char* name, bool create)
{
MutexLocker locker(sLock);
net_device_interface* interface = find_device_interface(name);
if (interface != NULL) {
if (atomic_add(&interface->ref_count, 1) != 0)
return interface;
// try to recreate interface - it just got removed
}
if (!create)
return NULL;
void* cookie = open_module_list("network/devices");
if (cookie == NULL)
return NULL;
while (true) {
char moduleName[B_FILE_NAME_LENGTH];
size_t length = sizeof(moduleName);
if (read_next_module_name(cookie, moduleName, &length) != B_OK)
break;
TRACE(("get_device_interface: ask \"%s\" for %s\n", moduleName, name));
net_device_module_info* module;
if (get_module(moduleName, (module_info**)&module) == B_OK) {
net_device* device;
status_t status = module->init_device(name, &device);
if (status == B_OK) {
interface = allocate_device_interface(device, module);
if (interface != NULL)
return interface;
module->uninit_device(device);
}
put_module(moduleName);
}
}
return NULL;
}
status_t
up_device_interface(net_device_interface* interface)
{
net_device* device = interface->device;
RecursiveLocker locker(interface->receive_lock);
if (interface->up_count != 0) {
interface->up_count++;
return B_OK;
}
status_t status = device->module->up(device);
if (status != B_OK)
return status;
if (device->module->receive_data != NULL) {
// give the thread a nice name
char name[B_OS_NAME_LENGTH];
snprintf(name, sizeof(name), "%s reader", device->name);
interface->reader_thread = spawn_kernel_thread(device_reader_thread,
name, B_REAL_TIME_DISPLAY_PRIORITY - 10, interface);
if (interface->reader_thread < B_OK)
return interface->reader_thread;
}
device->flags |= IFF_UP;
if (device->module->receive_data != NULL)
resume_thread(interface->reader_thread);
interface->up_count = 1;
return B_OK;
}
void
down_device_interface(net_device_interface* interface)
{
// Receive lock must be held when calling down_device_interface.
// Known callers are `interface_protocol_down' which gets
// here via one of the following paths:
//
// - domain_interface_control() [rx lock held, domain lock held]
// interface_set_down()
// interface_protocol_down()
//
// - domain_interface_control() [rx lock held, domain lock held]
// remove_interface_from_domain()
// delete_interface()
// interface_set_down()
net_device* device = interface->device;
device->flags &= ~IFF_UP;
device->module->down(device);
notify_device_monitors(interface, B_DEVICE_GOING_DOWN);
if (device->module->receive_data != NULL) {
thread_id readerThread = interface->reader_thread;
// make sure the reader thread is gone before shutting down the interface
status_t status;
wait_for_thread(readerThread, &status);
}
}
// #pragma mark - devices stack API
/*! Unregisters a previously registered deframer function. */
status_t
unregister_device_deframer(net_device* device)
{
MutexLocker locker(sLock);
// find device interface for this device
net_device_interface* interface = find_device_interface(device->name);
if (interface == NULL)
return ENODEV;
RecursiveLocker _(interface->receive_lock);
if (--interface->deframe_ref_count == 0)
interface->deframe_func = NULL;
return B_OK;
}
/*! Registers the deframer function for the specified \a device.
Note, however, that right now, you can only register one single
deframer function per device.
If the need arises, we might want to lift that limitation at a
later time (which would require a slight API change, though).
*/
status_t
register_device_deframer(net_device* device, net_deframe_func deframeFunc)
{
MutexLocker locker(sLock);
// find device interface for this device
net_device_interface* interface = find_device_interface(device->name);
if (interface == NULL)
return ENODEV;
RecursiveLocker _(interface->receive_lock);
if (interface->deframe_func != NULL
&& interface->deframe_func != deframeFunc)
return B_ERROR;
interface->deframe_func = deframeFunc;
interface->deframe_ref_count++;
return B_OK;
}
/*! Registers a domain to receive net_buffers from the specified \a device. */
status_t
register_domain_device_handler(struct net_device* device, int32 type,
struct net_domain* _domain)
{
net_domain_private* domain = (net_domain_private*)_domain;
if (domain->module == NULL || domain->module->receive_data == NULL)
return B_BAD_VALUE;
return register_device_handler(device, type, &domain_receive_adapter,
domain);
}
/*! Registers a receiving function callback for the specified \a device. */
status_t
register_device_handler(struct net_device* device, int32 type,
net_receive_func receiveFunc, void* cookie)
{
MutexLocker locker(sLock);
// find device interface for this device
net_device_interface* interface = find_device_interface(device->name);
if (interface == NULL)
return ENODEV;
RecursiveLocker _(interface->receive_lock);
// see if such a handler already for this device
DeviceHandlerList::Iterator iterator
= interface->receive_funcs.GetIterator();
while (net_device_handler* handler = iterator.Next()) {
if (handler->type == type)
return B_ERROR;
}
// Add new handler
net_device_handler* handler = new(std::nothrow) net_device_handler;
if (handler == NULL)
return B_NO_MEMORY;
handler->func = receiveFunc;
handler->type = type;
handler->cookie = cookie;
interface->receive_funcs.Add(handler);
return B_OK;
}
/*! Unregisters a previously registered device handler. */
status_t
unregister_device_handler(struct net_device* device, int32 type)
{
MutexLocker locker(sLock);
// find device interface for this device
net_device_interface* interface = find_device_interface(device->name);
if (interface == NULL)
return ENODEV;
RecursiveLocker _(interface->receive_lock);
// search for the handler
DeviceHandlerList::Iterator iterator
= interface->receive_funcs.GetIterator();
while (net_device_handler* handler = iterator.Next()) {
if (handler->type == type) {
// found it
iterator.Remove();
delete handler;
return B_OK;
}
}
return B_BAD_VALUE;
}
/*! Registers a device monitor for the specified device. */
status_t
register_device_monitor(net_device* device, net_device_monitor* monitor)
{
if (monitor->receive == NULL || monitor->event == NULL)
return B_BAD_VALUE;
MutexLocker locker(sLock);
// find device interface for this device
net_device_interface* interface = find_device_interface(device->name);
if (interface == NULL)
return ENODEV;
RecursiveLocker _(interface->receive_lock);
interface->monitor_funcs.Add(monitor);
return B_OK;
}
/*! Unregisters a previously registered device monitor. */
status_t
unregister_device_monitor(net_device* device, net_device_monitor* monitor)
{
MutexLocker locker(sLock);
// find device interface for this device
net_device_interface* interface = find_device_interface(device->name);
if (interface == NULL)
return ENODEV;
RecursiveLocker _(interface->receive_lock);
// search for the monitor
DeviceMonitorList::Iterator iterator = interface->monitor_funcs.GetIterator();
while (iterator.HasNext()) {
if (iterator.Next() == monitor) {
iterator.Remove();
return B_OK;
}
}
return B_BAD_VALUE;
}
/*! This function is called by device modules in case their link
state changed, ie. if an ethernet cable was plugged in or
removed.
*/
status_t
device_link_changed(net_device* device)
{
notify_link_changed(device);
return B_OK;
}
/*! This function is called by device modules once their device got
physically removed, ie. a USB networking card is unplugged.
*/
status_t
device_removed(net_device* device)
{
MutexLocker locker(sLock);
// hold a reference to the device interface being removed
// so our put_() will (eventually) do the final cleanup
net_device_interface* interface = get_device_interface(device->name, false);
if (interface == NULL)
return ENODEV;
// Propagate the loss of the device throughout the stack.
// This is very complex, refer to remove_interface() for
// further details.
// TODO!
//domain_removed_device_interface(interface);
notify_device_monitors(interface, B_DEVICE_BEING_REMOVED);
// By now all of the monitors must have removed themselves. If they
// didn't, they'll probably wait forever to be callback'ed again.
interface->monitor_funcs.RemoveAll();
// All of the readers should be gone as well since we are out of
// interfaces and put_domain_datalink_protocols() is called for
// each delete_interface().
put_device_interface(interface);
return B_OK;
}
status_t
device_enqueue_buffer(net_device* device, net_buffer* buffer)
{
net_device_interface* interface = get_device_interface(device->index);
if (interface == NULL)
return ENODEV;
status_t status = fifo_enqueue_buffer(&interface->receive_queue, buffer);
put_device_interface(interface);
return status;
}
// #pragma mark -
status_t
init_device_interfaces()
{
mutex_init(&sLock, "net device interfaces");
new (&sInterfaces) DeviceInterfaceList;
// static C++ objects are not initialized in the module startup
#if ENABLE_DEBUGGER_COMMANDS
add_debugger_command("net_device_interface", &dump_device_interface,
"Dump the given network device interface");
add_debugger_command("net_device_interfaces", &dump_device_interfaces,
"Dump network device interfaces");
#endif
return B_OK;
}
status_t
uninit_device_interfaces()
{
#if ENABLE_DEBUGGER_COMMANDS
remove_debugger_command("net_device_interface", &dump_device_interface);
remove_debugger_command("net_device_interfaces", &dump_device_interfaces);
#endif
mutex_destroy(&sLock);
return B_OK;
}

View File

@ -0,0 +1,84 @@
/*
* Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, axeld@pinc-software.de
*/
#ifndef DEVICE_INTERFACES_H
#define DEVICE_INTERFACES_H
#include <net_datalink.h>
#include <net_stack.h>
#include <util/DoublyLinkedList.h>
struct net_device_handler : DoublyLinkedListLinkImpl<net_device_handler> {
net_receive_func func;
int32 type;
void* cookie;
};
typedef DoublyLinkedList<net_device_handler> DeviceHandlerList;
typedef DoublyLinkedList<net_device_monitor,
DoublyLinkedListCLink<net_device_monitor> > DeviceMonitorList;
struct net_device_interface : DoublyLinkedListLinkImpl<net_device_interface> {
struct net_device* device;
thread_id reader_thread;
uint32 up_count;
// a device can be brought up by more than one interface
int32 ref_count;
net_deframe_func deframe_func;
int32 deframe_ref_count;
DeviceMonitorList monitor_funcs;
DeviceHandlerList receive_funcs;
recursive_lock receive_lock;
thread_id consumer_thread;
net_fifo receive_queue;
};
typedef DoublyLinkedList<net_device_interface> DeviceInterfaceList;
// device interfaces
net_device_interface* acquire_device_interface(net_device_interface* interface);
void get_device_interface_address(net_device_interface* interface,
sockaddr* address);
uint32 count_device_interfaces();
status_t list_device_interfaces(void* buffer, size_t* _bufferSize);
void put_device_interface(struct net_device_interface* interface);
struct net_device_interface* get_device_interface(uint32 index);
struct net_device_interface* get_device_interface(const char* name,
bool create = true);
status_t up_device_interface(net_device_interface* interface);
void down_device_interface(net_device_interface* interface);
// devices
status_t unregister_device_deframer(net_device* device);
status_t register_device_deframer(net_device* device, net_deframe_func deframeFunc);
status_t register_domain_device_handler(struct net_device* device, int32 type,
struct net_domain* domain);
status_t register_device_handler(struct net_device* device, int32 type,
net_receive_func receiveFunc, void* cookie);
status_t unregister_device_handler(struct net_device* device, int32 type);
status_t register_device_monitor(struct net_device* device,
struct net_device_monitor* monitor);
status_t unregister_device_monitor(struct net_device* device,
struct net_device_monitor* monitor);
status_t device_link_changed(net_device* device);
status_t device_removed(net_device* device);
status_t device_enqueue_buffer(net_device* device, net_buffer* buffer);
status_t init_device_interfaces();
status_t uninit_device_interfaces();
#endif // DEVICE_INTERFACES_H

View File

@ -47,6 +47,8 @@ static DomainList sDomains;
static net_domain_private*
lookup_domain(int family)
{
ASSERT_LOCKED_MUTEX(&sDomainLock);
DomainList::Iterator iterator = sDomains.GetIterator();
while (net_domain_private* domain = iterator.Next()) {
if (domain->family == family)
@ -68,19 +70,6 @@ dump_domains(int argc, char** argv)
kprintf("domain: %p, %s, %d\n", domain, domain->name, domain->family);
kprintf(" module: %p\n", domain->module);
kprintf(" address_module: %p\n", domain->address_module);
if (!list_is_empty(&domain->interfaces))
kprintf(" interfaces:\n");
net_interface* interface = NULL;
while (true) {
interface = (net_interface*)list_get_next_item(&domain->interfaces,
interface);
if (interface == NULL)
break;
kprintf(" %p\n", interface);
}
if (!domain->routes.IsEmpty())
kprintf(" routes:\n");
@ -119,230 +108,6 @@ get_domain(int family)
}
uint32
count_domain_interfaces()
{
MutexLocker locker(sDomainLock);
uint32 count = 0;
DomainList::Iterator iterator = sDomains.GetIterator();
while (net_domain_private* domain = iterator.Next()) {
net_interface* interface = NULL;
while (true) {
interface = (net_interface*)list_get_next_item(&domain->interfaces,
interface);
if (interface == NULL)
break;
count++;
}
}
return count;
}
/*! Dumps a list of all interfaces into the supplied userland buffer.
If the interfaces don't fit into the buffer, an error (\c ENOBUFS) is
returned.
*/
status_t
list_domain_interfaces(void* _buffer, size_t* bufferSize)
{
MutexLocker locker(sDomainLock);
UserBuffer buffer(_buffer, *bufferSize);
DomainList::Iterator iterator = sDomains.GetIterator();
while (net_domain_private* domain = iterator.Next()) {
RecursiveLocker locker(domain->lock);
net_interface* interface = NULL;
while (true) {
interface = (net_interface*)list_get_next_item(&domain->interfaces,
interface);
if (interface == NULL)
break;
ifreq request;
strlcpy(request.ifr_name, interface->name, IF_NAMESIZE);
if (interface->address != NULL) {
memcpy(&request.ifr_addr, interface->address,
interface->address->sa_len);
} else {
// empty address
request.ifr_addr.sa_len = 2;
request.ifr_addr.sa_family = AF_UNSPEC;
}
if (buffer.Copy(&request, IF_NAMESIZE
+ request.ifr_addr.sa_len) == NULL)
return buffer.Status();
}
}
*bufferSize = buffer.ConsumedAmount();
return B_OK;
}
status_t
add_interface_to_domain(net_domain* _domain,
struct ifreq& request)
{
net_domain_private* domain = (net_domain_private*)_domain;
const char* deviceName = request.ifr_parameter.device[0]
? request.ifr_parameter.device : request.ifr_name;
const char* baseName = request.ifr_parameter.base_name[0]
? request.ifr_parameter.base_name : request.ifr_name;
net_device_interface* deviceInterface = get_device_interface(deviceName);
if (deviceInterface == NULL)
return ENODEV;
RecursiveLocker locker(domain->lock);
net_interface_private* interface = NULL;
status_t status;
if (find_interface(domain, request.ifr_name) == NULL) {
// We must not hold the domain's link when creating the interface:
// this will call get_module() which might want to access a network
// device when booting from network.
locker.Unlock();
status = create_interface(domain, request.ifr_name,
baseName, deviceInterface, &interface);
locker.Lock();
if (find_interface(domain, request.ifr_name) != NULL) {
delete_interface(interface);
status = B_NAME_IN_USE;
}
} else
status = B_NAME_IN_USE;
put_device_interface(deviceInterface);
if (status == B_OK) {
list_add_item(&domain->interfaces, interface);
notify_interface_added(interface);
}
return status;
}
/*! Removes the interface from its domain, and deletes it.
You need to hold the domain's lock when calling this function.
*/
status_t
remove_interface_from_domain(net_interface* interface)
{
net_domain_private* domain = (net_domain_private*)interface->domain;
invalidate_routes(domain, interface);
list_remove_item(&domain->interfaces, interface);
notify_interface_removed(interface);
delete_interface((net_interface_private*)interface);
return B_OK;
}
status_t
domain_interface_control(net_domain_private* domain, int32 option,
ifreq* request)
{
const char* name = request->ifr_name;
status_t status = B_OK;
net_device_interface* device = get_device_interface(name, false);
if (device == NULL)
return ENODEV;
RecursiveLocker _(domain->lock);
net_interface* interface = find_interface(domain, name);
if (interface != NULL) {
switch (option) {
case SIOCDIFADDR:
remove_interface_from_domain(interface);
break;
case SIOCSIFFLAGS:
{
uint32 oldFlags = interface->flags;
uint32 requestFlags = request->ifr_flags;
request->ifr_flags &= ~(IFF_UP | IFF_LINK | IFF_BROADCAST);
if ((requestFlags & IFF_UP) != (interface->flags & IFF_UP)) {
if ((requestFlags & IFF_UP) != 0) {
status = interface->first_info->interface_up(
interface->first_protocol);
if (status == B_OK)
interface->flags |= IFF_UP;
} else {
interface_set_down(interface);
}
}
if (status == B_OK) {
// TODO: why shouldn't we able to delete IFF_BROADCAST?
interface->flags &= IFF_UP | IFF_LINK | IFF_BROADCAST;
interface->flags |= request->ifr_flags;
}
if (oldFlags != interface->flags) {
notify_interface_changed(interface, oldFlags,
interface->flags);
}
break;
}
}
}
// If the SIOCDIFADDR call above removed the last interface associated with
// the device interface, this will effectively remove the interface
put_device_interface(device);
return status;
}
/*! You need to hold the domain lock when calling this function. */
void
domain_interface_went_down(net_interface* interface)
{
ASSERT_LOCKED_RECURSIVE(&((net_domain_private*)interface->domain)->lock);
TRACE(("domain_interface_went_down(%i, %s)\n",
interface->domain->family, interface->name));
invalidate_routes(interface->domain, interface);
}
void
domain_removed_device_interface(net_device_interface* deviceInterface)
{
MutexLocker locker(sDomainLock);
DomainList::Iterator iterator = sDomains.GetIterator();
while (net_domain_private* domain = iterator.Next()) {
RecursiveLocker locker(domain->lock);
net_interface_private* interface = find_interface(domain,
deviceInterface->device->name);
if (interface == NULL)
continue;
remove_interface_from_domain(interface);
}
}
status_t
register_domain(int family, const char* name,
struct net_protocol_module_info* module,
@ -367,8 +132,6 @@ register_domain(int family, const char* name,
domain->module = module;
domain->address_module = addressModule;
list_init(&domain->interfaces);
sDomains.Add(domain);
*_domain = domain;
@ -387,16 +150,6 @@ unregister_domain(net_domain* _domain)
sDomains.Remove(domain);
net_interface_private* interface = NULL;
while (true) {
interface = (net_interface_private*)list_remove_head_item(
&domain->interfaces);
if (interface == NULL)
break;
delete_interface(interface);
}
recursive_lock_destroy(&domain->lock);
delete domain;
return B_OK;

View File

@ -28,23 +28,14 @@ struct net_domain_private : net_domain,
};
status_t init_domains();
status_t uninit_domains();
uint32 count_domain_interfaces();
status_t list_domain_interfaces(void* buffer, size_t* _bufferSize);
status_t add_interface_to_domain(net_domain* domain, struct ifreq& request);
status_t remove_interface_from_domain(net_interface* interface);
void domain_interface_went_down(net_interface* interface);
void domain_removed_device_interface(net_device_interface* interface);
status_t domain_interface_control(net_domain_private* domain, int32 option,
struct ifreq* request);
net_domain* get_domain(int family);
status_t register_domain(int family, const char* name,
struct net_protocol_module_info* module,
struct net_address_module_info* addressModule, net_domain* *_domain);
status_t unregister_domain(net_domain* domain);
status_t init_domains();
status_t uninit_domains();
#endif // DOMAINS_H

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
* Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -9,93 +9,175 @@
#define INTERFACES_H
#include "routes.h"
#include "stack_private.h"
#include <net_datalink.h>
#include <net_stack.h>
#include <Referenceable.h>
#include <util/DoublyLinkedList.h>
#include <util/OpenHashTable.h>
struct net_device_handler : DoublyLinkedListLinkImpl<net_device_handler> {
net_receive_func func;
int32 type;
void* cookie;
struct net_device_interface;
struct InterfaceAddress : DoublyLinkedListLinkImpl<InterfaceAddress>,
net_interface_address, Referenceable {
InterfaceAddress();
InterfaceAddress(net_interface* interface,
net_domain* domain);
virtual ~InterfaceAddress();
status_t SetTo(const ifaliasreq& request);
status_t SetLocal(const sockaddr* to);
status_t SetDestination(const sockaddr* to);
status_t SetMask(const sockaddr* to);
sockaddr** AddressFor(int32 option);
InterfaceAddress*& HashTableLink() { return fLink; }
#if ENABLE_DEBUGGER_COMMANDS
void Dump(size_t index = 0,
bool hideInterface = false);
#endif
static status_t Set(sockaddr** _address, const sockaddr* to);
static sockaddr* Prepare(sockaddr** _address, size_t length);
private:
void _Init(net_interface* interface,
net_domain* domain);
private:
InterfaceAddress* fLink;
};
typedef DoublyLinkedList<net_device_handler> DeviceHandlerList;
typedef DoublyLinkedList<InterfaceAddress> AddressList;
typedef DoublyLinkedList<net_device_monitor,
DoublyLinkedListCLink<net_device_monitor> > DeviceMonitorList;
struct domain_datalink {
domain_datalink* hash_link;
net_domain* domain;
struct net_device_interface : DoublyLinkedListLinkImpl<net_device_interface> {
struct net_device* device;
thread_id reader_thread;
uint32 up_count;
// a device can be brought up by more than one interface
int32 ref_count;
struct net_datalink_protocol* first_protocol;
struct net_datalink_protocol_module_info* first_info;
net_deframe_func deframe_func;
int32 deframe_ref_count;
DeviceMonitorList monitor_funcs;
DeviceHandlerList receive_funcs;
recursive_lock receive_lock;
thread_id consumer_thread;
net_fifo receive_queue;
};
typedef DoublyLinkedList<net_device_interface> DeviceInterfaceList;
struct net_interface_private : net_interface {
char base_name[IF_NAMESIZE];
net_device_interface* device_interface;
// support for binding to an interface
net_route_private direct_route;
InterfaceAddress direct_address;
};
struct DatalinkHashDefinition {
typedef const int KeyType;
typedef domain_datalink ValueType;
DatalinkHashDefinition()
{
}
size_t HashKey(const KeyType& key) const
{
return (size_t)key;
}
size_t Hash(domain_datalink* datalink) const
{
return datalink->domain->family;
}
bool Compare(const KeyType& key, domain_datalink* datalink) const
{
return datalink->domain->family == key;
}
domain_datalink*& GetLink(domain_datalink* datalink) const
{
return datalink->hash_link;
}
};
typedef BOpenHashTable<DatalinkHashDefinition, true, true> DatalinkTable;
class Interface : public DoublyLinkedListLinkImpl<Interface>,
public net_interface, public Referenceable {
public:
Interface(const char* name,
net_device_interface* deviceInterface);
virtual ~Interface();
InterfaceAddress* FirstForFamily(int family);
InterfaceAddress* FirstUnconfiguredForFamily(int family);
InterfaceAddress* AddressForDestination(net_domain* domain,
const sockaddr* destination);
status_t AddAddress(InterfaceAddress* address);
void RemoveAddress(InterfaceAddress* address);
bool GetNextAddress(InterfaceAddress** _address);
status_t Control(net_domain* domain, int32 option,
ifreq& request, ifreq* userRequest,
size_t length);
recursive_lock& Lock() { return fLock; }
net_device_interface* DeviceInterface() { return fDeviceInterface; }
status_t CreateDomainDatalinkIfNeeded(
net_domain* domain);
domain_datalink* DomainDatalink(uint8 family);
domain_datalink* DomainDatalink(net_domain* domain)
{ return DomainDatalink(domain->family); }
#if ENABLE_DEBUGGER_COMMANDS
void Dump() const;
#endif
private:
status_t _SetUp();
void _SetDown();
InterfaceAddress* _FirstForFamily(int family);
status_t _AddDomainDatalink(net_domain* domain);
private:
recursive_lock fLock;
net_device_interface* fDeviceInterface;
AddressList fAddresses;
DatalinkTable fDatalinkTable;
};
typedef DoublyLinkedList<Interface> InterfaceList;
status_t init_interfaces();
status_t uninit_interfaces();
// interfaces
struct net_interface_private* find_interface(struct net_domain* domain,
const char* name);
struct net_interface_private* find_interface(struct net_domain* domain,
uint32 index);
void put_interface(struct net_interface_private* interface);
struct net_interface_private* get_interface(net_domain* domain,
const char* name);
status_t create_interface(net_domain* domain, const char* name,
const char* baseName, net_device_interface* deviceInterface,
struct net_interface_private** _interface);
void delete_interface(net_interface_private* interface);
void interface_set_down(net_interface* interface);
status_t add_interface(const char* name, net_domain_private* domain,
const ifaliasreq& request, net_device_interface* deviceInterface);
status_t remove_interface(Interface* interface);
void interface_went_down(Interface* interface);
// device interfaces
void get_device_interface_address(net_device_interface* interface,
sockaddr* address);
uint32 count_device_interfaces();
status_t list_device_interfaces(void* buffer, size_t* _bufferSize);
void put_device_interface(struct net_device_interface* interface);
struct net_device_interface* get_device_interface(uint32 index);
struct net_device_interface* get_device_interface(const char* name,
bool create = true);
void down_device_interface(net_device_interface* interface);
status_t add_interface_address(Interface* interface, net_domain_private* domain,
const ifaliasreq& request);
status_t update_interface_address(InterfaceAddress* interfaceAddress,
int32 option, const sockaddr* oldAddress, const sockaddr* newAddress);
Interface* get_interface(net_domain* domain, uint32 index);
Interface* get_interface(net_domain* domain, const char* name);
Interface* get_interface_for_device(net_domain* domain, uint32 index);
InterfaceAddress* get_interface_address(const struct sockaddr* address);
InterfaceAddress* get_interface_address_for_destination(net_domain* domain,
const struct sockaddr* destination);
InterfaceAddress* get_interface_address_for_link(net_domain* domain,
const struct sockaddr* linkAddress, bool unconfiguredOnly);
uint32 count_interfaces();
status_t list_interfaces(int family, void* buffer, size_t* _bufferSize);
// devices
status_t unregister_device_deframer(net_device* device);
status_t register_device_deframer(net_device* device, net_deframe_func deframeFunc);
status_t register_domain_device_handler(struct net_device* device, int32 type,
struct net_domain* domain);
status_t register_device_handler(struct net_device* device, int32 type,
net_receive_func receiveFunc, void* cookie);
status_t unregister_device_handler(struct net_device* device, int32 type);
status_t register_device_monitor(struct net_device* device,
struct net_device_monitor* monitor);
status_t unregister_device_monitor(struct net_device* device,
struct net_device_monitor* monitor);
status_t device_link_changed(net_device* device);
status_t device_removed(net_device* device);
status_t device_enqueue_buffer(net_device* device, net_buffer* buffer);
#endif // INTERFACES_H

View File

@ -1,16 +1,18 @@
/*
* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
* Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, axeld@pinc-software.de
*/
//! The net_protocol one talks to when using the AF_LINK protocol
#include "datalink.h"
#include "device_interfaces.h"
#include "domains.h"
#include "interfaces.h"
#include "link.h"
#include "stack_private.h"
#include "utility.h"

View File

@ -28,6 +28,7 @@
#include <sys/uio.h>
#include "ancillary_data.h"
#include "interfaces.h"
#include "paranoia_config.h"
@ -127,6 +128,10 @@ struct data_node {
}
};
// TODO: we should think about moving the address fields into the buffer
// data itself via associated data or something like this. Or this
// structure as a whole, too...
struct net_buffer_private : net_buffer {
struct list buffers;
data_header* allocation_header;
@ -578,15 +583,24 @@ private:
static void
dump_address(const char* prefix, sockaddr* address)
dump_address(const char* prefix, sockaddr* address,
net_interface_address* interfaceAddress)
{
if (address == NULL || address->sa_len == 0)
return;
dprintf(" %s: length %u, family %u\n", prefix, address->sa_len,
address->sa_family);
if (interfaceAddress == NULL || interfaceAddress->domain == NULL) {
dprintf(" %s: length %u, family %u\n", prefix, address->sa_len,
address->sa_family);
dump_block((char*)address + 2, address->sa_len - 2, " ");
dump_block((char*)address + 2, address->sa_len - 2, " ");
} else {
char buffer[64];
interfaceAddress->domain->address_module->print_address_buffer(address,
buffer, sizeof(buffer), true);
dprintf(" %s: %s\n", prefix, buffer);
}
}
@ -596,11 +610,11 @@ dump_buffer(net_buffer* _buffer)
net_buffer_private* buffer = (net_buffer_private*)_buffer;
dprintf("buffer %p, size %" B_PRIu32 ", flags %" B_PRIx32 ", stored header "
"%" B_PRIu32 "\n", buffer, buffer->size, buffer->flags,
buffer->stored_header_length);
"%" B_PRIu32 ", interface address %p\n", buffer, buffer->size,
buffer->flags, buffer->stored_header_length, buffer->interface_address);
dump_address("source", buffer->source);
dump_address("destination", buffer->destination);
dump_address("source", buffer->source, buffer->interface_address);
dump_address("destination", buffer->destination, buffer->interface_address);
data_node* node = NULL;
while ((node = (data_node*)list_get_next_item(&buffer->buffers, node))
@ -1060,7 +1074,7 @@ copy_metadata(net_buffer* destination, const net_buffer* source)
min_c(source->destination->sa_len, sizeof(sockaddr_storage)));
destination->flags = source->flags;
destination->interface = source->interface;
destination->interface_address = source->interface_address;
destination->offset = source->offset;
destination->protocol = source->protocol;
destination->type = source->type;
@ -1107,13 +1121,11 @@ create_buffer(size_t headerSpace)
buffer->storage.source.ss_len = 0;
buffer->storage.destination.ss_len = 0;
buffer->interface = NULL;
buffer->interface_address = NULL;
buffer->offset = 0;
buffer->flags = 0;
buffer->size = 0;
buffer->type = -1;
CHECK_BUFFER(buffer);
CREATE_PARANOIA_CHECK_SET(buffer, "net_buffer");
SET_PARANOIA_CHECK(PARANOIA_SUSPICIOUS, buffer, &buffer->size,
@ -2086,23 +2098,29 @@ status_t
restore_header(net_buffer* _buffer, uint32 offset, void* data, size_t bytes)
{
net_buffer_private* buffer = (net_buffer_private*)_buffer;
data_node* node = (data_node*)list_get_first_item(&buffer->buffers);
if (node == NULL
|| offset + bytes > buffer->stored_header_length + buffer->size)
return B_BAD_VALUE;
// We have the data, so copy it out
memcpy(data, node->start - buffer->stored_header_length,
std::min(bytes, buffer->stored_header_length));
if (bytes <= buffer->stored_header_length)
return B_OK;
if (offset < buffer->stored_header_length) {
data_node* node = (data_node*)list_get_first_item(&buffer->buffers);
if (node == NULL
|| offset + bytes > buffer->stored_header_length + buffer->size)
return B_BAD_VALUE;
data = (uint8*)data + buffer->stored_header_length;
bytes -= buffer->stored_header_length;
// We have the data, so copy it out
return read_data(_buffer, 0, data, bytes);
size_t copied = std::min(bytes, buffer->stored_header_length - offset);
memcpy(data, node->start + offset - buffer->stored_header_length,
copied);
if (copied == bytes)
return B_OK;
data = (uint8*)data + copied;
bytes -= copied;
offset = 0;
} else
offset -= buffer->stored_header_length;
return read_data(_buffer, offset, data, bytes);
}
@ -2116,25 +2134,30 @@ append_restored_header(net_buffer* buffer, net_buffer* _source, uint32 offset,
size_t bytes)
{
net_buffer_private* source = (net_buffer_private*)_source;
data_node* node = (data_node*)list_get_first_item(&source->buffers);
if (node == NULL
|| offset + bytes > source->stored_header_length + source->size)
return B_BAD_VALUE;
// We have the data, so copy it out
if (offset < source->stored_header_length) {
data_node* node = (data_node*)list_get_first_item(&source->buffers);
if (node == NULL
|| offset + bytes > source->stored_header_length + source->size)
return B_BAD_VALUE;
status_t status = append_data(buffer,
node->start - source->stored_header_length,
std::min(bytes, source->stored_header_length));
if (status != B_OK)
return status;
// We have the data, so copy it out
if (bytes <= source->stored_header_length)
return B_OK;
size_t appended = std::min(bytes, source->stored_header_length - offset);
status_t status = append_data(buffer,
node->start + offset - source->stored_header_length, appended);
if (status != B_OK)
return status;
bytes -= source->stored_header_length;
if (appended == bytes)
return B_OK;
return append_cloned_data(buffer, source, 0, bytes);
bytes -= appended;
offset = 0;
} else
offset -= source->stored_header_length;
return append_cloned_data(buffer, source, offset, bytes);
}

View File

@ -31,9 +31,9 @@
//#define TRACE_ROUTES
#ifdef TRACE_ROUTES
# define TRACE(x) dprintf x
# define TRACE(x...) dprintf(STACK_DEBUG_PREFIX x)
#else
# define TRACE(x) ;
# define TRACE(x...) ;
#endif
@ -131,8 +131,9 @@ find_route(struct net_domain* _domain, const net_route* description)
if ((route->flags & RTF_DEFAULT) != 0
&& (description->flags & RTF_DEFAULT) != 0) {
// there can only be one default route per interface
if (route->interface == description->interface)
// there can only be one default route per interface address family
// TODO: check this better
if (route->interface_address == description->interface_address)
return route;
continue;
@ -147,8 +148,8 @@ find_route(struct net_domain* _domain, const net_route* description)
description->mask)
&& domain->address_module->equal_addresses(route->gateway,
description->gateway)
&& (description->interface == NULL
|| description->interface == route->interface))
&& (description->interface_address == NULL
|| description->interface_address == route->interface_address))
return route;
}
@ -166,8 +167,8 @@ find_route(net_domain* _domain, const sockaddr* address)
RouteList::Iterator iterator = domain->routes.GetIterator();
net_route_private* candidate = NULL;
TRACE(("test address %s for routes...\n",
AddressString(domain, address).Data()));
TRACE("test address %s for routes...\n",
AddressString(domain, address).Data());
// TODO: alternate equal default routes
@ -186,17 +187,18 @@ find_route(net_domain* _domain, const sockaddr* address)
continue;
// neglect routes that point to devices that have no link
if ((route->interface->device->flags & IFF_LINK) == 0) {
if ((route->interface_address->interface->device->flags & IFF_LINK)
== 0) {
if (candidate == NULL) {
TRACE((" found candidate: %s, flags %lx\n", AddressString(
domain, route->destination).Data(), route->flags));
TRACE(" found candidate: %s, flags %lx\n", AddressString(
domain, route->destination).Data(), route->flags);
candidate = route;
}
continue;
}
TRACE((" found route: %s, flags %lx\n",
AddressString(domain, route->destination).Data(), route->flags));
TRACE(" found route: %s, flags %lx\n",
AddressString(domain, route->destination).Data(), route->flags);
return route;
}
@ -215,6 +217,9 @@ put_route_internal(struct net_domain_private* domain, net_route* _route)
return;
// delete route - it must already have been removed at this point
if (route->interface_address != NULL)
((InterfaceAddress*)route->interface_address)->ReleaseReference();
delete route;
}
@ -234,7 +239,7 @@ get_route_internal(struct net_domain_private* domain,
while (iterator.HasNext()) {
route = iterator.Next();
net_device* device = route->interface->device;
net_device* device = route->interface_address->interface->device;
if ((link->sdl_nlen > 0
&& !strncmp(device->name, (const char*)link->sdl_data,
@ -291,7 +296,7 @@ fill_route_entry(route_entry* target, void* _buffer, size_t bufferSize,
target->destination = copy_address(buffer, route->destination);
target->mask = copy_address(buffer, route->mask);
target->gateway = copy_address(buffer, route->gateway);
target->source = copy_address(buffer, route->interface->address);
target->source = copy_address(buffer, route->interface_address->local);
target->flags = route->flags;
target->mtu = route->mtu;
@ -375,7 +380,8 @@ list_routes(net_domain_private* domain, void* buffer, size_t size)
return ENOBUFS;
ifreq request;
strlcpy(request.ifr_name, route->interface->name, IF_NAMESIZE);
strlcpy(request.ifr_name, route->interface_address->interface->name,
IF_NAMESIZE);
request.ifr_route.destination = destination;
request.ifr_route.mask = mask;
request.ifr_route.gateway = gateway;
@ -402,10 +408,10 @@ list_routes(net_domain_private* domain, void* buffer, size_t size)
status_t
control_routes(struct net_interface* interface, int32 option, void* argument,
size_t length)
control_routes(struct net_interface* _interface, net_domain* domain,
int32 option, void* argument, size_t length)
{
net_domain_private* domain = (net_domain_private*)interface->domain;
Interface* interface = (Interface*)_interface;
switch (option) {
case SIOCADDRT:
@ -429,14 +435,20 @@ control_routes(struct net_interface* interface, int32 option, void* argument,
!= B_OK)
return status;
InterfaceAddress* address
= interface->FirstForFamily(domain->family);
route.mtu = entry.mtu;
route.flags = entry.flags;
route.interface = interface;
route.interface_address = address;
if (option == SIOCADDRT)
return add_route(domain, &route);
status = add_route(domain, &route);
else
status = remove_route(domain, &route);
return remove_route(domain, &route);
address->ReleaseReference();
return status;
}
}
return B_BAD_VALUE;
@ -448,16 +460,20 @@ add_route(struct net_domain* _domain, const struct net_route* newRoute)
{
struct net_domain_private* domain = (net_domain_private*)_domain;
TRACE(("add route to domain %s: dest %s, mask %s, gw %s, flags %lx\n",
TRACE("add route to domain %s: dest %s, mask %s, gw %s, flags %lx\n",
domain->name,
AddressString(domain, newRoute->destination ? newRoute->destination : NULL).Data(),
AddressString(domain, newRoute->destination
? newRoute->destination : NULL).Data(),
AddressString(domain, newRoute->mask ? newRoute->mask : NULL).Data(),
AddressString(domain, newRoute->gateway ? newRoute->gateway : NULL).Data(),
newRoute->flags));
AddressString(domain, newRoute->gateway
? newRoute->gateway : NULL).Data(),
newRoute->flags);
if (domain == NULL || newRoute == NULL || newRoute->interface == NULL
if (domain == NULL || newRoute == NULL
|| newRoute->interface_address == NULL
|| ((newRoute->flags & RTF_HOST) != 0 && newRoute->mask != NULL)
|| ((newRoute->flags & RTF_DEFAULT) == 0 && newRoute->destination == NULL)
|| ((newRoute->flags & RTF_DEFAULT) == 0
&& newRoute->destination == NULL)
|| ((newRoute->flags & RTF_GATEWAY) != 0 && newRoute->gateway == NULL)
|| !domain->address_module->check_mask(newRoute->mask))
return B_BAD_VALUE;
@ -484,7 +500,8 @@ add_route(struct net_domain* _domain, const struct net_route* newRoute)
}
route->flags = newRoute->flags;
route->interface = newRoute->interface;
route->interface_address = newRoute->interface_address;
((InterfaceAddress*)route->interface_address)->AcquireReference();
route->mtu = 0;
route->ref_count = 1;
@ -504,8 +521,8 @@ add_route(struct net_domain* _domain, const struct net_route* newRoute)
&& (before->flags & RTF_DEFAULT) != 0) {
// both routes are equal - let the link speed decide the
// order
if (before->interface->device->link_speed
< route->interface->device->link_speed)
if (before->interface_address->interface->device->link_speed
< route->interface_address->interface->device->link_speed)
break;
}
}
@ -522,12 +539,15 @@ remove_route(struct net_domain* _domain, const struct net_route* removeRoute)
{
struct net_domain_private* domain = (net_domain_private*)_domain;
TRACE(("remove route from domain %s: dest %s, mask %s, gw %s, flags %lx\n",
TRACE("remove route from domain %s: dest %s, mask %s, gw %s, flags %lx\n",
domain->name,
AddressString(domain, removeRoute->destination ? removeRoute->destination : NULL).Data(),
AddressString(domain, removeRoute->mask ? removeRoute->mask : NULL).Data(),
AddressString(domain, removeRoute->gateway ? removeRoute->gateway : NULL).Data(),
removeRoute->flags));
AddressString(domain, removeRoute->destination
? removeRoute->destination : NULL).Data(),
AddressString(domain, removeRoute->mask
? removeRoute->mask : NULL).Data(),
AddressString(domain, removeRoute->gateway
? removeRoute->gateway : NULL).Data(),
removeRoute->flags);
RecursiveLocker locker(domain->lock);
@ -578,9 +598,8 @@ get_route_information(struct net_domain* _domain, void* value, size_t length)
void
invalidate_routes(net_domain* _domain, net_interface* interface)
{
// this function is called with the domain locked
// (see domain_interface_went_down)
net_domain_private* domain = (net_domain_private*)_domain;
RecursiveLocker locker(domain->lock);
dprintf("invalidate_routes(%i, %s)\n", domain->family, interface->name);
@ -588,7 +607,7 @@ invalidate_routes(net_domain* _domain, net_interface* interface)
while (iterator.HasNext()) {
net_route* route = iterator.Next();
if (route->interface->index == interface->index)
if (route->interface_address->interface == interface)
remove_route(domain, route);
}
}
@ -605,28 +624,20 @@ get_route(struct net_domain* _domain, const struct sockaddr* address)
status_t
get_device_route(struct net_domain* _domain, uint32 index, net_route** _route)
get_device_route(struct net_domain* domain, uint32 index, net_route** _route)
{
net_domain_private* domain = (net_domain_private*)_domain;
Interface* interface = get_interface_for_device(domain, index);
if (interface == NULL)
return ENETUNREACH;
RecursiveLocker _(domain->lock);
net_route_private* route
= &interface->DomainDatalink(domain->family)->direct_route;
net_interface_private* interface = NULL;
atomic_add(&route->ref_count, 1);
*_route = route;
while (true) {
interface = (net_interface_private*)list_get_next_item(
&domain->interfaces, interface);
if (interface == NULL)
break;
if (interface->device->index == index) {
atomic_add(&interface->direct_route.ref_count, 1);
*_route = &interface->direct_route;
return B_OK;
}
}
return ENETUNREACH;
interface->ReleaseReference();
return B_OK;
}
@ -647,9 +658,10 @@ get_buffer_route(net_domain* _domain, net_buffer* buffer, net_route** _route)
// TODO: we are quite relaxed in the address checking here
// as we might proceed with source = INADDR_ANY.
if (route->interface != NULL && route->interface->address != NULL) {
if (route->interface_address != NULL
&& route->interface_address->local != NULL) {
status = domain->address_module->update_to(source,
route->interface->address);
route->interface_address->local);
}
if (status != B_OK)

View File

@ -31,7 +31,7 @@ typedef DoublyLinkedList<net_route_info,
uint32 route_table_size(struct net_domain_private* domain);
status_t list_routes(struct net_domain_private* domain, void* buffer,
size_t size);
status_t control_routes(struct net_interface* interface,
status_t control_routes(struct net_interface* interface, net_domain* domain,
int32 option, void* argument, size_t length);
status_t add_route(struct net_domain* domain,

View File

@ -1,5 +1,5 @@
/*
* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
* Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -8,6 +8,7 @@
#include "ancillary_data.h"
#include "device_interfaces.h"
#include "domains.h"
#include "interfaces.h"
#include "link.h"
@ -501,9 +502,9 @@ put_domain_protocols(net_socket* socket)
static void
uninit_domain_datalink_protocols(net_interface* interface)
uninit_domain_datalink_protocols(domain_datalink* datalink)
{
net_datalink_protocol* protocol = interface->first_protocol;
net_datalink_protocol* protocol = datalink->first_protocol;
while (protocol != NULL) {
net_datalink_protocol* next = protocol->next;
protocol->module->uninit_protocol(protocol);
@ -511,22 +512,21 @@ uninit_domain_datalink_protocols(net_interface* interface)
protocol = next;
}
interface->first_protocol = NULL;
interface->first_info = NULL;
datalink->first_protocol = NULL;
datalink->first_info = NULL;
}
status_t
get_domain_datalink_protocols(net_interface* _interface)
get_domain_datalink_protocols(Interface* interface, net_domain* domain)
{
struct net_interface_private* interface = (net_interface_private*)_interface;
struct chain* chain;
{
MutexLocker _(sChainLock);
chain = chain::Lookup(sDatalinkProtocolChains, interface->domain->family,
interface->device_interface->device->type, 0);
chain = chain::Lookup(sDatalinkProtocolChains, domain->family,
interface->DeviceInterface()->device->type, 0);
if (chain == NULL)
return EAFNOSUPPORT;
}
@ -542,21 +542,26 @@ get_domain_datalink_protocols(net_interface* _interface)
for (int32 i = 0; chain->infos[i] != NULL; i++) {
net_datalink_protocol* protocol;
status_t status = ((net_datalink_protocol_module_info*)
chain->infos[i])->init_protocol(interface, &protocol);
if (status < B_OK) {
chain->infos[i])->init_protocol(interface, domain, &protocol);
if (status != B_OK) {
// free protocols we already initialized
uninit_domain_datalink_protocols(interface);
uninit_domain_datalink_protocols(
interface->DomainDatalink(domain->family));
chain->Release();
return status;
}
protocol->module = (net_datalink_protocol_module_info*)chain->infos[i];
protocol->interface = interface;
protocol->domain = domain;
protocol->next = NULL;
if (last == NULL) {
interface->first_protocol = protocol;
interface->first_info = protocol->module;
domain_datalink* datalink
= interface->DomainDatalink(domain->family);
datalink->first_protocol = protocol;
datalink->first_info = protocol->module;
} else
last->next = protocol;
@ -568,21 +573,20 @@ get_domain_datalink_protocols(net_interface* _interface)
status_t
put_domain_datalink_protocols(net_interface* _interface)
put_domain_datalink_protocols(Interface* interface, net_domain* domain)
{
struct net_interface_private* interface = (net_interface_private*)_interface;
struct chain* chain;
{
MutexLocker _(sChainLock);
chain = chain::Lookup(sDatalinkProtocolChains, interface->domain->family,
interface->device_interface->device->type, 0);
chain = chain::Lookup(sDatalinkProtocolChains, domain->family,
interface->DeviceInterface()->device->type, 0);
if (chain == NULL)
return B_ERROR;
}
uninit_domain_datalink_protocols(interface);
uninit_domain_datalink_protocols(interface->DomainDatalink(domain->family));
chain->Release();
return B_OK;
}
@ -756,10 +760,14 @@ init_stack()
if (status != B_OK)
goto err1;
status = init_timers();
status = init_device_interfaces();
if (status != B_OK)
goto err2;
status = init_timers();
if (status != B_OK)
goto err3;
status = init_notifications();
if (status < B_OK) {
// If this fails, it just means there won't be any notifications,
@ -771,7 +779,7 @@ init_stack()
module_info* dummy;
status = get_module(NET_SOCKET_MODULE_NAME, &dummy);
if (status != B_OK)
goto err3;
goto err4;
mutex_init(&sChainLock, "net chains");
mutex_init(&sInitializeChainLock, "net intialize chains");
@ -816,7 +824,6 @@ init_stack()
register_domain_datalink_protocols(AF_INET6, IFT_LOOP,
"network/datalink_protocols/loopback_frame/v1", NULL);
register_domain_datalink_protocols(AF_INET, IFT_ETHER,
"network/datalink_protocols/ipv4_datagram/v1",
"network/datalink_protocols/arp/v1",
"network/datalink_protocols/ethernet_frame/v1",
NULL);
@ -836,8 +843,10 @@ err6:
err5:
mutex_destroy(&sInitializeChainLock);
mutex_destroy(&sChainLock);
err3:
err4:
uninit_timers();
err3:
uninit_device_interfaces();
err2:
uninit_interfaces();
err1:
@ -853,6 +862,7 @@ uninit_stack()
put_module(NET_SOCKET_MODULE_NAME);
uninit_timers();
uninit_device_interfaces();
uninit_interfaces();
uninit_domains();
uninit_notifications();

View File

@ -18,6 +18,14 @@
#include <net_stack_interface.h>
// Stack-wide configuration
#define ENABLE_DEBUGGER_COMMANDS 1
#define STACK_DEBUG_PREFIX "\33[31mnet:\33[0m "
class Interface;
extern net_stack_module_info gNetStackModule;
extern net_buffer_module_info gNetBufferModule;
extern net_socket_module_info gNetSocketModule;
@ -28,10 +36,12 @@ extern net_stack_interface_module_info gNetStackInterfaceModule;
// stack.cpp
status_t register_domain_datalink_protocols(int family, int type, ...);
status_t register_domain_protocols(int family, int type, int protocol, ...);
status_t get_domain_protocols(net_socket *socket);
status_t put_domain_protocols(net_socket *socket);
status_t get_domain_datalink_protocols(net_interface *interface);
status_t put_domain_datalink_protocols(net_interface *interface);
status_t get_domain_protocols(net_socket* socket);
status_t put_domain_protocols(net_socket* socket);
status_t get_domain_datalink_protocols(Interface* interface,
net_domain* domain);
status_t put_domain_datalink_protocols(Interface* interface,
net_domain* domain);
// notifications.cpp
status_t notify_interface_added(net_interface* interface);

View File

@ -1,13 +1,15 @@
/*
* Copyright 2007, Haiku Inc. All rights reserved.
* Copyright 2007-2010, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Hugo Santos <hugosantos@gmail.com>
*/
#include <sys/sockio.h>
#include <termios.h>
#include <Drivers.h>
#include <tty.h>
#include <scsi.h>
@ -16,6 +18,7 @@
#include "Syscall.h"
#include "TypeHandler.h"
struct ioctl_info {
int index;
const char *name;
@ -83,7 +86,7 @@ static const ioctl_info kIOCtls[] = {
IOCTL_INFO_ENTRY_TYPE(SIOCGIFMETRIC, struct ifreq *),
IOCTL_INFO_ENTRY_TYPE(SIOCSIFMETRIC, struct ifreq *),
IOCTL_INFO_ENTRY_TYPE(SIOCDIFADDR, struct ifreq *),
IOCTL_INFO_ENTRY_TYPE(SIOCAIFADDR, struct ifreq *),
IOCTL_INFO_ENTRY_TYPE(SIOCAIFADDR, struct ifaliasreq *),
IOCTL_INFO_ENTRY(SIOCADDMULTI),
IOCTL_INFO_ENTRY(SIOCDELMULTI),
IOCTL_INFO_ENTRY_TYPE(SIOCGIFMTU, struct ifreq *),
@ -93,7 +96,6 @@ static const ioctl_info kIOCtls[] = {
IOCTL_INFO_ENTRY(SIOCGRTSIZE),
IOCTL_INFO_ENTRY(SIOCGRTTABLE),
IOCTL_INFO_ENTRY_TYPE(SIOCGIFSTATS, struct ifreq *),
IOCTL_INFO_ENTRY_TYPE(SIOCGIFPARAM, struct ifreq *),
IOCTL_INFO_ENTRY(SIOCGIFTYPE),
IOCTL_INFO_ENTRY(SIOCSPACKETCAP),
IOCTL_INFO_ENTRY(SIOCCPACKETCAP),

View File

@ -541,32 +541,29 @@ list_interface(const char* name, int addressFamily)
char address[256];
strcpy(address, "none");
if (ioctl(socket, SIOCGIFPARAM, &request, sizeof(struct ifreq)) == 0) {
prepare_request(request, request.ifr_parameter.device);
if (ioctl(linkSocket, SIOCGIFADDR, &request, sizeof(struct ifreq))
== 0) {
sockaddr_dl &link = *(sockaddr_dl*)&request.ifr_addr;
if (ioctl(linkSocket, SIOCGIFADDR, &request, sizeof(struct ifreq))
== 0) {
sockaddr_dl &link = *(sockaddr_dl*)&request.ifr_addr;
switch (link.sdl_type) {
case IFT_ETHER:
{
type = "Ethernet";
switch (link.sdl_type) {
case IFT_ETHER:
{
type = "Ethernet";
if (link.sdl_alen > 0) {
uint8 *mac = (uint8*)LLADDR(&link);
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;
if (link.sdl_alen > 0) {
uint8 *mac = (uint8*)LLADDR(&link);
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;
}
}
@ -778,10 +775,12 @@ configure_interface(const char* name, char* const* args,
if (index == 0) {
// the interface does not exist yet, we have to add it first
request.ifr_parameter.base_name[0] = '\0';
request.ifr_parameter.device[0] = '\0';
request.ifr_parameter.sub_type = 0;
// the default device is okay for us
ifaliasreq request;
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,

View File

@ -64,7 +64,7 @@ get_string(const char* val, const char* sep, u_int8_t* buf, int* lenp)
if (hexstr)
printf("%s: hexadecimal digits too long", __func__);
else
printf("string too long", __func__);
printf("%s: string too long", __func__);
return NULL;
}
if (hexstr) {

View File

@ -176,18 +176,11 @@ pcap_open_live(const char *device, int snapLength, int /*promisc*/,
return NULL;
}
// get link level interface for this interface
if (ioctl(socket, SIOCGIFPARAM, &request, sizeof(struct ifreq)) < 0) {
snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "Cannot get link level: %s\n",
strerror(errno));
close(socket);
return NULL;
}
close(socket);
// no longer needed after this point
// get link level interface for this interface
socket = ::socket(AF_LINK, SOCK_DGRAM, 0);
if (socket < 0) {
snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "No link level: %s\n",
@ -196,7 +189,6 @@ pcap_open_live(const char *device, int snapLength, int /*promisc*/,
}
// start monitoring
prepare_request(request, request.ifr_parameter.device);
if (ioctl(socket, SIOCSPACKETCAP, &request, sizeof(struct ifreq)) < 0) {
snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "Cannot start monitoring: %s\n",
strerror(errno));
@ -318,16 +310,12 @@ pcap_platform_finddevs(pcap_if_t** _allDevices, char* errorBuffer)
return -1;
}
if (ioctl(socket, SIOCGIFPARAM, &request, sizeof(struct ifreq))
if (ioctl(linkSocket, SIOCGIFADDR, &request, sizeof(struct ifreq))
== 0) {
prepare_request(request, request.ifr_parameter.device);
if (ioctl(linkSocket, SIOCGIFADDR, &request,
sizeof(struct ifreq)) == 0) {
sockaddr_dl &link = *(sockaddr_dl*)&request.ifr_addr;
sockaddr_dl &link = *(sockaddr_dl*)&request.ifr_addr;
if (link.sdl_type == IFT_LOOP)
flags = IFF_LOOPBACK;
}
if (link.sdl_type == IFT_LOOP)
flags = IFF_LOOPBACK;
}
close(linkSocket);
}

View File

@ -503,6 +503,8 @@ DHCPClient::_Negotiate(dhcp_state state)
case DHCP_OFFER:
{
syslog(LOG_DEBUG, "DHCP received offer for %s\n", Device());
// first offer wins
if (state != INIT)
break;
@ -537,6 +539,7 @@ DHCPClient::_Negotiate(dhcp_state state)
case DHCP_ACK:
{
syslog(LOG_DEBUG, "DHCP received ack for %s\n", Device());
if (state != REQUESTING && state != REBINDING
&& state != RENEWAL)
continue;
@ -565,6 +568,8 @@ DHCPClient::_Negotiate(dhcp_state state)
}
case DHCP_NACK:
syslog(LOG_DEBUG, "DHCP received nack for %s\n", Device());
if (state != REQUESTING)
continue;
@ -638,7 +643,7 @@ DHCPClient::_ParseOptions(dhcp_message& message, BMessage& address,
case OPTION_DOMAIN_NAME_SERVER:
{
for (uint32 i = 0; i < size / 4; i++) {
syslog(LOG_INFO, "DNS: %s\n",
syslog(LOG_INFO, "DHCP for %s got DNS: %s\n", Device(),
_ToString(&data[i * 4]).String());
resolverConfiguration.AddString("nameserver",
_ToString(&data[i * 4]).String());
@ -770,8 +775,8 @@ DHCPClient::_TimeoutShift(int socket, time_t& timeout, uint32& tries)
if (++tries > 2)
return false;
}
syslog(LOG_DEBUG, "DHCP timeout shift: %lu secs (try %lu)\n", timeout,
tries);
syslog(LOG_DEBUG, "DHCP timeout shift for %s: %lu secs (try %lu)\n",
Device(), timeout, tries);
struct timeval value;
value.tv_sec = timeout;
@ -802,6 +807,9 @@ status_t
DHCPClient::_SendMessage(int socket, dhcp_message& message,
sockaddr_in& address) const
{
syslog(LOG_DEBUG, "DHCP send message %u for %s\n", message.Type(),
Device());
ssize_t bytesSent = sendto(socket, &message, message.Size(),
address.sin_addr.s_addr == INADDR_BROADCAST ? MSG_BCAST : 0,
(struct sockaddr*)&address, sizeof(sockaddr_in));

View File

@ -406,14 +406,10 @@ NetServer::_IsValidInterface(int socket, const char* name)
// check if it has a hardware address, too, in case of ethernet
if (ioctl(socket, SIOCGIFPARAM, &request, sizeof(struct ifreq)) < 0)
return false;
int linkSocket = ::socket(AF_LINK, SOCK_DGRAM, 0);
if (linkSocket < 0)
return false;
prepare_request(request, request.ifr_parameter.device);
if (ioctl(linkSocket, SIOCGIFADDR, &request, sizeof(struct ifreq)) < 0) {
close(linkSocket);
return false;
@ -623,10 +619,12 @@ NetServer::_ConfigureInterface(int socket, BMessage& interface,
if (interfaceIndex == 0) {
// we need to create the interface first
request.ifr_parameter.base_name[0] = '\0';
request.ifr_parameter.device[0] = '\0';
request.ifr_parameter.sub_type = 0;
// the default device is okay for us
ifaliasreq request;
strlcpy(request.ifra_name, device, 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", Name(),

View File

@ -159,11 +159,17 @@ private:
if (ioctl(fSocket, SIOCGIFINDEX, &request, sizeof(request)) < 0) {
// not known yet -- add it
request.ifr_parameter.base_name[0] = '\0';
request.ifr_parameter.device[0] = '\0';
request.ifr_parameter.sub_type = 0;
ifaliasreq aliasRequest;
strcpy(aliasRequest.ifra_name, path);
aliasRequest.ifra_addr.ss_family = AF_UNSPEC;
aliasRequest.ifra_addr.ss_len = 2;
aliasRequest.ifra_broadaddr.ss_family = AF_UNSPEC;
aliasRequest.ifra_broadaddr.ss_len = 2;
aliasRequest.ifra_mask.ss_family = AF_UNSPEC;
aliasRequest.ifra_mask.ss_len = 2;
if (ioctl(fSocket, SIOCAIFADDR, &request, sizeof(request)) < 0) {
if (ioctl(fSocket, SIOCAIFADDR, &aliasRequest,
sizeof(aliasRequest)) < 0) {
dprintf("NetStackInitializer: adding interface failed for "
"device %s: %s\n", path, strerror(errno));
return;