51,21 → 51,24 |
#include "../../messages.h" |
#include "../../modules.h" |
|
#include "../../include/net_interface.h" |
#include "../../include/inet.h" |
#include "../../include/socket_codes.h" |
#include "../../include/arp_interface.h" |
#include "../../include/byteorder.h" |
#include "../../include/crc.h" |
#include "../../include/device.h" |
#include "../../include/arp_interface.h" |
#include "../../include/nil_interface.h" |
#include "../../include/icmp_client.h" |
#include "../../include/icmp_codes.h" |
#include "../../include/icmp_interface.h" |
#include "../../include/il_interface.h" |
#include "../../include/in.h" |
#include "../../include/in6.h" |
#include "../../include/inet.h" |
#include "../../include/ip_client.h" |
#include "../../include/ip_interface.h" |
#include "../../include/net_interface.h" |
#include "../../include/nil_interface.h" |
#include "../../include/tl_interface.h" |
#include "../../include/icmp_codes.h" |
#include "../../include/icmp_interface.h" |
#include "../../include/icmp_client.h" |
#include "../../include/socket_codes.h" |
#include "../../include/socket_errno.h" |
#include "../../structures/measured_strings.h" |
#include "../../structures/module_map.h" |
#include "../../structures/packet/packet_client.h" |
97,7 → 100,7 |
|
/** IP packet address length. |
*/ |
#define IP_ADDR sizeof( in_addr_t ) |
#define IP_ADDR sizeof( struct sockaddr_in6 ) |
|
/** IP packet prefix length. |
*/ |
179,9 → 182,9 |
int ip_send_route( packet_t packet, ip_netif_ref netif, ip_route_ref route, in_addr_t * src, in_addr_t dest, services_t error ); |
int ip_prepare_packet( in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination ); |
|
packet_t ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, size_t addr_len, services_t error ); |
int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, size_t addr_len ); |
int ip_fragment_packet_data( packet_t packet, packet_t new_packet, ip_header_ref header, ip_header_ref new_header, size_t length, void * src, void * dest, size_t address_length ); |
packet_t ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, socklen_t addr_len, services_t error ); |
int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, socklen_t addr_len ); |
int ip_fragment_packet_data( packet_t packet, packet_t new_packet, ip_header_ref header, ip_header_ref new_header, size_t length, const struct sockaddr * src, const struct sockaddr * dest, socklen_t addrlen ); |
ip_header_ref ip_create_middle_header( packet_t packet, ip_header_ref last ); |
void ip_create_last_header( ip_header_ref last, ip_header_ref first ); |
|
507,9 → 510,12 |
int ip_send_msg( int il_phone, device_id_t device_id, packet_t packet, services_t sender, services_t error ){ |
ERROR_DECLARE; |
|
int length; |
int addrlen; |
ip_netif_ref netif; |
ip_route_ref route; |
struct sockaddr * addr; |
struct sockaddr_in * address_in; |
// struct sockaddr_in6 * address_in6; |
in_addr_t * dest; |
in_addr_t * src; |
int phone; |
516,14 → 522,29 |
|
// addresses in the host byte order |
// should be the next hop address or the target destination address |
length = packet_get_addr( packet, NULL, ( uint8_t ** ) & dest ); |
if( length < 0 ){ |
return ip_release_and_return( packet, length ); |
addrlen = packet_get_addr( packet, NULL, ( uint8_t ** ) & addr ); |
if( addrlen < 0 ){ |
return ip_release_and_return( packet, addrlen ); |
} |
// TODO IPv6 |
if( length != IP_ADDR ){ |
if( addrlen < sizeof( struct sockaddr )){ |
return ip_release_and_return( packet, EINVAL ); |
} |
switch( addr->sa_family ){ |
case AF_INET: |
if( addrlen != sizeof( struct sockaddr_in )){ |
return ip_release_and_return( packet, EINVAL ); |
} |
address_in = ( struct sockaddr_in * ) addr; |
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 ip_release_and_return( packet, EAFNOSUPPORT ); |
} |
fibril_rwlock_read_lock( & ip_globals.netifs_lock ); |
// device specified? |
if( device_id > 0 ){ |
530,7 → 551,6 |
netif = ip_netifs_find( & ip_globals.netifs, device_id ); |
route = ip_netif_find_route( netif, * dest ); |
}else{ |
// TODO IPv6 |
route = ip_find_route( * dest ); |
netif = route ? route->netif : NULL; |
} |
552,21 → 572,12 |
return ip_release_and_return( packet, EINVAL ); |
} |
} |
// to me? |
if( route->address.s_addr == dest->s_addr ){ |
// TODO loopback deliver |
fibril_rwlock_read_unlock( & ip_globals.netifs_lock ); |
return ip_deliver_local( -1, packet, ( ip_header_ref ) packet_get_data( packet ), error ); |
} |
|
src = ip_netif_address( netif ); |
if( ! src ){ |
fibril_rwlock_read_unlock( & ip_globals.netifs_lock ); |
return ip_release_and_return( packet, ENOENT ); |
} |
if( ERROR_OCCURRED( ip_send_route( packet, netif, route, src, * dest, error ))){ |
pq_release( ip_globals.net_phone, packet_get_id( packet )); |
} |
ERROR_CODE = ip_send_route( packet, netif, route, src, * dest, error ); |
fibril_rwlock_read_unlock( & ip_globals.netifs_lock ); |
return ERROR_CODE; |
} |
591,8 → 602,10 |
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 ))){ |
sleep( 1 ); |
ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data )); |
// sleep( 1 ); |
// ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data )); |
pq_release( ip_globals.net_phone, packet_get_id( packet )); |
return ERROR_CODE; |
} |
if( !( translation && translation->value )){ |
if( translation ){ |
835,7 → 848,7 |
return EOK; |
} |
|
packet_t ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, size_t addr_len, services_t error ){ |
packet_t ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, socklen_t addr_len, services_t error ){ |
size_t length; |
packet_t next; |
packet_t new_packet; |
874,7 → 887,7 |
return packet; |
} |
|
int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, size_t addr_len ){ |
int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, socklen_t addr_len ){ |
ERROR_DECLARE; |
|
packet_t new_packet; |
881,14 → 894,14 |
ip_header_ref header; |
ip_header_ref middle_header; |
ip_header_ref last_header; |
uint8_t * src; |
uint8_t * dest; |
size_t address_length; |
struct sockaddr * src; |
struct sockaddr * dest; |
socklen_t addrlen; |
int result; |
|
result = packet_get_addr( packet, & src, & dest ); |
result = packet_get_addr( packet, ( uint8_t ** ) & src, ( uint8_t ** ) & dest ); |
if( result <= 0 ) return EINVAL; |
address_length = ( size_t ) result; |
addrlen = ( socklen_t ) result; |
if( packet_get_data_length( packet ) <= sizeof( ip_header_t )) return ENOMEM; |
// get header |
header = ( ip_header_ref ) packet_get_data( packet ); |
898,7 → 911,7 |
return EPERM; |
} |
// create the last fragment |
new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, ((( size_t ) address_length > addr_len ) ? ( size_t ) address_length : addr_len )); |
new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( addrlen > addr_len ) ? addrlen : addr_len )); |
if( ! new_packet ) return ENOMEM; |
// allocate as much as originally |
last_header = ( ip_header_ref ) packet_suffix( new_packet, IP_HEADER_LENGTH( header )); |
913,7 → 926,7 |
// biggest multiple of 8 lower than content |
// TODO even fragmentation? |
length = length & ( ~ 0x7 );// ( content / 8 ) * 8 |
if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, last_header, (( IP_TOTAL_LENGTH( header ) - length ) % ( length - IP_HEADER_LENGTH( last_header ))), src, dest, address_length ))){ |
if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, last_header, (( IP_TOTAL_LENGTH( header ) - length ) % ( length - IP_HEADER_LENGTH( last_header ))), src, dest, addrlen ))){ |
return ip_release_and_return( packet, ERROR_CODE ); |
} |
// mark the first as fragmented |
920,13 → 933,13 |
header->flags |= IPFLAG_MORE_FRAGMENTS; |
// create middle framgents |
while( IP_TOTAL_LENGTH( header ) > length ){ |
new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( address_length >= addr_len ) ? address_length : addr_len )); |
new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( addrlen >= addr_len ) ? addrlen : addr_len )); |
if( ! new_packet ) return ENOMEM; |
middle_header = ip_create_middle_header( new_packet, last_header ); |
if( ! middle_header ){ |
return ip_release_and_return( packet, ENOMEM ); |
} |
if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, middle_header, length - IP_HEADER_LENGTH( middle_header ), src, dest, address_length ))){ |
if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, middle_header, length - IP_HEADER_LENGTH( middle_header ), src, dest, addrlen ))){ |
return ip_release_and_return( packet, ERROR_CODE ); |
} |
} |
935,7 → 948,7 |
return EOK; |
} |
|
int ip_fragment_packet_data( packet_t packet, packet_t new_packet, ip_header_ref header, ip_header_ref new_header, size_t length, void * src, void * dest, size_t address_length ){ |
int ip_fragment_packet_data( packet_t packet, packet_t new_packet, ip_header_ref header, ip_header_ref new_header, size_t length, const struct sockaddr * src, const struct sockaddr * dest, socklen_t addrlen ){ |
ERROR_DECLARE; |
|
void * data; |
948,7 → 961,7 |
new_header->total_length = htons( IP_HEADER_LENGTH( new_header ) + length ); |
new_header->fragment_offset = header->fragment_offset + IP_HEADER_DATA_LENGTH( header ) / 8; |
new_header->header_checksum = IP_HEADER_CHECKSUM( new_header ); |
ERROR_PROPAGATE( packet_set_addr( new_packet, src, dest, address_length )); |
ERROR_PROPAGATE( packet_set_addr( new_packet, ( const uint8_t * ) src, ( const uint8_t * ) dest, addrlen )); |
return pq_insert_after( packet, new_packet ); |
} |
|
1015,6 → 1028,10 |
in_addr_t dest; |
ip_route_ref route; |
int phone; |
struct sockaddr * addr; |
struct sockaddr_in addr_in; |
// struct sockaddr_in addr_in6; |
socklen_t addrlen; |
|
header = ( ip_header_ref ) packet_get_data( packet ); |
if( ! header ){ |
1035,7 → 1052,26 |
} |
// process ipopt and get destination |
dest = ip_get_destination( header ); |
ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) & dest.s_addr, IP_ADDR )); |
// set the addrination address |
switch( header->version ){ |
case IPVERSION: |
addrlen = sizeof( addr_in ); |
bzero( & addr_in, addrlen ); |
addr_in.sin_family = AF_INET; |
memcpy( & addr_in.sin_addr.s_addr, & dest, sizeof( dest )); |
addr = ( struct sockaddr * ) & addr_in; |
break; |
/* case IPv6VERSION: |
addrlen = sizeof( dest_in6 ); |
bzero( & dest_in6, addrlen ); |
dest_in6.sin6_family = AF_INET6; |
memcpy( & dest_in6.sin6_addr.s6_addr, ); |
dest = ( struct sockaddr * ) & dest_in; |
break; |
*/ default: |
return EAFNOSUPPORT; |
} |
ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) & addr, addrlen )); |
route = ip_find_route( dest ); |
if( ! route ){ |
phone = ip_prepare_icmp_and_get_phone( 0, packet, header ); |
1081,7 → 1117,7 |
return ip_release_and_return( packet, ENOMEM ); |
} |
data = packet_get_data( packet ); |
header = ( ip_header_ref ) data + offset; |
header = ( ip_header_ref )( data + offset ); |
// destination host unreachable? |
if(( type == ICMP_DEST_UNREACH ) && ( code == ICMP_HOST_UNREACH )){ |
fibril_rwlock_read_lock( & ip_globals.netifs_lock ); |
1110,12 → 1146,45 |
|
ip_proto_ref proto; |
int phone; |
services_t service; |
tl_received_msg_t received_msg; |
struct sockaddr * src; |
struct sockaddr * dest; |
struct sockaddr_in src_in; |
struct sockaddr_in dest_in; |
// struct sockaddr_in src_in6; |
// struct sockaddr_in dest_in6; |
socklen_t addrlen; |
|
if(( header->flags & IPFLAG_MORE_FRAGMENTS ) || header->fragment_offset ){ |
// TODO fragmented |
return ENOTSUP; |
}else{ |
ERROR_PROPAGATE( packet_set_addr( packet, ( uint8_t * ) & header->source_address, ( uint8_t * ) & header->destination_address, IP_ADDR )); |
switch( header->version ){ |
case IPVERSION: |
addrlen = sizeof( src_in ); |
bzero( & src_in, addrlen ); |
src_in.sin_family = AF_INET; |
memcpy( & dest_in, & src_in, addrlen ); |
memcpy( & src_in.sin_addr.s_addr, & header->source_address, sizeof( header->source_address )); |
memcpy( & dest_in.sin_addr.s_addr, & header->destination_address, sizeof( header->destination_address )); |
src = ( struct sockaddr * ) & src_in; |
dest = ( struct sockaddr * ) & dest_in; |
break; |
/* case IPv6VERSION: |
addrlen = sizeof( src_in6 ); |
bzero( & src_in6, addrlen ); |
src_in6.sin6_family = AF_INET6; |
memcpy( & dest_in6, & src_in6, addrlen ); |
memcpy( & src_in6.sin6_addr.s6_addr, ); |
memcpy( & dest_in6.sin6_addr.s6_addr, ); |
src = ( struct sockaddr * ) & src_in; |
dest = ( struct sockaddr * ) & dest_in; |
break; |
*/ default: |
return EAFNOSUPPORT; |
} |
ERROR_PROPAGATE( packet_set_addr( packet, ( uint8_t * ) src, ( uint8_t * ) dest, addrlen )); |
fibril_rwlock_read_lock( & ip_globals.protos_lock ); |
proto = ip_protos_find( & ip_globals.protos, header->protocol ); |
if( ! proto ){ |
1128,11 → 1197,14 |
return ENOENT; |
} |
if( proto->received_msg ){ |
ERROR_CODE = proto->received_msg( device_id, packet, proto->service, error ); |
service = proto->service; |
received_msg = proto->received_msg; |
fibril_rwlock_read_unlock( & ip_globals.protos_lock ); |
ERROR_CODE = received_msg( device_id, packet, service, error ); |
}else{ |
ERROR_CODE = tl_received_msg( proto->phone, device_id, packet, proto->service, error ); |
fibril_rwlock_read_unlock( & ip_globals.protos_lock ); |
} |
fibril_rwlock_read_unlock( & ip_globals.protos_lock ); |
return ERROR_CODE; |
} |
} |
1147,6 → 1219,10 |
|
int ip_prepare_icmp( packet_t packet, ip_header_ref header ){ |
packet_t next; |
struct sockaddr * dest; |
struct sockaddr_in dest_in; |
// struct sockaddr_in dest_in6; |
socklen_t addrlen; |
|
// detach the first packet and release the others |
next = pq_detach( packet ); |
1162,8 → 1238,26 |
// only for the first fragment |
if( header->fragment_offset ) return EINVAL; |
// set the destination address |
return packet_set_addr( packet, NULL, ( uint8_t * ) & header->source_address, sizeof( header->source_address )); |
switch( header->version ){ |
case IPVERSION: |
addrlen = sizeof( dest_in ); |
bzero( & dest_in, addrlen ); |
dest_in.sin_family = AF_INET; |
memcpy( & dest_in.sin_addr.s_addr, & header->source_address, sizeof( header->source_address )); |
dest = ( struct sockaddr * ) & dest_in; |
break; |
/* case IPv6VERSION: |
addrlen = sizeof( dest_in6 ); |
bzero( & dest_in6, addrlen ); |
dest_in6.sin6_family = AF_INET6; |
memcpy( & dest_in6.sin6_addr.s6_addr, ); |
dest = ( struct sockaddr * ) & dest_in; |
break; |
*/ default: |
return EAFNOSUPPORT; |
} |
return packet_set_addr( packet, NULL, ( uint8_t * ) dest, addrlen ); |
} |
|
int ip_get_icmp_phone( void ){ |
ip_proto_ref proto; |