* Added a set_to_defaults() function to the address module: it can be used
to retrieve the default settings for the netmask/broadcast depending on the specified address/netmask. * interface_protocol_control() now uses this to reset the broadcast/netmask to their default values on SIOCSIFADDR resp. the former only on SIOCSIFNETMASK. * This fixes bug #1861. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24170 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2006, Haiku, Inc. All Rights Reserved.
|
* Copyright 2006-2008, 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
|
||||||
@@ -67,7 +67,7 @@ struct net_datalink_module_info {
|
|||||||
size_t *_length);
|
size_t *_length);
|
||||||
status_t (*send_data)(struct net_route *route, struct net_buffer *buffer);
|
status_t (*send_data)(struct net_route *route, struct 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);
|
struct net_domain *domain, struct net_buffer *buffer);
|
||||||
|
|
||||||
bool (*is_local_address)(struct net_domain *domain,
|
bool (*is_local_address)(struct net_domain *domain,
|
||||||
const struct sockaddr *address,
|
const struct sockaddr *address,
|
||||||
@@ -75,7 +75,7 @@ struct net_datalink_module_info {
|
|||||||
uint32 *_matchedType);
|
uint32 *_matchedType);
|
||||||
net_interface *(*get_interface)(struct net_domain *domain, uint32 index);
|
net_interface *(*get_interface)(struct net_domain *domain, uint32 index);
|
||||||
net_interface *(*get_interface_with_address)(struct net_domain *domain,
|
net_interface *(*get_interface_with_address)(struct net_domain *domain,
|
||||||
const struct sockaddr *address);
|
const struct sockaddr *address);
|
||||||
|
|
||||||
// routes
|
// routes
|
||||||
status_t (*add_route)(struct net_domain *domain,
|
status_t (*add_route)(struct net_domain *domain,
|
||||||
@@ -85,7 +85,7 @@ struct net_datalink_module_info {
|
|||||||
struct net_route *(*get_route)(struct net_domain *domain,
|
struct net_route *(*get_route)(struct net_domain *domain,
|
||||||
const struct sockaddr *address);
|
const struct sockaddr *address);
|
||||||
status_t (*get_buffer_route)(struct net_domain *domain,
|
status_t (*get_buffer_route)(struct net_domain *domain,
|
||||||
struct net_buffer *buffer, struct net_route **_route);
|
struct net_buffer *buffer, struct net_route **_route);
|
||||||
void (*put_route)(struct net_domain *domain, 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)(struct net_domain *domain,
|
||||||
@@ -100,7 +100,7 @@ struct net_address_module_info {
|
|||||||
module_info info;
|
module_info info;
|
||||||
|
|
||||||
status_t (*copy_address)(const sockaddr *from, sockaddr **to,
|
status_t (*copy_address)(const sockaddr *from, sockaddr **to,
|
||||||
bool replaceWithZeros /* = false */, const sockaddr *mask /* = NULL*/);
|
bool replaceWithZeros, const sockaddr *mask);
|
||||||
|
|
||||||
status_t (*mask_address)(const sockaddr *address, const sockaddr *mask,
|
status_t (*mask_address)(const sockaddr *address, const sockaddr *mask,
|
||||||
sockaddr *result);
|
sockaddr *result);
|
||||||
@@ -110,7 +110,7 @@ struct net_address_module_info {
|
|||||||
bool (*equal_addresses_and_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,
|
bool (*equal_masked_addresses)(const sockaddr *a, const sockaddr *b,
|
||||||
const sockaddr *mask);
|
const sockaddr *mask);
|
||||||
bool (*is_empty_address)(const sockaddr *address, bool checkPort /* = true */);
|
bool (*is_empty_address)(const sockaddr *address, bool checkPort);
|
||||||
|
|
||||||
int32 (*first_mask_bit)(const sockaddr *mask);
|
int32 (*first_mask_bit)(const sockaddr *mask);
|
||||||
|
|
||||||
@@ -126,6 +126,9 @@ struct net_address_module_info {
|
|||||||
|
|
||||||
status_t (*set_to)(sockaddr *address, const sockaddr *from);
|
status_t (*set_to)(sockaddr *address, const sockaddr *from);
|
||||||
status_t (*set_to_empty_address)(sockaddr *address);
|
status_t (*set_to_empty_address)(sockaddr *address);
|
||||||
|
status_t (*set_to_defaults)(sockaddr *defaultMask,
|
||||||
|
sockaddr *defaultBroadcast, sockaddr *address,
|
||||||
|
sockaddr *netmask);
|
||||||
|
|
||||||
status_t (*update_to)(sockaddr *address, const sockaddr *from);
|
status_t (*update_to)(sockaddr *address, const sockaddr *from);
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2006-2007, Haiku, Inc. All Rights Reserved.
|
* Copyright 2006-2008, Haiku, Inc. All Rights Reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -388,6 +388,55 @@ ipv4_set_to_empty_address(sockaddr *address)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
ipv4_set_to_defaults(sockaddr *_defaultMask, sockaddr *_defaultBroadcast,
|
||||||
|
sockaddr *_address, sockaddr *_mask)
|
||||||
|
{
|
||||||
|
sockaddr_in *defaultMask = (sockaddr_in *)_defaultMask;
|
||||||
|
sockaddr_in *defaultBroadcast = (sockaddr_in *)_defaultBroadcast;
|
||||||
|
sockaddr_in *address = (sockaddr_in *)_address;
|
||||||
|
sockaddr_in *mask = (sockaddr_in *)_mask;
|
||||||
|
|
||||||
|
if (address == NULL || (defaultMask == NULL && defaultBroadcast == NULL))
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
in_addr_t net;
|
||||||
|
if (mask == NULL) {
|
||||||
|
// choose default netmask depending on the class of the address
|
||||||
|
net = address->sin_addr.s_addr;
|
||||||
|
if (IN_CLASSA(net)
|
||||||
|
|| (ntohl(net) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) {
|
||||||
|
// class A, or loopback
|
||||||
|
net = IN_CLASSA_NET;
|
||||||
|
} else if (IN_CLASSB(net)) {
|
||||||
|
// class B
|
||||||
|
net = IN_CLASSB_NET;
|
||||||
|
} else {
|
||||||
|
// class C and rest
|
||||||
|
net = IN_CLASSC_NET;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
net = mask->sin_addr.s_addr;
|
||||||
|
|
||||||
|
if (defaultMask != NULL) {
|
||||||
|
defaultMask->sin_len = sizeof(sockaddr_in);
|
||||||
|
defaultMask->sin_family = AF_INET;
|
||||||
|
defaultMask->sin_port = 0;
|
||||||
|
defaultMask->sin_addr.s_addr = net;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defaultBroadcast != NULL) {
|
||||||
|
defaultBroadcast->sin_len = sizeof(sockaddr_in);
|
||||||
|
defaultBroadcast->sin_family = AF_INET;
|
||||||
|
defaultBroadcast->sin_port = 0;
|
||||||
|
defaultBroadcast->sin_addr.s_addr = (address->sin_addr.s_addr & net)
|
||||||
|
| ~net;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
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.
|
||||||
@@ -441,6 +490,7 @@ net_address_module_info gIPv4AddressModule = {
|
|||||||
ipv4_set_port,
|
ipv4_set_port,
|
||||||
ipv4_set_to,
|
ipv4_set_to,
|
||||||
ipv4_set_to_empty_address,
|
ipv4_set_to_empty_address,
|
||||||
|
ipv4_set_to_defaults,
|
||||||
ipv4_update_to,
|
ipv4_update_to,
|
||||||
ipv4_hash_address_pair,
|
ipv4_hash_address_pair,
|
||||||
ipv4_checksum_address,
|
ipv4_checksum_address,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2006-2007, Haiku, Inc. All Rights Reserved.
|
* Copyright 2006-2008, Haiku, Inc. All Rights Reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -164,6 +164,26 @@ add_default_routes(net_interface_private *interface, int32 option)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sockaddr *
|
||||||
|
reallocate_address(sockaddr **_address, uint32 size)
|
||||||
|
{
|
||||||
|
sockaddr *address = *_address;
|
||||||
|
|
||||||
|
size = max_c(size, sizeof(struct sockaddr));
|
||||||
|
if (address != NULL && address->sa_len >= size)
|
||||||
|
return address;
|
||||||
|
|
||||||
|
address = (sockaddr *)malloc(size);
|
||||||
|
if (address == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
free(*_address);
|
||||||
|
*_address = address;
|
||||||
|
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
datalink_control_interface(net_domain_private *domain, int32 option,
|
datalink_control_interface(net_domain_private *domain, int32 option,
|
||||||
void *value, size_t *_length, size_t expected, bool getByName)
|
void *value, size_t *_length, size_t expected, bool getByName)
|
||||||
@@ -624,27 +644,32 @@ interface_protocol_control(net_datalink_protocol *_protocol,
|
|||||||
if (_address == NULL)
|
if (_address == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
sockaddr *address = *_address;
|
|
||||||
sockaddr *original = address;
|
|
||||||
|
|
||||||
// allocate new address if needed
|
// allocate new address if needed
|
||||||
if (address == NULL
|
sockaddr *address = reallocate_address(_address,
|
||||||
|| (address->sa_len < request.ifr_addr.sa_len
|
request.ifr_addr.sa_len);
|
||||||
&& request.ifr_addr.sa_len > sizeof(struct sockaddr))) {
|
|
||||||
address = (sockaddr *)malloc(
|
|
||||||
max_c(request.ifr_addr.sa_len, sizeof(struct sockaddr)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy new address over
|
// copy new address over
|
||||||
if (address != NULL) {
|
if (address != NULL) {
|
||||||
remove_default_routes(interface, option);
|
remove_default_routes(interface, option);
|
||||||
|
memcpy(address, &request.ifr_addr, request.ifr_addr.sa_len);
|
||||||
|
|
||||||
if (original != address) {
|
if (option == SIOCSIFADDR || option == SIOCSIFNETMASK) {
|
||||||
free(original);
|
// reset netmask and broadcast addresses to defaults
|
||||||
*_address = address;
|
sockaddr *netmask = NULL;
|
||||||
|
sockaddr *oldNetmask = NULL;
|
||||||
|
if (option == SIOCSIFADDR) {
|
||||||
|
netmask = reallocate_address(&interface->mask,
|
||||||
|
request.ifr_addr.sa_len);
|
||||||
|
} else
|
||||||
|
oldNetmask = address;
|
||||||
|
|
||||||
|
sockaddr *broadcast = reallocate_address(
|
||||||
|
&interface->destination, request.ifr_addr.sa_len);
|
||||||
|
|
||||||
|
interface->domain->address_module->set_to_defaults(
|
||||||
|
netmask, broadcast, interface->address, oldNetmask);
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(address, &request.ifr_addr, request.ifr_addr.sa_len);
|
|
||||||
add_default_routes(interface, option);
|
add_default_routes(interface, option);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user