[openbeosnetteam] Re: routes
- From: "Axel Dörfler" <axeld@xxxxxxxxxxxxxxxx>
- To: openbeosnetteam@xxxxxxxxxxxxx
- Date: Mon, 31 Jul 2006 16:32:18 +0200 CEST
Oliver Tappe <openbeos@xxxxxxxxxxxxxxx> wrote:
> I'm glad you mention it, since I just wanted to start a new submodule
> of
> net_domain (address_arithmetic_module_info or anything like that) and
> move
> all the functions that deal with address-comparing/-masking and the
> like from
> route.cpp and interfaces.cpp into the new module. I suppose we could
> even get
> rid of address_offset and address_length.
If we do that, we can for sure get rid of address_offset and
address_length; they are only used for comparison and (not yet)
masking. It probably depends a bit on the needs of other address
domains if this is really necessary (in terms of required), anyway, but
I must admit I haven't had a closer look at IPv6 yet (I just went the
BONE route :-)).
> Anyway, I'll just wait for BerliOS to move...
WAITING? :-))
I've attached a routes.diff that has all the changes in it, it's not
that much, anyway :-)
If you want an updated route command as well, please tell.
Bye,
Axel.
Index: routes.cpp
===================================================================
--- routes.cpp (revision 18318)
+++ routes.cpp (working copy)
@@ -49,22 +49,90 @@
}
+// #pragma mark -
+
+
+static int32
+first_bit(net_domain_private *domain, sockaddr *address)
+{
+ uint8 *bits = (uint8 *)address + domain->address_offset;
+ size_t length = domain->address_length;
+
+ // TODO: this can be optimized, there are also some nice assembler
mnemonics for this
+ for (uint32 i = 0; i < length; i++) {
+ if (bits[i]) {
+ for (int32 bitMask = 128, bit = 0; bitMask > 0; bitMask
>>= 1, bit++) {
+ if (bits[i] & bitMask)
+ return bit;
+ }
+ }
+ }
+
+ return length;
+}
+
+
+static bool
+check_mask(net_domain_private *domain, const sockaddr *mask)
+{
+ if (mask == NULL)
+ return true;
+
+ uint8 *bits = (uint8 *)mask + domain->address_offset;
+ size_t length = domain->address_length;
+ bool zero = true;
+
+ // A mask starts with zeros, after the first one, only ones are allowed.
+
+ for (uint32 i = 0; i < length; i++) {
+ if (zero) {
+ if (bits[i]) {
+ for (int32 bitMask = 128, bit = 0; bitMask > 0;
bitMask >>= 1, bit++) {
+ if (bits[i] & bitMask) {
+ if (((int32)bits[i] + 1) & ((1
<< (bit + 1)) - 1))
+ return false;
+
+ break;
+ }
+ }
+ }
+ } else if (bits[i] != 0xff)
+ return false;
+ }
+
+ return true;
+}
+
+
static status_t
-copy_address(const sockaddr *from, sockaddr **to, sockaddr *mask = NULL)
+copy_address(net_domain_private *domain, const sockaddr *from, sockaddr **to,
+ bool replaceWithZeros = false, sockaddr *mask = NULL)
{
- if (from == NULL)
- return B_OK;
+ if (replaceWithZeros) {
+ size_t length = domain->address_offset + domain->address_length;
+ length = max_c(length, sizeof(sockaddr));
+ *to = (sockaddr *)malloc(length);
+ if (*to == NULL)
+ return B_NO_MEMORY;
- *to = (sockaddr *)malloc(from->sa_len);
- if (*to == NULL)
- return B_NO_MEMORY;
+ memset(*to, 0, length);
+ (*to)->sa_family = domain->family;
+ (*to)->sa_len = length;
+ } else {
+ if (from == NULL)
+ return B_OK;
- memcpy(*to, from, from->sa_len);
+ *to = (sockaddr *)malloc(from->sa_len);
+ if (*to == NULL)
+ return B_NO_MEMORY;
- if (mask != NULL) {
- // TODO: this only works for IPv4!
- // mask off unused bits from the address
- ((sockaddr_in *)*to)->sin_addr.s_addr &= ((sockaddr_in
*)mask)->sin_addr.s_addr;
+ memcpy(*to, from, from->sa_len);
+
+ if (mask != NULL) {
+ // TODO: this only works for IPv4!
+ // mask off unused bits from the address
+ ((sockaddr_in *)*to)->sin_addr.s_addr &= ((sockaddr_in
*)mask)->sin_addr.s_addr;
+ }
}
return B_OK;
}
@@ -97,14 +165,15 @@
static bool
-equal_addresses(sockaddr *a, sockaddr *b)
+equal_addresses(net_domain_private *domain, sockaddr *a, sockaddr *b)
{
if (a == NULL && b == NULL)
return true;
- if (a == NULL && b != NULL || a != NULL && b == NULL)
+ if (a != NULL && b == NULL || a == NULL || b != NULL)
return false;
- return !memcmp(a, b, a->sa_len);
+ return !memcmp((uint8 *)a + domain->address_offset,
+ (uint8 *)b + domain->address_offset, domain->address_length);
}
@@ -117,9 +186,11 @@
while (iterator.HasNext()) {
net_route_private *route = iterator.Next();
- if (equal_addresses(route->destination,
description->destination)
- && equal_addresses(route->destination,
description->destination)
- && equal_addresses(route->destination,
description->destination))
+ if ((route->flags & (RTF_GATEWAY | RTF_HOST | RTF_LOCAL)) ==
+ (description->flags & (RTF_GATEWAY | RTF_HOST |
RTF_LOCAL))
+ && equal_addresses(domain, route->destination,
description->destination)
+ && equal_addresses(domain, route->mask,
description->mask)
+ && equal_addresses(domain, route->gateway,
description->gateway))
return route;
}
@@ -242,6 +313,11 @@
RouteList::Iterator iterator = domain->routes.GetIterator();
size_t spaceLeft = size;
+ sockaddr zeros;
+ memset(&zeros, 0, sizeof(sockaddr));
+ zeros.sa_family = domain->family;
+ zeros.sa_len = sizeof(sockaddr);
+
while (iterator.HasNext()) {
net_route *route = iterator.Next();
@@ -303,11 +379,11 @@
case SIOCDELRT:
{
// add or remove a route
- if (length != sizeof(route_entry))
+ if (length != sizeof(struct ifreq))
return B_BAD_VALUE;
route_entry entry;
- if (user_memcpy(&entry, argument, sizeof(route_entry))
!= B_OK)
+ if (user_memcpy(&entry, &((ifreq
*)argument)->ifr_route, sizeof(route_entry)) != B_OK)
return B_BAD_ADDRESS;
net_route_private route;
@@ -326,41 +402,6 @@
return remove_route(domain, &route);
}
-
- case SIOCGRTSIZE:
- {
-dprintf("LENGTH = %ld, sizeof(ifconf) == %lu\n", length, sizeof(ifconf));
-// if (length != sizeof(ifconf))
-// return B_BAD_VALUE;
-
- struct ifconf config;
- config.ifc_value = 0;
-
- RouteList::Iterator iterator =
domain->routes.GetIterator();
- while (iterator.HasNext()) {
- net_route_private *route = iterator.Next();
- config.ifc_value += IF_NAMESIZE +
sizeof(route_entry);
-
- if (route->destination)
- config.ifc_value +=
route->destination->sa_len;
- if (route->mask)
- config.ifc_value += route->mask->sa_len;
- if (route->gateway)
- config.ifc_value +=
route->gateway->sa_len;
- }
-
- return user_memcpy(argument, &config, sizeof(struct
ifconf));
- }
-
- case SIOCGRTTABLE:
- if (length != sizeof(ifconf))
- return B_BAD_VALUE;
-
- struct ifconf config;
- if (user_memcpy(&config, argument, sizeof(struct
ifconf)) < B_OK)
- return B_BAD_ADDRESS;
-
- return list_routes(domain, config.ifc_buf,
config.ifc_len);
}
return B_BAD_VALUE;
}
@@ -381,16 +422,19 @@
if (domain == NULL || newRoute == NULL || newRoute->interface == NULL
|| ((newRoute->flags & RTF_HOST) != 0 && newRoute->mask != 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)
+ || !check_mask(domain, newRoute->mask))
return B_BAD_VALUE;
net_route_private *route = new (std::nothrow) net_route_private;
if (route == NULL)
return B_NO_MEMORY;
- if (copy_address(newRoute->destination, &route->destination,
newRoute->mask) != B_OK
- || copy_address(newRoute->mask, &route->mask) != B_OK
- || copy_address(newRoute->gateway, &route->gateway) != B_OK) {
+ if (copy_address(domain, newRoute->destination, &route->destination,
+ (newRoute->flags & RTF_DEFAULT) != 0,
newRoute->mask) != B_OK
+ || copy_address(domain, newRoute->mask, &route->mask,
+ (newRoute->flags & RTF_DEFAULT) != 0) != B_OK
+ || copy_address(domain, newRoute->gateway, &route->gateway) !=
B_OK) {
delete route;
return B_NO_MEMORY;
}
@@ -413,13 +457,12 @@
// if the before mask is larger than the one of the route, we
can insert it
// before that route.
+
if (before->mask == NULL && route->mask == NULL)
break;
- if (before->mask != NULL && route->mask != NULL) {
- in_addr_t beforeMask = ((sockaddr_in
*)before->mask)->sin_addr.s_addr;
- if ((beforeMask | ((sockaddr_in
*)route->mask)->sin_addr.s_addr) == beforeMask)
- break;
- }
+ if (before->mask != NULL && route->mask != NULL
+ && first_bit(domain, before->mask) < first_bit(domain,
route->mask))
+ break;
}
domain->routes.Insert(before, route);
- Follow-Ups:
- [openbeosnetteam] Re: routes
- From: Waldemar Kornewald
- [openbeosnetteam] Re: routes
- From: Oliver Tappe
- References:
- [openbeosnetteam] Re: routes
- From: Oliver Tappe
Other related posts:
- » [openbeosnetteam] routes
- » [openbeosnetteam] Re: routes
- » [openbeosnetteam] Re: routes
- » [openbeosnetteam] Re: routes
- » [openbeosnetteam] Re: routes
- » [openbeosnetteam] Re: routes
- » [openbeosnetteam] Re: routes
- » [openbeosnetteam] Re: routes
- » [openbeosnetteam] Re: routes
- » [openbeosnetteam] Re: routes
- [openbeosnetteam] Re: routes
- From: Waldemar Kornewald
- [openbeosnetteam] Re: routes
- From: Oliver Tappe
- [openbeosnetteam] Re: routes
- From: Oliver Tappe