* 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:
@@ -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
|
mkfifo mkfs mkindex mktemp modifiers mount mount_nfs mountvolume mv
|
||||||
netcat netstat nl nohup notify nproc
|
netcat netstat nl nohup notify nproc
|
||||||
od open
|
od open
|
||||||
passwd paste patch pathchk pc ping play playfile playsound playwav pr prio
|
passwd paste patch pathchk pc ping ping6 play playfile playsound playwav
|
||||||
printenv printf profile ps ptx pwd
|
pr prio printenv printf profile ps ptx pwd
|
||||||
query quit
|
query quit
|
||||||
rc readlink ReadOnlyBootPrompt reindex release renice rlog rm rmattr
|
rc readlink ReadOnlyBootPrompt reindex release renice rlog rm rmattr
|
||||||
rmindex rmdir roster route
|
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_DEVICES = ethernet loopback ;
|
||||||
SYSTEM_NETWORK_DATALINK_PROTOCOLS = ethernet_frame <module>arp loopback_frame
|
SYSTEM_NETWORK_DATALINK_PROTOCOLS = ethernet_frame <module>arp loopback_frame ;
|
||||||
ipv4_datagram ;
|
#ipv6_datagram ;
|
||||||
#SYSTEM_NETWORK_PPP = ipcp modem pap pppoe ;
|
#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
|
SYSTEM_ADD_ONS_ACCELERANTS = $(X86_ONLY)radeon.accelerant
|
||||||
$(X86_ONLY)nvidia.accelerant $(X86_ONLY)matrox.accelerant
|
$(X86_ONLY)nvidia.accelerant $(X86_ONLY)matrox.accelerant
|
||||||
|
|||||||
@@ -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.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef _NET_IF_H
|
#ifndef _NET_IF_H
|
||||||
@@ -16,12 +16,6 @@
|
|||||||
|
|
||||||
#define IFNAMSIZ IF_NAMESIZE
|
#define IFNAMSIZ IF_NAMESIZE
|
||||||
|
|
||||||
struct ifreq_parameter {
|
|
||||||
char base_name[IF_NAMESIZE];
|
|
||||||
char device[128];
|
|
||||||
uint8_t sub_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ifreq_stream_stats {
|
struct ifreq_stream_stats {
|
||||||
uint32_t packets;
|
uint32_t packets;
|
||||||
uint32_t errors;
|
uint32_t errors;
|
||||||
@@ -43,7 +37,6 @@ struct ifreq {
|
|||||||
struct sockaddr ifr_dstaddr;
|
struct sockaddr ifr_dstaddr;
|
||||||
struct sockaddr ifr_broadaddr;
|
struct sockaddr ifr_broadaddr;
|
||||||
struct sockaddr ifr_mask;
|
struct sockaddr ifr_mask;
|
||||||
struct ifreq_parameter ifr_parameter;
|
|
||||||
struct ifreq_stats ifr_stats;
|
struct ifreq_stats ifr_stats;
|
||||||
struct route_entry ifr_route;
|
struct route_entry ifr_route;
|
||||||
int ifr_flags;
|
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 */
|
/* interface flags */
|
||||||
#define IFF_UP 0x0001
|
#define IFF_UP 0x0001
|
||||||
#define IFF_BROADCAST 0x0002 /* valid broadcast address */
|
#define IFF_BROADCAST 0x0002 /* valid broadcast address */
|
||||||
|
|||||||
@@ -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.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef _SYS_SOCKIO_H
|
#ifndef _SYS_SOCKIO_H
|
||||||
@@ -38,7 +38,6 @@
|
|||||||
#define SIOCGETRT 8928 /* get route information for destination */
|
#define SIOCGETRT 8928 /* get route information for destination */
|
||||||
|
|
||||||
#define SIOCGIFSTATS 8929 /* get interface stats */
|
#define SIOCGIFSTATS 8929 /* get interface stats */
|
||||||
#define SIOCGIFPARAM 8930 /* get interface parameter */
|
|
||||||
#define SIOCGIFTYPE 8931 /* get interface type */
|
#define SIOCGIFTYPE 8931 /* get interface type */
|
||||||
|
|
||||||
#define SIOCSPACKETCAP 8932 /* Start capturing packets on an interface */
|
#define SIOCSPACKETCAP 8932 /* Start capturing packets on an interface */
|
||||||
|
|||||||
@@ -18,14 +18,9 @@
|
|||||||
typedef struct net_buffer {
|
typedef struct net_buffer {
|
||||||
struct list_link link;
|
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* source;
|
||||||
struct sockaddr* destination;
|
struct sockaddr* destination;
|
||||||
struct net_interface* interface;
|
struct net_interface_address* interface_address;
|
||||||
int32 type;
|
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
uint16 start;
|
uint16 start;
|
||||||
@@ -33,6 +28,7 @@ typedef struct net_buffer {
|
|||||||
} fragment;
|
} fragment;
|
||||||
uint32 sequence;
|
uint32 sequence;
|
||||||
uint32 offset;
|
uint32 offset;
|
||||||
|
int32 type;
|
||||||
};
|
};
|
||||||
uint32 flags;
|
uint32 flags;
|
||||||
uint32 size;
|
uint32 size;
|
||||||
|
|||||||
@@ -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.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef NET_DATALINK_H
|
#ifndef NET_DATALINK_H
|
||||||
@@ -18,84 +18,98 @@
|
|||||||
|
|
||||||
typedef struct net_datalink_protocol net_datalink_protocol;
|
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;
|
typedef struct net_domain {
|
||||||
struct net_address_module_info *address_module;
|
const char* name;
|
||||||
|
int family;
|
||||||
|
|
||||||
|
struct net_protocol_module_info* module;
|
||||||
|
struct net_address_module_info* address_module;
|
||||||
} net_domain;
|
} net_domain;
|
||||||
|
|
||||||
struct net_interface {
|
typedef struct net_interface_address {
|
||||||
struct list_link link;
|
struct net_domain* domain;
|
||||||
struct net_domain *domain;
|
struct net_interface* interface;
|
||||||
struct net_device *device;
|
struct sockaddr* local;
|
||||||
struct net_datalink_protocol *first_protocol;
|
struct sockaddr* destination;
|
||||||
struct net_datalink_protocol_module_info *first_info;
|
struct sockaddr* mask;
|
||||||
|
} net_interface_address;
|
||||||
|
|
||||||
|
typedef struct net_interface {
|
||||||
|
struct net_device* device;
|
||||||
|
|
||||||
char name[IF_NAMESIZE];
|
char name[IF_NAMESIZE];
|
||||||
struct sockaddr *address;
|
|
||||||
struct sockaddr *destination;
|
|
||||||
struct sockaddr *mask;
|
|
||||||
uint32 index;
|
uint32 index;
|
||||||
uint32 flags;
|
uint32 flags;
|
||||||
uint8 type;
|
uint8 type;
|
||||||
uint32 mtu;
|
uint32 mtu;
|
||||||
uint32 metric;
|
uint32 metric;
|
||||||
};
|
} net_interface;
|
||||||
|
|
||||||
struct net_route {
|
typedef struct net_route {
|
||||||
struct sockaddr *destination;
|
struct sockaddr* destination;
|
||||||
struct sockaddr *mask;
|
struct sockaddr* mask;
|
||||||
struct sockaddr *gateway;
|
struct sockaddr* gateway;
|
||||||
uint32 flags;
|
uint32 flags;
|
||||||
uint32 mtu;
|
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 list_link link;
|
||||||
struct net_route *route;
|
struct net_route* route;
|
||||||
struct sockaddr address;
|
struct sockaddr address;
|
||||||
};
|
} net_route_info;
|
||||||
|
|
||||||
|
|
||||||
struct net_datalink_module_info {
|
struct net_datalink_module_info {
|
||||||
module_info info;
|
module_info info;
|
||||||
|
|
||||||
status_t (*control)(struct net_domain *domain, int32 option, void *value,
|
status_t (*control)(net_domain* domain, int32 option, void* value,
|
||||||
size_t *_length);
|
size_t* _length);
|
||||||
status_t (*send_data)(struct net_route *route, struct net_buffer *buffer);
|
status_t (*send_data)(net_route* route, net_buffer* buffer);
|
||||||
status_t (*send_datagram)(struct net_protocol *protocol,
|
status_t (*send_datagram)(struct net_protocol* protocol,
|
||||||
struct net_domain *domain, struct net_buffer *buffer);
|
net_domain* domain, net_buffer* buffer);
|
||||||
|
|
||||||
bool (*is_local_address)(struct net_domain *domain,
|
bool (*is_local_address)(net_domain* domain,
|
||||||
const struct sockaddr *address, net_interface **_interface,
|
const struct sockaddr* address,
|
||||||
uint32 *_matchedType);
|
net_interface_address** _interfaceAddress,
|
||||||
bool (*is_local_link_address)(struct net_domain *domain, bool unconfigured,
|
uint32* _matchedType);
|
||||||
const struct sockaddr *address, net_interface **_interface);
|
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)(net_domain* domain, uint32 index);
|
||||||
net_interface *(*get_interface_with_address)(struct net_domain *domain,
|
net_interface* (*get_interface_with_address)(
|
||||||
const struct sockaddr *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
|
// routes
|
||||||
status_t (*add_route)(struct net_domain *domain,
|
status_t (*add_route)(net_domain* domain, const net_route* route);
|
||||||
const struct net_route *route);
|
status_t (*remove_route)(net_domain* domain, const net_route* route);
|
||||||
status_t (*remove_route)(struct net_domain *domain,
|
net_route* (*get_route)(net_domain* domain,
|
||||||
const struct net_route *route);
|
const struct sockaddr* address);
|
||||||
struct net_route *(*get_route)(struct net_domain *domain,
|
status_t (*get_buffer_route)(net_domain* domain,
|
||||||
const struct sockaddr *address);
|
struct net_buffer* buffer, net_route** _route);
|
||||||
status_t (*get_buffer_route)(struct net_domain *domain,
|
void (*put_route)(net_domain* domain, net_route* route);
|
||||||
struct net_buffer *buffer, struct net_route **_route);
|
|
||||||
void (*put_route)(struct net_domain *domain, struct net_route *route);
|
|
||||||
|
|
||||||
status_t (*register_route_info)(struct net_domain *domain,
|
status_t (*register_route_info)(net_domain* domain,
|
||||||
struct net_route_info *info);
|
net_route_info* info);
|
||||||
status_t (*unregister_route_info)(struct net_domain *domain,
|
status_t (*unregister_route_info)(net_domain* domain,
|
||||||
struct net_route_info *info);
|
net_route_info* info);
|
||||||
status_t (*update_route_info)(struct net_domain *domain,
|
status_t (*update_route_info)(net_domain* domain,
|
||||||
struct net_route_info *info);
|
net_route_info* info);
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS 0x01
|
#define NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS 0x01
|
||||||
@@ -104,47 +118,58 @@ struct net_address_module_info {
|
|||||||
module_info info;
|
module_info info;
|
||||||
uint32 flags;
|
uint32 flags;
|
||||||
|
|
||||||
status_t (*copy_address)(const sockaddr *from, sockaddr **to,
|
status_t (*copy_address)(const struct sockaddr* from,
|
||||||
bool replaceWithZeros, const sockaddr *mask);
|
struct sockaddr** to, bool replaceWithZeros,
|
||||||
|
const struct sockaddr* mask);
|
||||||
|
|
||||||
status_t (*mask_address)(const sockaddr *address, const sockaddr *mask,
|
status_t (*mask_address)(const struct sockaddr* address,
|
||||||
sockaddr *result);
|
const struct sockaddr* mask, struct sockaddr* result);
|
||||||
|
|
||||||
bool (*equal_addresses)(const sockaddr *a, const sockaddr *b);
|
bool (*equal_addresses)(const struct sockaddr* a,
|
||||||
bool (*equal_ports)(const sockaddr *a, const sockaddr *b);
|
const struct sockaddr* b);
|
||||||
bool (*equal_addresses_and_ports)(const sockaddr *a, const sockaddr *b);
|
bool (*equal_ports)(const struct sockaddr* a,
|
||||||
bool (*equal_masked_addresses)(const sockaddr *a, const sockaddr *b,
|
const struct sockaddr* b);
|
||||||
const sockaddr *mask);
|
bool (*equal_addresses_and_ports)(const struct sockaddr* a,
|
||||||
bool (*is_empty_address)(const sockaddr *address, bool checkPort);
|
const struct sockaddr* b);
|
||||||
bool (*is_same_family)(const sockaddr *address);
|
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,
|
status_t (*print_address)(const struct sockaddr* address,
|
||||||
bool printPort);
|
char** buffer, bool printPort);
|
||||||
status_t (*print_address_buffer)(const sockaddr *address, char *buffer,
|
status_t (*print_address_buffer)(const struct sockaddr* address,
|
||||||
size_t bufferSize, bool printPort);
|
char* buffer, size_t bufferSize, bool printPort);
|
||||||
|
|
||||||
uint16 (*get_port)(const sockaddr *address);
|
uint16 (*get_port)(const struct sockaddr* address);
|
||||||
status_t (*set_port)(sockaddr *address, uint16 port);
|
status_t (*set_port)(struct sockaddr* address, uint16 port);
|
||||||
|
|
||||||
status_t (*set_to)(sockaddr *address, const sockaddr *from);
|
status_t (*set_to)(struct sockaddr* address,
|
||||||
status_t (*set_to_empty_address)(sockaddr *address);
|
const struct sockaddr* from);
|
||||||
status_t (*set_to_defaults)(sockaddr *defaultMask,
|
status_t (*set_to_empty_address)(struct sockaddr* address);
|
||||||
sockaddr *defaultBroadcast, sockaddr *address,
|
status_t (*set_to_defaults)(struct sockaddr* defaultMask,
|
||||||
sockaddr *netmask);
|
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,
|
uint32 (*hash_address)(const struct sockaddr* address,
|
||||||
const sockaddr *peerAddress);
|
bool includePort);
|
||||||
|
uint32 (*hash_address_pair)(const struct sockaddr* ourAddress,
|
||||||
|
const struct sockaddr* peerAddress);
|
||||||
|
|
||||||
status_t (*checksum_address)(struct Checksum *checksum,
|
status_t (*checksum_address)(struct Checksum* checksum,
|
||||||
const sockaddr *address);
|
const struct sockaddr* address);
|
||||||
|
|
||||||
void (*get_loopback_address)(sockaddr *result);
|
void (*get_loopback_address)(struct sockaddr* result);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // NET_DATALINK_H
|
#endif // NET_DATALINK_H
|
||||||
|
|||||||
@@ -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.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef NET_DATALINK_PROTOCOL_H
|
#ifndef NET_DATALINK_PROTOCOL_H
|
||||||
@@ -10,31 +10,37 @@
|
|||||||
|
|
||||||
|
|
||||||
typedef struct net_datalink_protocol {
|
typedef struct net_datalink_protocol {
|
||||||
struct net_datalink_protocol *next;
|
struct net_datalink_protocol* next;
|
||||||
struct net_datalink_protocol_module_info *module;
|
struct net_datalink_protocol_module_info* module;
|
||||||
struct net_interface *interface;
|
struct net_interface* interface;
|
||||||
|
struct net_domain* domain;
|
||||||
} net_datalink_protocol;
|
} net_datalink_protocol;
|
||||||
|
|
||||||
struct net_datalink_protocol_module_info {
|
struct net_datalink_protocol_module_info {
|
||||||
module_info info;
|
module_info info;
|
||||||
|
|
||||||
status_t (*init_protocol)(struct net_interface *interface,
|
status_t (*init_protocol)(net_interface* interface, net_domain* domain,
|
||||||
net_datalink_protocol **_protocol);
|
net_datalink_protocol** _protocol);
|
||||||
status_t (*uninit_protocol)(net_datalink_protocol *self);
|
status_t (*uninit_protocol)(net_datalink_protocol* self);
|
||||||
|
|
||||||
status_t (*send_data)(net_datalink_protocol *self,
|
status_t (*send_data)(net_datalink_protocol* self, net_buffer* buffer);
|
||||||
net_buffer *buffer);
|
|
||||||
|
|
||||||
status_t (*interface_up)(net_datalink_protocol *self);
|
status_t (*interface_up)(net_datalink_protocol* self);
|
||||||
void (*interface_down)(net_datalink_protocol *self);
|
void (*interface_down)(net_datalink_protocol* self);
|
||||||
|
|
||||||
status_t (*control)(net_datalink_protocol *self,
|
status_t (*change_address)(net_datalink_protocol* self,
|
||||||
int32 op, void *argument, size_t length);
|
net_interface_address* address, int32 option,
|
||||||
|
const struct sockaddr* oldAddress,
|
||||||
|
const struct sockaddr* newAddress);
|
||||||
|
|
||||||
status_t (*join_multicast)(net_datalink_protocol *self,
|
status_t (*control)(net_datalink_protocol* self, int32 option,
|
||||||
const sockaddr *address);
|
void* argument, size_t length);
|
||||||
status_t (*leave_multicast)(net_datalink_protocol *self,
|
|
||||||
const sockaddr *address);
|
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
|
#endif // NET_DATALINK_PROTOCOL_H
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
SubDir HAIKU_TOP src add-ons kernel network datalink_protocols ;
|
SubDir HAIKU_TOP src add-ons kernel network datalink_protocols ;
|
||||||
|
|
||||||
SubInclude HAIKU_TOP src add-ons kernel network datalink_protocols arp ;
|
HaikuSubInclude arp ;
|
||||||
SubInclude HAIKU_TOP src add-ons kernel network datalink_protocols ethernet_frame ;
|
HaikuSubInclude ethernet_frame ;
|
||||||
SubInclude HAIKU_TOP src add-ons kernel network datalink_protocols ipv4_datagram ;
|
HaikuSubInclude ipv6_datagram ;
|
||||||
SubInclude HAIKU_TOP src add-ons kernel network datalink_protocols ipv6_datagram ;
|
HaikuSubInclude loopback_frame ;
|
||||||
SubInclude HAIKU_TOP src add-ons kernel network datalink_protocols loopback_frame ;
|
|
||||||
|
|||||||
@@ -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.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
* Hugo Santos, [email protected]
|
* Hugo Santos, [email protected]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
//! Ethernet Address Resolution Protocol, see RFC 826.
|
//! Ethernet Address Resolution Protocol, see RFC 826.
|
||||||
|
|
||||||
|
|
||||||
@@ -110,6 +111,7 @@ struct arp_entry {
|
|||||||
|
|
||||||
struct arp_protocol : net_datalink_protocol {
|
struct arp_protocol : net_datalink_protocol {
|
||||||
sockaddr_dl hardware_address;
|
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);
|
static void arp_timer(struct net_timer *timer, void *data);
|
||||||
|
|
||||||
net_buffer_module_info *gBufferModule;
|
net_buffer_module_info* gBufferModule;
|
||||||
static net_stack_module_info *sStackModule;
|
static net_stack_module_info* sStackModule;
|
||||||
static hash_table *sCache;
|
static net_datalink_module_info* sDatalinkModule;
|
||||||
|
static hash_table* sCache;
|
||||||
static mutex sCacheLock;
|
static mutex sCacheLock;
|
||||||
static bool sIgnoreReplies;
|
static bool sIgnoreReplies;
|
||||||
|
|
||||||
@@ -283,7 +286,7 @@ void
|
|||||||
arp_entry::MarkValid()
|
arp_entry::MarkValid()
|
||||||
{
|
{
|
||||||
TRACE(("ARP entry %p Marked as VALID, have %li packets queued.\n", this,
|
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;
|
flags = (flags & ~ARP_FLAG_REJECT) | ARP_FLAG_VALID;
|
||||||
|
|
||||||
@@ -316,9 +319,6 @@ arp_entry::ScheduleRemoval()
|
|||||||
static void
|
static void
|
||||||
ipv4_to_ether_multicast(sockaddr_dl *destination, const sockaddr_in *source)
|
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
|
// RFC 1112 - Host extensions for IP multicasting
|
||||||
//
|
//
|
||||||
// ``An IP host group address is mapped to an Ethernet multicast
|
// ``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
|
This function does not lock the cache - you have to do it yourself
|
||||||
before calling it.
|
before calling it.
|
||||||
*/
|
*/
|
||||||
status_t
|
static status_t
|
||||||
arp_update_entry(in_addr_t protocolAddress, sockaddr_dl *hardwareAddress,
|
arp_update_entry(in_addr_t protocolAddress, sockaddr_dl *hardwareAddress,
|
||||||
uint32 flags, arp_entry **_entry = NULL)
|
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.
|
static void
|
||||||
You need to hold the cache lock when calling this function.
|
arp_remove_local_entry(arp_protocol* protocol, const sockaddr* local,
|
||||||
*/
|
bool updateLocalAddress)
|
||||||
static status_t
|
|
||||||
arp_update_local(arp_protocol *protocol)
|
|
||||||
{
|
{
|
||||||
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;
|
in_addr_t inetAddress;
|
||||||
|
|
||||||
if (interface->address == NULL) {
|
if (local == NULL) {
|
||||||
// interface has not yet been set
|
// interface has not yet been set
|
||||||
inetAddress = INADDR_ANY;
|
inetAddress = INADDR_ANY;
|
||||||
} else
|
} 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;
|
sockaddr_dl address;
|
||||||
address.sdl_len = sizeof(sockaddr_dl);
|
address.sdl_len = sizeof(sockaddr_dl);
|
||||||
@@ -435,7 +486,7 @@ arp_update_local(arp_protocol *protocol)
|
|||||||
memcpy(&protocol->hardware_address, &address, sizeof(sockaddr_dl));
|
memcpy(&protocol->hardware_address, &address, sizeof(sockaddr_dl));
|
||||||
// cache the address in our protocol
|
// cache the address in our protocol
|
||||||
|
|
||||||
arp_entry *entry;
|
arp_entry* entry;
|
||||||
status_t status = arp_update_entry(inetAddress, &address,
|
status_t status = arp_update_entry(inetAddress, &address,
|
||||||
ARP_FLAG_LOCAL | ARP_FLAG_PERMANENT, &entry);
|
ARP_FLAG_LOCAL | ARP_FLAG_PERMANENT, &entry);
|
||||||
if (status == B_OK)
|
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
|
static status_t
|
||||||
handle_arp_request(net_buffer *buffer, arp_header &header)
|
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
|
#ifdef TRACE_ARP
|
||||||
dprintf(" hw sender: %02x:%02x:%02x:%02x:%02x:%02x\n",
|
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[0], header.hardware_sender[1],
|
||||||
header.hardware_sender[3], header.hardware_sender[4], header.hardware_sender[5]);
|
header.hardware_sender[2], header.hardware_sender[3],
|
||||||
dprintf(" proto sender: %ld.%ld.%ld.%ld\n", header.protocol_sender >> 24, (header.protocol_sender >> 16) & 0xff,
|
header.hardware_sender[4], header.hardware_sender[5]);
|
||||||
(header.protocol_sender >> 8) & 0xff, header.protocol_sender & 0xff);
|
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",
|
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[0], header.hardware_target[1],
|
||||||
header.hardware_target[3], header.hardware_target[4], header.hardware_target[5]);
|
header.hardware_target[2], header.hardware_target[3],
|
||||||
dprintf(" proto target: %ld.%ld.%ld.%ld\n", header.protocol_target >> 24, (header.protocol_target >> 16) & 0xff,
|
header.hardware_target[4], header.hardware_target[5]);
|
||||||
(header.protocol_target >> 8) & 0xff, header.protocol_target & 0xff);
|
addr = ntohl(header.protocol_target);
|
||||||
|
dprintf(" proto target: %d.%d.%d.%d\n", addr >> 24, (addr >> 16) & 0xff,
|
||||||
|
(addr >> 8) & 0xff, addr & 0xff);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ntohs(header.protocol_type) != ETHER_TYPE_IP
|
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_REMOVE_FAILED:
|
||||||
case ARP_STATE_STALE:
|
case ARP_STATE_STALE:
|
||||||
|
{
|
||||||
// the entry has aged so much that we're going to remove it
|
// the entry has aged so much that we're going to remove it
|
||||||
TRACE((" remove ARP entry %p!\n", entry));
|
TRACE((" remove ARP entry %p!\n", entry));
|
||||||
|
|
||||||
mutex_lock(&sCacheLock);
|
MutexLocker locker(sCacheLock);
|
||||||
if ((entry->flags & ARP_FLAG_REMOVED) != 0) {
|
if ((entry->flags & ARP_FLAG_REMOVED) != 0) {
|
||||||
// The entry has already been removed, and is about to be deleted
|
// The entry has already been removed, and is about to be
|
||||||
mutex_unlock(&sCacheLock);
|
// deleted
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
hash_remove(sCache, entry);
|
hash_remove(sCache, entry);
|
||||||
mutex_unlock(&sCacheLock);
|
locker.Unlock();
|
||||||
|
|
||||||
delete entry;
|
delete entry;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
@@ -649,8 +737,7 @@ arp_timer(struct net_timer *timer, void *data)
|
|||||||
You need to have the sCacheLock held when calling this function.
|
You need to have the sCacheLock held when calling this function.
|
||||||
*/
|
*/
|
||||||
static status_t
|
static status_t
|
||||||
arp_start_resolve(net_datalink_protocol *protocol, in_addr_t address,
|
arp_start_resolve(arp_protocol* protocol, in_addr_t address, arp_entry** _entry)
|
||||||
arp_entry **_entry)
|
|
||||||
{
|
{
|
||||||
ASSERT_LOCKED_MUTEX(&sCacheLock);
|
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);
|
header.opcode = htons(ARP_OPCODE_REQUEST);
|
||||||
|
|
||||||
memcpy(header.hardware_sender, device->address.data, ETHER_ADDRESS_LENGTH);
|
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);
|
memset(header.hardware_target, 0, ETHER_ADDRESS_LENGTH);
|
||||||
|
header.protocol_sender = protocol->local_address;
|
||||||
header.protocol_target = address;
|
header.protocol_target = address;
|
||||||
|
|
||||||
// prepare source and target addresses
|
// prepare source and target addresses
|
||||||
@@ -867,21 +946,25 @@ arp_uninit()
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
arp_init_protocol(struct net_interface *interface,
|
arp_init_protocol(net_interface* interface, net_domain* domain,
|
||||||
net_datalink_protocol **_protocol)
|
net_datalink_protocol** _protocol)
|
||||||
{
|
{
|
||||||
// We currently only support a single family and type!
|
// We currently only support a single family and type!
|
||||||
if (interface->domain->family != AF_INET
|
if (interface->device->type != IFT_ETHER
|
||||||
|| interface->device->type != IFT_ETHER)
|
|| domain->family != AF_INET)
|
||||||
return B_BAD_TYPE;
|
return B_BAD_TYPE;
|
||||||
|
|
||||||
status_t status = sStackModule->register_device_handler(interface->device,
|
status_t status = sStackModule->register_device_handler(interface->device,
|
||||||
ETHER_FRAME_TYPE | ETHER_TYPE_ARP, &arp_receive, NULL);
|
ETHER_FRAME_TYPE | ETHER_TYPE_ARP, &arp_receive, NULL);
|
||||||
|
if (status != B_OK)
|
||||||
if (status < B_OK)
|
|
||||||
return status;
|
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)
|
if (protocol == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
@@ -896,6 +979,8 @@ arp_uninit_protocol(net_datalink_protocol *protocol)
|
|||||||
{
|
{
|
||||||
sStackModule->unregister_device_handler(protocol->interface->device,
|
sStackModule->unregister_device_handler(protocol->interface->device,
|
||||||
ETHER_FRAME_TYPE | ETHER_TYPE_ARP);
|
ETHER_FRAME_TYPE | ETHER_TYPE_ARP);
|
||||||
|
sStackModule->unregister_device_handler(protocol->interface->device,
|
||||||
|
ETHER_FRAME_TYPE | ETHER_TYPE_IP);
|
||||||
|
|
||||||
delete protocol;
|
delete protocol;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -914,7 +999,7 @@ arp_send_data(net_datalink_protocol *_protocol, net_buffer *buffer)
|
|||||||
memcpy(buffer->source, &protocol->hardware_address,
|
memcpy(buffer->source, &protocol->hardware_address,
|
||||||
protocol->hardware_address.sdl_len);
|
protocol->hardware_address.sdl_len);
|
||||||
|
|
||||||
if (buffer->flags & MSG_MCAST) {
|
if ((buffer->flags & MSG_MCAST) != 0) {
|
||||||
sockaddr_dl multicastDestination;
|
sockaddr_dl multicastDestination;
|
||||||
ipv4_to_ether_multicast(&multicastDestination,
|
ipv4_to_ether_multicast(&multicastDestination,
|
||||||
(sockaddr_in *)buffer->destination);
|
(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);
|
((struct sockaddr_in *)buffer->destination)->sin_addr.s_addr);
|
||||||
if (entry == NULL) {
|
if (entry == NULL) {
|
||||||
status_t status = arp_start_resolve(protocol,
|
status_t status = arp_start_resolve(protocol,
|
||||||
((struct sockaddr_in *)buffer->destination)->sin_addr.s_addr, &entry);
|
((struct sockaddr_in*)buffer->destination)->sin_addr.s_addr,
|
||||||
if (status < B_OK)
|
&entry);
|
||||||
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry->flags & ARP_FLAG_REJECT)
|
if ((entry->flags & ARP_FLAG_REJECT) != 0)
|
||||||
return EHOSTUNREACH;
|
return EHOSTUNREACH;
|
||||||
else if (!(entry->flags & ARP_FLAG_VALID)) {
|
|
||||||
|
if ((entry->flags & ARP_FLAG_VALID) == 0) {
|
||||||
// entry is still being resolved.
|
// entry is still being resolved.
|
||||||
TRACE(("ARP Queuing packet %p, entry still being resolved.\n",
|
TRACE(("ARP Queuing packet %p, entry still being resolved.\n",
|
||||||
buffer));
|
buffer));
|
||||||
@@ -951,20 +1038,17 @@ arp_send_data(net_datalink_protocol *_protocol, net_buffer *buffer)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
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);
|
status_t status = protocol->next->module->interface_up(protocol->next);
|
||||||
if (status < B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
// cache this device's address for later use
|
// cache this device's address for later use
|
||||||
|
|
||||||
mutex_lock(&sCacheLock);
|
|
||||||
status = arp_update_local(protocol);
|
status = arp_update_local(protocol);
|
||||||
mutex_unlock(&sCacheLock);
|
if (status != B_OK) {
|
||||||
|
|
||||||
if (status < B_OK) {
|
|
||||||
protocol->next->module->interface_down(protocol->next);
|
protocol->next->module->interface_down(protocol->next);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@@ -976,70 +1060,55 @@ arp_up(net_datalink_protocol *_protocol)
|
|||||||
void
|
void
|
||||||
arp_down(net_datalink_protocol *protocol)
|
arp_down(net_datalink_protocol *protocol)
|
||||||
{
|
{
|
||||||
// remove local ARP entry from the cache
|
// remove local ARP entries from the cache
|
||||||
|
arp_remove_local((arp_protocol*)protocol);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protocol->next->module->interface_down(protocol->next);
|
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
|
status_t
|
||||||
arp_control(net_datalink_protocol *_protocol, int32 op, void *argument,
|
arp_control(net_datalink_protocol *_protocol, int32 op, void *argument,
|
||||||
size_t length)
|
size_t length)
|
||||||
{
|
{
|
||||||
arp_protocol *protocol = (arp_protocol *)_protocol;
|
arp_protocol* protocol = (arp_protocol*)_protocol;
|
||||||
|
return protocol->next->module->control(protocol->next, op, argument,
|
||||||
if (op == SIOCSIFADDR && (protocol->interface->flags & IFF_UP) != 0) {
|
length);
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1097,6 +1166,7 @@ static net_datalink_protocol_module_info sARPModule = {
|
|||||||
arp_send_data,
|
arp_send_data,
|
||||||
arp_up,
|
arp_up,
|
||||||
arp_down,
|
arp_down,
|
||||||
|
arp_change_address,
|
||||||
arp_control,
|
arp_control,
|
||||||
arp_join_multicast,
|
arp_join_multicast,
|
||||||
arp_leave_multicast,
|
arp_leave_multicast,
|
||||||
@@ -1104,12 +1174,13 @@ static net_datalink_protocol_module_info sARPModule = {
|
|||||||
|
|
||||||
|
|
||||||
module_dependency module_dependencies[] = {
|
module_dependency module_dependencies[] = {
|
||||||
{NET_STACK_MODULE_NAME, (module_info **)&sStackModule},
|
{NET_STACK_MODULE_NAME, (module_info**)&sStackModule},
|
||||||
{NET_BUFFER_MODULE_NAME, (module_info **)&gBufferModule},
|
{NET_DATALINK_MODULE_NAME, (module_info**)&sDatalinkModule},
|
||||||
|
{NET_BUFFER_MODULE_NAME, (module_info**)&gBufferModule},
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
module_info *modules[] = {
|
module_info* modules[] = {
|
||||||
(module_info *)&sARPModule,
|
(module_info*)&sARPModule,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -30,23 +30,23 @@ struct ethernet_frame_protocol : net_datalink_protocol {
|
|||||||
|
|
||||||
static const uint8 kBroadcastAddress[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
static const uint8 kBroadcastAddress[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||||
|
|
||||||
struct net_buffer_module_info *gBufferModule;
|
struct net_buffer_module_info* gBufferModule;
|
||||||
|
|
||||||
|
|
||||||
int32
|
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);
|
//dprintf("asked to deframe buffer for device %s\n", device->name);
|
||||||
|
|
||||||
NetBufferHeaderRemover<ether_header> bufferHeader(buffer);
|
NetBufferHeaderRemover<ether_header> bufferHeader(buffer);
|
||||||
if (bufferHeader.Status() < B_OK)
|
if (bufferHeader.Status() != B_OK)
|
||||||
return bufferHeader.Status();
|
return bufferHeader.Status();
|
||||||
|
|
||||||
ether_header &header = bufferHeader.Data();
|
ether_header& header = bufferHeader.Data();
|
||||||
uint16 type = ntohs(header.type);
|
uint16 type = ntohs(header.type);
|
||||||
|
|
||||||
struct sockaddr_dl &source = *(struct sockaddr_dl *)buffer->source;
|
struct sockaddr_dl& source = *(struct sockaddr_dl*)buffer->source;
|
||||||
struct sockaddr_dl &destination = *(struct sockaddr_dl *)buffer->destination;
|
struct sockaddr_dl& destination = *(struct sockaddr_dl*)buffer->destination;
|
||||||
|
|
||||||
source.sdl_len = sizeof(sockaddr_dl);
|
source.sdl_len = sizeof(sockaddr_dl);
|
||||||
source.sdl_family = AF_LINK;
|
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
|
// mark buffer if it was a broadcast/multicast packet
|
||||||
if (!memcmp(header.destination, kBroadcastAddress, ETHER_ADDRESS_LENGTH))
|
if (!memcmp(header.destination, kBroadcastAddress, ETHER_ADDRESS_LENGTH))
|
||||||
buffer->flags |= MSG_BCAST;
|
buffer->flags |= MSG_BCAST;
|
||||||
else if (header.destination[0] & 0x01)
|
else if ((header.destination[0] & 0x01) != 0)
|
||||||
buffer->flags |= MSG_MCAST;
|
buffer->flags |= MSG_MCAST;
|
||||||
|
|
||||||
return ETHER_FRAME_TYPE | type;
|
return ETHER_FRAME_TYPE | type;
|
||||||
@@ -79,20 +79,24 @@ ethernet_deframe(net_device *device, net_buffer *buffer)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
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;
|
net_stack_module_info* stack;
|
||||||
status_t status = get_module(NET_STACK_MODULE_NAME, (module_info **)&stack);
|
status_t status = get_module(NET_STACK_MODULE_NAME, (module_info**)&stack);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
status = stack->register_device_deframer(interface->device, ðernet_deframe);
|
status = stack->register_device_deframer(interface->device,
|
||||||
|
ðernet_deframe);
|
||||||
|
|
||||||
put_module(NET_STACK_MODULE_NAME);
|
put_module(NET_STACK_MODULE_NAME);
|
||||||
|
|
||||||
if (status < B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
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)
|
if (protocol == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
@@ -102,10 +106,10 @@ ethernet_frame_init(struct net_interface *interface, net_datalink_protocol **_pr
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ethernet_frame_uninit(net_datalink_protocol *protocol)
|
ethernet_frame_uninit(net_datalink_protocol* protocol)
|
||||||
{
|
{
|
||||||
net_stack_module_info *stack;
|
net_stack_module_info* stack;
|
||||||
if (get_module(NET_STACK_MODULE_NAME, (module_info **)&stack) == B_OK) {
|
if (get_module(NET_STACK_MODULE_NAME, (module_info**)&stack) == B_OK) {
|
||||||
stack->unregister_device_deframer(protocol->interface->device);
|
stack->unregister_device_deframer(protocol->interface->device);
|
||||||
put_module(NET_STACK_MODULE_NAME);
|
put_module(NET_STACK_MODULE_NAME);
|
||||||
}
|
}
|
||||||
@@ -116,24 +120,23 @@ ethernet_frame_uninit(net_datalink_protocol *protocol)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ethernet_frame_send_data(net_datalink_protocol *protocol,
|
ethernet_frame_send_data(net_datalink_protocol* protocol, net_buffer* buffer)
|
||||||
net_buffer *buffer)
|
|
||||||
{
|
{
|
||||||
struct sockaddr_dl &source = *(struct sockaddr_dl *)buffer->source;
|
struct sockaddr_dl& source = *(struct sockaddr_dl*)buffer->source;
|
||||||
struct sockaddr_dl &destination = *(struct sockaddr_dl *)buffer->destination;
|
struct sockaddr_dl& destination = *(struct sockaddr_dl*)buffer->destination;
|
||||||
|
|
||||||
if (source.sdl_family != AF_LINK || source.sdl_type != IFT_ETHER)
|
if (source.sdl_family != AF_LINK || source.sdl_type != IFT_ETHER)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
NetBufferPrepend<ether_header> bufferHeader(buffer);
|
NetBufferPrepend<ether_header> bufferHeader(buffer);
|
||||||
if (bufferHeader.Status() < B_OK)
|
if (bufferHeader.Status() != B_OK)
|
||||||
return bufferHeader.Status();
|
return bufferHeader.Status();
|
||||||
|
|
||||||
ether_header &header = bufferHeader.Data();
|
ether_header &header = bufferHeader.Data();
|
||||||
|
|
||||||
header.type = htons(source.sdl_e_type);
|
header.type = htons(source.sdl_e_type);
|
||||||
memcpy(header.source, source.sdl_data, ETHER_ADDRESS_LENGTH);
|
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);
|
memcpy(header.destination, kBroadcastAddress, ETHER_ADDRESS_LENGTH);
|
||||||
else
|
else
|
||||||
memcpy(header.destination, destination.sdl_data, ETHER_ADDRESS_LENGTH);
|
memcpy(header.destination, destination.sdl_data, ETHER_ADDRESS_LENGTH);
|
||||||
@@ -146,40 +149,49 @@ ethernet_frame_send_data(net_datalink_protocol *protocol,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
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);
|
return protocol->next->module->interface_up(protocol->next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ethernet_frame_down(net_datalink_protocol *protocol)
|
ethernet_frame_down(net_datalink_protocol* protocol)
|
||||||
{
|
{
|
||||||
return protocol->next->module->interface_down(protocol->next);
|
return protocol->next->module->interface_down(protocol->next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ethernet_frame_control(net_datalink_protocol *protocol,
|
ethernet_frame_change_address(net_datalink_protocol* protocol,
|
||||||
int32 op, void *argument, size_t length)
|
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
|
static status_t
|
||||||
ethernet_frame_join_multicast(net_datalink_protocol *protocol,
|
ethernet_frame_join_multicast(net_datalink_protocol* protocol,
|
||||||
const sockaddr *address)
|
const sockaddr* address)
|
||||||
{
|
{
|
||||||
return protocol->next->module->join_multicast(protocol->next, address);
|
return protocol->next->module->join_multicast(protocol->next, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
ethernet_frame_leave_multicast(net_datalink_protocol *protocol,
|
ethernet_frame_leave_multicast(net_datalink_protocol* protocol,
|
||||||
const sockaddr *address)
|
const sockaddr* address)
|
||||||
{
|
{
|
||||||
return protocol->next->module->leave_multicast(protocol->next, address);
|
return protocol->next->module->leave_multicast(protocol->next, address);
|
||||||
}
|
}
|
||||||
@@ -190,7 +202,8 @@ ethernet_frame_std_ops(int32 op, ...)
|
|||||||
{
|
{
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case B_MODULE_INIT:
|
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:
|
case B_MODULE_UNINIT:
|
||||||
put_module(NET_BUFFER_MODULE_NAME);
|
put_module(NET_BUFFER_MODULE_NAME);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -212,12 +225,13 @@ static net_datalink_protocol_module_info sEthernetFrameModule = {
|
|||||||
ethernet_frame_send_data,
|
ethernet_frame_send_data,
|
||||||
ethernet_frame_up,
|
ethernet_frame_up,
|
||||||
ethernet_frame_down,
|
ethernet_frame_down,
|
||||||
|
ethernet_frame_change_address,
|
||||||
ethernet_frame_control,
|
ethernet_frame_control,
|
||||||
ethernet_frame_join_multicast,
|
ethernet_frame_join_multicast,
|
||||||
ethernet_frame_leave_multicast,
|
ethernet_frame_leave_multicast,
|
||||||
};
|
};
|
||||||
|
|
||||||
module_info *modules[] = {
|
module_info* modules[] = {
|
||||||
(module_info *)&sEthernetFrameModule,
|
(module_info*)&sEthernetFrameModule,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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 ;
|
|
||||||
@@ -1,150 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2007, Haiku, Inc. All Rights Reserved.
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*
|
|
||||||
* Authors:
|
|
||||||
* Hugo Santos, [email protected]
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#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
|
|
||||||
};
|
|
||||||
@@ -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
|
static status_t
|
||||||
ipv6_datalink_control(net_datalink_protocol* protocol, int32 op, void* argument,
|
ipv6_datalink_control(net_datalink_protocol* protocol, int32 op, void* argument,
|
||||||
size_t length)
|
size_t length)
|
||||||
@@ -1105,6 +1165,7 @@ net_datalink_protocol_module_info gIPv6DataLinkModule = {
|
|||||||
ipv6_datalink_send_data,
|
ipv6_datalink_send_data,
|
||||||
ipv6_datalink_up,
|
ipv6_datalink_up,
|
||||||
ipv6_datalink_down,
|
ipv6_datalink_down,
|
||||||
|
ipv6_datalink_change_address,
|
||||||
ipv6_datalink_control,
|
ipv6_datalink_control,
|
||||||
ipv6_datalink_join_multicast,
|
ipv6_datalink_join_multicast,
|
||||||
ipv6_datalink_leave_multicast,
|
ipv6_datalink_leave_multicast,
|
||||||
|
|||||||
@@ -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.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* 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
|
int32
|
||||||
loopback_deframe(net_device *device, net_buffer *buffer)
|
loopback_deframe(net_device* device, net_buffer* buffer)
|
||||||
{
|
{
|
||||||
// there is not that much to do...
|
// there is not that much to do...
|
||||||
return 0;
|
return 0;
|
||||||
@@ -43,32 +43,34 @@ loopback_deframe(net_device *device, net_buffer *buffer)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
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!
|
// We currently only support a single family and type!
|
||||||
if (interface->device->type != IFT_LOOP)
|
if (interface->device->type != IFT_LOOP)
|
||||||
return B_BAD_TYPE;
|
return B_BAD_TYPE;
|
||||||
|
|
||||||
loopback_frame_protocol *protocol;
|
loopback_frame_protocol* protocol;
|
||||||
|
|
||||||
net_stack_module_info *stack;
|
net_stack_module_info* stack;
|
||||||
status_t status = get_module(NET_STACK_MODULE_NAME, (module_info **)&stack);
|
status_t status = get_module(NET_STACK_MODULE_NAME, (module_info**)&stack);
|
||||||
if (status < B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
status = stack->register_device_deframer(interface->device, &loopback_deframe);
|
status = stack->register_device_deframer(interface->device,
|
||||||
if (status < B_OK)
|
&loopback_deframe);
|
||||||
|
if (status != B_OK)
|
||||||
goto err1;
|
goto err1;
|
||||||
|
|
||||||
// We also register the domain as a handler for our packets
|
// We also register the domain as a handler for our packets
|
||||||
status = stack->register_domain_device_handler(interface->device,
|
status = stack->register_domain_device_handler(interface->device, 0,
|
||||||
0, interface->domain);
|
domain);
|
||||||
if (status < B_OK)
|
if (status != B_OK)
|
||||||
goto err2;
|
goto err2;
|
||||||
|
|
||||||
put_module(NET_STACK_MODULE_NAME);
|
put_module(NET_STACK_MODULE_NAME);
|
||||||
|
|
||||||
protocol = new (std::nothrow) loopback_frame_protocol;
|
protocol = new(std::nothrow) loopback_frame_protocol;
|
||||||
if (protocol == NULL)
|
if (protocol == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
@@ -84,10 +86,10 @@ err1:
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
loopback_frame_uninit(net_datalink_protocol *protocol)
|
loopback_frame_uninit(net_datalink_protocol* protocol)
|
||||||
{
|
{
|
||||||
net_stack_module_info *stack;
|
net_stack_module_info* stack;
|
||||||
if (get_module(NET_STACK_MODULE_NAME, (module_info **)&stack) == B_OK) {
|
if (get_module(NET_STACK_MODULE_NAME, (module_info**)&stack) == B_OK) {
|
||||||
stack->unregister_device_deframer(protocol->interface->device);
|
stack->unregister_device_deframer(protocol->interface->device);
|
||||||
stack->unregister_device_handler(protocol->interface->device, 0);
|
stack->unregister_device_handler(protocol->interface->device, 0);
|
||||||
put_module(NET_STACK_MODULE_NAME);
|
put_module(NET_STACK_MODULE_NAME);
|
||||||
@@ -99,48 +101,56 @@ loopback_frame_uninit(net_datalink_protocol *protocol)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
loopback_frame_send_data(net_datalink_protocol *protocol,
|
loopback_frame_send_data(net_datalink_protocol* protocol, net_buffer* buffer)
|
||||||
net_buffer *buffer)
|
|
||||||
{
|
{
|
||||||
return protocol->next->module->send_data(protocol->next, buffer);
|
return protocol->next->module->send_data(protocol->next, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
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);
|
return protocol->next->module->interface_up(protocol->next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
loopback_frame_down(net_datalink_protocol *protocol)
|
loopback_frame_down(net_datalink_protocol* protocol)
|
||||||
{
|
{
|
||||||
return protocol->next->module->interface_down(protocol->next);
|
return protocol->next->module->interface_down(protocol->next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
loopback_frame_control(net_datalink_protocol *protocol,
|
loopback_frame_change_address(net_datalink_protocol* protocol,
|
||||||
int32 op, void *argument, size_t length)
|
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
|
static status_t
|
||||||
loopback_frame_join_multicast(net_datalink_protocol *protocol,
|
loopback_frame_join_multicast(net_datalink_protocol* protocol,
|
||||||
const sockaddr *address)
|
const sockaddr* address)
|
||||||
{
|
{
|
||||||
return protocol->next->module->join_multicast(protocol->next, address);
|
return protocol->next->module->join_multicast(protocol->next, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
loopback_frame_leave_multicast(net_datalink_protocol *protocol,
|
loopback_frame_leave_multicast(net_datalink_protocol* protocol,
|
||||||
const sockaddr *address)
|
const sockaddr* address)
|
||||||
{
|
{
|
||||||
return protocol->next->module->leave_multicast(protocol->next, address);
|
return protocol->next->module->leave_multicast(protocol->next, address);
|
||||||
}
|
}
|
||||||
@@ -151,7 +161,8 @@ loopback_frame_std_ops(int32 op, ...)
|
|||||||
{
|
{
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case B_MODULE_INIT:
|
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:
|
case B_MODULE_UNINIT:
|
||||||
put_module(NET_BUFFER_MODULE_NAME);
|
put_module(NET_BUFFER_MODULE_NAME);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
@@ -173,12 +184,13 @@ static net_datalink_protocol_module_info sLoopbackFrameModule = {
|
|||||||
loopback_frame_send_data,
|
loopback_frame_send_data,
|
||||||
loopback_frame_up,
|
loopback_frame_up,
|
||||||
loopback_frame_down,
|
loopback_frame_down,
|
||||||
|
loopback_frame_change_address,
|
||||||
loopback_frame_control,
|
loopback_frame_control,
|
||||||
loopback_frame_join_multicast,
|
loopback_frame_join_multicast,
|
||||||
loopback_frame_leave_multicast,
|
loopback_frame_leave_multicast,
|
||||||
};
|
};
|
||||||
|
|
||||||
module_info *modules[] = {
|
module_info* modules[] = {
|
||||||
(module_info *)&sLoopbackFrameModule,
|
(module_info*)&sLoopbackFrameModule,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -86,8 +86,8 @@ static net_domain*
|
|||||||
get_domain(struct net_buffer* buffer)
|
get_domain(struct net_buffer* buffer)
|
||||||
{
|
{
|
||||||
net_domain* domain;
|
net_domain* domain;
|
||||||
if (buffer->interface != NULL)
|
if (buffer->interface_address != NULL)
|
||||||
domain = buffer->interface->domain;
|
domain = buffer->interface_address->domain;
|
||||||
else
|
else
|
||||||
domain = sStackModule->get_domain(buffer->source->sa_family);
|
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);
|
TRACE("ICMP received some data, buffer length %lu\n", buffer->size);
|
||||||
|
|
||||||
net_domain* domain;
|
net_domain* domain = get_domain(buffer);
|
||||||
if (buffer->interface != NULL)
|
if (domain == NULL)
|
||||||
domain = buffer->interface->domain;
|
|
||||||
else
|
|
||||||
domain = sStackModule->get_domain(buffer->source->sa_family);
|
|
||||||
|
|
||||||
if (domain == NULL || domain->module == NULL)
|
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
NetBufferHeaderReader<icmp_header> bufferHeader(buffer);
|
NetBufferHeaderReader<icmp_header> bufferHeader(buffer);
|
||||||
@@ -322,11 +317,11 @@ icmp_receive_data(net_buffer* buffer)
|
|||||||
if (domain == NULL)
|
if (domain == NULL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (buffer->interface != NULL) {
|
if (buffer->interface_address != NULL) {
|
||||||
// We only reply to echo requests of our local interface; we
|
// We only reply to echo requests of our local interface; we
|
||||||
// don't reply to broadcast requests
|
// don't reply to broadcast requests
|
||||||
if (!domain->address_module->equal_addresses(
|
if (!domain->address_module->equal_addresses(
|
||||||
buffer->interface->address, buffer->destination))
|
buffer->interface_address->local, buffer->destination))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ struct ipv4_protocol : net_protocol {
|
|||||||
uint8 time_to_live;
|
uint8 time_to_live;
|
||||||
uint8 multicast_time_to_live;
|
uint8 multicast_time_to_live;
|
||||||
uint32 flags;
|
uint32 flags;
|
||||||
struct sockaddr* interface_address; // for IP_MULTICAST_IF
|
struct sockaddr* multicast_address; // for IP_MULTICAST_IF
|
||||||
|
|
||||||
IPv4MulticastFilter multicast_filter;
|
IPv4MulticastFilter multicast_filter;
|
||||||
};
|
};
|
||||||
@@ -673,12 +673,14 @@ deliver_multicast(net_protocol_module_info* module, net_buffer* buffer,
|
|||||||
if (module->deliver_data == NULL)
|
if (module->deliver_data == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// TODO: fix multicast!
|
||||||
|
return false;
|
||||||
MutexLocker _(sMulticastGroupsLock);
|
MutexLocker _(sMulticastGroupsLock);
|
||||||
|
|
||||||
sockaddr_in* multicastAddr = (sockaddr_in*)buffer->destination;
|
sockaddr_in* multicastAddr = (sockaddr_in*)buffer->destination;
|
||||||
|
|
||||||
MulticastState::ValueIterator it = sMulticastState->Lookup(std::make_pair(
|
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;
|
size_t count = 0;
|
||||||
|
|
||||||
@@ -687,7 +689,7 @@ deliver_multicast(net_protocol_module_info* module, net_buffer* buffer,
|
|||||||
|
|
||||||
ipv4_protocol* ipProtocol = state->Parent()->Socket();
|
ipv4_protocol* ipProtocol = state->Parent()->Socket();
|
||||||
if (deliverToRaw && (ipProtocol->raw == NULL
|
if (deliverToRaw && (ipProtocol->raw == NULL
|
||||||
|| ipProtocol->socket->protocol != buffer->protocol))
|
|| ipProtocol->socket->protocol != buffer->protocol))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (state->FilterAccepts(buffer)) {
|
if (state->FilterAccepts(buffer)) {
|
||||||
@@ -819,11 +821,8 @@ IPv4Multicast::JoinGroup(IPv4GroupInterface* state)
|
|||||||
MutexLocker _(sMulticastGroupsLock);
|
MutexLocker _(sMulticastGroupsLock);
|
||||||
|
|
||||||
sockaddr_in groupAddr;
|
sockaddr_in groupAddr;
|
||||||
net_interface* interface = state->Interface();
|
status_t status = sDatalinkModule->join_multicast(state->Interface(),
|
||||||
|
sDomain, fill_sockaddr_in(&groupAddr, state->Address().s_addr));
|
||||||
status_t status = interface->first_info->join_multicast(
|
|
||||||
interface->first_protocol,
|
|
||||||
fill_sockaddr_in(&groupAddr, state->Address().s_addr));
|
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
@@ -840,10 +839,7 @@ IPv4Multicast::LeaveGroup(IPv4GroupInterface* state)
|
|||||||
sMulticastState->Remove(state);
|
sMulticastState->Remove(state);
|
||||||
|
|
||||||
sockaddr_in groupAddr;
|
sockaddr_in groupAddr;
|
||||||
net_interface* interface = state->Interface();
|
return sDatalinkModule->leave_multicast(state->Interface(), sDomain,
|
||||||
|
|
||||||
return interface->first_protocol->module->join_multicast(
|
|
||||||
interface->first_protocol,
|
|
||||||
fill_sockaddr_in(&groupAddr, state->Address().s_addr));
|
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,
|
net_interface* interface, const in_addr* groupAddr,
|
||||||
const in_addr* sourceAddr)
|
const in_addr* sourceAddr)
|
||||||
{
|
{
|
||||||
IPv4MulticastFilter &filter = protocol->multicast_filter;
|
IPv4MulticastFilter& filter = protocol->multicast_filter;
|
||||||
IPv4GroupInterface* state = NULL;
|
IPv4GroupInterface* state = NULL;
|
||||||
status_t status = B_OK;
|
status_t status = B_OK;
|
||||||
|
|
||||||
@@ -935,13 +931,14 @@ generic_to_ipv4(int option)
|
|||||||
static net_interface*
|
static net_interface*
|
||||||
get_multicast_interface(ipv4_protocol* protocol, const in_addr* address)
|
get_multicast_interface(ipv4_protocol* protocol, const in_addr* address)
|
||||||
{
|
{
|
||||||
|
// TODO: this is broken and leaks references
|
||||||
sockaddr_in groupAddr;
|
sockaddr_in groupAddr;
|
||||||
net_route* route = sDatalinkModule->get_route(sDomain,
|
net_route* route = sDatalinkModule->get_route(sDomain,
|
||||||
fill_sockaddr_in(&groupAddr, address ? address->s_addr : INADDR_ANY));
|
fill_sockaddr_in(&groupAddr, address ? address->s_addr : INADDR_ANY));
|
||||||
if (route == NULL)
|
if (route == NULL)
|
||||||
return 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);
|
interface = get_multicast_interface(protocol, groupAddr);
|
||||||
} else {
|
} else {
|
||||||
sockaddr_in address;
|
sockaddr_in address;
|
||||||
interface = sDatalinkModule->get_interface_with_address(sDomain,
|
interface = sDatalinkModule->get_interface_with_address(
|
||||||
fill_sockaddr_in(&address, interfaceAddr->s_addr));
|
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,
|
uint32 index, const sockaddr_storage* _groupAddr,
|
||||||
const sockaddr_storage* _sourceAddr)
|
const sockaddr_storage* _sourceAddr)
|
||||||
{
|
{
|
||||||
if (_groupAddr->ss_family != AF_INET)
|
if (_groupAddr->ss_family != AF_INET
|
||||||
return B_BAD_VALUE;
|
|| _sourceAddr != NULL && _sourceAddr->ss_family != AF_INET)
|
||||||
|
|
||||||
if (_sourceAddr && _sourceAddr->ss_family != AF_INET)
|
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
const in_addr* groupAddr = &((const sockaddr_in*)_groupAddr)->sin_addr;
|
const in_addr* groupAddr = &((const sockaddr_in*)_groupAddr)->sin_addr;
|
||||||
|
|
||||||
|
// TODO: this is broken and leaks references
|
||||||
net_interface* interface;
|
net_interface* interface;
|
||||||
if (index == 0)
|
if (index == 0)
|
||||||
interface = get_multicast_interface(protocol, groupAddr);
|
interface = get_multicast_interface(protocol, groupAddr);
|
||||||
@@ -990,7 +986,7 @@ ipv4_generic_delta_membership(ipv4_protocol* protocol, int option,
|
|||||||
return ENODEV;
|
return ENODEV;
|
||||||
|
|
||||||
const in_addr* sourceAddr = NULL;
|
const in_addr* sourceAddr = NULL;
|
||||||
if (_sourceAddr)
|
if (_sourceAddr != NULL)
|
||||||
sourceAddr = &((const sockaddr_in*)_sourceAddr)->sin_addr;
|
sourceAddr = &((const sockaddr_in*)_sourceAddr)->sin_addr;
|
||||||
|
|
||||||
return ipv4_delta_membership(protocol, generic_to_ipv4(option), interface,
|
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->time_to_live = kDefaultTTL;
|
||||||
protocol->multicast_time_to_live = kDefaultMulticastTTL;
|
protocol->multicast_time_to_live = kDefaultMulticastTTL;
|
||||||
protocol->flags = 0;
|
protocol->flags = 0;
|
||||||
protocol->interface_address = NULL;
|
protocol->multicast_address = NULL;
|
||||||
return protocol;
|
return protocol;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1024,7 +1020,7 @@ ipv4_uninit_protocol(net_protocol* _protocol)
|
|||||||
ipv4_protocol* protocol = (ipv4_protocol*)_protocol;
|
ipv4_protocol* protocol = (ipv4_protocol*)_protocol;
|
||||||
|
|
||||||
delete protocol->raw;
|
delete protocol->raw;
|
||||||
delete protocol->interface_address;
|
delete protocol->multicast_address;
|
||||||
delete protocol;
|
delete protocol;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -1217,21 +1213,23 @@ ipv4_setsockopt(net_protocol* _protocol, int level, int option,
|
|||||||
// Using INADDR_ANY to remove the previous setting.
|
// Using INADDR_ANY to remove the previous setting.
|
||||||
if (address->sin_addr.s_addr == htonl(INADDR_ANY)) {
|
if (address->sin_addr.s_addr == htonl(INADDR_ANY)) {
|
||||||
delete address;
|
delete address;
|
||||||
delete protocol->interface_address;
|
delete protocol->multicast_address;
|
||||||
protocol->interface_address = NULL;
|
protocol->multicast_address = NULL;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct net_interface* interface
|
struct net_interface* interface
|
||||||
= sDatalinkModule->get_interface_with_address(sDomain,
|
= sDatalinkModule->get_interface_with_address(
|
||||||
(struct sockaddr*)address);
|
(sockaddr*)address);
|
||||||
if (interface == NULL) {
|
if (interface == NULL) {
|
||||||
delete address;
|
delete address;
|
||||||
return EADDRNOTAVAIL;
|
return EADDRNOTAVAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete protocol->interface_address;
|
delete protocol->multicast_address;
|
||||||
protocol->interface_address = (struct sockaddr*)address;
|
protocol->multicast_address = (struct sockaddr*)address;
|
||||||
|
|
||||||
|
sDatalinkModule->put_interface(interface);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
if (option == IP_MULTICAST_TTL) {
|
if (option == IP_MULTICAST_TTL) {
|
||||||
@@ -1346,16 +1344,18 @@ ipv4_send_routed_data(net_protocol* _protocol, struct net_route* route,
|
|||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
ipv4_protocol* protocol = (ipv4_protocol*)_protocol;
|
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,
|
TRACE_SK(protocol, "SendRoutedData(%p, %p [%ld bytes])", route, buffer,
|
||||||
buffer->size);
|
buffer->size);
|
||||||
|
|
||||||
sockaddr_in& source = *(sockaddr_in*)buffer->source;
|
sockaddr_in& source = *(sockaddr_in*)buffer->source;
|
||||||
sockaddr_in& destination = *(sockaddr_in*)buffer->destination;
|
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)
|
if (protocol != NULL)
|
||||||
headerIncluded = (protocol->flags & IP_FLAG_HEADER_INCLUDED) != 0;
|
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
|
if ((interface->device->flags & IFF_BROADCAST) != 0
|
||||||
&& (destination.sin_addr.s_addr == INADDR_BROADCAST
|
&& (destination.sin_addr.s_addr == INADDR_BROADCAST
|
||||||
|| destination.sin_addr.s_addr
|
|| (broadcastAddress != NULL && destination.sin_addr.s_addr
|
||||||
== broadcastAddress.sin_addr.s_addr)) {
|
== broadcastAddress->sin_addr.s_addr))) {
|
||||||
if (protocol && !(protocol->socket->options & SO_BROADCAST))
|
if (protocol && !(protocol->socket->options & SO_BROADCAST))
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
buffer->flags |= MSG_BCAST;
|
buffer->flags |= MSG_BCAST;
|
||||||
@@ -1466,18 +1466,21 @@ ipv4_send_data(net_protocol* _protocol, net_buffer* buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle IP_MULTICAST_IF
|
// handle IP_MULTICAST_IF
|
||||||
if (IN_MULTICAST(ntohl(((sockaddr_in*)buffer->destination)->
|
if (IN_MULTICAST(ntohl(
|
||||||
sin_addr.s_addr)) && protocol->interface_address != NULL) {
|
((sockaddr_in*)buffer->destination)->sin_addr.s_addr))
|
||||||
net_interface* interface
|
&& protocol->multicast_address != NULL) {
|
||||||
= sDatalinkModule->get_interface_with_address(sDomain,
|
net_interface_address* address = sDatalinkModule->get_interface_address(
|
||||||
protocol->interface_address);
|
protocol->multicast_address);
|
||||||
if (interface == NULL || (interface->flags & IFF_UP) == 0)
|
if (address == NULL || (address->interface->flags & IFF_UP) == 0) {
|
||||||
|
sDatalinkModule->put_interface_address(address);
|
||||||
return EADDRNOTAVAIL;
|
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,
|
net_route* route = sDatalinkModule->get_route(sDomain, address->local);
|
||||||
interface->address);
|
|
||||||
if (route == NULL)
|
if (route == NULL)
|
||||||
return ENETUNREACH;
|
return ENETUNREACH;
|
||||||
|
|
||||||
@@ -1540,7 +1543,7 @@ ipv4_get_mtu(net_protocol* protocol, const struct sockaddr* address)
|
|||||||
if (route->mtu != 0)
|
if (route->mtu != 0)
|
||||||
mtu = route->mtu;
|
mtu = route->mtu;
|
||||||
else
|
else
|
||||||
mtu = route->interface->mtu;
|
mtu = route->interface_address->interface->mtu;
|
||||||
|
|
||||||
sDatalinkModule->put_route(sDomain, route);
|
sDatalinkModule->put_route(sDomain, route);
|
||||||
return mtu - sizeof(ipv4_header);
|
return mtu - sizeof(ipv4_header);
|
||||||
@@ -1588,9 +1591,9 @@ ipv4_receive_data(net_buffer* buffer)
|
|||||||
|
|
||||||
// test if the packet is really for us
|
// test if the packet is really for us
|
||||||
if (!sDatalinkModule->is_local_address(sDomain, (sockaddr*)&destination,
|
if (!sDatalinkModule->is_local_address(sDomain, (sockaddr*)&destination,
|
||||||
&buffer->interface, &matchedAddressType)
|
&buffer->interface_address, &matchedAddressType)
|
||||||
&& !sDatalinkModule->is_local_link_address(sDomain, true,
|
&& !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",
|
TRACE(" ipv4_receive_data(): packet was not for us %x -> %x",
|
||||||
ntohl(header.source), ntohl(header.destination));
|
ntohl(header.source), ntohl(header.destination));
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -107,6 +107,7 @@ ipv4_is_empty_address(const sockaddr *address, bool checkPort)
|
|||||||
&& (!checkPort || ((sockaddr_in *)address)->sin_port == 0);
|
&& (!checkPort || ((sockaddr_in *)address)->sin_port == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Checks if the given \a address is an IPv4 address.
|
/*! Checks if the given \a address is an IPv4 address.
|
||||||
\return false if \a address is NULL, or with family different from AF_INET
|
\return false if \a address is NULL, or with family different from AF_INET
|
||||||
true if it has AF_INET address family
|
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;
|
return address->sa_family == AF_INET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! 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
|
\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
|
static status_t
|
||||||
ipv4_set_to_defaults(sockaddr *_defaultMask, sockaddr *_defaultBroadcast,
|
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 *defaultMask = (sockaddr_in *)_defaultMask;
|
||||||
sockaddr_in *defaultBroadcast = (sockaddr_in *)_defaultBroadcast;
|
sockaddr_in *defaultBroadcast = (sockaddr_in *)_defaultBroadcast;
|
||||||
sockaddr_in *address = (sockaddr_in *)_address;
|
const sockaddr_in *address = (const sockaddr_in *)_address;
|
||||||
sockaddr_in *mask = (sockaddr_in *)_mask;
|
const sockaddr_in *mask = (const sockaddr_in *)_mask;
|
||||||
|
|
||||||
if (address == NULL || (defaultMask == NULL && defaultBroadcast == NULL))
|
if (address == NULL || (defaultMask == NULL && defaultBroadcast == NULL))
|
||||||
return B_BAD_VALUE;
|
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
|
/*! Computes a hash-value of the given addresses \a ourAddress
|
||||||
and \a peerAddress.
|
and \a peerAddress.
|
||||||
\return uint32 representing the hash-value
|
\return uint32 representing the hash-value
|
||||||
@@ -526,6 +545,7 @@ net_address_module_info gIPv4AddressModule = {
|
|||||||
ipv4_set_to_empty_address,
|
ipv4_set_to_empty_address,
|
||||||
ipv4_set_to_defaults,
|
ipv4_set_to_defaults,
|
||||||
ipv4_update_to,
|
ipv4_update_to,
|
||||||
|
ipv4_hash_address,
|
||||||
ipv4_hash_address_pair,
|
ipv4_hash_address_pair,
|
||||||
ipv4_checksum_address,
|
ipv4_checksum_address,
|
||||||
ipv4_get_loopback_address
|
ipv4_get_loopback_address
|
||||||
|
|||||||
@@ -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.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -14,19 +14,27 @@
|
|||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
static inline bool
|
|
||||||
operator==(const in_addr &a1, const in_addr &a2)
|
|
||||||
{
|
|
||||||
return a1.s_addr == a2.s_addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
using std::nothrow;
|
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>
|
template<typename Addressing>
|
||||||
MulticastGroupInterface<Addressing>::MulticastGroupInterface(Filter *parent,
|
MulticastGroupInterface<Addressing>::MulticastGroupInterface(Filter *parent,
|
||||||
const AddressType &address, net_interface *interface)
|
const AddressType &address, net_interface *interface)
|
||||||
: fParent(parent), fMulticastAddress(address), fInterface(interface)
|
:
|
||||||
|
fParent(parent),
|
||||||
|
fMulticastAddress(address),
|
||||||
|
fInterface(interface)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* 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
|
/*! Computes a hash-value of the given addresses \a ourAddress
|
||||||
and \a peerAddress.
|
and \a peerAddress.
|
||||||
\return uint32 representing the hash-value
|
\return uint32 representing the hash-value
|
||||||
@@ -485,26 +504,8 @@ ipv6_set_to_defaults(sockaddr *_defaultMask, sockaddr *_defaultBroadcast,
|
|||||||
static uint32
|
static uint32
|
||||||
ipv6_hash_address_pair(const sockaddr *ourAddress, const sockaddr *peerAddress)
|
ipv6_hash_address_pair(const sockaddr *ourAddress, const sockaddr *peerAddress)
|
||||||
{
|
{
|
||||||
uint32 result = 0;
|
uint32 result = ipv6_hash_address(peerAddress, true);
|
||||||
if (ourAddress) {
|
return jenkins_hashword(&result, 1, ipv6_hash_address(ourAddress, true));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -563,6 +564,7 @@ net_address_module_info gIPv6AddressModule = {
|
|||||||
ipv6_set_to_empty_address,
|
ipv6_set_to_empty_address,
|
||||||
ipv6_set_to_defaults,
|
ipv6_set_to_defaults,
|
||||||
ipv6_update_to,
|
ipv6_update_to,
|
||||||
|
ipv6_hash_address,
|
||||||
ipv6_hash_address_pair,
|
ipv6_hash_address_pair,
|
||||||
ipv6_checksum_address,
|
ipv6_checksum_address,
|
||||||
ipv6_get_loopback_address
|
ipv6_get_loopback_address
|
||||||
|
|||||||
@@ -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.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
|
* Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <net_datalink.h>
|
#include <net_datalink.h>
|
||||||
|
|
||||||
#include <ByteOrder.h>
|
#include <ByteOrder.h>
|
||||||
@@ -20,15 +21,13 @@
|
|||||||
#include <bluetooth/bdaddrUtils.h>
|
#include <bluetooth/bdaddrUtils.h>
|
||||||
#include <bluetooth/L2CAP/btL2CAP.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])
|
|
||||||
|
|
||||||
/*!
|
#define L2CAP_CHECKSUM(address) \
|
||||||
Routing utility function: copies address \a from into a new 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.
|
that is put into \a to.
|
||||||
If \a replaceWithZeros is set \a from will be replaced by an empty
|
If \a replaceWithZeros is set \a from will be replaced by an empty
|
||||||
address.
|
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.
|
the resulting address into \a result.
|
||||||
\return B_OK if the mask has been applied
|
\return B_OK if the mask has been applied
|
||||||
\return B_BAD_VALUE if \a address or \a mask is NULL
|
\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.
|
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,
|
\return true if \a address is NULL, uninitialized or the empty address,
|
||||||
false if not
|
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.
|
/*! Checks if the given \a address is L2CAP address.
|
||||||
\return false if \a address is NULL, or with family different from AF_BLUETOOTH
|
\return false if \a address is NULL, or with family different from
|
||||||
true if it has AF_BLUETOOTH address family
|
AF_BLUETOOTH true if it has AF_BLUETOOTH address family
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
l2cap_is_same_family(const sockaddr *address)
|
l2cap_is_same_family(const sockaddr *address)
|
||||||
@@ -115,8 +112,8 @@ l2cap_is_same_family(const sockaddr *address)
|
|||||||
return address->sa_family == AF_BLUETOOTH;
|
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
|
\return true if IP-addresses of \a a and \a b are equal, false if not
|
||||||
*/
|
*/
|
||||||
static bool
|
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
|
\return true if ports of \a a and \a b are equal, false if not
|
||||||
*/
|
*/
|
||||||
static bool
|
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.
|
\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
|
static bool
|
||||||
l2cap_equal_addresses_and_ports(const sockaddr *a, const sockaddr *b)
|
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.
|
the masked addresses match.
|
||||||
\return true if \a a matches \a b after masking both, false if not
|
\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.
|
in the given \a mask.
|
||||||
\return the number of the first bit that is set (0-32, where 32 means
|
\return the number of the first bit that is set (0-32, where 32 means
|
||||||
that there's no bit set in the mask).
|
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
|
means that (starting with LSB) consists zero or more unset bits, followed
|
||||||
by bits that are all set).
|
by bits that are all set).
|
||||||
\return true if \a mask is ok, false if not
|
\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>').
|
it (hexadecimal representation in host byte order or '<none>').
|
||||||
If \a printPort is set, the port is printed, too.
|
If \a printPort is set, the port is printed, too.
|
||||||
\return B_OK if the address could be printed, \a buffer will point to
|
\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
|
\return uint16 representing the port-nr
|
||||||
*/
|
*/
|
||||||
static uint16
|
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_OK if the port has been set
|
||||||
\return B_BAD_VALUE if \a address is NULL
|
\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_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_BAD_VALUE if either \a address or \a from is NULL
|
||||||
\return B_MISMATCHED_VALUES if from is not of family AF_BLUETOOTH
|
\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.
|
||||||
Sets \a address to the empty address (0.0.0.0).
|
|
||||||
\return B_OK if \a address has been set
|
\return B_OK if \a address has been set
|
||||||
\return B_BAD_VALUE if \a address is NULL
|
\return B_BAD_VALUE if \a address is NULL
|
||||||
*/
|
*/
|
||||||
@@ -366,14 +354,28 @@ l2cap_set_to_empty_address(sockaddr *address)
|
|||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
l2cap_set_to_defaults(sockaddr *_defaultMask, sockaddr *_defaultBroadcast,
|
l2cap_set_to_defaults(sockaddr *_defaultMask, sockaddr *_defaultBroadcast,
|
||||||
sockaddr *_address, sockaddr *_mask)
|
const sockaddr *_address, const sockaddr *_mask)
|
||||||
{
|
{
|
||||||
|
// TODO: not implemented
|
||||||
return B_OK;
|
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.
|
and \a peerAddress.
|
||||||
\return uint32 representing the hash-value
|
\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_OK if \a address has been added to the checksum
|
||||||
\return B_BAD_VALUE if either \a address or \a checksum is NULL
|
\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_empty_address,
|
||||||
l2cap_set_to_defaults,
|
l2cap_set_to_defaults,
|
||||||
l2cap_update_to,
|
l2cap_update_to,
|
||||||
|
l2cap_hash_address,
|
||||||
l2cap_hash_address_pair,
|
l2cap_hash_address_pair,
|
||||||
l2cap_checksum_address,
|
l2cap_checksum_address,
|
||||||
NULL // get_loopback_address
|
NULL // get_loopback_address
|
||||||
|
|||||||
@@ -2127,7 +2127,7 @@ TCPEndpoint::_PrepareSendPath(const sockaddr* peer)
|
|||||||
|
|
||||||
// make sure connection does not already exist
|
// make sure connection does not already exist
|
||||||
status_t status = fManager->SetConnection(this, *LocalAddress(), peer,
|
status_t status = fManager->SetConnection(this, *LocalAddress(), peer,
|
||||||
fRoute->interface->address);
|
fRoute->interface_address->local);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
|||||||
@@ -660,10 +660,11 @@ tcp_receive_data(net_buffer* buffer)
|
|||||||
{
|
{
|
||||||
TRACE(("TCP: Received buffer %p\n", 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;
|
return B_ERROR;
|
||||||
|
|
||||||
net_domain* domain = buffer->interface->domain;
|
net_domain* domain = buffer->interface_address->domain;
|
||||||
net_address_module_info* addressModule = domain->address_module;
|
net_address_module_info* addressModule = domain->address_module;
|
||||||
|
|
||||||
NetBufferHeaderReader<tcp_header> bufferHeader(buffer);
|
NetBufferHeaderReader<tcp_header> bufferHeader(buffer);
|
||||||
|
|||||||
@@ -367,7 +367,7 @@ UdpDomainSupport::ConnectEndpoint(UdpEndpoint *endpoint,
|
|||||||
= gDatalinkModule->get_route(fDomain, address);
|
= gDatalinkModule->get_route(fDomain, address);
|
||||||
if (routeToDestination) {
|
if (routeToDestination) {
|
||||||
status = endpoint->LocalAddress().SetTo(
|
status = endpoint->LocalAddress().SetTo(
|
||||||
routeToDestination->interface->address);
|
routeToDestination->interface_address->local);
|
||||||
gDatalinkModule->put_route(fDomain, routeToDestination);
|
gDatalinkModule->put_route(fDomain, routeToDestination);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
@@ -516,8 +516,8 @@ UdpDomainSupport::_DemuxBroadcast(net_buffer *buffer)
|
|||||||
sockaddr *peerAddr = buffer->source;
|
sockaddr *peerAddr = buffer->source;
|
||||||
sockaddr *broadcastAddr = buffer->destination;
|
sockaddr *broadcastAddr = buffer->destination;
|
||||||
sockaddr *mask = NULL;
|
sockaddr *mask = NULL;
|
||||||
if (buffer->interface)
|
if (buffer->interface_address != NULL)
|
||||||
mask = (sockaddr *)buffer->interface->mask;
|
mask = (sockaddr *)buffer->interface_address->mask;
|
||||||
|
|
||||||
TRACE_DOMAIN("_DemuxBroadcast(%p)", buffer);
|
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)
|
std::min(buffer->size, sizeof(udp_header))) != B_OK)
|
||||||
return B_BAD_VALUE;
|
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;
|
net_address_module_info* addressModule = domain->address_module;
|
||||||
|
|
||||||
SocketAddress source(addressModule, buffer->source);
|
SocketAddress source(addressModule, buffer->source);
|
||||||
@@ -760,13 +760,14 @@ UdpEndpointManager::Deframe(net_buffer *buffer)
|
|||||||
|
|
||||||
udp_header &header = bufferHeader.Data();
|
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 "
|
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;
|
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;
|
net_address_module_info *addressModule = domain->address_module;
|
||||||
|
|
||||||
SocketAddress source(addressModule, buffer->source);
|
SocketAddress source(addressModule, buffer->source);
|
||||||
@@ -869,11 +870,11 @@ UdpEndpointManager::_GetDomain(net_domain *domain, bool create)
|
|||||||
UdpDomainSupport*
|
UdpDomainSupport*
|
||||||
UdpEndpointManager::_GetDomain(net_buffer* buffer)
|
UdpEndpointManager::_GetDomain(net_buffer* buffer)
|
||||||
{
|
{
|
||||||
if (buffer->interface == NULL)
|
if (buffer->interface_address == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
MutexLocker _(fLock);
|
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
|
// 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
|
// whole RX path, we may not hold an endpoint's lock with the
|
||||||
// manager lock held.
|
// manager lock held.
|
||||||
@@ -1313,38 +1314,42 @@ init_udp()
|
|||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
goto err1;
|
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/udp/v1",
|
||||||
"network/protocols/ipv4/v1",
|
"network/protocols/ipv4/v1",
|
||||||
NULL);
|
NULL);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
goto err1;
|
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/udp/v1",
|
||||||
"network/protocols/ipv6/v1",
|
"network/protocols/ipv6/v1",
|
||||||
NULL);
|
NULL);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
goto err1;
|
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/udp/v1",
|
||||||
"network/protocols/ipv4/v1",
|
"network/protocols/ipv4/v1",
|
||||||
NULL);
|
NULL);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
goto err1;
|
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/udp/v1",
|
||||||
"network/protocols/ipv6/v1",
|
"network/protocols/ipv6/v1",
|
||||||
NULL);
|
NULL);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
goto err1;
|
goto err1;
|
||||||
|
|
||||||
status = gStackModule->register_domain_receiving_protocol(AF_INET, IPPROTO_UDP,
|
status = gStackModule->register_domain_receiving_protocol(AF_INET,
|
||||||
"network/protocols/udp/v1");
|
IPPROTO_UDP, "network/protocols/udp/v1");
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
goto err1;
|
goto err1;
|
||||||
status = gStackModule->register_domain_receiving_protocol(AF_INET6, IPPROTO_UDP,
|
status = gStackModule->register_domain_receiving_protocol(AF_INET6,
|
||||||
"network/protocols/udp/v1");
|
IPPROTO_UDP, "network/protocols/udp/v1");
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
goto err1;
|
goto err1;
|
||||||
|
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ unix_mask_address(const sockaddr *address, const sockaddr *mask,
|
|||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
unix_set_to_defaults(sockaddr *defaultMask, sockaddr *defaultBroadcast,
|
unix_set_to_defaults(sockaddr *defaultMask, sockaddr *defaultBroadcast,
|
||||||
sockaddr *address, sockaddr *netmask)
|
const sockaddr *address, const sockaddr *netmask)
|
||||||
{
|
{
|
||||||
if (address == NULL)
|
if (address == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
@@ -246,8 +246,9 @@ unix_update_to(sockaddr *address, const sockaddr *from)
|
|||||||
|
|
||||||
|
|
||||||
static uint32
|
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)
|
if (address == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -264,8 +265,8 @@ hash_address(const sockaddr_un* address)
|
|||||||
static uint32
|
static uint32
|
||||||
unix_hash_address_pair(const sockaddr *ourAddress, const sockaddr *peerAddress)
|
unix_hash_address_pair(const sockaddr *ourAddress, const sockaddr *peerAddress)
|
||||||
{
|
{
|
||||||
return hash_address((sockaddr_un*)ourAddress) * 17
|
return unix_hash_address(ourAddress, false) * 17
|
||||||
+ hash_address((sockaddr_un*)peerAddress);
|
+ unix_hash_address(peerAddress, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -309,6 +310,7 @@ net_address_module_info gAddressModule = {
|
|||||||
unix_set_to_empty_address,
|
unix_set_to_empty_address,
|
||||||
unix_set_to_defaults,
|
unix_set_to_defaults,
|
||||||
unix_update_to,
|
unix_update_to,
|
||||||
|
unix_hash_address,
|
||||||
unix_hash_address_pair,
|
unix_hash_address_pair,
|
||||||
unix_checksum_address,
|
unix_checksum_address,
|
||||||
NULL // get_loopback_address
|
NULL // get_loopback_address
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ UsePrivateHeaders net shared ;
|
|||||||
KernelAddon stack :
|
KernelAddon stack :
|
||||||
ancillary_data.cpp
|
ancillary_data.cpp
|
||||||
datalink.cpp
|
datalink.cpp
|
||||||
|
device_interfaces.cpp
|
||||||
domains.cpp
|
domains.cpp
|
||||||
interfaces.cpp
|
interfaces.cpp
|
||||||
net_buffer.cpp
|
net_buffer.cpp
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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
|
||||||
@@ -47,6 +47,8 @@ static DomainList sDomains;
|
|||||||
static net_domain_private*
|
static net_domain_private*
|
||||||
lookup_domain(int family)
|
lookup_domain(int family)
|
||||||
{
|
{
|
||||||
|
ASSERT_LOCKED_MUTEX(&sDomainLock);
|
||||||
|
|
||||||
DomainList::Iterator iterator = sDomains.GetIterator();
|
DomainList::Iterator iterator = sDomains.GetIterator();
|
||||||
while (net_domain_private* domain = iterator.Next()) {
|
while (net_domain_private* domain = iterator.Next()) {
|
||||||
if (domain->family == family)
|
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("domain: %p, %s, %d\n", domain, domain->name, domain->family);
|
||||||
kprintf(" module: %p\n", domain->module);
|
kprintf(" module: %p\n", domain->module);
|
||||||
kprintf(" address_module: %p\n", domain->address_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())
|
if (!domain->routes.IsEmpty())
|
||||||
kprintf(" routes:\n");
|
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
|
status_t
|
||||||
register_domain(int family, const char* name,
|
register_domain(int family, const char* name,
|
||||||
struct net_protocol_module_info* module,
|
struct net_protocol_module_info* module,
|
||||||
@@ -367,8 +132,6 @@ register_domain(int family, const char* name,
|
|||||||
domain->module = module;
|
domain->module = module;
|
||||||
domain->address_module = addressModule;
|
domain->address_module = addressModule;
|
||||||
|
|
||||||
list_init(&domain->interfaces);
|
|
||||||
|
|
||||||
sDomains.Add(domain);
|
sDomains.Add(domain);
|
||||||
|
|
||||||
*_domain = domain;
|
*_domain = domain;
|
||||||
@@ -387,16 +150,6 @@ unregister_domain(net_domain* _domain)
|
|||||||
|
|
||||||
sDomains.Remove(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);
|
recursive_lock_destroy(&domain->lock);
|
||||||
delete domain;
|
delete domain;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|||||||
@@ -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);
|
net_domain* get_domain(int family);
|
||||||
status_t register_domain(int family, const char* name,
|
status_t register_domain(int family, const char* name,
|
||||||
struct net_protocol_module_info* module,
|
struct net_protocol_module_info* module,
|
||||||
struct net_address_module_info* addressModule, net_domain* *_domain);
|
struct net_address_module_info* addressModule, net_domain* *_domain);
|
||||||
status_t unregister_domain(net_domain* domain);
|
status_t unregister_domain(net_domain* domain);
|
||||||
|
|
||||||
|
status_t init_domains();
|
||||||
|
status_t uninit_domains();
|
||||||
|
|
||||||
|
|
||||||
#endif // DOMAINS_H
|
#endif // DOMAINS_H
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -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.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -9,93 +9,175 @@
|
|||||||
#define INTERFACES_H
|
#define INTERFACES_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "routes.h"
|
||||||
|
#include "stack_private.h"
|
||||||
|
|
||||||
#include <net_datalink.h>
|
#include <net_datalink.h>
|
||||||
#include <net_stack.h>
|
#include <net_stack.h>
|
||||||
|
|
||||||
|
#include <Referenceable.h>
|
||||||
|
|
||||||
#include <util/DoublyLinkedList.h>
|
#include <util/DoublyLinkedList.h>
|
||||||
|
#include <util/OpenHashTable.h>
|
||||||
|
|
||||||
|
|
||||||
struct net_device_handler : DoublyLinkedListLinkImpl<net_device_handler> {
|
struct net_device_interface;
|
||||||
net_receive_func func;
|
|
||||||
int32 type;
|
|
||||||
void* cookie;
|
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,
|
struct domain_datalink {
|
||||||
DoublyLinkedListCLink<net_device_monitor> > DeviceMonitorList;
|
domain_datalink* hash_link;
|
||||||
|
net_domain* domain;
|
||||||
|
|
||||||
struct net_device_interface : DoublyLinkedListLinkImpl<net_device_interface> {
|
struct net_datalink_protocol* first_protocol;
|
||||||
struct net_device* device;
|
struct net_datalink_protocol_module_info* first_info;
|
||||||
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;
|
// support for binding to an interface
|
||||||
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;
|
|
||||||
net_route_private direct_route;
|
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 init_interfaces();
|
||||||
status_t uninit_interfaces();
|
status_t uninit_interfaces();
|
||||||
|
|
||||||
// interfaces
|
// interfaces
|
||||||
struct net_interface_private* find_interface(struct net_domain* domain,
|
status_t add_interface(const char* name, net_domain_private* domain,
|
||||||
const char* name);
|
const ifaliasreq& request, net_device_interface* deviceInterface);
|
||||||
struct net_interface_private* find_interface(struct net_domain* domain,
|
status_t remove_interface(Interface* interface);
|
||||||
uint32 index);
|
void interface_went_down(Interface* interface);
|
||||||
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);
|
|
||||||
|
|
||||||
// device interfaces
|
status_t add_interface_address(Interface* interface, net_domain_private* domain,
|
||||||
void get_device_interface_address(net_device_interface* interface,
|
const ifaliasreq& request);
|
||||||
sockaddr* address);
|
status_t update_interface_address(InterfaceAddress* interfaceAddress,
|
||||||
uint32 count_device_interfaces();
|
int32 option, const sockaddr* oldAddress, const sockaddr* newAddress);
|
||||||
status_t list_device_interfaces(void* buffer, size_t* _bufferSize);
|
|
||||||
void put_device_interface(struct net_device_interface* interface);
|
Interface* get_interface(net_domain* domain, uint32 index);
|
||||||
struct net_device_interface* get_device_interface(uint32 index);
|
Interface* get_interface(net_domain* domain, const char* name);
|
||||||
struct net_device_interface* get_device_interface(const char* name,
|
Interface* get_interface_for_device(net_domain* domain, uint32 index);
|
||||||
bool create = true);
|
InterfaceAddress* get_interface_address(const struct sockaddr* address);
|
||||||
void down_device_interface(net_device_interface* interface);
|
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
|
#endif // INTERFACES_H
|
||||||
|
|||||||
@@ -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.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Axel Dörfler, axeld@pinc-software.de
|
* Axel Dörfler, axeld@pinc-software.de
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
//! The net_protocol one talks to when using the AF_LINK protocol
|
//! The net_protocol one talks to when using the AF_LINK protocol
|
||||||
|
|
||||||
|
|
||||||
#include "datalink.h"
|
#include "datalink.h"
|
||||||
|
#include "device_interfaces.h"
|
||||||
#include "domains.h"
|
#include "domains.h"
|
||||||
#include "interfaces.h"
|
|
||||||
#include "link.h"
|
#include "link.h"
|
||||||
#include "stack_private.h"
|
#include "stack_private.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
|
|
||||||
#include "ancillary_data.h"
|
#include "ancillary_data.h"
|
||||||
|
#include "interfaces.h"
|
||||||
|
|
||||||
#include "paranoia_config.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 net_buffer_private : net_buffer {
|
||||||
struct list buffers;
|
struct list buffers;
|
||||||
data_header* allocation_header;
|
data_header* allocation_header;
|
||||||
@@ -578,15 +583,24 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
static void
|
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)
|
if (address == NULL || address->sa_len == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dprintf(" %s: length %u, family %u\n", prefix, address->sa_len,
|
if (interfaceAddress == NULL || interfaceAddress->domain == NULL) {
|
||||||
address->sa_family);
|
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;
|
net_buffer_private* buffer = (net_buffer_private*)_buffer;
|
||||||
|
|
||||||
dprintf("buffer %p, size %" B_PRIu32 ", flags %" B_PRIx32 ", stored header "
|
dprintf("buffer %p, size %" B_PRIu32 ", flags %" B_PRIx32 ", stored header "
|
||||||
"%" B_PRIu32 "\n", buffer, buffer->size, buffer->flags,
|
"%" B_PRIu32 ", interface address %p\n", buffer, buffer->size,
|
||||||
buffer->stored_header_length);
|
buffer->flags, buffer->stored_header_length, buffer->interface_address);
|
||||||
|
|
||||||
dump_address("source", buffer->source);
|
dump_address("source", buffer->source, buffer->interface_address);
|
||||||
dump_address("destination", buffer->destination);
|
dump_address("destination", buffer->destination, buffer->interface_address);
|
||||||
|
|
||||||
data_node* node = NULL;
|
data_node* node = NULL;
|
||||||
while ((node = (data_node*)list_get_next_item(&buffer->buffers, node))
|
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)));
|
min_c(source->destination->sa_len, sizeof(sockaddr_storage)));
|
||||||
|
|
||||||
destination->flags = source->flags;
|
destination->flags = source->flags;
|
||||||
destination->interface = source->interface;
|
destination->interface_address = source->interface_address;
|
||||||
destination->offset = source->offset;
|
destination->offset = source->offset;
|
||||||
destination->protocol = source->protocol;
|
destination->protocol = source->protocol;
|
||||||
destination->type = source->type;
|
destination->type = source->type;
|
||||||
@@ -1107,13 +1121,11 @@ create_buffer(size_t headerSpace)
|
|||||||
buffer->storage.source.ss_len = 0;
|
buffer->storage.source.ss_len = 0;
|
||||||
buffer->storage.destination.ss_len = 0;
|
buffer->storage.destination.ss_len = 0;
|
||||||
|
|
||||||
buffer->interface = NULL;
|
buffer->interface_address = NULL;
|
||||||
buffer->offset = 0;
|
buffer->offset = 0;
|
||||||
buffer->flags = 0;
|
buffer->flags = 0;
|
||||||
buffer->size = 0;
|
buffer->size = 0;
|
||||||
|
|
||||||
buffer->type = -1;
|
|
||||||
|
|
||||||
CHECK_BUFFER(buffer);
|
CHECK_BUFFER(buffer);
|
||||||
CREATE_PARANOIA_CHECK_SET(buffer, "net_buffer");
|
CREATE_PARANOIA_CHECK_SET(buffer, "net_buffer");
|
||||||
SET_PARANOIA_CHECK(PARANOIA_SUSPICIOUS, buffer, &buffer->size,
|
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)
|
restore_header(net_buffer* _buffer, uint32 offset, void* data, size_t bytes)
|
||||||
{
|
{
|
||||||
net_buffer_private* buffer = (net_buffer_private*)_buffer;
|
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)
|
if (offset < buffer->stored_header_length) {
|
||||||
return B_OK;
|
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;
|
// We have the data, so copy it out
|
||||||
bytes -= buffer->stored_header_length;
|
|
||||||
|
|
||||||
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)
|
size_t bytes)
|
||||||
{
|
{
|
||||||
net_buffer_private* source = (net_buffer_private*)_source;
|
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,
|
// We have the data, so copy it out
|
||||||
node->start - source->stored_header_length,
|
|
||||||
std::min(bytes, source->stored_header_length));
|
|
||||||
if (status != B_OK)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
if (bytes <= source->stored_header_length)
|
size_t appended = std::min(bytes, source->stored_header_length - offset);
|
||||||
return B_OK;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -31,9 +31,9 @@
|
|||||||
|
|
||||||
//#define TRACE_ROUTES
|
//#define TRACE_ROUTES
|
||||||
#ifdef TRACE_ROUTES
|
#ifdef TRACE_ROUTES
|
||||||
# define TRACE(x) dprintf x
|
# define TRACE(x...) dprintf(STACK_DEBUG_PREFIX x)
|
||||||
#else
|
#else
|
||||||
# define TRACE(x) ;
|
# define TRACE(x...) ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -131,8 +131,9 @@ find_route(struct net_domain* _domain, const net_route* description)
|
|||||||
|
|
||||||
if ((route->flags & RTF_DEFAULT) != 0
|
if ((route->flags & RTF_DEFAULT) != 0
|
||||||
&& (description->flags & RTF_DEFAULT) != 0) {
|
&& (description->flags & RTF_DEFAULT) != 0) {
|
||||||
// there can only be one default route per interface
|
// there can only be one default route per interface address family
|
||||||
if (route->interface == description->interface)
|
// TODO: check this better
|
||||||
|
if (route->interface_address == description->interface_address)
|
||||||
return route;
|
return route;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@@ -147,8 +148,8 @@ find_route(struct net_domain* _domain, const net_route* description)
|
|||||||
description->mask)
|
description->mask)
|
||||||
&& domain->address_module->equal_addresses(route->gateway,
|
&& domain->address_module->equal_addresses(route->gateway,
|
||||||
description->gateway)
|
description->gateway)
|
||||||
&& (description->interface == NULL
|
&& (description->interface_address == NULL
|
||||||
|| description->interface == route->interface))
|
|| description->interface_address == route->interface_address))
|
||||||
return route;
|
return route;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,8 +167,8 @@ find_route(net_domain* _domain, const sockaddr* address)
|
|||||||
RouteList::Iterator iterator = domain->routes.GetIterator();
|
RouteList::Iterator iterator = domain->routes.GetIterator();
|
||||||
net_route_private* candidate = NULL;
|
net_route_private* candidate = NULL;
|
||||||
|
|
||||||
TRACE(("test address %s for routes...\n",
|
TRACE("test address %s for routes...\n",
|
||||||
AddressString(domain, address).Data()));
|
AddressString(domain, address).Data());
|
||||||
|
|
||||||
// TODO: alternate equal default routes
|
// TODO: alternate equal default routes
|
||||||
|
|
||||||
@@ -186,17 +187,18 @@ find_route(net_domain* _domain, const sockaddr* address)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// neglect routes that point to devices that have no link
|
// 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) {
|
if (candidate == NULL) {
|
||||||
TRACE((" found candidate: %s, flags %lx\n", AddressString(
|
TRACE(" found candidate: %s, flags %lx\n", AddressString(
|
||||||
domain, route->destination).Data(), route->flags));
|
domain, route->destination).Data(), route->flags);
|
||||||
candidate = route;
|
candidate = route;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE((" found route: %s, flags %lx\n",
|
TRACE(" found route: %s, flags %lx\n",
|
||||||
AddressString(domain, route->destination).Data(), route->flags));
|
AddressString(domain, route->destination).Data(), route->flags);
|
||||||
|
|
||||||
return route;
|
return route;
|
||||||
}
|
}
|
||||||
@@ -215,6 +217,9 @@ put_route_internal(struct net_domain_private* domain, net_route* _route)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// delete route - it must already have been removed at this point
|
// delete route - it must already have been removed at this point
|
||||||
|
if (route->interface_address != NULL)
|
||||||
|
((InterfaceAddress*)route->interface_address)->ReleaseReference();
|
||||||
|
|
||||||
delete route;
|
delete route;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,7 +239,7 @@ get_route_internal(struct net_domain_private* domain,
|
|||||||
while (iterator.HasNext()) {
|
while (iterator.HasNext()) {
|
||||||
route = iterator.Next();
|
route = iterator.Next();
|
||||||
|
|
||||||
net_device* device = route->interface->device;
|
net_device* device = route->interface_address->interface->device;
|
||||||
|
|
||||||
if ((link->sdl_nlen > 0
|
if ((link->sdl_nlen > 0
|
||||||
&& !strncmp(device->name, (const char*)link->sdl_data,
|
&& !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->destination = copy_address(buffer, route->destination);
|
||||||
target->mask = copy_address(buffer, route->mask);
|
target->mask = copy_address(buffer, route->mask);
|
||||||
target->gateway = copy_address(buffer, route->gateway);
|
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->flags = route->flags;
|
||||||
target->mtu = route->mtu;
|
target->mtu = route->mtu;
|
||||||
|
|
||||||
@@ -375,7 +380,8 @@ list_routes(net_domain_private* domain, void* buffer, size_t size)
|
|||||||
return ENOBUFS;
|
return ENOBUFS;
|
||||||
|
|
||||||
ifreq request;
|
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.destination = destination;
|
||||||
request.ifr_route.mask = mask;
|
request.ifr_route.mask = mask;
|
||||||
request.ifr_route.gateway = gateway;
|
request.ifr_route.gateway = gateway;
|
||||||
@@ -402,10 +408,10 @@ list_routes(net_domain_private* domain, void* buffer, size_t size)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
control_routes(struct net_interface* interface, int32 option, void* argument,
|
control_routes(struct net_interface* _interface, net_domain* domain,
|
||||||
size_t length)
|
int32 option, void* argument, size_t length)
|
||||||
{
|
{
|
||||||
net_domain_private* domain = (net_domain_private*)interface->domain;
|
Interface* interface = (Interface*)_interface;
|
||||||
|
|
||||||
switch (option) {
|
switch (option) {
|
||||||
case SIOCADDRT:
|
case SIOCADDRT:
|
||||||
@@ -429,14 +435,20 @@ control_routes(struct net_interface* interface, int32 option, void* argument,
|
|||||||
!= B_OK)
|
!= B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
InterfaceAddress* address
|
||||||
|
= interface->FirstForFamily(domain->family);
|
||||||
|
|
||||||
route.mtu = entry.mtu;
|
route.mtu = entry.mtu;
|
||||||
route.flags = entry.flags;
|
route.flags = entry.flags;
|
||||||
route.interface = interface;
|
route.interface_address = address;
|
||||||
|
|
||||||
if (option == SIOCADDRT)
|
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;
|
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;
|
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,
|
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->mask ? newRoute->mask : NULL).Data(),
|
||||||
AddressString(domain, newRoute->gateway ? newRoute->gateway : NULL).Data(),
|
AddressString(domain, newRoute->gateway
|
||||||
newRoute->flags));
|
? 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_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)
|
|| ((newRoute->flags & RTF_GATEWAY) != 0 && newRoute->gateway == NULL)
|
||||||
|| !domain->address_module->check_mask(newRoute->mask))
|
|| !domain->address_module->check_mask(newRoute->mask))
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
@@ -484,7 +500,8 @@ add_route(struct net_domain* _domain, const struct net_route* newRoute)
|
|||||||
}
|
}
|
||||||
|
|
||||||
route->flags = newRoute->flags;
|
route->flags = newRoute->flags;
|
||||||
route->interface = newRoute->interface;
|
route->interface_address = newRoute->interface_address;
|
||||||
|
((InterfaceAddress*)route->interface_address)->AcquireReference();
|
||||||
route->mtu = 0;
|
route->mtu = 0;
|
||||||
route->ref_count = 1;
|
route->ref_count = 1;
|
||||||
|
|
||||||
@@ -504,8 +521,8 @@ add_route(struct net_domain* _domain, const struct net_route* newRoute)
|
|||||||
&& (before->flags & RTF_DEFAULT) != 0) {
|
&& (before->flags & RTF_DEFAULT) != 0) {
|
||||||
// both routes are equal - let the link speed decide the
|
// both routes are equal - let the link speed decide the
|
||||||
// order
|
// order
|
||||||
if (before->interface->device->link_speed
|
if (before->interface_address->interface->device->link_speed
|
||||||
< route->interface->device->link_speed)
|
< route->interface_address->interface->device->link_speed)
|
||||||
break;
|
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;
|
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,
|
domain->name,
|
||||||
AddressString(domain, removeRoute->destination ? removeRoute->destination : NULL).Data(),
|
AddressString(domain, removeRoute->destination
|
||||||
AddressString(domain, removeRoute->mask ? removeRoute->mask : NULL).Data(),
|
? removeRoute->destination : NULL).Data(),
|
||||||
AddressString(domain, removeRoute->gateway ? removeRoute->gateway : NULL).Data(),
|
AddressString(domain, removeRoute->mask
|
||||||
removeRoute->flags));
|
? removeRoute->mask : NULL).Data(),
|
||||||
|
AddressString(domain, removeRoute->gateway
|
||||||
|
? removeRoute->gateway : NULL).Data(),
|
||||||
|
removeRoute->flags);
|
||||||
|
|
||||||
RecursiveLocker locker(domain->lock);
|
RecursiveLocker locker(domain->lock);
|
||||||
|
|
||||||
@@ -578,9 +598,8 @@ get_route_information(struct net_domain* _domain, void* value, size_t length)
|
|||||||
void
|
void
|
||||||
invalidate_routes(net_domain* _domain, net_interface* interface)
|
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;
|
net_domain_private* domain = (net_domain_private*)_domain;
|
||||||
|
RecursiveLocker locker(domain->lock);
|
||||||
|
|
||||||
dprintf("invalidate_routes(%i, %s)\n", domain->family, interface->name);
|
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()) {
|
while (iterator.HasNext()) {
|
||||||
net_route* route = iterator.Next();
|
net_route* route = iterator.Next();
|
||||||
|
|
||||||
if (route->interface->index == interface->index)
|
if (route->interface_address->interface == interface)
|
||||||
remove_route(domain, route);
|
remove_route(domain, route);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -605,28 +624,20 @@ get_route(struct net_domain* _domain, const struct sockaddr* address)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
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->ReleaseReference();
|
||||||
interface = (net_interface_private*)list_get_next_item(
|
return B_OK;
|
||||||
&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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -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
|
// TODO: we are quite relaxed in the address checking here
|
||||||
// as we might proceed with source = INADDR_ANY.
|
// 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,
|
status = domain->address_module->update_to(source,
|
||||||
route->interface->address);
|
route->interface_address->local);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ typedef DoublyLinkedList<net_route_info,
|
|||||||
uint32 route_table_size(struct net_domain_private* domain);
|
uint32 route_table_size(struct net_domain_private* domain);
|
||||||
status_t list_routes(struct net_domain_private* domain, void* buffer,
|
status_t list_routes(struct net_domain_private* domain, void* buffer,
|
||||||
size_t size);
|
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);
|
int32 option, void* argument, size_t length);
|
||||||
|
|
||||||
status_t add_route(struct net_domain* domain,
|
status_t add_route(struct net_domain* domain,
|
||||||
|
|||||||
@@ -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.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "ancillary_data.h"
|
#include "ancillary_data.h"
|
||||||
|
#include "device_interfaces.h"
|
||||||
#include "domains.h"
|
#include "domains.h"
|
||||||
#include "interfaces.h"
|
#include "interfaces.h"
|
||||||
#include "link.h"
|
#include "link.h"
|
||||||
@@ -501,9 +502,9 @@ put_domain_protocols(net_socket* socket)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
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) {
|
while (protocol != NULL) {
|
||||||
net_datalink_protocol* next = protocol->next;
|
net_datalink_protocol* next = protocol->next;
|
||||||
protocol->module->uninit_protocol(protocol);
|
protocol->module->uninit_protocol(protocol);
|
||||||
@@ -511,22 +512,21 @@ uninit_domain_datalink_protocols(net_interface* interface)
|
|||||||
protocol = next;
|
protocol = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface->first_protocol = NULL;
|
datalink->first_protocol = NULL;
|
||||||
interface->first_info = NULL;
|
datalink->first_info = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
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;
|
struct chain* chain;
|
||||||
|
|
||||||
{
|
{
|
||||||
MutexLocker _(sChainLock);
|
MutexLocker _(sChainLock);
|
||||||
|
|
||||||
chain = chain::Lookup(sDatalinkProtocolChains, interface->domain->family,
|
chain = chain::Lookup(sDatalinkProtocolChains, domain->family,
|
||||||
interface->device_interface->device->type, 0);
|
interface->DeviceInterface()->device->type, 0);
|
||||||
if (chain == NULL)
|
if (chain == NULL)
|
||||||
return EAFNOSUPPORT;
|
return EAFNOSUPPORT;
|
||||||
}
|
}
|
||||||
@@ -542,21 +542,26 @@ get_domain_datalink_protocols(net_interface* _interface)
|
|||||||
for (int32 i = 0; chain->infos[i] != NULL; i++) {
|
for (int32 i = 0; chain->infos[i] != NULL; i++) {
|
||||||
net_datalink_protocol* protocol;
|
net_datalink_protocol* protocol;
|
||||||
status_t status = ((net_datalink_protocol_module_info*)
|
status_t status = ((net_datalink_protocol_module_info*)
|
||||||
chain->infos[i])->init_protocol(interface, &protocol);
|
chain->infos[i])->init_protocol(interface, domain, &protocol);
|
||||||
if (status < B_OK) {
|
if (status != B_OK) {
|
||||||
// free protocols we already initialized
|
// free protocols we already initialized
|
||||||
uninit_domain_datalink_protocols(interface);
|
uninit_domain_datalink_protocols(
|
||||||
|
interface->DomainDatalink(domain->family));
|
||||||
chain->Release();
|
chain->Release();
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol->module = (net_datalink_protocol_module_info*)chain->infos[i];
|
protocol->module = (net_datalink_protocol_module_info*)chain->infos[i];
|
||||||
protocol->interface = interface;
|
protocol->interface = interface;
|
||||||
|
protocol->domain = domain;
|
||||||
protocol->next = NULL;
|
protocol->next = NULL;
|
||||||
|
|
||||||
if (last == NULL) {
|
if (last == NULL) {
|
||||||
interface->first_protocol = protocol;
|
domain_datalink* datalink
|
||||||
interface->first_info = protocol->module;
|
= interface->DomainDatalink(domain->family);
|
||||||
|
|
||||||
|
datalink->first_protocol = protocol;
|
||||||
|
datalink->first_info = protocol->module;
|
||||||
} else
|
} else
|
||||||
last->next = protocol;
|
last->next = protocol;
|
||||||
|
|
||||||
@@ -568,21 +573,20 @@ get_domain_datalink_protocols(net_interface* _interface)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
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;
|
struct chain* chain;
|
||||||
|
|
||||||
{
|
{
|
||||||
MutexLocker _(sChainLock);
|
MutexLocker _(sChainLock);
|
||||||
|
|
||||||
chain = chain::Lookup(sDatalinkProtocolChains, interface->domain->family,
|
chain = chain::Lookup(sDatalinkProtocolChains, domain->family,
|
||||||
interface->device_interface->device->type, 0);
|
interface->DeviceInterface()->device->type, 0);
|
||||||
if (chain == NULL)
|
if (chain == NULL)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
uninit_domain_datalink_protocols(interface);
|
uninit_domain_datalink_protocols(interface->DomainDatalink(domain->family));
|
||||||
chain->Release();
|
chain->Release();
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -756,10 +760,14 @@ init_stack()
|
|||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
goto err1;
|
goto err1;
|
||||||
|
|
||||||
status = init_timers();
|
status = init_device_interfaces();
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
goto err2;
|
goto err2;
|
||||||
|
|
||||||
|
status = init_timers();
|
||||||
|
if (status != B_OK)
|
||||||
|
goto err3;
|
||||||
|
|
||||||
status = init_notifications();
|
status = init_notifications();
|
||||||
if (status < B_OK) {
|
if (status < B_OK) {
|
||||||
// If this fails, it just means there won't be any notifications,
|
// If this fails, it just means there won't be any notifications,
|
||||||
@@ -771,7 +779,7 @@ init_stack()
|
|||||||
module_info* dummy;
|
module_info* dummy;
|
||||||
status = get_module(NET_SOCKET_MODULE_NAME, &dummy);
|
status = get_module(NET_SOCKET_MODULE_NAME, &dummy);
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
goto err3;
|
goto err4;
|
||||||
|
|
||||||
mutex_init(&sChainLock, "net chains");
|
mutex_init(&sChainLock, "net chains");
|
||||||
mutex_init(&sInitializeChainLock, "net intialize chains");
|
mutex_init(&sInitializeChainLock, "net intialize chains");
|
||||||
@@ -816,7 +824,6 @@ init_stack()
|
|||||||
register_domain_datalink_protocols(AF_INET6, IFT_LOOP,
|
register_domain_datalink_protocols(AF_INET6, IFT_LOOP,
|
||||||
"network/datalink_protocols/loopback_frame/v1", NULL);
|
"network/datalink_protocols/loopback_frame/v1", NULL);
|
||||||
register_domain_datalink_protocols(AF_INET, IFT_ETHER,
|
register_domain_datalink_protocols(AF_INET, IFT_ETHER,
|
||||||
"network/datalink_protocols/ipv4_datagram/v1",
|
|
||||||
"network/datalink_protocols/arp/v1",
|
"network/datalink_protocols/arp/v1",
|
||||||
"network/datalink_protocols/ethernet_frame/v1",
|
"network/datalink_protocols/ethernet_frame/v1",
|
||||||
NULL);
|
NULL);
|
||||||
@@ -836,8 +843,10 @@ err6:
|
|||||||
err5:
|
err5:
|
||||||
mutex_destroy(&sInitializeChainLock);
|
mutex_destroy(&sInitializeChainLock);
|
||||||
mutex_destroy(&sChainLock);
|
mutex_destroy(&sChainLock);
|
||||||
err3:
|
err4:
|
||||||
uninit_timers();
|
uninit_timers();
|
||||||
|
err3:
|
||||||
|
uninit_device_interfaces();
|
||||||
err2:
|
err2:
|
||||||
uninit_interfaces();
|
uninit_interfaces();
|
||||||
err1:
|
err1:
|
||||||
@@ -853,6 +862,7 @@ uninit_stack()
|
|||||||
|
|
||||||
put_module(NET_SOCKET_MODULE_NAME);
|
put_module(NET_SOCKET_MODULE_NAME);
|
||||||
uninit_timers();
|
uninit_timers();
|
||||||
|
uninit_device_interfaces();
|
||||||
uninit_interfaces();
|
uninit_interfaces();
|
||||||
uninit_domains();
|
uninit_domains();
|
||||||
uninit_notifications();
|
uninit_notifications();
|
||||||
|
|||||||
@@ -18,6 +18,14 @@
|
|||||||
#include <net_stack_interface.h>
|
#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_stack_module_info gNetStackModule;
|
||||||
extern net_buffer_module_info gNetBufferModule;
|
extern net_buffer_module_info gNetBufferModule;
|
||||||
extern net_socket_module_info gNetSocketModule;
|
extern net_socket_module_info gNetSocketModule;
|
||||||
@@ -28,10 +36,12 @@ extern net_stack_interface_module_info gNetStackInterfaceModule;
|
|||||||
// stack.cpp
|
// stack.cpp
|
||||||
status_t register_domain_datalink_protocols(int family, int type, ...);
|
status_t register_domain_datalink_protocols(int family, int type, ...);
|
||||||
status_t register_domain_protocols(int family, int type, int protocol, ...);
|
status_t register_domain_protocols(int family, int type, int protocol, ...);
|
||||||
status_t get_domain_protocols(net_socket *socket);
|
status_t get_domain_protocols(net_socket* socket);
|
||||||
status_t put_domain_protocols(net_socket *socket);
|
status_t put_domain_protocols(net_socket* socket);
|
||||||
status_t get_domain_datalink_protocols(net_interface *interface);
|
status_t get_domain_datalink_protocols(Interface* interface,
|
||||||
status_t put_domain_datalink_protocols(net_interface *interface);
|
net_domain* domain);
|
||||||
|
status_t put_domain_datalink_protocols(Interface* interface,
|
||||||
|
net_domain* domain);
|
||||||
|
|
||||||
// notifications.cpp
|
// notifications.cpp
|
||||||
status_t notify_interface_added(net_interface* interface);
|
status_t notify_interface_added(net_interface* interface);
|
||||||
|
|||||||
@@ -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.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
* Hugo Santos <hugosantos@gmail.com>
|
* Hugo Santos <hugosantos@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <sys/sockio.h>
|
#include <sys/sockio.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
|
|
||||||
#include <Drivers.h>
|
#include <Drivers.h>
|
||||||
#include <tty.h>
|
#include <tty.h>
|
||||||
#include <scsi.h>
|
#include <scsi.h>
|
||||||
@@ -16,6 +18,7 @@
|
|||||||
#include "Syscall.h"
|
#include "Syscall.h"
|
||||||
#include "TypeHandler.h"
|
#include "TypeHandler.h"
|
||||||
|
|
||||||
|
|
||||||
struct ioctl_info {
|
struct ioctl_info {
|
||||||
int index;
|
int index;
|
||||||
const char *name;
|
const char *name;
|
||||||
@@ -83,7 +86,7 @@ static const ioctl_info kIOCtls[] = {
|
|||||||
IOCTL_INFO_ENTRY_TYPE(SIOCGIFMETRIC, struct ifreq *),
|
IOCTL_INFO_ENTRY_TYPE(SIOCGIFMETRIC, struct ifreq *),
|
||||||
IOCTL_INFO_ENTRY_TYPE(SIOCSIFMETRIC, struct ifreq *),
|
IOCTL_INFO_ENTRY_TYPE(SIOCSIFMETRIC, struct ifreq *),
|
||||||
IOCTL_INFO_ENTRY_TYPE(SIOCDIFADDR, 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(SIOCADDMULTI),
|
||||||
IOCTL_INFO_ENTRY(SIOCDELMULTI),
|
IOCTL_INFO_ENTRY(SIOCDELMULTI),
|
||||||
IOCTL_INFO_ENTRY_TYPE(SIOCGIFMTU, struct ifreq *),
|
IOCTL_INFO_ENTRY_TYPE(SIOCGIFMTU, struct ifreq *),
|
||||||
@@ -93,7 +96,6 @@ static const ioctl_info kIOCtls[] = {
|
|||||||
IOCTL_INFO_ENTRY(SIOCGRTSIZE),
|
IOCTL_INFO_ENTRY(SIOCGRTSIZE),
|
||||||
IOCTL_INFO_ENTRY(SIOCGRTTABLE),
|
IOCTL_INFO_ENTRY(SIOCGRTTABLE),
|
||||||
IOCTL_INFO_ENTRY_TYPE(SIOCGIFSTATS, struct ifreq *),
|
IOCTL_INFO_ENTRY_TYPE(SIOCGIFSTATS, struct ifreq *),
|
||||||
IOCTL_INFO_ENTRY_TYPE(SIOCGIFPARAM, struct ifreq *),
|
|
||||||
IOCTL_INFO_ENTRY(SIOCGIFTYPE),
|
IOCTL_INFO_ENTRY(SIOCGIFTYPE),
|
||||||
IOCTL_INFO_ENTRY(SIOCSPACKETCAP),
|
IOCTL_INFO_ENTRY(SIOCSPACKETCAP),
|
||||||
IOCTL_INFO_ENTRY(SIOCCPACKETCAP),
|
IOCTL_INFO_ENTRY(SIOCCPACKETCAP),
|
||||||
|
|||||||
@@ -541,32 +541,29 @@ list_interface(const char* name, int addressFamily)
|
|||||||
char address[256];
|
char address[256];
|
||||||
strcpy(address, "none");
|
strcpy(address, "none");
|
||||||
|
|
||||||
if (ioctl(socket, SIOCGIFPARAM, &request, sizeof(struct ifreq)) == 0) {
|
if (ioctl(linkSocket, SIOCGIFADDR, &request, sizeof(struct ifreq))
|
||||||
prepare_request(request, request.ifr_parameter.device);
|
== 0) {
|
||||||
if (ioctl(linkSocket, SIOCGIFADDR, &request, sizeof(struct ifreq))
|
sockaddr_dl &link = *(sockaddr_dl*)&request.ifr_addr;
|
||||||
== 0) {
|
|
||||||
sockaddr_dl &link = *(sockaddr_dl*)&request.ifr_addr;
|
|
||||||
|
|
||||||
switch (link.sdl_type) {
|
switch (link.sdl_type) {
|
||||||
case IFT_ETHER:
|
case IFT_ETHER:
|
||||||
{
|
{
|
||||||
type = "Ethernet";
|
type = "Ethernet";
|
||||||
|
|
||||||
if (link.sdl_alen > 0) {
|
if (link.sdl_alen > 0) {
|
||||||
uint8 *mac = (uint8*)LLADDR(&link);
|
uint8 *mac = (uint8*)LLADDR(&link);
|
||||||
sprintf(address, "%02x:%02x:%02x:%02x:%02x:%02x",
|
sprintf(address, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||||
} else
|
} else
|
||||||
strcpy(address, "not available");
|
strcpy(address, "not available");
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case IFT_LOOP:
|
|
||||||
type = "Local Loopback";
|
|
||||||
break;
|
|
||||||
case IFT_MODEM:
|
|
||||||
type = "Modem";
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
case IFT_LOOP:
|
||||||
|
type = "Local Loopback";
|
||||||
|
break;
|
||||||
|
case IFT_MODEM:
|
||||||
|
type = "Modem";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -778,10 +775,12 @@ configure_interface(const char* name, char* const* args,
|
|||||||
|
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
// the interface does not exist yet, we have to add it first
|
// the interface does not exist yet, we have to add it first
|
||||||
request.ifr_parameter.base_name[0] = '\0';
|
ifaliasreq request;
|
||||||
request.ifr_parameter.device[0] = '\0';
|
strlcpy(request.ifra_name, name, IF_NAMESIZE);
|
||||||
request.ifr_parameter.sub_type = 0;
|
|
||||||
// the default device is okay for us
|
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) {
|
if (ioctl(socket, SIOCAIFADDR, &request, sizeof(request)) < 0) {
|
||||||
fprintf(stderr, "%s: Could not add interface: %s\n", kProgramName,
|
fprintf(stderr, "%s: Could not add interface: %s\n", kProgramName,
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ get_string(const char* val, const char* sep, u_int8_t* buf, int* lenp)
|
|||||||
if (hexstr)
|
if (hexstr)
|
||||||
printf("%s: hexadecimal digits too long", __func__);
|
printf("%s: hexadecimal digits too long", __func__);
|
||||||
else
|
else
|
||||||
printf("string too long", __func__);
|
printf("%s: string too long", __func__);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (hexstr) {
|
if (hexstr) {
|
||||||
|
|||||||
@@ -176,18 +176,11 @@ pcap_open_live(const char *device, int snapLength, int /*promisc*/,
|
|||||||
return NULL;
|
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);
|
close(socket);
|
||||||
// no longer needed after this point
|
// no longer needed after this point
|
||||||
|
|
||||||
|
// get link level interface for this interface
|
||||||
|
|
||||||
socket = ::socket(AF_LINK, SOCK_DGRAM, 0);
|
socket = ::socket(AF_LINK, SOCK_DGRAM, 0);
|
||||||
if (socket < 0) {
|
if (socket < 0) {
|
||||||
snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "No link level: %s\n",
|
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
|
// start monitoring
|
||||||
prepare_request(request, request.ifr_parameter.device);
|
|
||||||
if (ioctl(socket, SIOCSPACKETCAP, &request, sizeof(struct ifreq)) < 0) {
|
if (ioctl(socket, SIOCSPACKETCAP, &request, sizeof(struct ifreq)) < 0) {
|
||||||
snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "Cannot start monitoring: %s\n",
|
snprintf(errorBuffer, PCAP_ERRBUF_SIZE, "Cannot start monitoring: %s\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
@@ -318,16 +310,12 @@ pcap_platform_finddevs(pcap_if_t** _allDevices, char* errorBuffer)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ioctl(socket, SIOCGIFPARAM, &request, sizeof(struct ifreq))
|
if (ioctl(linkSocket, SIOCGIFADDR, &request, sizeof(struct ifreq))
|
||||||
== 0) {
|
== 0) {
|
||||||
prepare_request(request, request.ifr_parameter.device);
|
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;
|
|
||||||
|
|
||||||
if (link.sdl_type == IFT_LOOP)
|
if (link.sdl_type == IFT_LOOP)
|
||||||
flags = IFF_LOOPBACK;
|
flags = IFF_LOOPBACK;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
close(linkSocket);
|
close(linkSocket);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -503,6 +503,8 @@ DHCPClient::_Negotiate(dhcp_state state)
|
|||||||
|
|
||||||
case DHCP_OFFER:
|
case DHCP_OFFER:
|
||||||
{
|
{
|
||||||
|
syslog(LOG_DEBUG, "DHCP received offer for %s\n", Device());
|
||||||
|
|
||||||
// first offer wins
|
// first offer wins
|
||||||
if (state != INIT)
|
if (state != INIT)
|
||||||
break;
|
break;
|
||||||
@@ -537,6 +539,7 @@ DHCPClient::_Negotiate(dhcp_state state)
|
|||||||
|
|
||||||
case DHCP_ACK:
|
case DHCP_ACK:
|
||||||
{
|
{
|
||||||
|
syslog(LOG_DEBUG, "DHCP received ack for %s\n", Device());
|
||||||
if (state != REQUESTING && state != REBINDING
|
if (state != REQUESTING && state != REBINDING
|
||||||
&& state != RENEWAL)
|
&& state != RENEWAL)
|
||||||
continue;
|
continue;
|
||||||
@@ -565,6 +568,8 @@ DHCPClient::_Negotiate(dhcp_state state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case DHCP_NACK:
|
case DHCP_NACK:
|
||||||
|
syslog(LOG_DEBUG, "DHCP received nack for %s\n", Device());
|
||||||
|
|
||||||
if (state != REQUESTING)
|
if (state != REQUESTING)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -638,7 +643,7 @@ DHCPClient::_ParseOptions(dhcp_message& message, BMessage& address,
|
|||||||
case OPTION_DOMAIN_NAME_SERVER:
|
case OPTION_DOMAIN_NAME_SERVER:
|
||||||
{
|
{
|
||||||
for (uint32 i = 0; i < size / 4; i++) {
|
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());
|
_ToString(&data[i * 4]).String());
|
||||||
resolverConfiguration.AddString("nameserver",
|
resolverConfiguration.AddString("nameserver",
|
||||||
_ToString(&data[i * 4]).String());
|
_ToString(&data[i * 4]).String());
|
||||||
@@ -770,8 +775,8 @@ DHCPClient::_TimeoutShift(int socket, time_t& timeout, uint32& tries)
|
|||||||
if (++tries > 2)
|
if (++tries > 2)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
syslog(LOG_DEBUG, "DHCP timeout shift: %lu secs (try %lu)\n", timeout,
|
syslog(LOG_DEBUG, "DHCP timeout shift for %s: %lu secs (try %lu)\n",
|
||||||
tries);
|
Device(), timeout, tries);
|
||||||
|
|
||||||
struct timeval value;
|
struct timeval value;
|
||||||
value.tv_sec = timeout;
|
value.tv_sec = timeout;
|
||||||
@@ -802,6 +807,9 @@ status_t
|
|||||||
DHCPClient::_SendMessage(int socket, dhcp_message& message,
|
DHCPClient::_SendMessage(int socket, dhcp_message& message,
|
||||||
sockaddr_in& address) const
|
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(),
|
ssize_t bytesSent = sendto(socket, &message, message.Size(),
|
||||||
address.sin_addr.s_addr == INADDR_BROADCAST ? MSG_BCAST : 0,
|
address.sin_addr.s_addr == INADDR_BROADCAST ? MSG_BCAST : 0,
|
||||||
(struct sockaddr*)&address, sizeof(sockaddr_in));
|
(struct sockaddr*)&address, sizeof(sockaddr_in));
|
||||||
|
|||||||
@@ -406,14 +406,10 @@ NetServer::_IsValidInterface(int socket, const char* name)
|
|||||||
|
|
||||||
// check if it has a hardware address, too, in case of ethernet
|
// 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);
|
int linkSocket = ::socket(AF_LINK, SOCK_DGRAM, 0);
|
||||||
if (linkSocket < 0)
|
if (linkSocket < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
prepare_request(request, request.ifr_parameter.device);
|
|
||||||
if (ioctl(linkSocket, SIOCGIFADDR, &request, sizeof(struct ifreq)) < 0) {
|
if (ioctl(linkSocket, SIOCGIFADDR, &request, sizeof(struct ifreq)) < 0) {
|
||||||
close(linkSocket);
|
close(linkSocket);
|
||||||
return false;
|
return false;
|
||||||
@@ -623,10 +619,12 @@ NetServer::_ConfigureInterface(int socket, BMessage& interface,
|
|||||||
|
|
||||||
if (interfaceIndex == 0) {
|
if (interfaceIndex == 0) {
|
||||||
// we need to create the interface first
|
// we need to create the interface first
|
||||||
request.ifr_parameter.base_name[0] = '\0';
|
ifaliasreq request;
|
||||||
request.ifr_parameter.device[0] = '\0';
|
strlcpy(request.ifra_name, device, IF_NAMESIZE);
|
||||||
request.ifr_parameter.sub_type = 0;
|
|
||||||
// the default device is okay for us
|
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) {
|
if (ioctl(socket, SIOCAIFADDR, &request, sizeof(request)) < 0) {
|
||||||
fprintf(stderr, "%s: Could not add interface: %s\n", Name(),
|
fprintf(stderr, "%s: Could not add interface: %s\n", Name(),
|
||||||
|
|||||||
@@ -159,11 +159,17 @@ private:
|
|||||||
|
|
||||||
if (ioctl(fSocket, SIOCGIFINDEX, &request, sizeof(request)) < 0) {
|
if (ioctl(fSocket, SIOCGIFINDEX, &request, sizeof(request)) < 0) {
|
||||||
// not known yet -- add it
|
// not known yet -- add it
|
||||||
request.ifr_parameter.base_name[0] = '\0';
|
ifaliasreq aliasRequest;
|
||||||
request.ifr_parameter.device[0] = '\0';
|
strcpy(aliasRequest.ifra_name, path);
|
||||||
request.ifr_parameter.sub_type = 0;
|
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 "
|
dprintf("NetStackInitializer: adding interface failed for "
|
||||||
"device %s: %s\n", path, strerror(errno));
|
"device %s: %s\n", path, strerror(errno));
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user