82,10 → 82,18 |
#include "ip_messages.h" |
#include "ip_module.h" |
|
/** Default IP version. |
/** IP version 4. |
*/ |
#define DEFAULT_IPV 4 |
#define IPV4 4 |
|
/** Default network interface IP version. |
*/ |
#define NET_DEFAULT_IPV IPV4 |
|
/** Default network interface IP routing. |
*/ |
#define NET_DEFAULT_IP_ROUTING false |
|
/** Minimum IP packet content. |
*/ |
#define IP_MIN_CONTENT 576 |
134,6 → 142,11 |
*/ |
#define IP_HEADER_CHECKSUM( header ) ( htons( ip_checksum(( uint8_t * )( header ), IP_HEADER_LENGTH( header )))) |
|
/** Returns the fragment offest. |
* @param length The prefixed data total length. Input parameter. |
*/ |
#define IP_FRAGMENT_OFFSET( length ) (( length ) / 8 ) |
|
/** IP global data. |
*/ |
ip_globals_t ip_globals; |
304,6 → 317,9 |
|
ip_netif->arp = NULL; |
route = NULL; |
ip_netif->ipv = NET_DEFAULT_IPV; |
ip_netif->dhcp = false; |
ip_netif->routing = NET_DEFAULT_IP_ROUTING; |
configuration = & names[ 0 ]; |
// get configuration |
ERROR_PROPAGATE( net_get_device_conf_req( ip_globals.net_phone, ip_netif->device_id, & configuration, count, & data )); |
310,8 → 326,6 |
if( configuration ){ |
if( configuration[ 0 ].value ){ |
ip_netif->ipv = strtol( configuration[ 0 ].value, NULL, 0 ); |
}else{ |
ip_netif->ipv = DEFAULT_IPV; |
} |
ip_netif->dhcp = ! str_lcmp( configuration[ 1 ].value, "dhcp", configuration[ 1 ].length ); |
if( ip_netif->dhcp ){ |
318,7 → 332,7 |
// TODO dhcp |
net_free_settings( configuration, data ); |
return ENOTSUP; |
}else if( ip_netif->ipv == 4 ){ |
}else if( ip_netif->ipv == IPV4 ){ |
route = ( ip_route_ref ) malloc( sizeof( ip_route_t )); |
if( ! route ){ |
net_free_settings( configuration, data ); |
355,10 → 369,10 |
net_free_settings( configuration, data ); |
return EINVAL; |
} |
}else{ |
ip_netif->arp = NULL; |
} |
ip_netif->routing = configuration[ 9 ].value && ( configuration[ 9 ].value[ 0 ] == 'y' ); |
if( configuration[ 9 ].value ){ |
ip_netif->routing = ( configuration[ 9 ].value[ 0 ] == 'y' ); |
} |
net_free_settings( configuration, data ); |
} |
// binds the netif service which also initializes the device |
598,7 → 612,7 |
int phone; |
|
// get destination hardware address |
if( netif->arp ){ |
if( netif->arp && ( route->address.s_addr != dest.s_addr )){ |
destination.value = route->gateway.s_addr ? ( char * ) & route->gateway.s_addr : ( char * ) & dest.s_addr; |
destination.length = CONVERT_SIZE( dest.s_addr, char, 1 ); |
if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ))){ |
649,8 → 663,10 |
header = ( ip_header_ref ) packet_get_data( packet ); |
if( destination ){ |
ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length ))); |
}else{ |
ERROR_PROPAGATE( packet_set_addr( packet, NULL, NULL, 0 )); |
} |
header->version = 4; |
header->version = IPV4; |
header->fragment_offset = 0; |
header->header_checksum = 0; |
if( source ) header->source_address = source->s_addr; |
671,7 → 687,7 |
memcpy( middle_header, last_header, IP_HEADER_LENGTH( last_header )); |
header->flags |= IPFLAG_MORE_FRAGMENTS; |
middle_header->total_length = htons( packet_get_data_length( next )); |
middle_header->fragment_offset = length / 8; |
middle_header->fragment_offset = IP_FRAGMENT_OFFSET( length ); |
middle_header->header_checksum = IP_HEADER_CHECKSUM( middle_header ); |
if( destination ){ |
ERROR_PROPAGATE( packet_set_addr( next, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length ))); |
683,7 → 699,7 |
if( ! middle_header ) return ENOMEM; |
memcpy( middle_header, last_header, IP_HEADER_LENGTH( last_header )); |
middle_header->total_length = htons( packet_get_data_length( next )); |
middle_header->fragment_offset = length / 8; |
middle_header->fragment_offset = IP_FRAGMENT_OFFSET( length ); |
middle_header->header_checksum = IP_HEADER_CHECKSUM( middle_header ); |
if( destination ){ |
ERROR_PROPAGATE( packet_set_addr( next, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length ))); |
702,6 → 718,10 |
ERROR_DECLARE; |
|
packet_t packet; |
struct sockaddr * addr; |
size_t addrlen; |
ip_pseudo_header_ref header; |
size_t headerlen; |
|
* answer_count = 0; |
switch( IPC_GET_METHOD( * call )){ |
726,6 → 746,15 |
return ip_add_route_req( 0, IPC_GET_DEVICE( call ), IP_GET_ADDRESS( call ), IP_GET_NETMASK( call ), IP_GET_GATEWAY( call )); |
case NET_IP_SET_GATEWAY: |
return ip_set_gateway_req( 0, IPC_GET_DEVICE( call ), IP_GET_GATEWAY( call )); |
case NET_IP_GET_ROUTE: |
ERROR_PROPAGATE( data_receive(( void ** ) & addr, & addrlen )); |
ERROR_PROPAGATE( ip_get_route_req( 0, IP_GET_PROTOCOL( call ), addr, ( socklen_t ) addrlen, IPC_SET_DEVICE( answer ), & header, & headerlen )); |
* IP_SET_HEADERLEN( answer ) = headerlen; |
if( ! ERROR_OCCURRED( data_reply( & headerlen, sizeof( headerlen )))){ |
ERROR_CODE = data_reply( header, headerlen ); |
} |
free( header ); |
return ERROR_CODE; |
case NET_IL_PACKET_SPACE: |
ERROR_PROPAGATE( ip_packet_size_req( 0, IPC_GET_DEVICE( call ), IPC_SET_ADDR( answer ), IPC_SET_PREFIX( answer ), IPC_SET_CONTENT( answer ), IPC_SET_SUFFIX( answer ))); |
* answer_count = 3; |
1285,5 → 1314,55 |
return result; |
} |
|
int ip_get_route_req( int ip_phone, ip_protocol_t protocol, const struct sockaddr * destination, socklen_t addrlen, device_id_t * device_id, ip_pseudo_header_ref * header, size_t * headerlen ){ |
struct sockaddr_in * address_in; |
// struct sockaddr_in6 * address_in6; |
in_addr_t * dest; |
in_addr_t * src; |
ip_route_ref route; |
ipv4_pseudo_header_ref header_in; |
|
if( !( destination && ( addrlen > 0 ))) return EINVAL; |
if( !( device_id && header && headerlen )) return EBADMEM; |
if( addrlen < sizeof( struct sockaddr )){ |
return EINVAL; |
} |
switch( destination->sa_family ){ |
case AF_INET: |
if( addrlen != sizeof( struct sockaddr_in )){ |
return EINVAL; |
} |
address_in = ( struct sockaddr_in * ) destination; |
dest = & address_in->sin_addr; |
break; |
// TODO IPv6 |
/* case AF_INET6: |
if( addrlen != sizeof( struct sockaddr_in6 )) return EINVAL; |
address_in6 = ( struct sockaddr_in6 * ) dest; |
address_in6.sin6_addr.s6_addr; |
*/ default: |
return EAFNOSUPPORT; |
} |
fibril_rwlock_read_lock( & ip_globals.lock ); |
route = ip_find_route( * dest ); |
if( !( route && route->netif )){ |
fibril_rwlock_read_unlock( & ip_globals.lock ); |
return ENOENT; |
} |
* device_id = route->netif->device_id; |
src = ip_netif_address( route->netif ); |
fibril_rwlock_read_unlock( & ip_globals.lock ); |
* headerlen = sizeof( * header_in ); |
header_in = ( ipv4_pseudo_header_ref ) malloc( * headerlen ); |
if( ! header_in ) return ENOMEM; |
bzero( header_in, * headerlen ); |
header_in->destination_address = dest->s_addr; |
header_in->source_address = src->s_addr; |
header_in->protocol = protocol; |
header_in->data_length = 0; |
* header = ( ip_pseudo_header_ref ) header_in; |
return EOK; |
} |
|
/** @} |
*/ |