Rev 4351 | Rev 4506 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4351 | Rev 4505 | ||
---|---|---|---|
Line 39... | Line 39... | ||
39 | #include <string.h> |
39 | #include <string.h> |
40 | 40 | ||
41 | #include <ipc/ipc.h> |
41 | #include <ipc/ipc.h> |
42 | #include <ipc/services.h> |
42 | #include <ipc/services.h> |
43 | 43 | ||
- | 44 | #include <sys/types.h> |
|
- | 45 | ||
44 | #include "../../err.h" |
46 | #include "../../err.h" |
45 | #include "../../messages.h" |
47 | #include "../../messages.h" |
46 | #include "../../modules.h" |
48 | #include "../../modules.h" |
47 | 49 | ||
48 | #include "../../include/net_interface.h" |
50 | #include "../../include/net_interface.h" |
49 | #include "../../include/sockaddr.h" |
51 | #include "../../include/sockaddr.h" |
50 | #include "../../include/socket.h" |
52 | #include "../../include/socket.h" |
- | 53 | #include "../../include/byteorder.h" |
|
- | 54 | #include "../../include/crc.h" |
|
51 | #include "../../include/device.h" |
55 | #include "../../include/device.h" |
52 | #include "../../include/arp_interface.h" |
56 | #include "../../include/arp_interface.h" |
53 | #include "../../include/nil_interface.h" |
57 | #include "../../include/nil_interface.h" |
54 | #include "../../include/il_interface.h" |
58 | #include "../../include/il_interface.h" |
- | 59 | #include "../../include/ip_client.h" |
|
55 | #include "../../include/ip_interface.h" |
60 | #include "../../include/ip_interface.h" |
- | 61 | #include "../../include/tl_interface.h" |
|
56 | #include "../../structures/measured_strings.h" |
62 | #include "../../structures/measured_strings.h" |
57 | #include "../../structures/module_map.h" |
63 | #include "../../structures/module_map.h" |
58 | #include "../../structures/packet/packet_client.h" |
64 | #include "../../structures/packet/packet_client.h" |
59 | 65 | ||
60 | #include "../../nil/nil_messages.h" |
66 | #include "../../nil/nil_messages.h" |
61 | 67 | ||
62 | #include "../il_messages.h" |
68 | #include "../il_messages.h" |
63 | 69 | ||
64 | #include "ip.h" |
70 | #include "ip.h" |
- | 71 | #include "ip_header.h" |
|
- | 72 | #include "ip_messages.h" |
|
65 | #include "ip_module.h" |
73 | #include "ip_module.h" |
66 | 74 | ||
67 | #define DEFAULT_IPV 4 |
75 | #define DEFAULT_IPV 4 |
- | 76 | #define IP_MIN_CONTENT 576 |
|
68 | 77 | ||
69 | #define ARP_NAME "arp" |
78 | #define ARP_NAME "arp" |
70 | #define ARP_FILENAME "/srv/arp" |
79 | #define ARP_FILENAME "/srv/arp" |
71 | 80 | ||
- | 81 | #define IP_ADDR sizeof( in_addr_t ) |
|
- | 82 | #define IP_PREFIX sizeof( ip_header_t ) |
|
- | 83 | #define IP_SUFFIX 0 |
|
- | 84 | #define IP_MAX_CONTENT 65535 |
|
- | 85 | #define IP_HEADER_LENGTH( header ) (( header )->ihl * 4 ) |
|
- | 86 | #define IP_TOTAL_LENGTH( header ) ntohs(( header )->total_length ) |
|
- | 87 | #define IP_HEADER_DATA_LENGTH( header ) ( IP_TOTAL_LENGTH( header ) - IP_HEADER_LENGTH( header )) |
|
- | 88 | #define IP_HEADER_CHECKSUM( header ) ( htons( ip_checksum(( uint8_t * )( header ), IP_HEADER_LENGTH( header )))) |
|
- | 89 | ||
- | 90 | //zero is returned as 0xFFFF (not flipped) |
|
- | 91 | #define IP_HEADER_CHECKSUM_ZERO 0xFFFF |
|
- | 92 | ||
72 | ip_globals_t ip_globals; |
93 | ip_globals_t ip_globals; |
73 | 94 | ||
74 | DEVICE_MAP_IMPLEMENT( ip_netifs, ip_netif_t ) |
95 | DEVICE_MAP_IMPLEMENT( ip_netifs, ip_netif_t ) |
75 | 96 | ||
76 | INT_MAP_IMPLEMENT( ip_protos, ip_proto_t ) |
97 | INT_MAP_IMPLEMENT( ip_protos, ip_proto_t ) |
77 | 98 | ||
- | 99 | GENERIC_FIELD_IMPLEMENT( ip_routes, ip_route_t ) |
|
- | 100 | ||
78 | int ip_device_state_msg( int il_phone, device_id_t device_id, device_state_t state ); |
101 | int ip_device_state_msg( int il_phone, device_id_t device_id, device_state_t state ); |
- | 102 | int ip_register( int protocol, services_t service, int phone, tl_received_msg_t tl_received_msg ); |
|
- | 103 | int ip_netif_initialize( ip_netif_ref ip_netif ); |
|
- | 104 | ||
- | 105 | int ip_send_route( packet_t packet, ip_netif_ref netif, ip_route_ref route, in_addr_t * src, in_addr_t dest ); |
|
- | 106 | int ip_prepare_packet( in_addr_t * source, packet_t packet, measured_string_ref destination ); |
|
- | 107 | ||
- | 108 | packet_t ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, size_t addr_len ); |
|
- | 109 | int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, size_t addr_len ); |
|
- | 110 | 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 ); |
|
- | 111 | ip_header_ref ip_create_middle_header( packet_t packet, ip_header_ref last ); |
|
- | 112 | ip_header_ref ip_create_last_header( packet_t packet, ip_header_ref first ); |
|
- | 113 | ||
- | 114 | in_addr_t * ip_netif_addr( ip_netif_ref netif ); |
|
- | 115 | ip_route_ref ip_find_route( in_addr_t destination ); |
|
- | 116 | ip_route_ref ip_netif_find_route( ip_netif_ref netif, in_addr_t destination ); |
|
- | 117 | ||
79 | int ip_register( int il_phone, int protocol, int phone ); |
118 | int ip_received_msg( device_id_t device_id, packet_t packet ); |
- | 119 | int ip_process_packet( device_id_t device_id, packet_t packet ); |
|
- | 120 | in_addr_t ip_get_destination( ip_header_ref header ); |
|
- | 121 | int ip_deliver_local( device_id_t device_id, packet_t packet, ip_header_ref header ); |
|
- | 122 | ||
- | 123 | /** Computes the ip header checksum. |
|
- | 124 | * To compute the checksum of a new packet, the checksum header field must be zero. |
|
- | 125 | * To check the checksum of a received packet, the checksum may be left set. |
|
- | 126 | * The zero (0) value will returned in this case if valid. |
|
- | 127 | * @param data The header data. Input parameter. |
|
- | 128 | * @param length The header length in bytes. Input parameter. |
|
- | 129 | * @returns The internet protocol header checksum. |
|
- | 130 | * @returns IP_HEADER_CHECKSUM_ZERO if the computed checksum is zero. |
|
- | 131 | */ |
|
- | 132 | uint16_t ip_checksum( uint8_t * data, int length ); |
|
- | 133 | ||
- | 134 | uint16_t ip_checksum( uint8_t * data, int length ){ |
|
- | 135 | uint16_t checksum; |
|
- | 136 | ||
- | 137 | checksum = compact_checksum(compute_checksum( 0, data, length )); |
|
- | 138 | ||
- | 139 | // flip, zero is returned as 0xFFFF (not flipped) |
|
- | 140 | return ( ~ checksum ) ? ~ checksum : IP_HEADER_CHECKSUM_ZERO; |
|
- | 141 | } |
|
80 | 142 | ||
81 | /** Initializes the module. |
143 | /** Initializes the module. |
82 | */ |
144 | */ |
83 | int ip_initialize( async_client_conn_t client_connection ){ |
145 | int ip_initialize( async_client_conn_t client_connection ){ |
84 | ERROR_DECLARE; |
146 | ERROR_DECLARE; |
85 | 147 | ||
- | 148 | ip_globals.packet_counter = 0; |
|
- | 149 | ip_globals.gateway.address.s_addr = 0; |
|
- | 150 | ip_globals.gateway.netmask.s_addr = 0; |
|
- | 151 | ip_globals.gateway.gateway.s_addr = 0; |
|
- | 152 | ip_globals.gateway.netif = NULL; |
|
86 | ERROR_PROPAGATE( ip_netifs_initialize( & ip_globals.netifs )); |
153 | ERROR_PROPAGATE( ip_netifs_initialize( & ip_globals.netifs )); |
87 | ERROR_PROPAGATE( ip_protos_initialize( & ip_globals.protos )); |
154 | ERROR_PROPAGATE( ip_protos_initialize( & ip_globals.protos )); |
88 | ip_globals.client_connection = client_connection; |
155 | ip_globals.client_connection = client_connection; |
89 | ERROR_PROPAGATE( modules_initialize( & ip_globals.modules )); |
156 | ERROR_PROPAGATE( modules_initialize( & ip_globals.modules )); |
90 | ERROR_PROPAGATE( add_module( NULL, & ip_globals.modules, ARP_NAME, ARP_FILENAME, SERVICE_ARP, arp_task_get_id(), arp_connect_module )); |
157 | ERROR_PROPAGATE( add_module( NULL, & ip_globals.modules, ARP_NAME, ARP_FILENAME, SERVICE_ARP, arp_task_get_id(), arp_connect_module )); |
Line 92... | Line 159... | ||
92 | } |
159 | } |
93 | 160 | ||
94 | int ip_device_req( int il_phone, device_id_t device_id, services_t netif ){ |
161 | int ip_device_req( int il_phone, device_id_t device_id, services_t netif ){ |
95 | ERROR_DECLARE; |
162 | ERROR_DECLARE; |
96 | 163 | ||
97 | ip_netif_ref ip_netif; |
164 | ip_netif_ref ip_netif; |
- | 165 | ip_route_ref route; |
|
- | 166 | int index; |
|
- | 167 | char * data; |
|
- | 168 | ||
- | 169 | ip_netif = ( ip_netif_ref ) malloc( sizeof( ip_netif_t )); |
|
- | 170 | if( ! ip_netif ) return ENOMEM; |
|
- | 171 | if( ERROR_OCCURRED( ip_routes_initialize( & ip_netif->routes ))){ |
|
- | 172 | free( ip_netif ); |
|
- | 173 | return ERROR_CODE; |
|
- | 174 | } |
|
- | 175 | ip_netif->device_id = device_id; |
|
- | 176 | ip_netif->service = netif; |
|
- | 177 | ip_netif->state = NETIF_STOPPED; |
|
- | 178 | if( ERROR_OCCURRED( ip_netif_initialize( ip_netif ))){ |
|
- | 179 | ip_routes_destroy( & ip_netif->routes ); |
|
- | 180 | free( ip_netif ); |
|
- | 181 | return ERROR_CODE; |
|
- | 182 | } |
|
- | 183 | if( ip_netif->arp ) ++ ip_netif->arp->usage; |
|
- | 184 | // print the settings |
|
- | 185 | printf( "New device registered:\n\tid\t= %d\n\tphone\t= %d\n\tIPV\t= %d\n", ip_netif->device_id, ip_netif->phone, ip_netif->ipv ); |
|
- | 186 | printf( "\tconfiguration\t= %s\n", ip_netif->dhcp ? "dhcp" : "static" ); |
|
- | 187 | // TODO ipv6 addresses |
|
- | 188 | data = ( char * ) malloc( INET_ADDRSTRLEN ); |
|
- | 189 | if( data ){ |
|
- | 190 | for( index = 0; index < ip_routes_count( & ip_netif->routes ); ++ index ){ |
|
- | 191 | route = ip_routes_get_index( & ip_netif->routes, index ); |
|
- | 192 | if( route ){ |
|
- | 193 | printf( "\tRouting %d:\n", index ); |
|
- | 194 | inet_ntop( AF_INET, ( uint8_t * ) & route->address.s_addr, data, INET_ADDRSTRLEN ); |
|
- | 195 | printf( "\t\taddress\t= %s\n", data ); |
|
- | 196 | inet_ntop( AF_INET, ( uint8_t * ) & route->netmask.s_addr, data, INET_ADDRSTRLEN ); |
|
- | 197 | printf( "\t\tnetmask\t= %s\n", data ); |
|
- | 198 | inet_ntop( AF_INET, ( uint8_t * ) & route->gateway.s_addr, data, INET_ADDRSTRLEN ); |
|
- | 199 | printf( "\t\tgateway\t= %s\n", data ); |
|
- | 200 | } |
|
- | 201 | } |
|
- | 202 | inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->broadcast.s_addr, data, INET_ADDRSTRLEN ); |
|
- | 203 | printf( "\tbroadcast\t= %s\n", data ); |
|
- | 204 | inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->dns1, data, INET_ADDRSTRLEN ); |
|
- | 205 | printf( "\tdns1\t= %s\n", data ); |
|
- | 206 | inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->dns2, data, INET_ADDRSTRLEN ); |
|
- | 207 | printf( "\tdns2\t= %s\n", data ); |
|
- | 208 | free( data ); |
|
- | 209 | } |
|
- | 210 | return EOK; |
|
- | 211 | } |
|
- | 212 | ||
- | 213 | int ip_netif_initialize( ip_netif_ref ip_netif ){ |
|
- | 214 | ERROR_DECLARE; |
|
- | 215 | ||
98 | measured_string_t names[ 9 ] = {{ "IPV", 3 }, { "IP_CONFIG", 9 }, { "IP_ADDR", 7 }, { "NETMASK", 7 }, { "GATEWAY", 7 }, { "BROADCAST", 9 }, { "DNS1", 4 }, { "DNS2", 4 }, { "ARP", 3 }}; |
216 | measured_string_t names[ 9 ] = {{ "IPV", 3 }, { "IP_CONFIG", 9 }, { "IP_ADDR", 7 }, { "NETMASK", 7 }, { "GATEWAY", 7 }, { "BROADCAST", 9 }, { "DNS1", 4 }, { "DNS2", 4 }, { "ARP", 3 }}; |
99 | measured_string_ref configuration; |
217 | measured_string_ref configuration; |
100 | int count = 9; |
218 | size_t count = sizeof( names ) / sizeof( measured_string_t ); |
101 | char * data; |
219 | char * data; |
102 | int index; |
220 | int index; |
- | 221 | ip_route_ref route; |
|
- | 222 | in_addr_t gateway; |
|
103 | 223 | ||
104 | configuration = & names[ 0 ]; |
224 | configuration = & names[ 0 ]; |
105 | ip_netif = ( ip_netif_ref ) malloc( sizeof( ip_netif_t )); |
- | |
106 | if( ! ip_netif ) return ENOMEM; |
- | |
107 | ip_netif->device_id = device_id; |
- | |
108 | // get configuration |
225 | // get configuration |
109 | ERROR_PROPAGATE( net_get_device_conf_req( ip_globals.net_phone, ip_netif->device_id, & configuration, count, & data )); |
226 | ERROR_PROPAGATE( net_get_device_conf_req( ip_globals.net_phone, ip_netif->device_id, & configuration, count, & data )); |
110 | if( configuration ){ |
227 | if( configuration ){ |
111 | if( configuration[ 0 ].value ){ |
228 | if( configuration[ 0 ].value ){ |
112 | ip_netif->ipv = strtol( configuration[ 0 ].value, NULL, 0 ); |
229 | ip_netif->ipv = strtol( configuration[ 0 ].value, NULL, 0 ); |
Line 115... | Line 232... | ||
115 | } |
232 | } |
116 | ip_netif->dhcp = ! str_lcmp( configuration[ 1 ].value, "dhcp", configuration[ 1 ].length ); |
233 | ip_netif->dhcp = ! str_lcmp( configuration[ 1 ].value, "dhcp", configuration[ 1 ].length ); |
117 | if( ip_netif->dhcp ){ |
234 | if( ip_netif->dhcp ){ |
118 | // TODO dhcp |
235 | // TODO dhcp |
119 | net_free_settings( configuration, data ); |
236 | net_free_settings( configuration, data ); |
120 | free( ip_netif ); |
- | |
121 | return ENOTSUP; |
237 | return ENOTSUP; |
122 | }else if( ip_netif->ipv == 4 ){ |
238 | }else if( ip_netif->ipv == 4 ){ |
- | 239 | route = ( ip_route_ref ) malloc( sizeof( ip_route_t )); |
|
- | 240 | if( ! route ){ |
|
- | 241 | net_free_settings( configuration, data ); |
|
- | 242 | return ENOMEM; |
|
- | 243 | } |
|
- | 244 | route->address.s_addr = 0; |
|
- | 245 | route->netmask.s_addr = 0; |
|
- | 246 | route->gateway.s_addr = 0; |
|
- | 247 | route->netif = ip_netif; |
|
- | 248 | index = ip_routes_add( & ip_netif->routes, route ); |
|
- | 249 | if( index < 0 ){ |
|
- | 250 | net_free_settings( configuration, data ); |
|
- | 251 | free( route ); |
|
- | 252 | return index; |
|
- | 253 | } |
|
123 | if( ERROR_OCCURRED( inet_pton( AF_INET, configuration[ 2 ].value, ( uint8_t * ) & ip_netif->address )) |
254 | if( ERROR_OCCURRED( inet_pton( AF_INET, configuration[ 2 ].value, ( uint8_t * ) & route->address.s_addr )) |
124 | || ERROR_OCCURRED( inet_pton( AF_INET, configuration[ 3 ].value, ( uint8_t * ) & ip_netif->netmask )) |
255 | || ERROR_OCCURRED( inet_pton( AF_INET, configuration[ 3 ].value, ( uint8_t * ) & route->netmask.s_addr )) |
125 | || ( inet_pton( AF_INET, configuration[ 4 ].value, ( uint8_t * ) & ip_netif->gateway ) == EINVAL ) |
256 | || ( inet_pton( AF_INET, configuration[ 4 ].value, ( uint8_t * ) & gateway.s_addr ) == EINVAL ) |
126 | || ( inet_pton( AF_INET, configuration[ 5 ].value, ( uint8_t * ) & ip_netif->broadcast ) == EINVAL ) |
257 | || ( inet_pton( AF_INET, configuration[ 5 ].value, ( uint8_t * ) & ip_netif->broadcast.s_addr ) == EINVAL ) |
127 | || ( inet_pton( AF_INET, configuration[ 6 ].value, ( uint8_t * ) & ip_netif->dns1 ) == EINVAL ) |
258 | || ( inet_pton( AF_INET, configuration[ 6 ].value, ( uint8_t * ) & ip_netif->dns1 ) == EINVAL ) |
128 | || ( inet_pton( AF_INET, configuration[ 7 ].value, ( uint8_t * ) & ip_netif->dns2 ) == EINVAL )){ |
259 | || ( inet_pton( AF_INET, configuration[ 7 ].value, ( uint8_t * ) & ip_netif->dns2 ) == EINVAL )){ |
129 | net_free_settings( configuration, data ); |
260 | net_free_settings( configuration, data ); |
130 | free( ip_netif ); |
- | |
131 | return EINVAL; |
261 | return EINVAL; |
132 | } |
262 | } |
133 | }else{ |
263 | }else{ |
134 | // TODO ipv6 |
264 | // TODO ipv6 in separate module |
135 | net_free_settings( configuration, data ); |
265 | net_free_settings( configuration, data ); |
136 | free( ip_netif ); |
- | |
137 | return ENOTSUP; |
266 | return ENOTSUP; |
138 | } |
267 | } |
139 | if( configuration[ 8 ].value ){ |
268 | if( configuration[ 8 ].value ){ |
140 | ip_netif->arp = get_running_module( & ip_globals.modules, configuration[ 8 ].value ); |
269 | ip_netif->arp = get_running_module( & ip_globals.modules, configuration[ 8 ].value ); |
141 | if( ! ip_netif->arp ){ |
270 | if( ! ip_netif->arp ){ |
142 | printf( "Failed to start the arp %s\n", configuration[ 8 ].value ); |
271 | printf( "Failed to start the arp %s\n", configuration[ 8 ].value ); |
143 | net_free_settings( configuration, data ); |
272 | net_free_settings( configuration, data ); |
144 | free( ip_netif ); |
- | |
145 | return EINVAL; |
273 | return EINVAL; |
146 | } |
274 | } |
147 | }else{ |
275 | }else{ |
148 | ip_netif->arp = NULL; |
276 | ip_netif->arp = NULL; |
149 | } |
277 | } |
150 | net_free_settings( configuration, data ); |
278 | net_free_settings( configuration, data ); |
151 | } |
279 | } |
152 | ip_netif->phone = bind_service( netif, ip_netif->device_id, SERVICE_IP, 0, ip_globals.client_connection ); |
280 | ip_netif->phone = bind_service( ip_netif->service, ip_netif->device_id, SERVICE_IP, 0, ip_globals.client_connection ); |
153 | if( ip_netif->phone < 0 ){ |
281 | if( ip_netif->phone < 0 ){ |
154 | printf( "Failed to contact the nil service %d\n", netif ); |
282 | printf( "Failed to contact the nil service %d\n", ip_netif->service ); |
155 | free( ip_netif ); |
- | |
156 | return ip_netif->phone; |
283 | return ip_netif->phone; |
157 | } |
284 | } |
- | 285 | // MUST BE AFTER the bind_service up there! |
|
158 | if( ip_netif->arp ){ |
286 | if( ip_netif->arp ){ |
159 | configuration[ 0 ].value = ( char * ) & ip_netif->address; |
287 | configuration[ 0 ].value = ( char * ) & route->address.s_addr; |
160 | configuration[ 0 ].length = CONVERT_SIZE( in_addr_t, char, 1 ); |
288 | configuration[ 0 ].length = CONVERT_SIZE( in_addr_t, char, 1 ); |
161 | if( ERROR_OCCURRED( arp_device_req( ip_netif->arp->phone, ip_netif->device_id, SERVICE_IP, netif, & configuration[ 0 ] ))){ |
289 | ERROR_PROPAGATE( arp_device_req( ip_netif->arp->phone, ip_netif->device_id, SERVICE_IP, ip_netif->service, & configuration[ 0 ] )); |
162 | free( ip_netif ); |
- | |
163 | return ERROR_CODE; |
- | |
164 | } |
- | |
165 | } |
290 | } |
- | 291 | // get packet dimensions |
|
166 | index = ip_netifs_add( & ip_globals.netifs, ip_netif->device_id, ip_netif ); |
292 | ERROR_PROPAGATE( nil_packet_size_req( ip_netif->phone, ip_netif->device_id, & ip_netif->addr_len, & ip_netif->prefix, & ip_netif->content, & ip_netif->suffix )); |
167 | if( index < 0 ){ |
293 | if( ip_netif->content < IP_MIN_CONTENT ){ |
168 | free( ip_netif ); |
294 | printf( "Maximum transmission unit %d bytes is too small, at least %d bytes are needed\n", ip_netif->content, IP_MIN_CONTENT ); |
169 | return index; |
295 | ip_netif->content = IP_MIN_CONTENT; |
170 | } |
296 | } |
171 | if( ip_netif->arp ) ++ ip_netif->arp->usage; |
- | |
172 | // print the settings |
- | |
173 | printf( "New device registered:\n\tid\t= %d\n\tphone\t= %d\n\tIPV\t= %d\n", ip_netif->device_id, ip_netif->phone, ip_netif->ipv ); |
- | |
174 | printf( "\tconfiguration\t= %s\n", ip_netif->dhcp ? "dhcp" : "static" ); |
297 | index = ip_netifs_add( & ip_globals.netifs, ip_netif->device_id, ip_netif ); |
175 | // TODO ipv6 addresses |
298 | if( index < 0 ) return index; |
176 | data = malloc( INET_ADDRSTRLEN ); |
- | |
177 | if( data ){ |
299 | if( gateway.s_addr ){ |
178 | inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->address, data, INET_ADDRSTRLEN ); |
- | |
179 | printf( "\taddress\t= %s\n", data ); |
300 | // the default gateway |
180 | inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->netmask, data, INET_ADDRSTRLEN ); |
- | |
181 | printf( "\tnetmask\t= %s\n", data ); |
301 | ip_globals.gateway.address.s_addr = 0; |
182 | inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->gateway, data, INET_ADDRSTRLEN ); |
- | |
183 | printf( "\tgateway\t= %s\n", data ); |
302 | ip_globals.gateway.netmask.s_addr = 0; |
184 | inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->broadcast, data, INET_ADDRSTRLEN ); |
- | |
185 | printf( "\tbroadcast\t= %s\n", data ); |
303 | ip_globals.gateway.gateway.s_addr = gateway.s_addr; |
186 | inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->dns1, data, INET_ADDRSTRLEN ); |
- | |
187 | printf( "\tdns1\t= %s\n", data ); |
- | |
188 | inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->dns2, data, INET_ADDRSTRLEN ); |
- | |
189 | printf( "\tdns2\t= %s\n", data ); |
304 | ip_globals.gateway.netif = ip_netif; |
190 | free( data ); |
- | |
191 | } |
305 | } |
192 | return EOK; |
306 | return EOK; |
193 | } |
307 | } |
194 | 308 | ||
195 | int ip_device_state_msg( int il_phone, device_id_t device_id, device_state_t state ){ |
309 | int ip_device_state_msg( int il_phone, device_id_t device_id, device_state_t state ){ |
196 | // ERROR_DECLARE; |
310 | ERROR_DECLARE; |
197 | - | ||
198 | ip_netif_ref netif; |
- | |
199 | 311 | ||
200 | /* measured_string_t address; |
312 | /* measured_string_t address; |
201 | measured_string_ref translation; |
313 | measured_string_ref translation; |
202 | char * data; |
314 | char * data; |
203 | */ |
315 | */ |
- | 316 | packet_t packet; |
|
- | 317 | in_addr_t destination; |
|
- | 318 | ||
- | 319 | ip_netif_ref netif; |
|
- | 320 | ||
204 | netif = ip_netifs_find( & ip_globals.netifs, device_id ); |
321 | netif = ip_netifs_find( & ip_globals.netifs, device_id ); |
205 | if( ! netif ) return ENOENT; |
322 | if( ! netif ) return ENOENT; |
- | 323 | netif->state = state; |
|
206 | // TODO state |
324 | // TODO state |
207 | printf( "ip - device %d changed state to %d\n\n", device_id, state ); |
325 | printf( "ip - device %d changed state to %d\n\n", device_id, state ); |
208 | /* if( netif->arp ){ |
326 | if( netif->arp ){ |
- | 327 | /* address.value = ( char * ) & ip_globals.gateway.gateway.s_addr; |
|
- | 328 | address.length = CONVERT_SIZE( ip_globals.gateway.gateway.s_addr, char, 1 ); |
|
- | 329 | if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ))){ |
|
- | 330 | ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data )); |
|
- | 331 | } |
|
- | 332 | printf( "\tgateway translated to\t= %X:%X:%X:%X:%X:%X\n", data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ] ); |
|
- | 333 | free( translation ); |
|
- | 334 | free( data ); |
|
209 | address.value = ( char * ) & netif->gateway; |
335 | address.value = ( char * ) & ip_globals.gateway.gateway.s_addr; |
210 | address.length = CONVERT_SIZE( in_addr_t, char, 1 ); |
336 | address.length = CONVERT_SIZE( ip_globals.gateway.gateway.s_addr, char, 1 ); |
211 | if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ))){ |
337 | if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ))){ |
212 | sleep( 2 ); |
338 | sleep( 2 ); |
213 | ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data )); |
339 | ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data )); |
214 | } |
340 | } |
215 | printf( "\tgateway translated to\t= %X:%X:%X:%X:%X:%X\n", data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ] ); |
341 | printf( "\tgateway translated to\t= %X:%X:%X:%X:%X:%X\n", data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ] ); |
216 | free( translation ); |
342 | free( translation ); |
217 | free( data ); |
343 | free( data ); |
- | 344 | */ printf( "IP - testing to send packet:\n" ); |
|
- | 345 | ERROR_PROPAGATE( inet_pton( AF_INET, "90.182.101.18", ( uint8_t * ) & destination.s_addr )); |
|
- | 346 | packet = packet_get_4( ip_globals.net_phone, 30, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix ); |
|
- | 347 | if( ! packet ) return ENOMEM; |
|
- | 348 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
|
- | 349 | packet = packet_get_4( ip_globals.net_phone, 30, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix ); |
|
- | 350 | if( ! packet ) return ENOMEM; |
|
- | 351 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
|
- | 352 | packet = packet_get_4( ip_globals.net_phone, 30, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix ); |
|
- | 353 | if( ! packet ) return ENOMEM; |
|
- | 354 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
|
- | 355 | packet = packet_get_4( ip_globals.net_phone, 1500, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix ); |
|
- | 356 | if( ! packet ) return ENOMEM; |
|
- | 357 | // try this long version |
|
- | 358 | // if( ERROR_OCCURRED( packet_copy_data( packet, "Hi, this is IP, wery long version 1, wery long version 2, wery long version 3, wery long version 4, wery long version 5, wery long version 6, wery long version 7, wery long version 8, wery long version 9, wery long version 10, wery long version 11, wery long version 12, wery long version 13, wery long version 14, wery long version 15, wery long version 16, wery long version 17, wery long version 18, wery long version 19, wery long version 20, wery long version 21, wery long version 22, wery long version 23, wery long version 24, wery long version 25, wery long version 26, wery long version 27, wery long version 28, wery long version 29, wery long version 30Hi, this is IP, wery long version 1, wery long version 2, wery long version 3, wery long version 4, wery long version 5, wery long version 6, wery long version 7, wery long version 8, wery long version 9, wery long version 10, wery long version 11, wery long version 12, wery long version 13, wery long version 14, wery long version 15, wery long version 16, wery long version 17, wery long version 18, wery long version 19, wery long version 20, wery long version 21, wery long version 22, wery long version 23, wery long version 24, wery long version 25, wery long version 26, wery long version 27, wery long version 28, wery long version 29, wery long version 30", 1330 )) |
|
- | 359 | if( ERROR_OCCURRED( packet_copy_data( packet, "Hi, this is IP", 14 )) |
|
- | 360 | || ERROR_OCCURRED( packet_set_addr( packet, NULL, ( uint8_t * ) & destination.s_addr, 4 )) |
|
- | 361 | || ERROR_OCCURRED( ip_client_prepare_packet( packet, 0, 0, 0, 0, 0 ))){ |
|
- | 362 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
|
- | 363 | } |
|
- | 364 | ERROR_CODE = ip_send_msg( 0, 0, packet, SERVICE_IP ); |
|
- | 365 | printf( "send returned %d\n", ERROR_CODE ); |
|
218 | } |
366 | } |
219 | */ return EOK; |
- | |
220 | } |
- | |
221 | - | ||
222 | int ip_bind_service( services_t service, services_t me, async_client_conn_t receiver ){ |
- | |
223 | //TODO receive function |
- | |
224 | return EOK; |
367 | return EOK; |
225 | } |
368 | } |
226 | 369 | ||
227 | int ip_connect_module( services_t service ){ |
370 | int ip_connect_module( services_t service ){ |
228 | return EOK; |
371 | return EOK; |
229 | } |
372 | } |
230 | 373 | ||
- | 374 | int ip_bind_service( services_t service, int protocol, services_t me, async_client_conn_t receiver, tl_received_msg_t tl_received_msg ){ |
|
231 | int ip_register( int il_phone, int protocol, int phone ){ |
375 | return ip_register( protocol, me, 0, tl_received_msg ); |
- | 376 | } |
|
- | 377 | ||
- | 378 | int ip_register( int protocol, services_t service, int phone, tl_received_msg_t tl_received_msg ){ |
|
232 | ip_proto_ref proto; |
379 | ip_proto_ref proto; |
233 | int index; |
380 | int index; |
234 | 381 | ||
- | 382 | if( !( protocol && service && (( phone > 0 ) || ( tl_received_msg )))) return EINVAL; |
|
235 | proto = ( ip_proto_ref ) malloc( sizeof( ip_protos_t )); |
383 | proto = ( ip_proto_ref ) malloc( sizeof( ip_protos_t )); |
236 | if( ! proto ) return ENOMEM; |
384 | if( ! proto ) return ENOMEM; |
237 | proto->protocol = protocol; |
385 | proto->protocol = protocol; |
- | 386 | proto->service = service; |
|
238 | proto->phone = phone; |
387 | proto->phone = phone; |
- | 388 | proto->tl_received_msg = tl_received_msg; |
|
239 | index = ip_protos_add( & ip_globals.protos, proto->protocol, proto ); |
389 | index = ip_protos_add( & ip_globals.protos, proto->protocol, proto ); |
240 | if( index < 0 ){ |
390 | if( index < 0 ){ |
241 | free( proto ); |
391 | free( proto ); |
242 | return index; |
392 | return index; |
243 | } |
393 | } |
244 | printf( "New protocol registered:\n\tprotocol\t= %d\n\tphone\t= %d\n", proto->protocol, proto->phone ); |
394 | printf( "New protocol registered:\n\tprotocol\t= %d\n\tphone\t= %d\n", proto->protocol, proto->phone ); |
245 | return EOK; |
395 | return EOK; |
246 | } |
396 | } |
247 | 397 | ||
248 | int ip_send_msg( int il_phone, device_id_t device_id, packet_t packet, services_t target ){ |
398 | int ip_send_msg( int il_phone, device_id_t device_id, packet_t packet, services_t sender ){ |
- | 399 | ERROR_DECLARE; |
|
- | 400 | ||
- | 401 | int length; |
|
- | 402 | ip_netif_ref netif; |
|
- | 403 | ip_route_ref route; |
|
- | 404 | in_addr_t dest; |
|
- | 405 | in_addr_t * src; |
|
- | 406 | ||
- | 407 | // addresses in the host byte order |
|
- | 408 | // should be the next hop address or the target destination address |
|
- | 409 | length = packet_get_addr( packet, NULL, ( void * )( & dest.s_addr )); |
|
- | 410 | if( length < 0 ){ |
|
- | 411 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
|
- | 412 | return length; |
|
- | 413 | } |
|
- | 414 | // TODO IPv6 |
|
- | 415 | if( length != IP_ADDR ){ |
|
- | 416 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
|
- | 417 | return EINVAL; |
|
- | 418 | } |
|
- | 419 | // rwlock_read_lock( & ip_globals.devices_lock ); |
|
- | 420 | // device specified? |
|
- | 421 | // dest.s_addr = ntohl( dest.s_addr ); |
|
- | 422 | if( device_id ){ |
|
- | 423 | netif = ip_netifs_find( & ip_globals.netifs, device_id ); |
|
- | 424 | route = ip_netif_find_route( netif, dest ); |
|
- | 425 | }else{ |
|
- | 426 | // TODO IPv6 |
|
- | 427 | route = ip_find_route( dest ); |
|
- | 428 | netif = route ? route->netif : NULL; |
|
- | 429 | } |
|
- | 430 | if( !( netif && route )){ |
|
- | 431 | // rwlock_read_unlock( & ip_globals.devices_lock ); |
|
- | 432 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
|
- | 433 | return ENOENT; |
|
- | 434 | } |
|
- | 435 | // to me? |
|
- | 436 | if( route->address.s_addr == dest.s_addr ){ |
|
249 | // TODO send packet |
437 | // TODO loopback deliver |
- | 438 | } |
|
- | 439 | ||
- | 440 | src = ip_netif_addr( netif ); |
|
- | 441 | if( ! src ){ |
|
250 | printf( "Packet to send via %d: %s\n", device_id, packet_get_data( packet )); |
442 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
- | 443 | return ENOENT; |
|
- | 444 | } |
|
- | 445 | if( ERROR_OCCURRED( ip_send_route( packet, netif, route, src, dest ))){ |
|
251 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
446 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
- | 447 | } |
|
- | 448 | return ERROR_CODE; |
|
- | 449 | } |
|
- | 450 | ||
- | 451 | in_addr_t * ip_netif_addr( ip_netif_ref netif ){ |
|
- | 452 | ip_route_ref route; |
|
- | 453 | ||
- | 454 | route = ip_routes_get_index( & netif->routes, 0 ); |
|
- | 455 | return route ? & route->address : NULL; |
|
- | 456 | } |
|
- | 457 | ||
- | 458 | int ip_send_route( packet_t packet, ip_netif_ref netif, ip_route_ref route, in_addr_t * src, in_addr_t dest ){ |
|
- | 459 | ERROR_DECLARE; |
|
- | 460 | ||
- | 461 | packet_t next; |
|
- | 462 | packet_t tmp; |
|
- | 463 | measured_string_t destination; |
|
- | 464 | measured_string_ref translation; |
|
- | 465 | char * data; |
|
- | 466 | ||
- | 467 | if( route->gateway.s_addr ){ |
|
- | 468 | dest.s_addr = route->gateway.s_addr; |
|
- | 469 | } |
|
- | 470 | // get destination hardware address |
|
- | 471 | if( netif->arp ){ |
|
- | 472 | destination.value = ( char * ) & dest.s_addr; |
|
- | 473 | destination.length = CONVERT_SIZE( dest.s_addr, char, 1 ); |
|
- | 474 | if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ))){ |
|
- | 475 | usleep( 200000 ); |
|
- | 476 | ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data )); |
|
- | 477 | } |
|
- | 478 | // TODO unreachable |
|
- | 479 | if( ! translation ) return EINVAL; |
|
- | 480 | if( ! translation->value ){ |
|
- | 481 | // TODO unreachable |
|
- | 482 | free( translation ); |
|
- | 483 | free( data ); |
|
- | 484 | return EINVAL; |
|
- | 485 | } |
|
- | 486 | }else translation = NULL; |
|
- | 487 | // process packet queue |
|
- | 488 | next = packet; |
|
- | 489 | do{ |
|
- | 490 | if( ERROR_OCCURRED( ip_prepare_packet( src, next, translation ))){ |
|
- | 491 | // release invalid packet |
|
- | 492 | tmp = pq_detach( next ); |
|
- | 493 | if( next == packet ) packet = tmp; |
|
- | 494 | pq_release( ip_globals.net_phone, packet_get_id( next )); |
|
- | 495 | next = tmp; |
|
- | 496 | }else{ |
|
- | 497 | next = pq_next( next ); |
|
- | 498 | } |
|
- | 499 | }while( next ); |
|
- | 500 | if( translation ){ |
|
- | 501 | free( translation ); |
|
- | 502 | free( data ); |
|
- | 503 | } |
|
- | 504 | // send packet queue |
|
- | 505 | if( packet ){ |
|
- | 506 | packet = ip_split_packet( packet, netif->prefix, netif->content, netif->suffix, netif->addr_len ); |
|
- | 507 | if( packet ){ |
|
- | 508 | nil_send_msg( netif->phone, netif->device_id, packet, SERVICE_IP ); |
|
- | 509 | } |
|
- | 510 | } |
|
- | 511 | // rwlock_read_unlock( & ip_globals.netifs_lock ); |
|
- | 512 | return EOK; |
|
- | 513 | } |
|
- | 514 | ||
- | 515 | int ip_prepare_packet( in_addr_t * source, packet_t packet, measured_string_ref destination ){ |
|
- | 516 | ERROR_DECLARE; |
|
- | 517 | ||
- | 518 | int length; |
|
- | 519 | ip_header_ref header; |
|
- | 520 | ||
- | 521 | length = packet_get_data_length( packet ); |
|
- | 522 | if(( length < sizeof( ip_header_t )) || ( length > IP_MAX_CONTENT )) return EINVAL; |
|
- | 523 | header = ( ip_header_ref ) packet_get_data( packet ); |
|
- | 524 | if( destination ){ |
|
- | 525 | ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length ))); |
|
- | 526 | } |
|
- | 527 | header->version = 4; |
|
- | 528 | header->total_length = htons( length ); |
|
- | 529 | header->fragment_offset = 0; |
|
- | 530 | if( source ) header->source_address = source->s_addr;//htonl( source.s_addr ); |
|
- | 531 | ++ ip_globals.packet_counter; |
|
- | 532 | header->identification = htons( ip_globals.packet_counter ); |
|
- | 533 | header->header_checksum = 0; |
|
- | 534 | // unnecessary for all protocols |
|
- | 535 | header->header_checksum = IP_HEADER_CHECKSUM( header ); |
|
252 | return EOK; |
536 | return EOK; |
253 | } |
537 | } |
254 | 538 | ||
255 | int ip_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){ |
539 | int ip_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){ |
256 | ERROR_DECLARE; |
540 | ERROR_DECLARE; |
Line 262... | Line 546... | ||
262 | case IPC_M_PHONE_HUNGUP: |
546 | case IPC_M_PHONE_HUNGUP: |
263 | return EOK; |
547 | return EOK; |
264 | case NET_IL_DEVICE: |
548 | case NET_IL_DEVICE: |
265 | return ip_device_req( 0, IPC_GET_DEVICE( call ), IPC_GET_SERVICE( call )); |
549 | return ip_device_req( 0, IPC_GET_DEVICE( call ), IPC_GET_SERVICE( call )); |
266 | case IPC_M_CONNECT_TO_ME: |
550 | case IPC_M_CONNECT_TO_ME: |
267 | return ip_register( 0, IL_GET_PROTO( call ), IPC_GET_PHONE( call )); |
551 | return ip_register( IL_GET_PROTO( call ), IL_GET_SERVICE( call ), IPC_GET_PHONE( call ), NULL ); |
268 | case NET_IL_SEND: |
552 | case NET_IL_SEND: |
269 | ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call ))); |
553 | ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call ))); |
270 | return ip_send_msg( 0, IPC_GET_DEVICE( call ), packet, 0 ); |
554 | return ip_send_msg( 0, IPC_GET_DEVICE( call ), packet, 0 ); |
271 | case NET_IL_DEVICE_STATE: |
555 | case NET_IL_DEVICE_STATE: |
272 | case NET_NIL_DEVICE_STATE: |
556 | case NET_NIL_DEVICE_STATE: |
273 | return ip_device_state_msg( 0, IPC_GET_DEVICE( call ), IPC_GET_STATE( call )); |
557 | return ip_device_state_msg( 0, IPC_GET_DEVICE( call ), IPC_GET_STATE( call )); |
274 | // TODO packet received |
- | |
275 | case NET_IL_RECEIVED: |
558 | case NET_IL_RECEIVED: |
276 | case NET_NIL_RECEIVED: |
559 | case NET_NIL_RECEIVED: |
277 | ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call ))); |
560 | ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call ))); |
278 | //return il_receive_msg( 0, IPC_GET_DEVICE( call ), packet ); |
561 | return ip_received_msg( IPC_GET_DEVICE( call ), packet ); |
- | 562 | case NET_IP_ADD_ROUTE: |
|
- | 563 | return ip_add_route_req( 0, IPC_GET_DEVICE( call ), IP_GET_ADDRESS( call ), IP_GET_NETMASK( call ), IP_GET_GATEWAY( call )); |
|
- | 564 | case NET_IP_SET_GATEWAY: |
|
- | 565 | return ip_set_gateway_req( 0, IPC_GET_DEVICE( call ), IP_GET_GATEWAY( call )); |
|
- | 566 | case NET_IL_PACKET_SPACE: |
|
- | 567 | 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 ))); |
|
- | 568 | * answer_count = 3; |
|
- | 569 | return EOK; |
|
279 | } |
570 | } |
280 | return ENOTSUP; |
571 | return ENOTSUP; |
281 | } |
572 | } |
282 | 573 | ||
- | 574 | int ip_packet_size_req( int ip_phone, device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix ){ |
|
- | 575 | ip_netif_ref netif; |
|
- | 576 | ||
- | 577 | if( !( addr_len && prefix && content && suffix )) return EBADMEM; |
|
- | 578 | // rwlock_read_lock( & ip_globals.netifs_lock ); |
|
- | 579 | netif = ip_netifs_find( & ip_globals.netifs, device_id ); |
|
- | 580 | if( ! netif ){ |
|
- | 581 | // rwlock_read_unlock( & ip_globals.netifs_lock ); |
|
- | 582 | return ENOENT; |
|
- | 583 | } |
|
- | 584 | * content = IP_MAX_CONTENT - IP_PREFIX; |
|
- | 585 | * addr_len = ( netif->addr_len > IP_ADDR ) ? netif->addr_len : IP_ADDR; |
|
- | 586 | * prefix = netif->prefix + IP_PREFIX; |
|
- | 587 | * suffix = netif->suffix + IP_SUFFIX; |
|
- | 588 | // rwlock_read_unlock( & ip_globals.netifs_lock ); |
|
- | 589 | return EOK; |
|
- | 590 | } |
|
- | 591 | ||
- | 592 | int ip_add_route_req( int ip_phone, device_id_t device_id, in_addr_t address, in_addr_t netmask, in_addr_t gateway ){ |
|
- | 593 | ip_route_ref route; |
|
- | 594 | ip_netif_ref netif; |
|
- | 595 | int index; |
|
- | 596 | ||
- | 597 | netif = ip_netifs_find( & ip_globals.netifs, device_id ); |
|
- | 598 | if( ! netif ) return ENOENT; |
|
- | 599 | route = ( ip_route_ref ) malloc( sizeof( ip_route_t )); |
|
- | 600 | if( ! route ) return ENOMEM; |
|
- | 601 | route->address.s_addr = address.s_addr; |
|
- | 602 | route->netmask.s_addr = netmask.s_addr; |
|
- | 603 | route->gateway.s_addr = gateway.s_addr; |
|
- | 604 | route->netif = netif; |
|
- | 605 | index = ip_routes_add( & netif->routes, route ); |
|
- | 606 | if( index < 0 ) free( route ); |
|
- | 607 | return index; |
|
- | 608 | } |
|
- | 609 | ||
- | 610 | ip_route_ref ip_find_route( in_addr_t destination ){ |
|
- | 611 | int index; |
|
- | 612 | ip_route_ref route; |
|
- | 613 | ip_netif_ref netif; |
|
- | 614 | ||
- | 615 | // start with the last netif - the newest one |
|
- | 616 | index = ip_netifs_count( & ip_globals.netifs ) - 1; |
|
- | 617 | while( index >= 0 ){ |
|
- | 618 | netif = ip_netifs_get_index( & ip_globals.netifs, index ); |
|
- | 619 | if( netif && ( netif->state == NETIF_ACTIVE )){ |
|
- | 620 | route = ip_netif_find_route( netif, destination ); |
|
- | 621 | if( route ) return route; |
|
- | 622 | } |
|
- | 623 | -- index; |
|
- | 624 | } |
|
- | 625 | return & ip_globals.gateway; |
|
- | 626 | } |
|
- | 627 | ||
- | 628 | ip_route_ref ip_netif_find_route( ip_netif_ref netif, in_addr_t destination ){ |
|
- | 629 | int index; |
|
- | 630 | ip_route_ref route; |
|
- | 631 | ||
- | 632 | if( netif ){ |
|
- | 633 | // start with the first one - the direct route |
|
- | 634 | for( index = 0; index < ip_routes_count( & netif->routes ); ++ index ){ |
|
- | 635 | route = ip_routes_get_index( & netif->routes, index ); |
|
- | 636 | if( route && (( route->address.s_addr & route->netmask.s_addr ) == ( destination.s_addr & route->netmask.s_addr ))){ |
|
- | 637 | return route; |
|
- | 638 | } |
|
- | 639 | } |
|
- | 640 | } |
|
- | 641 | return NULL; |
|
- | 642 | } |
|
- | 643 | ||
- | 644 | int ip_set_gateway_req( int ip_phone, device_id_t device_id, in_addr_t gateway ){ |
|
- | 645 | ip_netif_ref netif; |
|
- | 646 | ||
- | 647 | netif = ip_netifs_find( & ip_globals.netifs, device_id ); |
|
- | 648 | if( ! netif ) return ENOENT; |
|
- | 649 | ip_globals.gateway.address.s_addr = 0; |
|
- | 650 | ip_globals.gateway.netmask.s_addr = 0; |
|
- | 651 | ip_globals.gateway.gateway.s_addr = gateway.s_addr; |
|
- | 652 | ip_globals.gateway.netif = netif; |
|
- | 653 | return EOK; |
|
- | 654 | } |
|
- | 655 | ||
- | 656 | packet_t ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, size_t addr_len ){ |
|
- | 657 | size_t length; |
|
- | 658 | packet_t next; |
|
- | 659 | packet_t new_packet; |
|
- | 660 | ||
- | 661 | next = packet; |
|
- | 662 | // check all packets |
|
- | 663 | while( next ){ |
|
- | 664 | length = packet_get_data_length( next ); |
|
- | 665 | // too long? |
|
- | 666 | if( length > content ){ |
|
- | 667 | if( ip_fragment_packet( next, content, prefix, suffix, addr_len ) != EOK ){ |
|
- | 668 | new_packet = pq_detach( next ); |
|
- | 669 | if( next == packet ){ |
|
- | 670 | packet = new_packet; |
|
- | 671 | } |
|
- | 672 | pq_release( ip_globals.net_phone, packet_get_id( next )); |
|
- | 673 | next = new_packet; |
|
- | 674 | continue; |
|
- | 675 | } |
|
- | 676 | } |
|
- | 677 | next = pq_next( next ); |
|
- | 678 | } |
|
- | 679 | return packet; |
|
- | 680 | } |
|
- | 681 | ||
- | 682 | int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, size_t addr_len ){ |
|
- | 683 | ERROR_DECLARE; |
|
- | 684 | ||
- | 685 | packet_t new_packet; |
|
- | 686 | ip_header_ref header; |
|
- | 687 | ip_header_ref middle_header; |
|
- | 688 | ip_header_ref last_header; |
|
- | 689 | uint8_t * src; |
|
- | 690 | uint8_t * dest; |
|
- | 691 | int address_length; |
|
- | 692 | ||
- | 693 | address_length = packet_get_addr( packet, & src, & dest ); |
|
- | 694 | if( address_length <= 0 ) return EINVAL; |
|
- | 695 | if( packet_get_data_length( packet ) <= sizeof( ip_header_t )) return ENOMEM; |
|
- | 696 | // get header |
|
- | 697 | header = ( ip_header_ref ) packet_get_data( packet ); |
|
- | 698 | if( ! header ) return EINVAL; |
|
- | 699 | // fragmentation forbidden? |
|
- | 700 | if( header->flags & IPFLAG_DONT_FRAGMENT ){ |
|
- | 701 | // TODO fragmentation necessary ICMP |
|
- | 702 | return EPERM; |
|
- | 703 | } |
|
- | 704 | // create the last fragment |
|
- | 705 | new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( address_length > addr_len ) ? address_length : addr_len )); |
|
- | 706 | if( ! new_packet ) return ENOMEM; |
|
- | 707 | last_header = ip_create_last_header( new_packet, header ); |
|
- | 708 | if( ! last_header ){ |
|
- | 709 | pq_release( ip_globals.net_phone, packet_get_id( new_packet )); |
|
- | 710 | return ENOMEM; |
|
- | 711 | } |
|
- | 712 | // biggest multiple of 8 lower than content |
|
- | 713 | // TODO even fragmentation? |
|
- | 714 | length = length & ( ~ 0x7 );// ( content / 8 ) * 8 |
|
- | 715 | 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 ))){ |
|
- | 716 | pq_release( ip_globals.net_phone, packet_get_id( new_packet )); |
|
- | 717 | return ERROR_CODE; |
|
- | 718 | } |
|
- | 719 | // mark the first as fragmented |
|
- | 720 | header->flags |= IPFLAG_MORE_FRAGMENTS; |
|
- | 721 | // create middle framgents |
|
- | 722 | while( IP_TOTAL_LENGTH( header ) > length ){ |
|
- | 723 | new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( address_length >= addr_len ) ? address_length : addr_len )); |
|
- | 724 | if( ! new_packet ) return ENOMEM; |
|
- | 725 | middle_header = ip_create_middle_header( new_packet, last_header ); |
|
- | 726 | if( ! middle_header ){ |
|
- | 727 | pq_release( ip_globals.net_phone, packet_get_id( new_packet )); |
|
- | 728 | return ENOMEM; |
|
- | 729 | } |
|
- | 730 | if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, middle_header, length - IP_HEADER_LENGTH( middle_header ), src, dest, address_length ))){ |
|
- | 731 | pq_release( ip_globals.net_phone, packet_get_id( new_packet )); |
|
- | 732 | return ERROR_CODE; |
|
- | 733 | } |
|
- | 734 | } |
|
- | 735 | // finish the first fragment |
|
- | 736 | header->header_checksum = IP_HEADER_CHECKSUM( header ); |
|
- | 737 | printf( "ok\n" ); |
|
- | 738 | return EOK; |
|
- | 739 | } |
|
- | 740 | ||
- | 741 | 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 ){ |
|
- | 742 | ERROR_DECLARE; |
|
- | 743 | ||
- | 744 | void * data; |
|
- | 745 | ||
- | 746 | data = packet_suffix( new_packet, length ); |
|
- | 747 | if( ! data ) return ENOMEM; |
|
- | 748 | memcpy( data, (( void * ) header ) + IP_TOTAL_LENGTH( header ) - length, length ); |
|
- | 749 | ERROR_PROPAGATE( packet_trim( packet, 0, length )); |
|
- | 750 | header->total_length = htons( IP_TOTAL_LENGTH( header ) - length ); |
|
- | 751 | new_header->total_length = htons( IP_HEADER_LENGTH( new_header ) + length ); |
|
- | 752 | new_header->fragment_offset = header->fragment_offset + IP_HEADER_DATA_LENGTH( header ) / 8; |
|
- | 753 | new_header->header_checksum = IP_HEADER_CHECKSUM( new_header ); |
|
- | 754 | ERROR_PROPAGATE( packet_set_addr( new_packet, src, dest, address_length )); |
|
- | 755 | return pq_insert_after( packet, new_packet ); |
|
- | 756 | } |
|
- | 757 | ||
- | 758 | ip_header_ref ip_create_middle_header( packet_t packet, ip_header_ref last ){ |
|
- | 759 | ip_header_ref middle; |
|
- | 760 | ||
- | 761 | middle = ( ip_header_ref ) packet_suffix( packet, IP_HEADER_LENGTH( last )); |
|
- | 762 | if( ! middle ) return NULL; |
|
- | 763 | memcpy( middle, last, IP_HEADER_LENGTH( last )); |
|
- | 764 | middle->flags |= IPFLAG_MORE_FRAGMENTS; |
|
- | 765 | return middle; |
|
- | 766 | } |
|
- | 767 | ||
- | 768 | ip_header_ref ip_create_last_header( packet_t packet, ip_header_ref first ){ |
|
- | 769 | ip_header_ref last; |
|
- | 770 | ip_option_ref option; |
|
- | 771 | size_t next; |
|
- | 772 | size_t length; |
|
- | 773 | ||
- | 774 | // allocate as much as originally |
|
- | 775 | last = ( ip_header_ref ) packet_suffix( packet, IP_HEADER_LENGTH( first )); |
|
- | 776 | if( ! last ) return NULL; |
|
- | 777 | // copy first itself |
|
- | 778 | memcpy( last, first, sizeof( ip_header_t )); |
|
- | 779 | length = sizeof( ip_header_t ); |
|
- | 780 | next = sizeof( ip_header_t ); |
|
- | 781 | // process all ip options |
|
- | 782 | while( next < first->ihl ){ |
|
- | 783 | option = ( ip_option_ref ) ((( void * ) first ) + next ); |
|
- | 784 | // skip end or noop |
|
- | 785 | if(( option->type == IPOPT_END ) || ( option->type == IPOPT_NOOP )){ |
|
- | 786 | ++ next; |
|
- | 787 | }else{ |
|
- | 788 | // copy if said so or skip |
|
- | 789 | if( IPOPT_COPIED( option->type )){ |
|
- | 790 | memcpy((( void * ) last ) + length, (( void * ) first ) + next, option->length ); |
|
- | 791 | length += option->length; |
|
- | 792 | } |
|
- | 793 | // next option |
|
- | 794 | next += option->length; |
|
- | 795 | } |
|
- | 796 | } |
|
- | 797 | // align 4 byte boundary |
|
- | 798 | if( length % 4 ){ |
|
- | 799 | bzero((( void * ) last ) + length, 4 - ( length % 4 )); |
|
- | 800 | last->ihl = length / 4 + 1; |
|
- | 801 | }else{ |
|
- | 802 | last->ihl = length / 4; |
|
- | 803 | } |
|
- | 804 | // trim the unused space |
|
- | 805 | if( packet_trim( packet, 0, IP_HEADER_LENGTH( first ) - IP_HEADER_LENGTH( last )) != EOK ) return NULL; |
|
- | 806 | return last; |
|
- | 807 | } |
|
- | 808 | ||
- | 809 | int ip_received_msg( device_id_t device_id, packet_t packet ){ |
|
- | 810 | packet_t next; |
|
- | 811 | ||
- | 812 | do{ |
|
- | 813 | next = pq_detach( packet ); |
|
- | 814 | if( ip_process_packet( device_id, packet ) != EOK ){ |
|
- | 815 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
|
- | 816 | } |
|
- | 817 | packet = next; |
|
- | 818 | }while( packet ); |
|
- | 819 | return EOK; |
|
- | 820 | } |
|
- | 821 | ||
- | 822 | int ip_process_packet( device_id_t device_id, packet_t packet ){ |
|
- | 823 | ERROR_DECLARE; |
|
- | 824 | ||
- | 825 | ip_header_ref header; |
|
- | 826 | in_addr_t dest; |
|
- | 827 | ip_route_ref route; |
|
- | 828 | ||
- | 829 | header = ( ip_header_ref ) packet_get_data( packet ); |
|
- | 830 | if( ! header ) return ENOMEM; |
|
- | 831 | // checksum |
|
- | 832 | if(( header->header_checksum ) && ( IP_HEADER_CHECKSUM( header ))){ |
|
- | 833 | // TODO checksum error ICMP? |
|
- | 834 | return EINVAL; |
|
- | 835 | } |
|
- | 836 | // TODO ttl oxceeded ICMP? |
|
- | 837 | if( !( -- header->ttl )) return EINVAL; |
|
- | 838 | // process ipopt and get destination |
|
- | 839 | dest = ip_get_destination( header ); |
|
- | 840 | ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) & dest.s_addr, IP_ADDR )); |
|
- | 841 | route = ip_find_route( dest ); |
|
- | 842 | // TODO unreachable ICMP? |
|
- | 843 | if( ! route ) return ENOENT; |
|
- | 844 | if( route->address.s_addr == dest.s_addr ){ |
|
- | 845 | // local delivery |
|
- | 846 | return ip_deliver_local( device_id, packet, header ); |
|
- | 847 | }else{ |
|
- | 848 | return ip_send_route( packet, route->netif, route, NULL, dest ); |
|
- | 849 | } |
|
- | 850 | } |
|
- | 851 | ||
- | 852 | int ip_deliver_local( device_id_t device_id, packet_t packet, ip_header_ref header ){ |
|
- | 853 | ERROR_DECLARE; |
|
- | 854 | ||
- | 855 | ip_proto_ref proto; |
|
- | 856 | ||
- | 857 | if(( header->flags & IPFLAG_MORE_FRAGMENTS ) || header->fragment_offset ){ |
|
- | 858 | // TODO fragmented |
|
- | 859 | return ENOTSUP; |
|
- | 860 | }else{ |
|
- | 861 | proto = ip_protos_find( & ip_globals.protos, header->protocol ); |
|
- | 862 | if( ! proto ) return ENOENT; |
|
- | 863 | ERROR_PROPAGATE( packet_set_addr( packet, ( uint8_t * ) & header->source_address, ( uint8_t * ) & header->destination_address, IP_ADDR )); |
|
- | 864 | if( proto->tl_received_msg ){ |
|
- | 865 | return proto->tl_received_msg( device_id, packet, SERVICE_IP ); |
|
- | 866 | }else{ |
|
- | 867 | return tl_received_msg( proto->phone, device_id, packet, proto->service ); |
|
- | 868 | } |
|
- | 869 | } |
|
- | 870 | } |
|
- | 871 | ||
- | 872 | in_addr_t ip_get_destination( ip_header_ref header ){ |
|
- | 873 | in_addr_t destination; |
|
- | 874 | ||
- | 875 | // TODO search set ipopt route? |
|
- | 876 | destination.s_addr = header->destination_address; //ntohl( header->destination_address ); |
|
- | 877 | return destination; |
|
- | 878 | } |
|
- | 879 | ||
283 | /** @} |
880 | /** @} |
284 | */ |
881 | */ |