/** IPv4 address */
struct in_addr address;
- /** Subnet mask */
+ /** Subnet mask
+ *
+ * An address with all of these bits in common with our IPv4
+ * address is in the local subnet.
+ */
struct in_addr netmask;
- /** Gateway address */
+ /** Host mask
+ *
+ * An address in the local subnet with all of these bits set
+ * to zero represents the network address, and an address in
+ * the local subnet with all of these bits set to one
+ * represents the directed broadcast address. All other
+ * addresses in the local subnet are valid host addresses.
+ *
+ * For most subnets, this is the inverse of the subnet mask.
+ * In a small subnet (/31 or /32) there is no network address
+ * or directed broadcast address, and all addresses in the
+ * subnet are valid host addresses.
+ */
+ struct in_addr hostmask;
+ /** Gateway address, or zero for no gateway */
struct in_addr gateway;
};
struct in_addr address, struct in_addr netmask,
struct in_addr gateway ) {
struct ipv4_miniroute *miniroute;
+ struct in_addr hostmask;
+ struct in_addr broadcast;
+ /* Calculate host mask */
+ hostmask.s_addr = ( IN_IS_SMALL ( netmask.s_addr ) ?
+ INADDR_NONE : ~netmask.s_addr );
+ broadcast.s_addr = ( address.s_addr | hostmask.s_addr );
+
+ /* Print debugging information */
DBGC ( netdev, "IPv4 add %s", inet_ntoa ( address ) );
DBGC ( netdev, "/%s ", inet_ntoa ( netmask ) );
+ DBGC ( netdev, "bc %s ", inet_ntoa ( broadcast ) );
if ( gateway.s_addr )
DBGC ( netdev, "gw %s ", inet_ntoa ( gateway ) );
DBGC ( netdev, "via %s\n", netdev->name );
miniroute->netdev = netdev_get ( netdev );
miniroute->address = address;
miniroute->netmask = netmask;
+ miniroute->hostmask = hostmask;
miniroute->gateway = gateway;
-
+
/* Add to end of list if we have a gateway, otherwise
* to start of list.
*/
struct sockaddr_in *sin_dest = ( ( struct sockaddr_in * ) st_dest );
struct ipv4_miniroute *miniroute;
struct in_addr next_hop;
- struct in_addr netmask = { .s_addr = 0 };
+ struct in_addr hostmask = { .s_addr = INADDR_NONE };
uint8_t ll_dest_buf[MAX_LL_ADDR_LEN];
const void *ll_dest;
int rc;
( ( miniroute = ipv4_route ( sin_dest->sin_scope_id,
&next_hop ) ) != NULL ) ) {
iphdr->src = miniroute->address;
- netmask = miniroute->netmask;
+ hostmask = miniroute->hostmask;
netdev = miniroute->netdev;
}
if ( ! netdev ) {
ntohs ( iphdr->chksum ) );
/* Calculate link-layer destination address, if possible */
- if ( ( ( next_hop.s_addr ^ INADDR_BROADCAST ) & ~netmask.s_addr ) == 0){
+ if ( ( ( ~next_hop.s_addr ) & hostmask.s_addr ) == 0 ) {
/* Broadcast address */
ipv4_stats.out_bcast_pkts++;
ll_dest = netdev->ll_broadcast;