Author: axeld Date: 2010-07-28 19:38:23 +0200 (Wed, 28 Jul 2010) New Revision: 37794 Changeset: http://dev.haiku-os.org/changeset/37794 Added: haiku/trunk/src/add-ons/kernel/network/stack/device_interfaces.cpp haiku/trunk/src/add-ons/kernel/network/stack/device_interfaces.h Removed: haiku/trunk/src/add-ons/kernel/network/datalink_protocols/ipv4_datagram/ Modified: haiku/trunk/build/jam/HaikuImage haiku/trunk/headers/posix/net/if.h haiku/trunk/headers/posix/sys/sockio.h haiku/trunk/headers/private/net/net_buffer.h haiku/trunk/headers/private/net/net_datalink.h haiku/trunk/headers/private/net/net_datalink_protocol.h haiku/trunk/src/add-ons/kernel/network/datalink_protocols/Jamfile haiku/trunk/src/add-ons/kernel/network/datalink_protocols/arp/arp.cpp haiku/trunk/src/add-ons/kernel/network/datalink_protocols/ethernet_frame/ethernet_frame.cpp haiku/trunk/src/add-ons/kernel/network/datalink_protocols/ipv6_datagram/ipv6_datagram.cpp haiku/trunk/src/add-ons/kernel/network/datalink_protocols/loopback_frame/loopback_frame.cpp haiku/trunk/src/add-ons/kernel/network/protocols/icmp/icmp.cpp haiku/trunk/src/add-ons/kernel/network/protocols/ipv4/ipv4.cpp haiku/trunk/src/add-ons/kernel/network/protocols/ipv4/ipv4_address.cpp haiku/trunk/src/add-ons/kernel/network/protocols/ipv4/multicast.cpp haiku/trunk/src/add-ons/kernel/network/protocols/ipv6/ipv6_address.cpp haiku/trunk/src/add-ons/kernel/network/protocols/l2cap/l2cap_address.cpp haiku/trunk/src/add-ons/kernel/network/protocols/tcp/TCPEndpoint.cpp haiku/trunk/src/add-ons/kernel/network/protocols/tcp/tcp.cpp haiku/trunk/src/add-ons/kernel/network/protocols/udp/udp.cpp haiku/trunk/src/add-ons/kernel/network/protocols/unix/UnixAddress.cpp haiku/trunk/src/add-ons/kernel/network/stack/Jamfile haiku/trunk/src/add-ons/kernel/network/stack/datalink.cpp haiku/trunk/src/add-ons/kernel/network/stack/domains.cpp haiku/trunk/src/add-ons/kernel/network/stack/domains.h haiku/trunk/src/add-ons/kernel/network/stack/interfaces.cpp haiku/trunk/src/add-ons/kernel/network/stack/interfaces.h haiku/trunk/src/add-ons/kernel/network/stack/link.cpp haiku/trunk/src/add-ons/kernel/network/stack/net_buffer.cpp haiku/trunk/src/add-ons/kernel/network/stack/routes.cpp haiku/trunk/src/add-ons/kernel/network/stack/routes.h haiku/trunk/src/add-ons/kernel/network/stack/stack.cpp haiku/trunk/src/add-ons/kernel/network/stack/stack_private.h haiku/trunk/src/bin/debug/strace/ioctl.cpp haiku/trunk/src/bin/network/ifconfig/ifconfig.cpp haiku/trunk/src/bin/network/setwep/setwep.c haiku/trunk/src/bin/network/tcpdump/libpcap/pcap-haiku.cpp haiku/trunk/src/servers/net/DHCPClient.cpp haiku/trunk/src/servers/net/NetServer.cpp haiku/trunk/src/system/kernel/fs/vfs_net_boot.cpp Log: * 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. Modified: haiku/trunk/build/jam/HaikuImage =================================================================== --- haiku/trunk/build/jam/HaikuImage 2010-07-28 17:09:12 UTC (rev 37793) +++ haiku/trunk/build/jam/HaikuImage 2010-07-28 17:38:23 UTC (rev 37794) @@ -46,8 +46,8 @@ mkfifo mkfs mkindex mktemp modifiers mount mount_nfs mountvolume mv netcat netstat nl nohup notify nproc od open - passwd paste patch pathchk pc ping play playfile playsound playwav pr prio - printenv printf profile ps ptx pwd + passwd paste patch pathchk pc ping ping6 play playfile playsound playwav + pr prio printenv printf profile ps ptx pwd query quit rc readlink ReadOnlyBootPrompt reindex release renice rlog rm rmattr rmindex rmdir roster route @@ -105,10 +105,10 @@ ; SYSTEM_NETWORK_DEVICES = ethernet loopback ; -SYSTEM_NETWORK_DATALINK_PROTOCOLS = ethernet_frame <module>arp loopback_frame - ipv4_datagram ; +SYSTEM_NETWORK_DATALINK_PROTOCOLS = ethernet_frame <module>arp loopback_frame ; + #ipv6_datagram ; #SYSTEM_NETWORK_PPP = ipcp modem pap pppoe ; -SYSTEM_NETWORK_PROTOCOLS = ipv4 tcp udp icmp unix ; +SYSTEM_NETWORK_PROTOCOLS = ipv4 tcp udp icmp unix ; # icmp6 ipv6 ; SYSTEM_ADD_ONS_ACCELERANTS = $(X86_ONLY)radeon.accelerant $(X86_ONLY)nvidia.accelerant $(X86_ONLY)matrox.accelerant Modified: haiku/trunk/headers/posix/net/if.h =================================================================== --- haiku/trunk/headers/posix/net/if.h 2010-07-28 17:09:12 UTC (rev 37793) +++ haiku/trunk/headers/posix/net/if.h 2010-07-28 17:38:23 UTC (rev 37794) @@ -1,5 +1,5 @@ /* - * Copyright 2006-2007, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2010, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. */ #ifndef _NET_IF_H @@ -16,12 +16,6 @@ #define IFNAMSIZ IF_NAMESIZE -struct ifreq_parameter { - char base_name[IF_NAMESIZE]; - char device[128]; - uint8_t sub_type; -}; - struct ifreq_stream_stats { uint32_t packets; uint32_t errors; @@ -43,7 +37,6 @@ struct sockaddr ifr_dstaddr; struct sockaddr ifr_broadaddr; struct sockaddr ifr_mask; - struct ifreq_parameter ifr_parameter; struct ifreq_stats ifr_stats; struct route_entry ifr_route; int ifr_flags; @@ -56,6 +49,14 @@ }; }; +/* used with SIOCAIFADDR */ +struct ifaliasreq { + char ifra_name[IF_NAMESIZE]; + struct sockaddr_storage ifra_addr; + struct sockaddr_storage ifra_broadaddr; + struct sockaddr_storage ifra_mask; +}; + /* interface flags */ #define IFF_UP 0x0001 #define IFF_BROADCAST 0x0002 /* valid broadcast address */ Modified: haiku/trunk/headers/posix/sys/sockio.h =================================================================== --- haiku/trunk/headers/posix/sys/sockio.h 2010-07-28 17:09:12 UTC (rev 37793) +++ haiku/trunk/headers/posix/sys/sockio.h 2010-07-28 17:38:23 UTC (rev 37794) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007, Haiku Inc. All Rights Reserved. + * Copyright 2002-2010, Haiku Inc. All Rights Reserved. * Distributed under the terms of the MIT License. */ #ifndef _SYS_SOCKIO_H @@ -38,7 +38,6 @@ #define SIOCGETRT 8928 /* get route information for destination */ #define SIOCGIFSTATS 8929 /* get interface stats */ -#define SIOCGIFPARAM 8930 /* get interface parameter */ #define SIOCGIFTYPE 8931 /* get interface type */ #define SIOCSPACKETCAP 8932 /* Start capturing packets on an interface */ Modified: haiku/trunk/headers/private/net/net_buffer.h =================================================================== --- haiku/trunk/headers/private/net/net_buffer.h 2010-07-28 17:09:12 UTC (rev 37793) +++ haiku/trunk/headers/private/net/net_buffer.h 2010-07-28 17:38:23 UTC (rev 37794) @@ -18,14 +18,9 @@ typedef struct net_buffer { struct list_link link; - // TODO: we should think about moving the address fields into the buffer - // data itself via associated data or something like this. Or this - // structure as a whole, too... - struct sockaddr* source; struct sockaddr* destination; - struct net_interface* interface; - int32 type; + struct net_interface_address* interface_address; union { struct { uint16 start; @@ -33,6 +28,7 @@ } fragment; uint32 sequence; uint32 offset; + int32 type; }; uint32 flags; uint32 size; Modified: haiku/trunk/headers/private/net/net_datalink.h =================================================================== --- haiku/trunk/headers/private/net/net_datalink.h 2010-07-28 17:09:12 UTC (rev 37793) +++ haiku/trunk/headers/private/net/net_datalink.h 2010-07-28 17:38:23 UTC (rev 37794) @@ -1,5 +1,5 @@ /* - * Copyright 2006-2008, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2010, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. */ #ifndef NET_DATALINK_H @@ -18,84 +18,98 @@ typedef struct net_datalink_protocol net_datalink_protocol; + typedef struct net_domain { - const char *name; + const char* name; int family; - struct list interfaces; - struct net_protocol_module_info *module; - struct net_address_module_info *address_module; + struct net_protocol_module_info* module; + struct net_address_module_info* address_module; } net_domain; -struct net_interface { - struct list_link link; - struct net_domain *domain; - struct net_device *device; - struct net_datalink_protocol *first_protocol; - struct net_datalink_protocol_module_info *first_info; +typedef struct net_interface_address { + struct net_domain* domain; + struct net_interface* interface; + struct sockaddr* local; + struct sockaddr* destination; + struct sockaddr* mask; +} net_interface_address; +typedef struct net_interface { + struct net_device* device; + char name[IF_NAMESIZE]; - struct sockaddr *address; - struct sockaddr *destination; - struct sockaddr *mask; uint32 index; uint32 flags; uint8 type; uint32 mtu; uint32 metric; -}; +} net_interface; -struct net_route { - struct sockaddr *destination; - struct sockaddr *mask; - struct sockaddr *gateway; +typedef struct net_route { + struct sockaddr* destination; + struct sockaddr* mask; + struct sockaddr* gateway; uint32 flags; uint32 mtu; - struct net_interface *interface; -}; + struct net_interface_address* interface_address; +} net_route; -struct net_route_info { +typedef struct net_route_info { struct list_link link; - struct net_route *route; + struct net_route* route; struct sockaddr address; -}; +} net_route_info; + struct net_datalink_module_info { module_info info; - status_t (*control)(struct net_domain *domain, int32 option, void *value, - size_t *_length); - status_t (*send_data)(struct net_route *route, struct net_buffer *buffer); - status_t (*send_datagram)(struct net_protocol *protocol, - struct net_domain *domain, struct net_buffer *buffer); + status_t (*control)(net_domain* domain, int32 option, void* value, + size_t* _length); + status_t (*send_data)(net_route* route, net_buffer* buffer); + status_t (*send_datagram)(struct net_protocol* protocol, + net_domain* domain, net_buffer* buffer); - bool (*is_local_address)(struct net_domain *domain, - const struct sockaddr *address, net_interface **_interface, - uint32 *_matchedType); - bool (*is_local_link_address)(struct net_domain *domain, bool unconfigured, - const struct sockaddr *address, net_interface **_interface); + bool (*is_local_address)(net_domain* domain, + const struct sockaddr* address, + net_interface_address** _interfaceAddress, + uint32* _matchedType); + bool (*is_local_link_address)(net_domain* domain, + bool unconfigured, const struct sockaddr* address, + net_interface_address** _interfaceAddress); - net_interface *(*get_interface)(struct net_domain *domain, uint32 index); - net_interface *(*get_interface_with_address)(struct net_domain *domain, - const struct sockaddr *address); + net_interface* (*get_interface)(net_domain* domain, uint32 index); + net_interface* (*get_interface_with_address)( + const struct sockaddr* address); + void (*put_interface)(net_interface* interface); + net_interface_address* (*get_interface_address)( + const struct sockaddr* address); + bool (*get_next_interface_address)(net_interface* interface, + net_interface_address** _address); + void (*put_interface_address)(net_interface_address* address); + + status_t (*join_multicast)(net_interface* interface, + net_domain* domain, const struct sockaddr* address); + status_t (*leave_multicast)(net_interface* interface, + net_domain* domain, const struct sockaddr* address); + // routes - status_t (*add_route)(struct net_domain *domain, - const struct net_route *route); - status_t (*remove_route)(struct net_domain *domain, - const struct net_route *route); - struct net_route *(*get_route)(struct net_domain *domain, - const struct sockaddr *address); - status_t (*get_buffer_route)(struct net_domain *domain, - struct net_buffer *buffer, struct net_route **_route); - void (*put_route)(struct net_domain *domain, struct net_route *route); + status_t (*add_route)(net_domain* domain, const net_route* route); + status_t (*remove_route)(net_domain* domain, const net_route* route); + net_route* (*get_route)(net_domain* domain, + const struct sockaddr* address); + status_t (*get_buffer_route)(net_domain* domain, + struct net_buffer* buffer, net_route** _route); + void (*put_route)(net_domain* domain, net_route* route); - status_t (*register_route_info)(struct net_domain *domain, - struct net_route_info *info); - status_t (*unregister_route_info)(struct net_domain *domain, - struct net_route_info *info); - status_t (*update_route_info)(struct net_domain *domain, - struct net_route_info *info); + status_t (*register_route_info)(net_domain* domain, + net_route_info* info); + status_t (*unregister_route_info)(net_domain* domain, + net_route_info* info); + status_t (*update_route_info)(net_domain* domain, + net_route_info* info); }; #define NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS 0x01 @@ -104,47 +118,58 @@ module_info info; uint32 flags; - status_t (*copy_address)(const sockaddr *from, sockaddr **to, - bool replaceWithZeros, const sockaddr *mask); + status_t (*copy_address)(const struct sockaddr* from, + struct sockaddr** to, bool replaceWithZeros, + const struct sockaddr* mask); - status_t (*mask_address)(const sockaddr *address, const sockaddr *mask, - sockaddr *result); + status_t (*mask_address)(const struct sockaddr* address, + const struct sockaddr* mask, struct sockaddr* result); - bool (*equal_addresses)(const sockaddr *a, const sockaddr *b); - bool (*equal_ports)(const sockaddr *a, const sockaddr *b); - bool (*equal_addresses_and_ports)(const sockaddr *a, const sockaddr *b); - bool (*equal_masked_addresses)(const sockaddr *a, const sockaddr *b, - const sockaddr *mask); - bool (*is_empty_address)(const sockaddr *address, bool checkPort); - bool (*is_same_family)(const sockaddr *address); + bool (*equal_addresses)(const struct sockaddr* a, + const struct sockaddr* b); + bool (*equal_ports)(const struct sockaddr* a, + const struct sockaddr* b); + bool (*equal_addresses_and_ports)(const struct sockaddr* a, + const struct sockaddr* b); + bool (*equal_masked_addresses)(const struct sockaddr* a, + const struct sockaddr* b, const struct sockaddr* mask); + bool (*is_empty_address)(const struct sockaddr* address, + bool checkPort); + bool (*is_same_family)(const struct sockaddr* address); - int32 (*first_mask_bit)(const sockaddr *mask); + int32 (*first_mask_bit)(const struct sockaddr* mask); - bool (*check_mask)(const sockaddr *address); + bool (*check_mask)(const struct sockaddr* address); - status_t (*print_address)(const sockaddr *address, char **buffer, - bool printPort); - status_t (*print_address_buffer)(const sockaddr *address, char *buffer, - size_t bufferSize, bool printPort); + status_t (*print_address)(const struct sockaddr* address, + char** buffer, bool printPort); + status_t (*print_address_buffer)(const struct sockaddr* address, + char* buffer, size_t bufferSize, bool printPort); - uint16 (*get_port)(const sockaddr *address); - status_t (*set_port)(sockaddr *address, uint16 port); + uint16 (*get_port)(const struct sockaddr* address); + status_t (*set_port)(struct sockaddr* address, uint16 port); - status_t (*set_to)(sockaddr *address, const sockaddr *from); - status_t (*set_to_empty_address)(sockaddr *address); - status_t (*set_to_defaults)(sockaddr *defaultMask, - sockaddr *defaultBroadcast, sockaddr *address, - sockaddr *netmask); + status_t (*set_to)(struct sockaddr* address, + const struct sockaddr* from); + status_t (*set_to_empty_address)(struct sockaddr* address); + status_t (*set_to_defaults)(struct sockaddr* defaultMask, + struct sockaddr* defaultBroadcast, + const struct sockaddr* address, + const struct sockaddr* netmask); - status_t (*update_to)(sockaddr *address, const sockaddr *from); + status_t (*update_to)(struct sockaddr* address, + const struct sockaddr* from); - uint32 (*hash_address_pair)(const sockaddr *ourAddress, - const sockaddr *peerAddress); + uint32 (*hash_address)(const struct sockaddr* address, + bool includePort); + uint32 (*hash_address_pair)(const struct sockaddr* ourAddress, + const struct sockaddr* peerAddress); - status_t (*checksum_address)(struct Checksum *checksum, - const sockaddr *address); + status_t (*checksum_address)(struct Checksum* checksum, + const struct sockaddr* address); - void (*get_loopback_address)(sockaddr *result); + void (*get_loopback_address)(struct sockaddr* result); }; + #endif // NET_DATALINK_H Modified: haiku/trunk/headers/private/net/net_datalink_protocol.h =================================================================== --- haiku/trunk/headers/private/net/net_datalink_protocol.h 2010-07-28 17:09:12 UTC (rev 37793) +++ haiku/trunk/headers/private/net/net_datalink_protocol.h 2010-07-28 17:38:23 UTC (rev 37794) @@ -1,5 +1,5 @@ /* - * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2010, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. */ #ifndef NET_DATALINK_PROTOCOL_H @@ -10,31 +10,37 @@ typedef struct net_datalink_protocol { - struct net_datalink_protocol *next; - struct net_datalink_protocol_module_info *module; - struct net_interface *interface; + struct net_datalink_protocol* next; + struct net_datalink_protocol_module_info* module; + struct net_interface* interface; + struct net_domain* domain; } net_datalink_protocol; struct net_datalink_protocol_module_info { module_info info; - status_t (*init_protocol)(struct net_interface *interface, - net_datalink_protocol **_protocol); - status_t (*uninit_protocol)(net_datalink_protocol *self); + status_t (*init_protocol)(net_interface* interface, net_domain* domain, + net_datalink_protocol** _protocol); + status_t (*uninit_protocol)(net_datalink_protocol* self); - status_t (*send_data)(net_datalink_protocol *self, - net_buffer *buffer); + status_t (*send_data)(net_datalink_protocol* self, net_buffer* buffer); - status_t (*interface_up)(net_datalink_protocol *self); - void (*interface_down)(net_datalink_protocol *self); + status_t (*interface_up)(net_datalink_protocol* self); + void (*interface_down)(net_datalink_protocol* self); - status_t (*control)(net_datalink_protocol *self, - int32 op, void *argument, size_t length); + status_t (*change_address)(net_datalink_protocol* self, + net_interface_address* address, int32 option, + const struct sockaddr* oldAddress, + const struct sockaddr* newAddress); - status_t (*join_multicast)(net_datalink_protocol *self, - const sockaddr *address); - status_t (*leave_multicast)(net_datalink_protocol *self, - const sockaddr *address); + status_t (*control)(net_datalink_protocol* self, int32 option, + void* argument, size_t length); + + status_t (*join_multicast)(net_datalink_protocol* self, + const struct sockaddr* address); + status_t (*leave_multicast)(net_datalink_protocol* self, + const struct sockaddr* address); }; + #endif // NET_DATALINK_PROTOCOL_H Modified: haiku/trunk/src/add-ons/kernel/network/datalink_protocols/Jamfile =================================================================== --- haiku/trunk/src/add-ons/kernel/network/datalink_protocols/Jamfile 2010-07-28 17:09:12 UTC (rev 37793) +++ haiku/trunk/src/add-ons/kernel/network/datalink_protocols/Jamfile 2010-07-28 17:38:23 UTC (rev 37794) @@ -1,7 +1,6 @@ SubDir HAIKU_TOP src add-ons kernel network datalink_protocols ; -SubInclude HAIKU_TOP src add-ons kernel network datalink_protocols arp ; -SubInclude HAIKU_TOP src add-ons kernel network datalink_protocols ethernet_frame ; -SubInclude HAIKU_TOP src add-ons kernel network datalink_protocols ipv4_datagram ; -SubInclude HAIKU_TOP src add-ons kernel network datalink_protocols ipv6_datagram ; -SubInclude HAIKU_TOP src add-ons kernel network datalink_protocols loopback_frame ; +HaikuSubInclude arp ; +HaikuSubInclude ethernet_frame ; +HaikuSubInclude ipv6_datagram ; +HaikuSubInclude loopback_frame ; Modified: haiku/trunk/src/add-ons/kernel/network/datalink_protocols/arp/arp.cpp =================================================================== --- haiku/trunk/src/add-ons/kernel/network/datalink_protocols/arp/arp.cpp 2010-07-28 17:09:12 UTC (rev 37793) +++ haiku/trunk/src/add-ons/kernel/network/datalink_protocols/arp/arp.cpp 2010-07-28 17:38:23 UTC (rev 37794) @@ -1,5 +1,5 @@ /* - * Copyright 2006-2009, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2010, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -7,6 +7,7 @@ * Hugo Santos, hugosantos@xxxxxxxxx */ + //! Ethernet Address Resolution Protocol, see RFC 826. @@ -110,6 +111,7 @@ struct arp_protocol : net_datalink_protocol { sockaddr_dl hardware_address; + in_addr_t local_address; }; @@ -117,9 +119,10 @@ static void arp_timer(struct net_timer *timer, void *data); -net_buffer_module_info *gBufferModule; -static net_stack_module_info *sStackModule; -static hash_table *sCache; +net_buffer_module_info* gBufferModule; +static net_stack_module_info* sStackModule; +static net_datalink_module_info* sDatalinkModule; +static hash_table* sCache; static mutex sCacheLock; static bool sIgnoreReplies; @@ -283,7 +286,7 @@ arp_entry::MarkValid() { TRACE(("ARP entry %p Marked as VALID, have %li packets queued.\n", this, - queue.Size())); + queue.Count())); flags = (flags & ~ARP_FLAG_REJECT) | ARP_FLAG_VALID; @@ -316,9 +319,6 @@ static void ipv4_to_ether_multicast(sockaddr_dl *destination, const sockaddr_in *source) { - // TODO: this is ethernet specific, and doesn't belong here - // (should be moved to the ethernet_frame module) - // RFC 1112 - Host extensions for IP multicasting // // ``An IP host group address is mapped to an Ethernet multicast @@ -352,7 +352,7 @@ This function does not lock the cache - you have to do it yourself before calling it. */ -status_t +static status_t arp_update_entry(in_addr_t protocolAddress, sockaddr_dl *hardwareAddress, uint32 flags, arp_entry **_entry = NULL) { @@ -405,23 +405,74 @@ } -/*! Creates a permanent local entry for the interface belonging to this protocol. - You need to hold the cache lock when calling this function. +static void +arp_remove_local_entry(arp_protocol* protocol, const sockaddr* local, + bool updateLocalAddress) +{ + in_addr_t inetAddress = ((sockaddr_in*)local)->sin_addr.s_addr; + + 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_update_local(arp_protocol *protocol) +arp_set_local_entry(arp_protocol* protocol, const sockaddr* local) { - ASSERT_LOCKED_MUTEX(&sCacheLock); - - net_interface *interface = protocol->interface; + MutexLocker locker(sCacheLock); + + net_interface* interface = protocol->interface; in_addr_t inetAddress; - - if (interface->address == NULL) { + + if (local == NULL) { // interface has not yet been set inetAddress = INADDR_ANY; } else - inetAddress = ((sockaddr_in *)interface->address)->sin_addr.s_addr; + inetAddress = ((sockaddr_in*)local)->sin_addr.s_addr; + if (protocol->local_address == 0) + protocol->local_address = inetAddress; + sockaddr_dl address; address.sdl_len = sizeof(sockaddr_dl); address.sdl_family = AF_LINK; @@ -435,7 +486,7 @@ memcpy(&protocol->hardware_address, &address, sizeof(sockaddr_dl)); // cache the address in our protocol - arp_entry *entry; + arp_entry* entry; status_t status = arp_update_entry(inetAddress, &address, ARP_FLAG_LOCAL | ARP_FLAG_PERMANENT, &entry); if (status == B_OK) @@ -445,7 +496,38 @@ } +/*! Creates permanent local entries for all addresses of the interface belonging + to this protocol. + Returns an error if no entry could be added. +*/ static status_t +arp_update_local(arp_protocol* protocol) +{ + protocol->local_address = 0; + // TODO: test if this actually works - maybe we should use + // INADDR_BROADCAST instead + + ssize_t count = 0; + + net_interface_address* address = NULL; + while (sDatalinkModule->get_next_interface_address(protocol->interface, + &address)) { + if (address->local == NULL || address->local->sa_family != AF_INET) + continue; + + if (arp_set_local_entry(protocol, address->local) == B_OK) { + count++; + } + } + + if (count == 0) + return arp_set_local_entry(protocol, NULL); + + return B_OK; +} + + +static status_t handle_arp_request(net_buffer *buffer, arp_header &header) { MutexLocker locker(sCacheLock); @@ -518,15 +600,19 @@ #ifdef TRACE_ARP dprintf(" hw sender: %02x:%02x:%02x:%02x:%02x:%02x\n", - header.hardware_sender[0], header.hardware_sender[1], header.hardware_sender[2], - header.hardware_sender[3], header.hardware_sender[4], header.hardware_sender[5]); - dprintf(" proto sender: %ld.%ld.%ld.%ld\n", header.protocol_sender >> 24, (header.protocol_sender >> 16) & 0xff, - (header.protocol_sender >> 8) & 0xff, header.protocol_sender & 0xff); + header.hardware_sender[0], header.hardware_sender[1], + header.hardware_sender[2], header.hardware_sender[3], + header.hardware_sender[4], header.hardware_sender[5]); + unsigned int addr = ntohl(header.protocol_sender); + dprintf(" proto sender: %d.%d.%d.%d\n", addr >> 24, (addr >> 16) & 0xff, + (addr >> 8) & 0xff, addr & 0xff); dprintf(" hw target: %02x:%02x:%02x:%02x:%02x:%02x\n", - header.hardware_target[0], header.hardware_target[1], header.hardware_target[2], - header.hardware_target[3], header.hardware_target[4], header.hardware_target[5]); - dprintf(" proto target: %ld.%ld.%ld.%ld\n", header.protocol_target >> 24, (header.protocol_target >> 16) & 0xff, - (header.protocol_target >> 8) & 0xff, header.protocol_target & 0xff); + header.hardware_target[0], header.hardware_target[1], + header.hardware_target[2], header.hardware_target[3], + header.hardware_target[4], header.hardware_target[5]); + addr = ntohl(header.protocol_target); + dprintf(" proto target: %d.%d.%d.%d\n", addr >> 24, (addr >> 16) & 0xff, + (addr >> 8) & 0xff, addr & 0xff); #endif if (ntohs(header.protocol_type) != ETHER_TYPE_IP @@ -588,21 +674,23 @@ case ARP_STATE_REMOVE_FAILED: case ARP_STATE_STALE: + { // the entry has aged so much that we're going to remove it TRACE((" remove ARP entry %p!\n", entry)); - mutex_lock(&sCacheLock); + MutexLocker locker(sCacheLock); if ((entry->flags & ARP_FLAG_REMOVED) != 0) { - // The entry has already been removed, and is about to be deleted - mutex_unlock(&sCacheLock); + // The entry has already been removed, and is about to be + // deleted break; } hash_remove(sCache, entry); - mutex_unlock(&sCacheLock); + locker.Unlock(); delete entry; break; + } default: { @@ -649,8 +737,7 @@ You need to have the sCacheLock held when calling this function. */ static status_t -arp_start_resolve(net_datalink_protocol *protocol, in_addr_t address, - arp_entry **_entry) +arp_start_resolve(arp_protocol* protocol, in_addr_t address, arp_entry** _entry) { ASSERT_LOCKED_MUTEX(&sCacheLock); @@ -686,16 +773,8 @@ header.opcode = htons(ARP_OPCODE_REQUEST); memcpy(header.hardware_sender, device->address.data, ETHER_ADDRESS_LENGTH); - if (protocol->interface->address != NULL) { - header.protocol_sender - = ((sockaddr_in *)protocol->interface->address)->sin_addr.s_addr; - } else { - header.protocol_sender = 0; - // TODO: test if this actually works - maybe we should use - // INADDR_BROADCAST instead - } - memset(header.hardware_target, 0, ETHER_ADDRESS_LENGTH); + header.protocol_sender = protocol->local_address; header.protocol_target = address; // prepare source and target addresses @@ -867,21 +946,25 @@ status_t -arp_init_protocol(struct net_interface *interface, - net_datalink_protocol **_protocol) +arp_init_protocol(net_interface* interface, net_domain* domain, + net_datalink_protocol** _protocol) { // We currently only support a single family and type! - if (interface->domain->family != AF_INET - || interface->device->type != IFT_ETHER) + if (interface->device->type != IFT_ETHER + || domain->family != AF_INET) return B_BAD_TYPE; status_t status = sStackModule->register_device_handler(interface->device, ETHER_FRAME_TYPE | ETHER_TYPE_ARP, &arp_receive, NULL); + if (status != B_OK) + return status; - if (status < B_OK) + 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; + arp_protocol* protocol = new(std::nothrow) arp_protocol; if (protocol == NULL) return B_NO_MEMORY; @@ -896,6 +979,8 @@ { sStackModule->unregister_device_handler(protocol->interface->device, ETHER_FRAME_TYPE | ETHER_TYPE_ARP); + sStackModule->unregister_device_handler(protocol->interface->device, + ETHER_FRAME_TYPE | ETHER_TYPE_IP); delete protocol; return B_OK; @@ -914,7 +999,7 @@ memcpy(buffer->source, &protocol->hardware_address, protocol->hardware_address.sdl_len); - if (buffer->flags & MSG_MCAST) { + if ((buffer->flags & MSG_MCAST) != 0) { sockaddr_dl multicastDestination; ipv4_to_ether_multicast(&multicastDestination, (sockaddr_in *)buffer->destination); @@ -926,14 +1011,16 @@ ((struct sockaddr_in *)buffer->destination)->sin_addr.s_addr); if (entry == NULL) { status_t status = arp_start_resolve(protocol, - ((struct sockaddr_in *)buffer->destination)->sin_addr.s_addr, &entry); - if (status < B_OK) + ((struct sockaddr_in*)buffer->destination)->sin_addr.s_addr, + &entry); + if (status != B_OK) return status; } - if (entry->flags & ARP_FLAG_REJECT) + if ((entry->flags & ARP_FLAG_REJECT) != 0) return EHOSTUNREACH; - else if (!(entry->flags & ARP_FLAG_VALID)) { + + if ((entry->flags & ARP_FLAG_VALID) == 0) { // entry is still being resolved. TRACE(("ARP Queuing packet %p, entry still being resolved.\n", buffer)); @@ -951,20 +1038,17 @@ status_t -arp_up(net_datalink_protocol *_protocol) +arp_up(net_datalink_protocol* _protocol) { - arp_protocol *protocol = (arp_protocol *)_protocol; + arp_protocol* protocol = (arp_protocol*)_protocol; status_t status = protocol->next->module->interface_up(protocol->next); - if (status < B_OK) + if (status != B_OK) return status; // cache this device's address for later use - mutex_lock(&sCacheLock); status = arp_update_local(protocol); - mutex_unlock(&sCacheLock); - - if (status < B_OK) { + if (status != B_OK) { protocol->next->module->interface_down(protocol->next); return status; } @@ -976,70 +1060,55 @@ void 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); } status_t -arp_control(net_datalink_protocol *_protocol, int32 op, void *argument, - size_t length) +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; + arp_protocol* protocol = (arp_protocol*)_protocol; - if (op == SIOCSIFADDR && (protocol->interface->flags & IFF_UP) != 0) { - // The interface may get a new address, so we need to update our - // local entries. - in_addr_t oldAddress = 0; - if (protocol->interface->address != NULL) { - oldAddress - = ((sockaddr_in *)protocol->interface->address)->sin_addr.s_addr; - } + 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; + } - status_t status = protocol->next->module->control(protocol->next, - SIOCSIFADDR, argument, length); - if (status < B_OK) - return status; + if (oldAddress != NULL && oldAddress->sa_family == AF_INET) + arp_remove_local_entry(protocol, oldAddress, true); + } + break; - MutexLocker locker(sCacheLock); + default: + break; + } - arp_update_local(protocol); + return protocol->next->module->change_address(protocol->next, address, + option, oldAddress, newAddress); +} - 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); +status_t +arp_control(net_datalink_protocol *_protocol, int32 op, void *argument, + size_t length) +{ + arp_protocol* protocol = (arp_protocol*)_protocol; + return protocol->next->module->control(protocol->next, op, argument, + length); } @@ -1097,6 +1166,7 @@ arp_send_data, arp_up, arp_down, + arp_change_address, arp_control, arp_join_multicast, arp_leave_multicast, @@ -1104,12 +1174,13 @@ module_dependency module_dependencies[] = { - {NET_STACK_MODULE_NAME, (module_info **)&sStackModule}, - {NET_BUFFER_MODULE_NAME, (module_info **)&gBufferModule}, + {NET_STACK_MODULE_NAME, (module_info**)&sStackModule}, + {NET_DATALINK_MODULE_NAME, (module_info**)&sDatalinkModule}, + {NET_BUFFER_MODULE_NAME, (module_info**)&gBufferModule}, {} }; -module_info *modules[] = { - (module_info *)&sARPModule, +module_info* modules[] = { + (module_info*)&sARPModule, NULL }; Modified: haiku/trunk/src/add-ons/kernel/network/datalink_protocols/ethernet_frame/ethernet_frame.cpp =================================================================== --- haiku/trunk/src/add-ons/kernel/network/datalink_protocols/ethernet_frame/ethernet_frame.cpp 2010-07-28 17:09:12 UTC (rev 37793) +++ haiku/trunk/src/add-ons/kernel/network/datalink_protocols/ethernet_frame/ethernet_frame.cpp 2010-07-28 17:38:23 UTC (rev 37794) @@ -1,5 +1,5 @@ /* - * Copyright 2006-2009, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2010, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -30,23 +30,23 @@ static const uint8 kBroadcastAddress[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; -struct net_buffer_module_info *gBufferModule; +struct net_buffer_module_info* gBufferModule; int32 -ethernet_deframe(net_device *device, net_buffer *buffer) +ethernet_deframe(net_device* device, net_buffer* buffer) { //dprintf("asked to deframe buffer for device %s\n", device->name); [... truncated: 6933 lines follow ...]