Rev 4728 | Rev 4735 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4728 | Rev 4731 | ||
---|---|---|---|
1 | /* |
1 | /* |
2 | * Copyright (c) 2009 Lukas Mejdrech |
2 | * Copyright (c) 2009 Lukas Mejdrech |
3 | * All rights reserved. |
3 | * All rights reserved. |
4 | * |
4 | * |
5 | * Redistribution and use in source and binary forms, with or without |
5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions |
6 | * modification, are permitted provided that the following conditions |
7 | * are met: |
7 | * are met: |
8 | * |
8 | * |
9 | * - Redistributions of source code must retain the above copyright |
9 | * - Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. |
10 | * notice, this list of conditions and the following disclaimer. |
11 | * - Redistributions in binary form must reproduce the above copyright |
11 | * - Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the |
12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. |
13 | * documentation and/or other materials provided with the distribution. |
14 | * - The name of the author may not be used to endorse or promote products |
14 | * - The name of the author may not be used to endorse or promote products |
15 | * derived from this software without specific prior written permission. |
15 | * derived from this software without specific prior written permission. |
16 | * |
16 | * |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | */ |
27 | */ |
28 | 28 | ||
29 | /** @addtogroup ip |
29 | /** @addtogroup ip |
30 | * @{ |
30 | * @{ |
31 | */ |
31 | */ |
32 | 32 | ||
33 | /** @file |
33 | /** @file |
34 | * IP module implementation. |
34 | * IP module implementation. |
35 | * @see arp.h |
35 | * @see arp.h |
36 | * \todo |
36 | * \todo |
37 | */ |
37 | */ |
38 | 38 | ||
39 | #include <async.h> |
39 | #include <async.h> |
40 | #include <errno.h> |
40 | #include <errno.h> |
41 | #include <fibril_sync.h> |
41 | #include <fibril_sync.h> |
42 | #include <stdio.h> |
42 | #include <stdio.h> |
43 | #include <string.h> |
43 | #include <string.h> |
44 | 44 | ||
45 | #include <ipc/ipc.h> |
45 | #include <ipc/ipc.h> |
46 | #include <ipc/services.h> |
46 | #include <ipc/services.h> |
47 | 47 | ||
48 | #include <sys/types.h> |
48 | #include <sys/types.h> |
49 | 49 | ||
50 | #include "../../err.h" |
50 | #include "../../err.h" |
51 | #include "../../messages.h" |
51 | #include "../../messages.h" |
52 | #include "../../modules.h" |
52 | #include "../../modules.h" |
53 | 53 | ||
54 | #include "../../include/arp_interface.h" |
54 | #include "../../include/arp_interface.h" |
55 | #include "../../include/byteorder.h" |
55 | #include "../../include/byteorder.h" |
56 | #include "../../include/crc.h" |
56 | #include "../../include/crc.h" |
57 | #include "../../include/device.h" |
57 | #include "../../include/device.h" |
58 | #include "../../include/icmp_client.h" |
58 | #include "../../include/icmp_client.h" |
59 | #include "../../include/icmp_codes.h" |
59 | #include "../../include/icmp_codes.h" |
60 | #include "../../include/icmp_interface.h" |
60 | #include "../../include/icmp_interface.h" |
61 | #include "../../include/il_interface.h" |
61 | #include "../../include/il_interface.h" |
62 | #include "../../include/in.h" |
62 | #include "../../include/in.h" |
63 | #include "../../include/in6.h" |
63 | #include "../../include/in6.h" |
64 | #include "../../include/inet.h" |
64 | #include "../../include/inet.h" |
65 | #include "../../include/ip_client.h" |
65 | #include "../../include/ip_client.h" |
66 | #include "../../include/ip_interface.h" |
66 | #include "../../include/ip_interface.h" |
67 | #include "../../include/net_interface.h" |
67 | #include "../../include/net_interface.h" |
68 | #include "../../include/nil_interface.h" |
68 | #include "../../include/nil_interface.h" |
69 | #include "../../include/tl_interface.h" |
69 | #include "../../include/tl_interface.h" |
70 | #include "../../include/socket_codes.h" |
70 | #include "../../include/socket_codes.h" |
71 | #include "../../include/socket_errno.h" |
71 | #include "../../include/socket_errno.h" |
72 | #include "../../structures/measured_strings.h" |
72 | #include "../../structures/measured_strings.h" |
73 | #include "../../structures/module_map.h" |
73 | #include "../../structures/module_map.h" |
74 | #include "../../structures/packet/packet_client.h" |
74 | #include "../../structures/packet/packet_client.h" |
75 | 75 | ||
76 | #include "../../nil/nil_messages.h" |
76 | #include "../../nil/nil_messages.h" |
77 | 77 | ||
78 | #include "../il_messages.h" |
78 | #include "../il_messages.h" |
79 | 79 | ||
80 | #include "ip.h" |
80 | #include "ip.h" |
81 | #include "ip_header.h" |
81 | #include "ip_header.h" |
82 | #include "ip_messages.h" |
82 | #include "ip_messages.h" |
83 | #include "ip_module.h" |
83 | #include "ip_module.h" |
84 | 84 | ||
85 | /** IP version 4. |
85 | /** IP version 4. |
86 | */ |
86 | */ |
87 | #define IPV4 4 |
87 | #define IPV4 4 |
88 | 88 | ||
89 | /** Default network interface IP version. |
89 | /** Default network interface IP version. |
90 | */ |
90 | */ |
91 | #define NET_DEFAULT_IPV IPV4 |
91 | #define NET_DEFAULT_IPV IPV4 |
92 | 92 | ||
93 | /** Default network interface IP routing. |
93 | /** Default network interface IP routing. |
94 | */ |
94 | */ |
95 | #define NET_DEFAULT_IP_ROUTING false |
95 | #define NET_DEFAULT_IP_ROUTING false |
96 | 96 | ||
97 | /** Minimum IP packet content. |
97 | /** Minimum IP packet content. |
98 | */ |
98 | */ |
99 | #define IP_MIN_CONTENT 576 |
99 | #define IP_MIN_CONTENT 576 |
100 | 100 | ||
101 | /** ARP module name. |
101 | /** ARP module name. |
102 | */ |
102 | */ |
103 | #define ARP_NAME "arp" |
103 | #define ARP_NAME "arp" |
104 | 104 | ||
105 | /** ARP module filename. |
105 | /** ARP module filename. |
106 | */ |
106 | */ |
107 | #define ARP_FILENAME "/srv/arp" |
107 | #define ARP_FILENAME "/srv/arp" |
108 | 108 | ||
109 | /** IP packet address length. |
109 | /** IP packet address length. |
110 | */ |
110 | */ |
111 | #define IP_ADDR sizeof( struct sockaddr_in6 ) |
111 | #define IP_ADDR sizeof( struct sockaddr_in6 ) |
112 | 112 | ||
113 | /** IP packet prefix length. |
113 | /** IP packet prefix length. |
114 | */ |
114 | */ |
115 | #define IP_PREFIX sizeof( ip_header_t ) |
115 | #define IP_PREFIX sizeof( ip_header_t ) |
116 | 116 | ||
117 | /** IP packet suffix length. |
117 | /** IP packet suffix length. |
118 | */ |
118 | */ |
119 | #define IP_SUFFIX 0 |
119 | #define IP_SUFFIX 0 |
120 | 120 | ||
121 | /** IP packet maximum content length. |
121 | /** IP packet maximum content length. |
122 | */ |
122 | */ |
123 | #define IP_MAX_CONTENT 65535 |
123 | #define IP_MAX_CONTENT 65535 |
124 | 124 | ||
125 | /** The IP localhost address. |
125 | /** The IP localhost address. |
126 | */ |
126 | */ |
127 | #define IPV4_LOCALHOST_ADDRESS htonl(( 127 << 24 ) + 1 ) |
127 | #define IPV4_LOCALHOST_ADDRESS htonl(( 127 << 24 ) + 1 ) |
128 | 128 | ||
129 | /** IP global data. |
129 | /** IP global data. |
130 | */ |
130 | */ |
131 | ip_globals_t ip_globals; |
131 | ip_globals_t ip_globals; |
132 | 132 | ||
133 | DEVICE_MAP_IMPLEMENT( ip_netifs, ip_netif_t ) |
133 | DEVICE_MAP_IMPLEMENT( ip_netifs, ip_netif_t ) |
134 | 134 | ||
135 | INT_MAP_IMPLEMENT( ip_protos, ip_proto_t ) |
135 | INT_MAP_IMPLEMENT( ip_protos, ip_proto_t ) |
136 | 136 | ||
137 | GENERIC_FIELD_IMPLEMENT( ip_routes, ip_route_t ) |
137 | GENERIC_FIELD_IMPLEMENT( ip_routes, ip_route_t ) |
138 | 138 | ||
139 | /** Updates the device content length according to the new MTU value. |
139 | /** Updates the device content length according to the new MTU value. |
140 | * @param device_id The device identifier. Input parameter. |
140 | * @param device_id The device identifier. Input parameter. |
141 | * @param mtu The new mtu value. Input parameter. |
141 | * @param mtu The new mtu value. Input parameter. |
142 | * @returns EOK on success. |
142 | * @returns EOK on success. |
143 | * @returns ENOENT if device is not found. |
143 | * @returns ENOENT if device is not found. |
144 | */ |
144 | */ |
145 | int ip_mtu_changed_message( device_id_t device_id, size_t mtu ); |
145 | int ip_mtu_changed_message( device_id_t device_id, size_t mtu ); |
146 | 146 | ||
147 | /** Updates the device state. |
147 | /** Updates the device state. |
148 | * @param device_id The device identifier. Input parameter. |
148 | * @param device_id The device identifier. Input parameter. |
149 | * @param state The new state value. Input parameter. |
149 | * @param state The new state value. Input parameter. |
150 | * @returns EOK on success. |
150 | * @returns EOK on success. |
151 | * @returns ENOENT if device is not found. |
151 | * @returns ENOENT if device is not found. |
152 | */ |
152 | */ |
153 | int ip_device_state_message( device_id_t device_id, device_state_t state ); |
153 | int ip_device_state_message( device_id_t device_id, device_state_t state ); |
154 | 154 | ||
155 | int ip_register( int protocol, services_t service, int phone, tl_received_msg_t tl_received_msg ); |
155 | int ip_register( int protocol, services_t service, int phone, tl_received_msg_t tl_received_msg ); |
156 | 156 | ||
157 | /** Initializes a new network interface specific data. |
157 | /** Initializes a new network interface specific data. |
158 | * Connects to the network interface layer module, reads the netif configuration, starts an ARP module if needed and sets the netif routing table. |
158 | * Connects to the network interface layer module, reads the netif configuration, starts an ARP module if needed and sets the netif routing table. |
159 | * The device identifier and the nil service has to be set. |
159 | * The device identifier and the nil service has to be set. |
160 | * @param ip_netif Network interface specific data. Input/output parameter. |
160 | * @param ip_netif Network interface specific data. Input/output parameter. |
161 | * @returns EOK on success. |
161 | * @returns EOK on success. |
162 | * @returns ENOTSUP if DHCP is configured. |
162 | * @returns ENOTSUP if DHCP is configured. |
163 | * @returns ENOTSUP if IPv6 is configured. |
163 | * @returns ENOTSUP if IPv6 is configured. |
164 | * @returns EINVAL if any of the addresses is invalid. |
164 | * @returns EINVAL if any of the addresses is invalid. |
165 | * @returns EINVAL if the used ARP module is not known. |
165 | * @returns EINVAL if the used ARP module is not known. |
166 | * @returns ENOMEM if there is not enough memory left. |
166 | * @returns ENOMEM if there is not enough memory left. |
167 | * @returns Other error codes as defined for the net_get_device_conf_req() function. |
167 | * @returns Other error codes as defined for the net_get_device_conf_req() function. |
168 | * @returns Other error codes as defined for the bind_service() function. |
168 | * @returns Other error codes as defined for the bind_service() function. |
169 | * @returns Other error codes as defined for the specific arp_device_req() function. |
169 | * @returns Other error codes as defined for the specific arp_device_req() function. |
170 | * @returns Other error codes as defined for the nil_packet_size_req() function. |
170 | * @returns Other error codes as defined for the nil_packet_size_req() function. |
171 | */ |
171 | */ |
172 | int ip_netif_initialize( ip_netif_ref ip_netif ); |
172 | int ip_netif_initialize( ip_netif_ref ip_netif ); |
173 | 173 | ||
174 | 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 ); |
174 | 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 ); |
175 | int ip_prepare_packet( in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination ); |
175 | int ip_prepare_packet( in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination ); |
176 | 176 | ||
177 | packet_t ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, socklen_t addr_len, services_t error ); |
177 | packet_t ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, socklen_t addr_len, services_t error ); |
178 | int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, socklen_t addr_len ); |
178 | int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, socklen_t addr_len ); |
179 | 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 ); |
179 | 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 ); |
180 | ip_header_ref ip_create_middle_header( packet_t packet, ip_header_ref last ); |
180 | ip_header_ref ip_create_middle_header( packet_t packet, ip_header_ref last ); |
181 | void ip_create_last_header( ip_header_ref last, ip_header_ref first ); |
181 | void ip_create_last_header( ip_header_ref last, ip_header_ref first ); |
182 | 182 | ||
183 | in_addr_t * ip_netif_address( ip_netif_ref netif ); |
183 | in_addr_t * ip_netif_address( ip_netif_ref netif ); |
184 | ip_route_ref ip_find_route( in_addr_t destination ); |
184 | ip_route_ref ip_find_route( in_addr_t destination ); |
185 | ip_route_ref ip_netif_find_route( ip_netif_ref netif, in_addr_t destination ); |
185 | ip_route_ref ip_netif_find_route( ip_netif_ref netif, in_addr_t destination ); |
186 | 186 | ||
187 | /** Processes the received IP packet. |
187 | /** Processes the received IP packet. |
188 | * @param device_id The source device identifier. Input parameter. |
188 | * @param device_id The source device identifier. Input parameter. |
189 | * @param packet The received packet. Input/output parameter. |
189 | * @param packet The received packet. Input/output parameter. |
190 | * @returns EOK on success and the packet is no longer needed. |
190 | * @returns EOK on success and the packet is no longer needed. |
191 | * @returns EINVAL if the packet is too small to carry the IP packet. |
191 | * @returns EINVAL if the packet is too small to carry the IP packet. |
192 | * @returns EINVAL if the received address lengths differs from the registered values. |
192 | * @returns EINVAL if the received address lengths differs from the registered values. |
193 | * @returns ENOENT if the device is not found in the cache. |
193 | * @returns ENOENT if the device is not found in the cache. |
194 | * @returns ENOENT if the protocol for the device is not found in the cache. |
194 | * @returns ENOENT if the protocol for the device is not found in the cache. |
195 | * @returns ENOMEM if there is not enough memory left. |
195 | * @returns ENOMEM if there is not enough memory left. |
196 | */ |
196 | */ |
197 | int ip_receive_message( device_id_t device_id, packet_t packet ); |
197 | int ip_receive_message( device_id_t device_id, packet_t packet ); |
198 | 198 | ||
199 | int ip_process_packet( device_id_t device_id, packet_t packet ); |
199 | int ip_process_packet( device_id_t device_id, packet_t packet ); |
200 | in_addr_t ip_get_destination( ip_header_ref header ); |
200 | in_addr_t ip_get_destination( ip_header_ref header ); |
201 | int ip_deliver_local( device_id_t device_id, packet_t packet, ip_header_ref header, services_t error ); |
201 | int ip_deliver_local( device_id_t device_id, packet_t packet, ip_header_ref header, services_t error ); |
202 | 202 | ||
203 | int ip_prepare_icmp_and_get_phone( services_t error, packet_t packet, ip_header_ref header ); |
203 | int ip_prepare_icmp_and_get_phone( services_t error, packet_t packet, ip_header_ref header ); |
204 | int ip_get_icmp_phone( void ); |
204 | int ip_get_icmp_phone( void ); |
205 | int ip_prepare_icmp( packet_t packet, ip_header_ref header ); |
205 | int ip_prepare_icmp( packet_t packet, ip_header_ref header ); |
206 | 206 | ||
207 | int ip_release_and_return( packet_t packet, int result ); |
207 | int ip_release_and_return( packet_t packet, int result ); |
208 | 208 | ||
209 | int ip_initialize( async_client_conn_t client_connection ){ |
209 | int ip_initialize( async_client_conn_t client_connection ){ |
210 | ERROR_DECLARE; |
210 | ERROR_DECLARE; |
211 | 211 | ||
212 | fibril_rwlock_initialize( & ip_globals.lock ); |
212 | fibril_rwlock_initialize( & ip_globals.lock ); |
213 | fibril_rwlock_write_lock( & ip_globals.lock ); |
213 | fibril_rwlock_write_lock( & ip_globals.lock ); |
214 | fibril_rwlock_initialize( & ip_globals.protos_lock ); |
214 | fibril_rwlock_initialize( & ip_globals.protos_lock ); |
215 | fibril_rwlock_initialize( & ip_globals.netifs_lock ); |
215 | fibril_rwlock_initialize( & ip_globals.netifs_lock ); |
216 | ip_globals.packet_counter = 0; |
216 | ip_globals.packet_counter = 0; |
217 | ip_globals.gateway.address.s_addr = 0; |
217 | ip_globals.gateway.address.s_addr = 0; |
218 | ip_globals.gateway.netmask.s_addr = 0; |
218 | ip_globals.gateway.netmask.s_addr = 0; |
219 | ip_globals.gateway.gateway.s_addr = 0; |
219 | ip_globals.gateway.gateway.s_addr = 0; |
220 | ip_globals.gateway.netif = NULL; |
220 | ip_globals.gateway.netif = NULL; |
221 | ERROR_PROPAGATE( ip_netifs_initialize( & ip_globals.netifs )); |
221 | ERROR_PROPAGATE( ip_netifs_initialize( & ip_globals.netifs )); |
222 | ERROR_PROPAGATE( ip_protos_initialize( & ip_globals.protos )); |
222 | ERROR_PROPAGATE( ip_protos_initialize( & ip_globals.protos )); |
223 | ip_globals.client_connection = client_connection; |
223 | ip_globals.client_connection = client_connection; |
224 | ERROR_PROPAGATE( modules_initialize( & ip_globals.modules )); |
224 | ERROR_PROPAGATE( modules_initialize( & ip_globals.modules )); |
225 | ERROR_PROPAGATE( add_module( NULL, & ip_globals.modules, ARP_NAME, ARP_FILENAME, SERVICE_ARP, arp_task_get_id(), arp_connect_module )); |
225 | ERROR_PROPAGATE( add_module( NULL, & ip_globals.modules, ARP_NAME, ARP_FILENAME, SERVICE_ARP, arp_task_get_id(), arp_connect_module )); |
226 | fibril_rwlock_write_unlock( & ip_globals.lock ); |
226 | fibril_rwlock_write_unlock( & ip_globals.lock ); |
227 | return EOK; |
227 | return EOK; |
228 | } |
228 | } |
229 | 229 | ||
230 | int ip_device_req( int il_phone, device_id_t device_id, services_t netif ){ |
230 | int ip_device_req( int il_phone, device_id_t device_id, services_t netif ){ |
231 | ERROR_DECLARE; |
231 | ERROR_DECLARE; |
232 | 232 | ||
233 | ip_netif_ref ip_netif; |
233 | ip_netif_ref ip_netif; |
234 | ip_route_ref route; |
234 | ip_route_ref route; |
235 | int index; |
235 | int index; |
236 | char * data; |
236 | char * data; |
237 | 237 | ||
238 | ip_netif = ( ip_netif_ref ) malloc( sizeof( ip_netif_t )); |
238 | ip_netif = ( ip_netif_ref ) malloc( sizeof( ip_netif_t )); |
239 | if( ! ip_netif ) return ENOMEM; |
239 | if( ! ip_netif ) return ENOMEM; |
240 | if( ERROR_OCCURRED( ip_routes_initialize( & ip_netif->routes ))){ |
240 | if( ERROR_OCCURRED( ip_routes_initialize( & ip_netif->routes ))){ |
241 | free( ip_netif ); |
241 | free( ip_netif ); |
242 | return ERROR_CODE; |
242 | return ERROR_CODE; |
243 | } |
243 | } |
244 | ip_netif->device_id = device_id; |
244 | ip_netif->device_id = device_id; |
245 | ip_netif->service = netif; |
245 | ip_netif->service = netif; |
246 | ip_netif->state = NETIF_STOPPED; |
246 | ip_netif->state = NETIF_STOPPED; |
247 | fibril_rwlock_write_lock( & ip_globals.netifs_lock ); |
247 | fibril_rwlock_write_lock( & ip_globals.netifs_lock ); |
248 | if( ERROR_OCCURRED( ip_netif_initialize( ip_netif ))){ |
248 | if( ERROR_OCCURRED( ip_netif_initialize( ip_netif ))){ |
249 | fibril_rwlock_write_unlock( & ip_globals.netifs_lock ); |
249 | fibril_rwlock_write_unlock( & ip_globals.netifs_lock ); |
250 | ip_routes_destroy( & ip_netif->routes ); |
250 | ip_routes_destroy( & ip_netif->routes ); |
251 | free( ip_netif ); |
251 | free( ip_netif ); |
252 | return ERROR_CODE; |
252 | return ERROR_CODE; |
253 | } |
253 | } |
254 | if( ip_netif->arp ) ++ ip_netif->arp->usage; |
254 | if( ip_netif->arp ) ++ ip_netif->arp->usage; |
255 | // print the settings |
255 | // print the settings |
256 | 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 ); |
256 | 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 ); |
257 | printf( "\tconfiguration\t= %s\n", ip_netif->dhcp ? "dhcp" : "static" ); |
257 | printf( "\tconfiguration\t= %s\n", ip_netif->dhcp ? "dhcp" : "static" ); |
258 | // TODO ipv6 addresses |
258 | // TODO ipv6 addresses |
259 | data = ( char * ) malloc( INET_ADDRSTRLEN ); |
259 | data = ( char * ) malloc( INET_ADDRSTRLEN ); |
260 | if( data ){ |
260 | if( data ){ |
261 | for( index = 0; index < ip_routes_count( & ip_netif->routes ); ++ index ){ |
261 | for( index = 0; index < ip_routes_count( & ip_netif->routes ); ++ index ){ |
262 | route = ip_routes_get_index( & ip_netif->routes, index ); |
262 | route = ip_routes_get_index( & ip_netif->routes, index ); |
263 | if( route ){ |
263 | if( route ){ |
264 | printf( "\tRouting %d:\n", index ); |
264 | printf( "\tRouting %d:\n", index ); |
265 | inet_ntop( AF_INET, ( uint8_t * ) & route->address.s_addr, data, INET_ADDRSTRLEN ); |
265 | inet_ntop( AF_INET, ( uint8_t * ) & route->address.s_addr, data, INET_ADDRSTRLEN ); |
266 | printf( "\t\taddress\t= %s\n", data ); |
266 | printf( "\t\taddress\t= %s\n", data ); |
267 | inet_ntop( AF_INET, ( uint8_t * ) & route->netmask.s_addr, data, INET_ADDRSTRLEN ); |
267 | inet_ntop( AF_INET, ( uint8_t * ) & route->netmask.s_addr, data, INET_ADDRSTRLEN ); |
268 | printf( "\t\tnetmask\t= %s\n", data ); |
268 | printf( "\t\tnetmask\t= %s\n", data ); |
269 | inet_ntop( AF_INET, ( uint8_t * ) & route->gateway.s_addr, data, INET_ADDRSTRLEN ); |
269 | inet_ntop( AF_INET, ( uint8_t * ) & route->gateway.s_addr, data, INET_ADDRSTRLEN ); |
270 | printf( "\t\tgateway\t= %s\n", data ); |
270 | printf( "\t\tgateway\t= %s\n", data ); |
271 | } |
271 | } |
272 | } |
272 | } |
273 | inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->broadcast.s_addr, data, INET_ADDRSTRLEN ); |
273 | inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->broadcast.s_addr, data, INET_ADDRSTRLEN ); |
274 | printf( "\tbroadcast\t= %s\n", data ); |
274 | printf( "\tbroadcast\t= %s\n", data ); |
275 | inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->dns1, data, INET_ADDRSTRLEN ); |
275 | inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->dns1, data, INET_ADDRSTRLEN ); |
276 | printf( "\tdns1\t= %s\n", data ); |
276 | printf( "\tdns1\t= %s\n", data ); |
277 | inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->dns2, data, INET_ADDRSTRLEN ); |
277 | inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->dns2, data, INET_ADDRSTRLEN ); |
278 | printf( "\tdns2\t= %s\n", data ); |
278 | printf( "\tdns2\t= %s\n", data ); |
279 | free( data ); |
279 | free( data ); |
280 | } |
280 | } |
281 | fibril_rwlock_write_unlock( & ip_globals.netifs_lock ); |
281 | fibril_rwlock_write_unlock( & ip_globals.netifs_lock ); |
282 | return EOK; |
282 | return EOK; |
283 | } |
283 | } |
284 | 284 | ||
285 | int ip_netif_initialize( ip_netif_ref ip_netif ){ |
285 | int ip_netif_initialize( ip_netif_ref ip_netif ){ |
286 | ERROR_DECLARE; |
286 | ERROR_DECLARE; |
287 | 287 | ||
288 | measured_string_t names[] = {{ "IPV", 3 }, { "IP_CONFIG", 9 }, { "IP_ADDR", 7 }, { "NETMASK", 7 }, { "GATEWAY", 7 }, { "BROADCAST", 9 }, { "DNS1", 4 }, { "DNS2", 4 }, { "ARP", 3 }, { "IP_ROUTING", 10 }}; |
288 | measured_string_t names[] = {{ "IPV", 3 }, { "IP_CONFIG", 9 }, { "IP_ADDR", 7 }, { "NETMASK", 7 }, { "GATEWAY", 7 }, { "BROADCAST", 9 }, { "DNS1", 4 }, { "DNS2", 4 }, { "ARP", 3 }, { "IP_ROUTING", 10 }}; |
289 | measured_string_ref configuration; |
289 | measured_string_ref configuration; |
290 | size_t count = sizeof( names ) / sizeof( measured_string_t ); |
290 | size_t count = sizeof( names ) / sizeof( measured_string_t ); |
291 | char * data; |
291 | char * data; |
292 | measured_string_t address; |
292 | measured_string_t address; |
293 | int index; |
293 | int index; |
294 | ip_route_ref route; |
294 | ip_route_ref route; |
295 | in_addr_t gateway; |
295 | in_addr_t gateway; |
296 | 296 | ||
297 | ip_netif->arp = NULL; |
297 | ip_netif->arp = NULL; |
298 | route = NULL; |
298 | route = NULL; |
299 | ip_netif->ipv = NET_DEFAULT_IPV; |
299 | ip_netif->ipv = NET_DEFAULT_IPV; |
300 | ip_netif->dhcp = false; |
300 | ip_netif->dhcp = false; |
301 | ip_netif->routing = NET_DEFAULT_IP_ROUTING; |
301 | ip_netif->routing = NET_DEFAULT_IP_ROUTING; |
302 | configuration = & names[ 0 ]; |
302 | configuration = & names[ 0 ]; |
303 | // get configuration |
303 | // get configuration |
304 | ERROR_PROPAGATE( net_get_device_conf_req( ip_globals.net_phone, ip_netif->device_id, & configuration, count, & data )); |
304 | ERROR_PROPAGATE( net_get_device_conf_req( ip_globals.net_phone, ip_netif->device_id, & configuration, count, & data )); |
305 | if( configuration ){ |
305 | if( configuration ){ |
306 | if( configuration[ 0 ].value ){ |
306 | if( configuration[ 0 ].value ){ |
307 | ip_netif->ipv = strtol( configuration[ 0 ].value, NULL, 0 ); |
307 | ip_netif->ipv = strtol( configuration[ 0 ].value, NULL, 0 ); |
308 | } |
308 | } |
309 | ip_netif->dhcp = ! str_lcmp( configuration[ 1 ].value, "dhcp", configuration[ 1 ].length ); |
309 | ip_netif->dhcp = ! str_lcmp( configuration[ 1 ].value, "dhcp", configuration[ 1 ].length ); |
310 | if( ip_netif->dhcp ){ |
310 | if( ip_netif->dhcp ){ |
311 | // TODO dhcp |
311 | // TODO dhcp |
312 | net_free_settings( configuration, data ); |
312 | net_free_settings( configuration, data ); |
313 | return ENOTSUP; |
313 | return ENOTSUP; |
314 | }else if( ip_netif->ipv == IPV4 ){ |
314 | }else if( ip_netif->ipv == IPV4 ){ |
315 | route = ( ip_route_ref ) malloc( sizeof( ip_route_t )); |
315 | route = ( ip_route_ref ) malloc( sizeof( ip_route_t )); |
316 | if( ! route ){ |
316 | if( ! route ){ |
317 | net_free_settings( configuration, data ); |
317 | net_free_settings( configuration, data ); |
318 | return ENOMEM; |
318 | return ENOMEM; |
319 | } |
319 | } |
320 | route->address.s_addr = 0; |
320 | route->address.s_addr = 0; |
321 | route->netmask.s_addr = 0; |
321 | route->netmask.s_addr = 0; |
322 | route->gateway.s_addr = 0; |
322 | route->gateway.s_addr = 0; |
323 | route->netif = ip_netif; |
323 | route->netif = ip_netif; |
324 | index = ip_routes_add( & ip_netif->routes, route ); |
324 | index = ip_routes_add( & ip_netif->routes, route ); |
325 | if( index < 0 ){ |
325 | if( index < 0 ){ |
326 | net_free_settings( configuration, data ); |
326 | net_free_settings( configuration, data ); |
327 | free( route ); |
327 | free( route ); |
328 | return index; |
328 | return index; |
329 | } |
329 | } |
330 | if( ERROR_OCCURRED( inet_pton( AF_INET, configuration[ 2 ].value, ( uint8_t * ) & route->address.s_addr )) |
330 | if( ERROR_OCCURRED( inet_pton( AF_INET, configuration[ 2 ].value, ( uint8_t * ) & route->address.s_addr )) |
331 | || ERROR_OCCURRED( inet_pton( AF_INET, configuration[ 3 ].value, ( uint8_t * ) & route->netmask.s_addr )) |
331 | || ERROR_OCCURRED( inet_pton( AF_INET, configuration[ 3 ].value, ( uint8_t * ) & route->netmask.s_addr )) |
332 | || ( inet_pton( AF_INET, configuration[ 4 ].value, ( uint8_t * ) & gateway.s_addr ) == EINVAL ) |
332 | || ( inet_pton( AF_INET, configuration[ 4 ].value, ( uint8_t * ) & gateway.s_addr ) == EINVAL ) |
333 | || ( inet_pton( AF_INET, configuration[ 5 ].value, ( uint8_t * ) & ip_netif->broadcast.s_addr ) == EINVAL ) |
333 | || ( inet_pton( AF_INET, configuration[ 5 ].value, ( uint8_t * ) & ip_netif->broadcast.s_addr ) == EINVAL ) |
334 | || ( inet_pton( AF_INET, configuration[ 6 ].value, ( uint8_t * ) & ip_netif->dns1 ) == EINVAL ) |
334 | || ( inet_pton( AF_INET, configuration[ 6 ].value, ( uint8_t * ) & ip_netif->dns1 ) == EINVAL ) |
335 | || ( inet_pton( AF_INET, configuration[ 7 ].value, ( uint8_t * ) & ip_netif->dns2 ) == EINVAL )){ |
335 | || ( inet_pton( AF_INET, configuration[ 7 ].value, ( uint8_t * ) & ip_netif->dns2 ) == EINVAL )){ |
336 | net_free_settings( configuration, data ); |
336 | net_free_settings( configuration, data ); |
337 | return EINVAL; |
337 | return EINVAL; |
338 | } |
338 | } |
339 | }else{ |
339 | }else{ |
340 | // TODO ipv6 in separate module |
340 | // TODO ipv6 in separate module |
341 | net_free_settings( configuration, data ); |
341 | net_free_settings( configuration, data ); |
342 | return ENOTSUP; |
342 | return ENOTSUP; |
343 | } |
343 | } |
344 | if( configuration[ 8 ].value ){ |
344 | if( configuration[ 8 ].value ){ |
345 | ip_netif->arp = get_running_module( & ip_globals.modules, configuration[ 8 ].value ); |
345 | ip_netif->arp = get_running_module( & ip_globals.modules, configuration[ 8 ].value ); |
346 | if( ! ip_netif->arp ){ |
346 | if( ! ip_netif->arp ){ |
347 | printf( "Failed to start the arp %s\n", configuration[ 8 ].value ); |
347 | printf( "Failed to start the arp %s\n", configuration[ 8 ].value ); |
348 | net_free_settings( configuration, data ); |
348 | net_free_settings( configuration, data ); |
349 | return EINVAL; |
349 | return EINVAL; |
350 | } |
350 | } |
351 | } |
351 | } |
352 | if( configuration[ 9 ].value ){ |
352 | if( configuration[ 9 ].value ){ |
353 | ip_netif->routing = ( configuration[ 9 ].value[ 0 ] == 'y' ); |
353 | ip_netif->routing = ( configuration[ 9 ].value[ 0 ] == 'y' ); |
354 | } |
354 | } |
355 | net_free_settings( configuration, data ); |
355 | net_free_settings( configuration, data ); |
356 | } |
356 | } |
357 | // binds the netif service which also initializes the device |
357 | // binds the netif service which also initializes the device |
358 | ip_netif->phone = bind_service( ip_netif->service, ( ipcarg_t ) ip_netif->device_id, SERVICE_IP, 0, ip_globals.client_connection ); |
358 | ip_netif->phone = bind_service( ip_netif->service, ( ipcarg_t ) ip_netif->device_id, SERVICE_IP, 0, ip_globals.client_connection ); |
359 | if( ip_netif->phone < 0 ){ |
359 | if( ip_netif->phone < 0 ){ |
360 | printf( "Failed to contact the nil service %d\n", ip_netif->service ); |
360 | printf( "Failed to contact the nil service %d\n", ip_netif->service ); |
361 | return ip_netif->phone; |
361 | return ip_netif->phone; |
362 | } |
362 | } |
363 | // has to be after the device netif module initialization |
363 | // has to be after the device netif module initialization |
364 | if( ip_netif->arp ){ |
364 | if( ip_netif->arp ){ |
365 | if( route ){ |
365 | if( route ){ |
366 | address.value = ( char * ) & route->address.s_addr; |
366 | address.value = ( char * ) & route->address.s_addr; |
367 | address.length = CONVERT_SIZE( in_addr_t, char, 1 ); |
367 | address.length = CONVERT_SIZE( in_addr_t, char, 1 ); |
368 | ERROR_PROPAGATE( arp_device_req( ip_netif->arp->phone, ip_netif->device_id, SERVICE_IP, ip_netif->service, & address )); |
368 | ERROR_PROPAGATE( arp_device_req( ip_netif->arp->phone, ip_netif->device_id, SERVICE_IP, ip_netif->service, & address )); |
369 | }else{ |
369 | }else{ |
370 | ip_netif->arp = 0; |
370 | ip_netif->arp = 0; |
371 | } |
371 | } |
372 | } |
372 | } |
373 | // get packet dimensions |
373 | // get packet dimensions |
374 | 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 )); |
374 | 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 )); |
375 | if( ip_netif->content < IP_MIN_CONTENT ){ |
375 | if( ip_netif->content < IP_MIN_CONTENT ){ |
376 | printf( "Maximum transmission unit %d bytes is too small, at least %d bytes are needed\n", ip_netif->content, IP_MIN_CONTENT ); |
376 | printf( "Maximum transmission unit %d bytes is too small, at least %d bytes are needed\n", ip_netif->content, IP_MIN_CONTENT ); |
377 | ip_netif->content = IP_MIN_CONTENT; |
377 | ip_netif->content = IP_MIN_CONTENT; |
378 | } |
378 | } |
379 | index = ip_netifs_add( & ip_globals.netifs, ip_netif->device_id, ip_netif ); |
379 | index = ip_netifs_add( & ip_globals.netifs, ip_netif->device_id, ip_netif ); |
380 | if( index < 0 ) return index; |
380 | if( index < 0 ) return index; |
381 | if( gateway.s_addr ){ |
381 | if( gateway.s_addr ){ |
382 | // the default gateway |
382 | // the default gateway |
383 | ip_globals.gateway.address.s_addr = 0; |
383 | ip_globals.gateway.address.s_addr = 0; |
384 | ip_globals.gateway.netmask.s_addr = 0; |
384 | ip_globals.gateway.netmask.s_addr = 0; |
385 | ip_globals.gateway.gateway.s_addr = gateway.s_addr; |
385 | ip_globals.gateway.gateway.s_addr = gateway.s_addr; |
386 | ip_globals.gateway.netif = ip_netif; |
386 | ip_globals.gateway.netif = ip_netif; |
387 | } |
387 | } |
388 | return EOK; |
388 | return EOK; |
389 | } |
389 | } |
390 | 390 | ||
391 | int ip_mtu_changed_message( device_id_t device_id, size_t mtu ){ |
391 | int ip_mtu_changed_message( device_id_t device_id, size_t mtu ){ |
392 | ip_netif_ref netif; |
392 | ip_netif_ref netif; |
393 | 393 | ||
394 | fibril_rwlock_write_lock( & ip_globals.netifs_lock ); |
394 | fibril_rwlock_write_lock( & ip_globals.netifs_lock ); |
395 | netif = ip_netifs_find( & ip_globals.netifs, device_id ); |
395 | netif = ip_netifs_find( & ip_globals.netifs, device_id ); |
396 | if( ! netif ){ |
396 | if( ! netif ){ |
397 | fibril_rwlock_write_unlock( & ip_globals.netifs_lock ); |
397 | fibril_rwlock_write_unlock( & ip_globals.netifs_lock ); |
398 | return ENOENT; |
398 | return ENOENT; |
399 | } |
399 | } |
400 | netif->content = mtu; |
400 | netif->content = mtu; |
401 | printf( "ip - device %d changed mtu to %d\n\n", device_id, mtu ); |
401 | printf( "ip - device %d changed mtu to %d\n\n", device_id, mtu ); |
402 | fibril_rwlock_write_unlock( & ip_globals.netifs_lock ); |
402 | fibril_rwlock_write_unlock( & ip_globals.netifs_lock ); |
403 | return EOK; |
403 | return EOK; |
404 | } |
404 | } |
405 | 405 | ||
406 | int ip_device_state_message( device_id_t device_id, device_state_t state ){ |
406 | int ip_device_state_message( device_id_t device_id, device_state_t state ){ |
407 | // ERROR_DECLARE; |
- | |
408 | - | ||
409 | /* measured_string_t address; |
- | |
410 | measured_string_ref translation; |
- | |
411 | char * data; |
- | |
412 | */ |
- | |
413 | /* packet_t packet; |
- | |
414 | in_addr_t destination; |
- | |
415 | */ |
- | |
416 | ip_netif_ref netif; |
407 | ip_netif_ref netif; |
417 | 408 | ||
418 | fibril_rwlock_write_lock( & ip_globals.netifs_lock ); |
409 | fibril_rwlock_write_lock( & ip_globals.netifs_lock ); |
- | 410 | // find the device |
|
419 | netif = ip_netifs_find( & ip_globals.netifs, device_id ); |
411 | netif = ip_netifs_find( & ip_globals.netifs, device_id ); |
420 | if( ! netif ){ |
412 | if( ! netif ){ |
421 | fibril_rwlock_write_unlock( & ip_globals.netifs_lock ); |
413 | fibril_rwlock_write_unlock( & ip_globals.netifs_lock ); |
422 | return ENOENT; |
414 | return ENOENT; |
423 | } |
415 | } |
424 | netif->state = state; |
416 | netif->state = state; |
425 | // TODO state |
- | |
426 | printf( "ip - device %d changed state to %d\n\n", device_id, state ); |
417 | printf( "ip - device %d changed state to %d\n\n", device_id, state ); |
427 | fibril_rwlock_write_unlock( & ip_globals.netifs_lock ); |
418 | fibril_rwlock_write_unlock( & ip_globals.netifs_lock ); |
428 | // if( netif->arp ){ |
- | |
429 | /* address.value = ( char * ) & ip_globals.gateway.gateway.s_addr; |
- | |
430 | address.length = CONVERT_SIZE( ip_globals.gateway.gateway.s_addr, char, 1 ); |
- | |
431 | if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ))){ |
- | |
432 | ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data )); |
- | |
433 | } |
- | |
434 | printf( "\tgateway translated to\t= %X:%X:%X:%X:%X:%X\n", data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ] ); |
- | |
435 | free( translation ); |
- | |
436 | free( data ); |
- | |
437 | address.value = ( char * ) & ip_globals.gateway.gateway.s_addr; |
- | |
438 | address.length = CONVERT_SIZE( ip_globals.gateway.gateway.s_addr, char, 1 ); |
- | |
439 | if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data ))){ |
- | |
440 | sleep( 2 ); |
- | |
441 | ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address, & translation, & data )); |
- | |
442 | } |
- | |
443 | printf( "\tgateway translated to\t= %X:%X:%X:%X:%X:%X\n", data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ] ); |
- | |
444 | free( translation ); |
- | |
445 | free( data ); |
- | |
446 | *//* printf( "IP - testing to send packet:\n" ); |
- | |
447 | ERROR_PROPAGATE( inet_pton( AF_INET, "90.182.101.18", ( uint8_t * ) & destination.s_addr )); |
- | |
448 | packet = packet_get_4( ip_globals.net_phone, 30, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix ); |
- | |
449 | if( ! packet ) return ENOMEM; |
- | |
450 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
- | |
451 | packet = packet_get_4( ip_globals.net_phone, 30, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix ); |
- | |
452 | if( ! packet ) return ENOMEM; |
- | |
453 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
- | |
454 | packet = packet_get_4( ip_globals.net_phone, 30, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix ); |
- | |
455 | if( ! packet ) return ENOMEM; |
- | |
456 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
- | |
457 | packet = packet_get_4( ip_globals.net_phone, 1500, netif->addr_len, netif->prefix + sizeof( ip_header_t ), netif->suffix ); |
- | |
458 | if( ! packet ) return ENOMEM; |
- | |
459 | // try this long version |
- | |
460 | // 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 )) |
- | |
461 | if( ERROR_OCCURRED( packet_copy_data( packet, "Hi, this is IP", 14 )) |
- | |
462 | || ERROR_OCCURRED( packet_set_addr( packet, NULL, ( uint8_t * ) & destination.s_addr, 4 )) |
- | |
463 | || ERROR_OCCURRED( ip_client_prepare_packet( packet, 0, 0, 0, 0, 0 ))){ |
- | |
464 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
- | |
465 | } |
- | |
466 | ERROR_CODE = ip_send_msg( 0, 0, packet, SERVICE_IP ); |
- | |
467 | printf( "send returned %d\n", ERROR_CODE ); |
- | |
468 | } |
- | |
469 | */ return EOK; |
419 | return EOK; |
470 | } |
420 | } |
471 | 421 | ||
472 | int ip_connect_module( services_t service ){ |
422 | int ip_connect_module( services_t service ){ |
473 | return EOK; |
423 | return EOK; |
474 | } |
424 | } |
475 | 425 | ||
476 | int ip_bind_service( services_t service, int protocol, services_t me, async_client_conn_t receiver, tl_received_msg_t received_msg ){ |
426 | int ip_bind_service( services_t service, int protocol, services_t me, async_client_conn_t receiver, tl_received_msg_t received_msg ){ |
477 | return ip_register( protocol, me, 0, received_msg ); |
427 | return ip_register( protocol, me, 0, received_msg ); |
478 | } |
428 | } |
479 | 429 | ||
480 | int ip_register( int protocol, services_t service, int phone, tl_received_msg_t received_msg ){ |
430 | int ip_register( int protocol, services_t service, int phone, tl_received_msg_t received_msg ){ |
481 | ip_proto_ref proto; |
431 | ip_proto_ref proto; |
482 | int index; |
432 | int index; |
483 | 433 | ||
484 | if( !( protocol && service && (( phone > 0 ) || ( received_msg )))) return EINVAL; |
434 | if( !( protocol && service && (( phone > 0 ) || ( received_msg )))) return EINVAL; |
485 | proto = ( ip_proto_ref ) malloc( sizeof( ip_protos_t )); |
435 | proto = ( ip_proto_ref ) malloc( sizeof( ip_protos_t )); |
486 | if( ! proto ) return ENOMEM; |
436 | if( ! proto ) return ENOMEM; |
487 | proto->protocol = protocol; |
437 | proto->protocol = protocol; |
488 | proto->service = service; |
438 | proto->service = service; |
489 | proto->phone = phone; |
439 | proto->phone = phone; |
490 | proto->received_msg = received_msg; |
440 | proto->received_msg = received_msg; |
491 | fibril_rwlock_write_lock( & ip_globals.protos_lock ); |
441 | fibril_rwlock_write_lock( & ip_globals.protos_lock ); |
492 | index = ip_protos_add( & ip_globals.protos, proto->protocol, proto ); |
442 | index = ip_protos_add( & ip_globals.protos, proto->protocol, proto ); |
493 | if( index < 0 ){ |
443 | if( index < 0 ){ |
494 | fibril_rwlock_write_unlock( & ip_globals.protos_lock ); |
444 | fibril_rwlock_write_unlock( & ip_globals.protos_lock ); |
495 | free( proto ); |
445 | free( proto ); |
496 | return index; |
446 | return index; |
497 | } |
447 | } |
498 | printf( "New protocol registered:\n\tprotocol\t= %d\n\tphone\t= %d\n", proto->protocol, proto->phone ); |
448 | printf( "New protocol registered:\n\tprotocol\t= %d\n\tphone\t= %d\n", proto->protocol, proto->phone ); |
499 | fibril_rwlock_write_unlock( & ip_globals.protos_lock ); |
449 | fibril_rwlock_write_unlock( & ip_globals.protos_lock ); |
500 | return EOK; |
450 | return EOK; |
501 | } |
451 | } |
502 | 452 | ||
503 | int ip_send_msg( int il_phone, device_id_t device_id, packet_t packet, services_t sender, services_t error ){ |
453 | int ip_send_msg( int il_phone, device_id_t device_id, packet_t packet, services_t sender, services_t error ){ |
504 | ERROR_DECLARE; |
454 | ERROR_DECLARE; |
505 | 455 | ||
506 | int addrlen; |
456 | int addrlen; |
507 | ip_netif_ref netif; |
457 | ip_netif_ref netif; |
508 | ip_route_ref route; |
458 | ip_route_ref route; |
509 | struct sockaddr * addr; |
459 | struct sockaddr * addr; |
510 | struct sockaddr_in * address_in; |
460 | struct sockaddr_in * address_in; |
511 | // struct sockaddr_in6 * address_in6; |
461 | // struct sockaddr_in6 * address_in6; |
512 | in_addr_t * dest; |
462 | in_addr_t * dest; |
513 | in_addr_t * src; |
463 | in_addr_t * src; |
514 | int phone; |
464 | int phone; |
515 | 465 | ||
516 | // addresses in the host byte order |
466 | // addresses in the host byte order |
517 | // should be the next hop address or the target destination address |
467 | // should be the next hop address or the target destination address |
518 | addrlen = packet_get_addr( packet, NULL, ( uint8_t ** ) & addr ); |
468 | addrlen = packet_get_addr( packet, NULL, ( uint8_t ** ) & addr ); |
519 | if( addrlen < 0 ){ |
469 | if( addrlen < 0 ){ |
520 | return ip_release_and_return( packet, addrlen ); |
470 | return ip_release_and_return( packet, addrlen ); |
521 | } |
471 | } |
522 | if( addrlen < sizeof( struct sockaddr )){ |
472 | if( addrlen < sizeof( struct sockaddr )){ |
523 | return ip_release_and_return( packet, EINVAL ); |
473 | return ip_release_and_return( packet, EINVAL ); |
524 | } |
474 | } |
525 | switch( addr->sa_family ){ |
475 | switch( addr->sa_family ){ |
526 | case AF_INET: |
476 | case AF_INET: |
527 | if( addrlen != sizeof( struct sockaddr_in )){ |
477 | if( addrlen != sizeof( struct sockaddr_in )){ |
528 | return ip_release_and_return( packet, EINVAL ); |
478 | return ip_release_and_return( packet, EINVAL ); |
529 | } |
479 | } |
530 | address_in = ( struct sockaddr_in * ) addr; |
480 | address_in = ( struct sockaddr_in * ) addr; |
531 | dest = & address_in->sin_addr; |
481 | dest = & address_in->sin_addr; |
532 | break; |
482 | break; |
533 | // TODO IPv6 |
483 | // TODO IPv6 |
534 | /* case AF_INET6: |
484 | /* case AF_INET6: |
535 | if( addrlen != sizeof( struct sockaddr_in6 )) return EINVAL; |
485 | if( addrlen != sizeof( struct sockaddr_in6 )) return EINVAL; |
536 | address_in6 = ( struct sockaddr_in6 * ) dest; |
486 | address_in6 = ( struct sockaddr_in6 * ) dest; |
537 | address_in6.sin6_addr.s6_addr; |
487 | address_in6.sin6_addr.s6_addr; |
538 | */ default: |
488 | */ default: |
539 | return ip_release_and_return( packet, EAFNOSUPPORT ); |
489 | return ip_release_and_return( packet, EAFNOSUPPORT ); |
540 | } |
490 | } |
541 | fibril_rwlock_read_lock( & ip_globals.netifs_lock ); |
491 | fibril_rwlock_read_lock( & ip_globals.netifs_lock ); |
542 | // device specified? |
492 | // device specified? |
543 | if( device_id > 0 ){ |
493 | if( device_id > 0 ){ |
544 | netif = ip_netifs_find( & ip_globals.netifs, device_id ); |
494 | netif = ip_netifs_find( & ip_globals.netifs, device_id ); |
545 | route = ip_netif_find_route( netif, * dest ); |
495 | route = ip_netif_find_route( netif, * dest ); |
546 | }else{ |
496 | }else{ |
547 | route = ip_find_route( * dest ); |
497 | route = ip_find_route( * dest ); |
548 | netif = route ? route->netif : NULL; |
498 | netif = route ? route->netif : NULL; |
549 | } |
499 | } |
550 | if( !( netif && route )){ |
500 | if( !( netif && route )){ |
551 | fibril_rwlock_read_unlock( & ip_globals.netifs_lock ); |
501 | fibril_rwlock_read_unlock( & ip_globals.netifs_lock ); |
552 | phone = ip_prepare_icmp_and_get_phone( error, packet, NULL ); |
502 | phone = ip_prepare_icmp_and_get_phone( error, packet, NULL ); |
553 | if( phone >= 0 ){ |
503 | if( phone >= 0 ){ |
554 | // unreachable ICMP if no routing |
504 | // unreachable ICMP if no routing |
555 | icmp_destination_unreachable_msg( phone, ICMP_NET_UNREACH, 0, packet ); |
505 | icmp_destination_unreachable_msg( phone, ICMP_NET_UNREACH, 0, packet ); |
556 | } |
506 | } |
557 | return ENOENT; |
507 | return ENOENT; |
558 | } |
508 | } |
559 | if( error ){ |
509 | if( error ){ |
560 | // do not send for broadcast, anycast packets or network broadcast |
510 | // do not send for broadcast, anycast packets or network broadcast |
561 | if(( ! dest->s_addr ) |
511 | if(( ! dest->s_addr ) |
562 | || ( !( ~ dest->s_addr )) |
512 | || ( !( ~ dest->s_addr )) |
563 | || ( !( ~(( dest->s_addr & ( ~ route->netmask.s_addr )) | route->netmask.s_addr ))) |
513 | || ( !( ~(( dest->s_addr & ( ~ route->netmask.s_addr )) | route->netmask.s_addr ))) |
564 | || ( !( dest->s_addr & ( ~ route->netmask.s_addr )))){ |
514 | || ( !( dest->s_addr & ( ~ route->netmask.s_addr )))){ |
565 | return ip_release_and_return( packet, EINVAL ); |
515 | return ip_release_and_return( packet, EINVAL ); |
566 | } |
516 | } |
567 | } |
517 | } |
568 | if( route->address.s_addr == dest->s_addr ){ |
518 | if( route->address.s_addr == dest->s_addr ){ |
569 | // find the loopback device to deliver |
519 | // find the loopback device to deliver |
570 | dest->s_addr = IPV4_LOCALHOST_ADDRESS; |
520 | dest->s_addr = IPV4_LOCALHOST_ADDRESS; |
571 | route = ip_find_route( * dest ); |
521 | route = ip_find_route( * dest ); |
572 | netif = route ? route->netif : NULL; |
522 | netif = route ? route->netif : NULL; |
573 | if( !( netif && route )){ |
523 | if( !( netif && route )){ |
574 | fibril_rwlock_read_unlock( & ip_globals.netifs_lock ); |
524 | fibril_rwlock_read_unlock( & ip_globals.netifs_lock ); |
575 | phone = ip_prepare_icmp_and_get_phone( error, packet, NULL ); |
525 | phone = ip_prepare_icmp_and_get_phone( error, packet, NULL ); |
576 | if( phone >= 0 ){ |
526 | if( phone >= 0 ){ |
577 | // unreachable ICMP if no routing |
527 | // unreachable ICMP if no routing |
578 | icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet ); |
528 | icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet ); |
579 | } |
529 | } |
580 | return ENOENT; |
530 | return ENOENT; |
581 | } |
531 | } |
582 | } |
532 | } |
583 | src = ip_netif_address( netif ); |
533 | src = ip_netif_address( netif ); |
584 | if( ! src ){ |
534 | if( ! src ){ |
585 | fibril_rwlock_read_unlock( & ip_globals.netifs_lock ); |
535 | fibril_rwlock_read_unlock( & ip_globals.netifs_lock ); |
586 | return ip_release_and_return( packet, ENOENT ); |
536 | return ip_release_and_return( packet, ENOENT ); |
587 | } |
537 | } |
588 | ERROR_CODE = ip_send_route( packet, netif, route, src, * dest, error ); |
538 | ERROR_CODE = ip_send_route( packet, netif, route, src, * dest, error ); |
589 | fibril_rwlock_read_unlock( & ip_globals.netifs_lock ); |
539 | fibril_rwlock_read_unlock( & ip_globals.netifs_lock ); |
590 | return ERROR_CODE; |
540 | return ERROR_CODE; |
591 | } |
541 | } |
592 | 542 | ||
593 | in_addr_t * ip_netif_address( ip_netif_ref netif ){ |
543 | in_addr_t * ip_netif_address( ip_netif_ref netif ){ |
594 | ip_route_ref route; |
544 | ip_route_ref route; |
595 | 545 | ||
596 | route = ip_routes_get_index( & netif->routes, 0 ); |
546 | route = ip_routes_get_index( & netif->routes, 0 ); |
597 | return route ? & route->address : NULL; |
547 | return route ? & route->address : NULL; |
598 | } |
548 | } |
599 | 549 | ||
600 | 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 ){ |
550 | 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 ){ |
601 | ERROR_DECLARE; |
551 | ERROR_DECLARE; |
602 | 552 | ||
603 | measured_string_t destination; |
553 | measured_string_t destination; |
604 | measured_string_ref translation; |
554 | measured_string_ref translation; |
605 | char * data; |
555 | char * data; |
606 | int phone; |
556 | int phone; |
607 | 557 | ||
608 | // get destination hardware address |
558 | // get destination hardware address |
609 | if( netif->arp && ( route->address.s_addr != dest.s_addr )){ |
559 | if( netif->arp && ( route->address.s_addr != dest.s_addr )){ |
610 | destination.value = route->gateway.s_addr ? ( char * ) & route->gateway.s_addr : ( char * ) & dest.s_addr; |
560 | destination.value = route->gateway.s_addr ? ( char * ) & route->gateway.s_addr : ( char * ) & dest.s_addr; |
611 | destination.length = CONVERT_SIZE( dest.s_addr, char, 1 ); |
561 | destination.length = CONVERT_SIZE( dest.s_addr, char, 1 ); |
612 | if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ))){ |
562 | if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ))){ |
613 | // sleep( 1 ); |
563 | // sleep( 1 ); |
614 | // ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data )); |
564 | // ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data )); |
615 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
565 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
616 | return ERROR_CODE; |
566 | return ERROR_CODE; |
617 | } |
567 | } |
618 | if( !( translation && translation->value )){ |
568 | if( !( translation && translation->value )){ |
619 | if( translation ){ |
569 | if( translation ){ |
620 | free( translation ); |
570 | free( translation ); |
621 | free( data ); |
571 | free( data ); |
622 | } |
572 | } |
623 | phone = ip_prepare_icmp_and_get_phone( error, packet, NULL ); |
573 | phone = ip_prepare_icmp_and_get_phone( error, packet, NULL ); |
624 | if( phone >= 0 ){ |
574 | if( phone >= 0 ){ |
625 | // unreachable ICMP if no routing |
575 | // unreachable ICMP if no routing |
626 | icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet ); |
576 | icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet ); |
627 | } |
577 | } |
628 | return EINVAL; |
578 | return EINVAL; |
629 | } |
579 | } |
630 | }else translation = NULL; |
580 | }else translation = NULL; |
631 | if( ERROR_OCCURRED( ip_prepare_packet( src, dest, packet, translation ))){ |
581 | if( ERROR_OCCURRED( ip_prepare_packet( src, dest, packet, translation ))){ |
632 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
582 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
633 | }else{ |
583 | }else{ |
634 | packet = ip_split_packet( packet, netif->prefix, netif->content, netif->suffix, netif->addr_len, error ); |
584 | packet = ip_split_packet( packet, netif->prefix, netif->content, netif->suffix, netif->addr_len, error ); |
635 | if( packet ){ |
585 | if( packet ){ |
636 | nil_send_msg( netif->phone, netif->device_id, packet, SERVICE_IP ); |
586 | nil_send_msg( netif->phone, netif->device_id, packet, SERVICE_IP ); |
637 | } |
587 | } |
638 | } |
588 | } |
639 | if( translation ){ |
589 | if( translation ){ |
640 | free( translation ); |
590 | free( translation ); |
641 | free( data ); |
591 | free( data ); |
642 | } |
592 | } |
643 | return ERROR_CODE; |
593 | return ERROR_CODE; |
644 | } |
594 | } |
645 | 595 | ||
646 | int ip_prepare_packet( in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination ){ |
596 | int ip_prepare_packet( in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination ){ |
647 | ERROR_DECLARE; |
597 | ERROR_DECLARE; |
648 | 598 | ||
649 | size_t length; |
599 | size_t length; |
650 | ip_header_ref header; |
600 | ip_header_ref header; |
651 | ip_header_ref last_header; |
601 | ip_header_ref last_header; |
652 | ip_header_ref middle_header; |
602 | ip_header_ref middle_header; |
653 | packet_t next; |
603 | packet_t next; |
654 | 604 | ||
655 | length = packet_get_data_length( packet ); |
605 | length = packet_get_data_length( packet ); |
656 | if(( length < sizeof( ip_header_t )) || ( length > IP_MAX_CONTENT )) return EINVAL; |
606 | if(( length < sizeof( ip_header_t )) || ( length > IP_MAX_CONTENT )) return EINVAL; |
657 | header = ( ip_header_ref ) packet_get_data( packet ); |
607 | header = ( ip_header_ref ) packet_get_data( packet ); |
658 | if( destination ){ |
608 | if( destination ){ |
659 | ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length ))); |
609 | ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length ))); |
660 | }else{ |
610 | }else{ |
661 | ERROR_PROPAGATE( packet_set_addr( packet, NULL, NULL, 0 )); |
611 | ERROR_PROPAGATE( packet_set_addr( packet, NULL, NULL, 0 )); |
662 | } |
612 | } |
663 | header->version = IPV4; |
613 | header->version = IPV4; |
- | 614 | header->fragment_offset_high = 0; |
|
664 | header->fragment_offset = 0; |
615 | header->fragment_offset_low = 0; |
665 | header->header_checksum = 0; |
616 | header->header_checksum = 0; |
666 | if( source ) header->source_address = source->s_addr; |
617 | if( source ) header->source_address = source->s_addr; |
667 | header->destination_address = dest.s_addr; |
618 | header->destination_address = dest.s_addr; |
668 | fibril_rwlock_write_lock( & ip_globals.lock ); |
619 | fibril_rwlock_write_lock( & ip_globals.lock ); |
669 | ++ ip_globals.packet_counter; |
620 | ++ ip_globals.packet_counter; |
670 | header->identification = htons( ip_globals.packet_counter ); |
621 | header->identification = htons( ip_globals.packet_counter ); |
671 | fibril_rwlock_write_unlock( & ip_globals.lock ); |
622 | fibril_rwlock_write_unlock( & ip_globals.lock ); |
672 | length = packet_get_data_length( packet ); |
623 | // length = packet_get_data_length( packet ); |
673 | if( pq_next( packet )){ |
624 | if( pq_next( packet )){ |
674 | last_header = ( ip_header_ref ) malloc( IP_HEADER_LENGTH( header )); |
625 | last_header = ( ip_header_ref ) malloc( IP_HEADER_LENGTH( header )); |
675 | if( ! last_header ) return ENOMEM; |
626 | if( ! last_header ) return ENOMEM; |
676 | ip_create_last_header( last_header, header ); |
627 | ip_create_last_header( last_header, header ); |
677 | next = pq_next( packet ); |
628 | next = pq_next( packet ); |
678 | while( pq_next( next )){ |
629 | while( pq_next( next )){ |
679 | middle_header = ( ip_header_ref ) packet_prefix( next, IP_HEADER_LENGTH( last_header )); |
630 | middle_header = ( ip_header_ref ) packet_prefix( next, IP_HEADER_LENGTH( last_header )); |
680 | if( ! middle_header ) return ENOMEM; |
631 | if( ! middle_header ) return ENOMEM; |
681 | memcpy( middle_header, last_header, IP_HEADER_LENGTH( last_header )); |
632 | memcpy( middle_header, last_header, IP_HEADER_LENGTH( last_header )); |
682 | header->flags |= IPFLAG_MORE_FRAGMENTS; |
633 | header->flags |= IPFLAG_MORE_FRAGMENTS; |
683 | middle_header->total_length = htons( packet_get_data_length( next )); |
634 | middle_header->total_length = htons( packet_get_data_length( next )); |
- | 635 | middle_header->fragment_offset_high = IP_COMPUTE_FRAGMENT_OFFSET_HIGH( length ); |
|
684 | middle_header->fragment_offset = IP_COMPUTE_FRAGMENT_OFFSET( length ); |
636 | middle_header->fragment_offset_low = IP_COMPUTE_FRAGMENT_OFFSET_LOW( length ); |
685 | middle_header->header_checksum = IP_HEADER_CHECKSUM( middle_header ); |
637 | middle_header->header_checksum = IP_HEADER_CHECKSUM( middle_header ); |
686 | if( destination ){ |
638 | if( destination ){ |
687 | ERROR_PROPAGATE( packet_set_addr( next, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length ))); |
639 | ERROR_PROPAGATE( packet_set_addr( next, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length ))); |
688 | } |
640 | } |
689 | length += packet_get_data_length( next ); |
641 | length += packet_get_data_length( next ); |
690 | next = pq_next( next ); |
642 | next = pq_next( next ); |
691 | } |
643 | } |
692 | middle_header = ( ip_header_ref ) packet_prefix( next, IP_HEADER_LENGTH( last_header )); |
644 | middle_header = ( ip_header_ref ) packet_prefix( next, IP_HEADER_LENGTH( last_header )); |
693 | if( ! middle_header ) return ENOMEM; |
645 | if( ! middle_header ) return ENOMEM; |
694 | memcpy( middle_header, last_header, IP_HEADER_LENGTH( last_header )); |
646 | memcpy( middle_header, last_header, IP_HEADER_LENGTH( last_header )); |
695 | middle_header->total_length = htons( packet_get_data_length( next )); |
647 | middle_header->total_length = htons( packet_get_data_length( next )); |
- | 648 | middle_header->fragment_offset_high = IP_COMPUTE_FRAGMENT_OFFSET_HIGH( length ); |
|
696 | middle_header->fragment_offset = IP_COMPUTE_FRAGMENT_OFFSET( length ); |
649 | middle_header->fragment_offset_low = IP_COMPUTE_FRAGMENT_OFFSET_LOW( length ); |
697 | middle_header->header_checksum = IP_HEADER_CHECKSUM( middle_header ); |
650 | middle_header->header_checksum = IP_HEADER_CHECKSUM( middle_header ); |
698 | if( destination ){ |
651 | if( destination ){ |
699 | ERROR_PROPAGATE( packet_set_addr( next, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length ))); |
652 | ERROR_PROPAGATE( packet_set_addr( next, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length ))); |
700 | } |
653 | } |
701 | length += packet_get_data_length( next ); |
654 | length += packet_get_data_length( next ); |
702 | free( last_header ); |
655 | free( last_header ); |
703 | header->flags |= IPFLAG_MORE_FRAGMENTS; |
656 | header->flags |= IPFLAG_MORE_FRAGMENTS; |
704 | } |
657 | } |
705 | header->total_length = htons( length ); |
658 | header->total_length = htons( length ); |
706 | // unnecessary for all protocols |
659 | // unnecessary for all protocols |
707 | header->header_checksum = IP_HEADER_CHECKSUM( header ); |
660 | header->header_checksum = IP_HEADER_CHECKSUM( header ); |
708 | return EOK; |
661 | return EOK; |
709 | } |
662 | } |
710 | 663 | ||
711 | int ip_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){ |
664 | int ip_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){ |
712 | ERROR_DECLARE; |
665 | ERROR_DECLARE; |
713 | 666 | ||
714 | packet_t packet; |
667 | packet_t packet; |
715 | struct sockaddr * addr; |
668 | struct sockaddr * addr; |
716 | size_t addrlen; |
669 | size_t addrlen; |
717 | ip_pseudo_header_ref header; |
670 | ip_pseudo_header_ref header; |
718 | size_t headerlen; |
671 | size_t headerlen; |
719 | 672 | ||
720 | * answer_count = 0; |
673 | * answer_count = 0; |
721 | switch( IPC_GET_METHOD( * call )){ |
674 | switch( IPC_GET_METHOD( * call )){ |
722 | case IPC_M_PHONE_HUNGUP: |
675 | case IPC_M_PHONE_HUNGUP: |
723 | return EOK; |
676 | return EOK; |
724 | case NET_IL_DEVICE: |
677 | case NET_IL_DEVICE: |
725 | return ip_device_req( 0, IPC_GET_DEVICE( call ), IPC_GET_SERVICE( call )); |
678 | return ip_device_req( 0, IPC_GET_DEVICE( call ), IPC_GET_SERVICE( call )); |
726 | case IPC_M_CONNECT_TO_ME: |
679 | case IPC_M_CONNECT_TO_ME: |
727 | return ip_register( IL_GET_PROTO( call ), IL_GET_SERVICE( call ), IPC_GET_PHONE( call ), NULL ); |
680 | return ip_register( IL_GET_PROTO( call ), IL_GET_SERVICE( call ), IPC_GET_PHONE( call ), NULL ); |
728 | case NET_IL_SEND: |
681 | case NET_IL_SEND: |
729 | ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call ))); |
682 | ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call ))); |
730 | return ip_send_msg( 0, IPC_GET_DEVICE( call ), packet, 0, IPC_GET_ERROR( call )); |
683 | return ip_send_msg( 0, IPC_GET_DEVICE( call ), packet, 0, IPC_GET_ERROR( call )); |
731 | case NET_IL_DEVICE_STATE: |
684 | case NET_IL_DEVICE_STATE: |
732 | return ip_device_state_message( IPC_GET_DEVICE( call ), IPC_GET_STATE( call )); |
685 | return ip_device_state_message( IPC_GET_DEVICE( call ), IPC_GET_STATE( call )); |
733 | case NET_IL_RECEIVED: |
686 | case NET_IL_RECEIVED: |
734 | ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call ))); |
687 | ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call ))); |
735 | return ip_receive_message( IPC_GET_DEVICE( call ), packet ); |
688 | return ip_receive_message( IPC_GET_DEVICE( call ), packet ); |
736 | case NET_IP_RECEIVED_ERROR: |
689 | case NET_IP_RECEIVED_ERROR: |
737 | ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call ))); |
690 | ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call ))); |
738 | return ip_received_error_msg( 0, IPC_GET_DEVICE( call ), packet, IPC_GET_TARGET( call ), IPC_GET_ERROR( call )); |
691 | return ip_received_error_msg( 0, IPC_GET_DEVICE( call ), packet, IPC_GET_TARGET( call ), IPC_GET_ERROR( call )); |
739 | case NET_IP_ADD_ROUTE: |
692 | case NET_IP_ADD_ROUTE: |
740 | return ip_add_route_req( 0, IPC_GET_DEVICE( call ), IP_GET_ADDRESS( call ), IP_GET_NETMASK( call ), IP_GET_GATEWAY( call )); |
693 | return ip_add_route_req( 0, IPC_GET_DEVICE( call ), IP_GET_ADDRESS( call ), IP_GET_NETMASK( call ), IP_GET_GATEWAY( call )); |
741 | case NET_IP_SET_GATEWAY: |
694 | case NET_IP_SET_GATEWAY: |
742 | return ip_set_gateway_req( 0, IPC_GET_DEVICE( call ), IP_GET_GATEWAY( call )); |
695 | return ip_set_gateway_req( 0, IPC_GET_DEVICE( call ), IP_GET_GATEWAY( call )); |
743 | case NET_IP_GET_ROUTE: |
696 | case NET_IP_GET_ROUTE: |
744 | ERROR_PROPAGATE( data_receive(( void ** ) & addr, & addrlen )); |
697 | ERROR_PROPAGATE( data_receive(( void ** ) & addr, & addrlen )); |
745 | ERROR_PROPAGATE( ip_get_route_req( 0, IP_GET_PROTOCOL( call ), addr, ( socklen_t ) addrlen, IPC_SET_DEVICE( answer ), & header, & headerlen )); |
698 | ERROR_PROPAGATE( ip_get_route_req( 0, IP_GET_PROTOCOL( call ), addr, ( socklen_t ) addrlen, IPC_SET_DEVICE( answer ), & header, & headerlen )); |
746 | * IP_SET_HEADERLEN( answer ) = headerlen; |
699 | * IP_SET_HEADERLEN( answer ) = headerlen; |
747 | if( ! ERROR_OCCURRED( data_reply( & headerlen, sizeof( headerlen )))){ |
700 | if( ! ERROR_OCCURRED( data_reply( & headerlen, sizeof( headerlen )))){ |
748 | ERROR_CODE = data_reply( header, headerlen ); |
701 | ERROR_CODE = data_reply( header, headerlen ); |
749 | } |
702 | } |
750 | free( header ); |
703 | free( header ); |
751 | return ERROR_CODE; |
704 | return ERROR_CODE; |
752 | case NET_IL_PACKET_SPACE: |
705 | case NET_IL_PACKET_SPACE: |
753 | 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 ))); |
706 | 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 ))); |
754 | * answer_count = 3; |
707 | * answer_count = 3; |
755 | return EOK; |
708 | return EOK; |
756 | case NET_IL_MTU_CHANGED: |
709 | case NET_IL_MTU_CHANGED: |
757 | return ip_mtu_changed_message( IPC_GET_DEVICE( call ), IPC_GET_MTU( call )); |
710 | return ip_mtu_changed_message( IPC_GET_DEVICE( call ), IPC_GET_MTU( call )); |
758 | } |
711 | } |
759 | return ENOTSUP; |
712 | return ENOTSUP; |
760 | } |
713 | } |
761 | 714 | ||
762 | 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 ){ |
715 | 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 ){ |
763 | ip_netif_ref netif; |
716 | ip_netif_ref netif; |
764 | int index; |
717 | int index; |
765 | 718 | ||
766 | if( !( addr_len && prefix && content && suffix )) return EBADMEM; |
719 | if( !( addr_len && prefix && content && suffix )) return EBADMEM; |
767 | * content = IP_MAX_CONTENT - IP_PREFIX; |
720 | * content = IP_MAX_CONTENT - IP_PREFIX; |
768 | fibril_rwlock_read_lock( & ip_globals.netifs_lock ); |
721 | fibril_rwlock_read_lock( & ip_globals.netifs_lock ); |
769 | if( device_id < 0 ){ |
722 | if( device_id < 0 ){ |
770 | * addr_len = IP_ADDR; |
723 | * addr_len = IP_ADDR; |
771 | * prefix = 0; |
724 | * prefix = 0; |
772 | * suffix = 0; |
725 | * suffix = 0; |
773 | for( index = ip_netifs_count( & ip_globals.netifs ) - 1; index >= 0; -- index ){ |
726 | for( index = ip_netifs_count( & ip_globals.netifs ) - 1; index >= 0; -- index ){ |
774 | netif = ip_netifs_get_index( & ip_globals.netifs, index ); |
727 | netif = ip_netifs_get_index( & ip_globals.netifs, index ); |
775 | if( netif ){ |
728 | if( netif ){ |
776 | if( netif->addr_len > * addr_len ) * addr_len = netif->addr_len; |
729 | if( netif->addr_len > * addr_len ) * addr_len = netif->addr_len; |
777 | if( netif->prefix > * prefix ) * prefix = netif->prefix; |
730 | if( netif->prefix > * prefix ) * prefix = netif->prefix; |
778 | if( netif->suffix > * suffix ) * suffix = netif->suffix; |
731 | if( netif->suffix > * suffix ) * suffix = netif->suffix; |
779 | } |
732 | } |
780 | } |
733 | } |
781 | * prefix = * prefix + IP_PREFIX; |
734 | * prefix = * prefix + IP_PREFIX; |
782 | * suffix = * suffix + IP_SUFFIX; |
735 | * suffix = * suffix + IP_SUFFIX; |
783 | }else{ |
736 | }else{ |
784 | netif = ip_netifs_find( & ip_globals.netifs, device_id ); |
737 | netif = ip_netifs_find( & ip_globals.netifs, device_id ); |
785 | if( ! netif ){ |
738 | if( ! netif ){ |
786 | fibril_rwlock_read_unlock( & ip_globals.netifs_lock ); |
739 | fibril_rwlock_read_unlock( & ip_globals.netifs_lock ); |
787 | return ENOENT; |
740 | return ENOENT; |
788 | } |
741 | } |
789 | * addr_len = ( netif->addr_len > IP_ADDR ) ? netif->addr_len : IP_ADDR; |
742 | * addr_len = ( netif->addr_len > IP_ADDR ) ? netif->addr_len : IP_ADDR; |
790 | * prefix = netif->prefix + IP_PREFIX; |
743 | * prefix = netif->prefix + IP_PREFIX; |
791 | * suffix = netif->suffix + IP_SUFFIX; |
744 | * suffix = netif->suffix + IP_SUFFIX; |
792 | } |
745 | } |
793 | fibril_rwlock_read_unlock( & ip_globals.netifs_lock ); |
746 | fibril_rwlock_read_unlock( & ip_globals.netifs_lock ); |
794 | return EOK; |
747 | return EOK; |
795 | } |
748 | } |
796 | 749 | ||
797 | 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 ){ |
750 | 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 ){ |
798 | ip_route_ref route; |
751 | ip_route_ref route; |
799 | ip_netif_ref netif; |
752 | ip_netif_ref netif; |
800 | int index; |
753 | int index; |
801 | 754 | ||
802 | fibril_rwlock_write_lock( & ip_globals.netifs_lock ); |
755 | fibril_rwlock_write_lock( & ip_globals.netifs_lock ); |
803 | netif = ip_netifs_find( & ip_globals.netifs, device_id ); |
756 | netif = ip_netifs_find( & ip_globals.netifs, device_id ); |
804 | if( ! netif ){ |
757 | if( ! netif ){ |
805 | fibril_rwlock_write_unlock( & ip_globals.netifs_lock ); |
758 | fibril_rwlock_write_unlock( & ip_globals.netifs_lock ); |
806 | return ENOENT; |
759 | return ENOENT; |
807 | } |
760 | } |
808 | route = ( ip_route_ref ) malloc( sizeof( ip_route_t )); |
761 | route = ( ip_route_ref ) malloc( sizeof( ip_route_t )); |
809 | if( ! route ){ |
762 | if( ! route ){ |
810 | fibril_rwlock_write_unlock( & ip_globals.netifs_lock ); |
763 | fibril_rwlock_write_unlock( & ip_globals.netifs_lock ); |
811 | return ENOMEM; |
764 | return ENOMEM; |
812 | } |
765 | } |
813 | route->address.s_addr = address.s_addr; |
766 | route->address.s_addr = address.s_addr; |
814 | route->netmask.s_addr = netmask.s_addr; |
767 | route->netmask.s_addr = netmask.s_addr; |
815 | route->gateway.s_addr = gateway.s_addr; |
768 | route->gateway.s_addr = gateway.s_addr; |
816 | route->netif = netif; |
769 | route->netif = netif; |
817 | index = ip_routes_add( & netif->routes, route ); |
770 | index = ip_routes_add( & netif->routes, route ); |
818 | if( index < 0 ) free( route ); |
771 | if( index < 0 ) free( route ); |
819 | fibril_rwlock_write_unlock( & ip_globals.netifs_lock ); |
772 | fibril_rwlock_write_unlock( & ip_globals.netifs_lock ); |
820 | return index; |
773 | return index; |
821 | } |
774 | } |
822 | 775 | ||
823 | ip_route_ref ip_find_route( in_addr_t destination ){ |
776 | ip_route_ref ip_find_route( in_addr_t destination ){ |
824 | int index; |
777 | int index; |
825 | ip_route_ref route; |
778 | ip_route_ref route; |
826 | ip_netif_ref netif; |
779 | ip_netif_ref netif; |
827 | 780 | ||
828 | // start with the last netif - the newest one |
781 | // start with the last netif - the newest one |
829 | index = ip_netifs_count( & ip_globals.netifs ) - 1; |
782 | index = ip_netifs_count( & ip_globals.netifs ) - 1; |
830 | while( index >= 0 ){ |
783 | while( index >= 0 ){ |
831 | netif = ip_netifs_get_index( & ip_globals.netifs, index ); |
784 | netif = ip_netifs_get_index( & ip_globals.netifs, index ); |
832 | if( netif && ( netif->state == NETIF_ACTIVE )){ |
785 | if( netif && ( netif->state == NETIF_ACTIVE )){ |
833 | route = ip_netif_find_route( netif, destination ); |
786 | route = ip_netif_find_route( netif, destination ); |
834 | if( route ) return route; |
787 | if( route ) return route; |
835 | } |
788 | } |
836 | -- index; |
789 | -- index; |
837 | } |
790 | } |
838 | return & ip_globals.gateway; |
791 | return & ip_globals.gateway; |
839 | } |
792 | } |
840 | 793 | ||
841 | ip_route_ref ip_netif_find_route( ip_netif_ref netif, in_addr_t destination ){ |
794 | ip_route_ref ip_netif_find_route( ip_netif_ref netif, in_addr_t destination ){ |
842 | int index; |
795 | int index; |
843 | ip_route_ref route; |
796 | ip_route_ref route; |
844 | 797 | ||
845 | if( netif ){ |
798 | if( netif ){ |
846 | // start with the first one - the direct route |
799 | // start with the first one - the direct route |
847 | for( index = 0; index < ip_routes_count( & netif->routes ); ++ index ){ |
800 | for( index = 0; index < ip_routes_count( & netif->routes ); ++ index ){ |
848 | route = ip_routes_get_index( & netif->routes, index ); |
801 | route = ip_routes_get_index( & netif->routes, index ); |
849 | if( route && (( route->address.s_addr & route->netmask.s_addr ) == ( destination.s_addr & route->netmask.s_addr ))){ |
802 | if( route && (( route->address.s_addr & route->netmask.s_addr ) == ( destination.s_addr & route->netmask.s_addr ))){ |
850 | return route; |
803 | return route; |
851 | } |
804 | } |
852 | } |
805 | } |
853 | } |
806 | } |
854 | return NULL; |
807 | return NULL; |
855 | } |
808 | } |
856 | 809 | ||
857 | int ip_set_gateway_req( int ip_phone, device_id_t device_id, in_addr_t gateway ){ |
810 | int ip_set_gateway_req( int ip_phone, device_id_t device_id, in_addr_t gateway ){ |
858 | ip_netif_ref netif; |
811 | ip_netif_ref netif; |
859 | 812 | ||
860 | fibril_rwlock_write_lock( & ip_globals.netifs_lock ); |
813 | fibril_rwlock_write_lock( & ip_globals.netifs_lock ); |
861 | netif = ip_netifs_find( & ip_globals.netifs, device_id ); |
814 | netif = ip_netifs_find( & ip_globals.netifs, device_id ); |
862 | if( ! netif ){ |
815 | if( ! netif ){ |
863 | fibril_rwlock_write_unlock( & ip_globals.netifs_lock ); |
816 | fibril_rwlock_write_unlock( & ip_globals.netifs_lock ); |
864 | return ENOENT; |
817 | return ENOENT; |
865 | } |
818 | } |
866 | ip_globals.gateway.address.s_addr = 0; |
819 | ip_globals.gateway.address.s_addr = 0; |
867 | ip_globals.gateway.netmask.s_addr = 0; |
820 | ip_globals.gateway.netmask.s_addr = 0; |
868 | ip_globals.gateway.gateway.s_addr = gateway.s_addr; |
821 | ip_globals.gateway.gateway.s_addr = gateway.s_addr; |
869 | ip_globals.gateway.netif = netif; |
822 | ip_globals.gateway.netif = netif; |
870 | fibril_rwlock_write_unlock( & ip_globals.netifs_lock ); |
823 | fibril_rwlock_write_unlock( & ip_globals.netifs_lock ); |
871 | return EOK; |
824 | return EOK; |
872 | } |
825 | } |
873 | 826 | ||
874 | packet_t ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, socklen_t addr_len, services_t error ){ |
827 | packet_t ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, socklen_t addr_len, services_t error ){ |
875 | size_t length; |
828 | size_t length; |
876 | packet_t next; |
829 | packet_t next; |
877 | packet_t new_packet; |
830 | packet_t new_packet; |
878 | int result; |
831 | int result; |
879 | int phone; |
832 | int phone; |
880 | 833 | ||
881 | next = packet; |
834 | next = packet; |
882 | // check all packets |
835 | // check all packets |
883 | while( next ){ |
836 | while( next ){ |
884 | length = packet_get_data_length( next ); |
837 | length = packet_get_data_length( next ); |
885 | // too long? |
838 | // too long? |
886 | if( length > content ){ |
839 | if( length > content ){ |
887 | result = ip_fragment_packet( next, content, prefix, suffix, addr_len ); |
840 | result = ip_fragment_packet( next, content, prefix, suffix, addr_len ); |
888 | if( result != EOK ){ |
841 | if( result != EOK ){ |
889 | new_packet = pq_detach( next ); |
842 | new_packet = pq_detach( next ); |
890 | if( next == packet ){ |
843 | if( next == packet ){ |
891 | // the new first packet of the queue |
844 | // the new first packet of the queue |
892 | packet = new_packet; |
845 | packet = new_packet; |
893 | } |
846 | } |
894 | // fragmentation needed? |
847 | // fragmentation needed? |
895 | if( result == EPERM ){ |
848 | if( result == EPERM ){ |
896 | phone = ip_prepare_icmp_and_get_phone( error, next, NULL ); |
849 | phone = ip_prepare_icmp_and_get_phone( error, next, NULL ); |
897 | if( phone >= 0 ){ |
850 | if( phone >= 0 ){ |
898 | // fragmentation necessary ICMP |
851 | // fragmentation necessary ICMP |
899 | icmp_destination_unreachable_msg( phone, ICMP_FRAG_NEEDED, content, next ); |
852 | icmp_destination_unreachable_msg( phone, ICMP_FRAG_NEEDED, content, next ); |
900 | } |
853 | } |
901 | }else{ |
854 | }else{ |
902 | pq_release( ip_globals.net_phone, packet_get_id( next )); |
855 | pq_release( ip_globals.net_phone, packet_get_id( next )); |
903 | } |
856 | } |
904 | next = new_packet; |
857 | next = new_packet; |
905 | continue; |
858 | continue; |
906 | } |
859 | } |
907 | } |
860 | } |
908 | next = pq_next( next ); |
861 | next = pq_next( next ); |
909 | } |
862 | } |
910 | return packet; |
863 | return packet; |
911 | } |
864 | } |
912 | 865 | ||
913 | int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, socklen_t addr_len ){ |
866 | int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, socklen_t addr_len ){ |
914 | ERROR_DECLARE; |
867 | ERROR_DECLARE; |
915 | 868 | ||
916 | packet_t new_packet; |
869 | packet_t new_packet; |
917 | ip_header_ref header; |
870 | ip_header_ref header; |
918 | ip_header_ref middle_header; |
871 | ip_header_ref middle_header; |
919 | ip_header_ref last_header; |
872 | ip_header_ref last_header; |
920 | struct sockaddr * src; |
873 | struct sockaddr * src; |
921 | struct sockaddr * dest; |
874 | struct sockaddr * dest; |
922 | socklen_t addrlen; |
875 | socklen_t addrlen; |
923 | int result; |
876 | int result; |
924 | 877 | ||
925 | result = packet_get_addr( packet, ( uint8_t ** ) & src, ( uint8_t ** ) & dest ); |
878 | result = packet_get_addr( packet, ( uint8_t ** ) & src, ( uint8_t ** ) & dest ); |
926 | if( result <= 0 ) return EINVAL; |
879 | if( result <= 0 ) return EINVAL; |
927 | addrlen = ( socklen_t ) result; |
880 | addrlen = ( socklen_t ) result; |
928 | if( packet_get_data_length( packet ) <= sizeof( ip_header_t )) return ENOMEM; |
881 | if( packet_get_data_length( packet ) <= sizeof( ip_header_t )) return ENOMEM; |
929 | // get header |
882 | // get header |
930 | header = ( ip_header_ref ) packet_get_data( packet ); |
883 | header = ( ip_header_ref ) packet_get_data( packet ); |
931 | if( ! header ) return EINVAL; |
884 | if( ! header ) return EINVAL; |
932 | // fragmentation forbidden? |
885 | // fragmentation forbidden? |
933 | if( header->flags & IPFLAG_DONT_FRAGMENT ){ |
886 | if( header->flags & IPFLAG_DONT_FRAGMENT ){ |
934 | return EPERM; |
887 | return EPERM; |
935 | } |
888 | } |
936 | // create the last fragment |
889 | // create the last fragment |
937 | new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( addrlen > addr_len ) ? addrlen : addr_len )); |
890 | new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( addrlen > addr_len ) ? addrlen : addr_len )); |
938 | if( ! new_packet ) return ENOMEM; |
891 | if( ! new_packet ) return ENOMEM; |
939 | // allocate as much as originally |
892 | // allocate as much as originally |
940 | last_header = ( ip_header_ref ) packet_suffix( new_packet, IP_HEADER_LENGTH( header )); |
893 | last_header = ( ip_header_ref ) packet_suffix( new_packet, IP_HEADER_LENGTH( header )); |
941 | if( ! last_header ){ |
894 | if( ! last_header ){ |
942 | return ip_release_and_return( packet, ENOMEM ); |
895 | return ip_release_and_return( packet, ENOMEM ); |
943 | } |
896 | } |
944 | ip_create_last_header( last_header, header ); |
897 | ip_create_last_header( last_header, header ); |
945 | // trim the unused space |
898 | // trim the unused space |
946 | if( ERROR_OCCURRED( packet_trim( new_packet, 0, IP_HEADER_LENGTH( header ) - IP_HEADER_LENGTH( last_header )))){ |
899 | if( ERROR_OCCURRED( packet_trim( new_packet, 0, IP_HEADER_LENGTH( header ) - IP_HEADER_LENGTH( last_header )))){ |
947 | return ip_release_and_return( packet, ERROR_CODE ); |
900 | return ip_release_and_return( packet, ERROR_CODE ); |
948 | } |
901 | } |
949 | // biggest multiple of 8 lower than content |
902 | // biggest multiple of 8 lower than content |
950 | // TODO even fragmentation? |
903 | // TODO even fragmentation? |
951 | length = length & ( ~ 0x7 );// ( content / 8 ) * 8 |
904 | length = length & ( ~ 0x7 );// ( content / 8 ) * 8 |
952 | 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 ))){ |
905 | if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, last_header, (( IP_HEADER_DATA_LENGTH( header ) - (( length - IP_HEADER_LENGTH( header )) & ( ~ 0x7 ))) % (( length - IP_HEADER_LENGTH( last_header )) & ( ~ 0x7 ))), src, dest, addrlen ))){ |
953 | return ip_release_and_return( packet, ERROR_CODE ); |
906 | return ip_release_and_return( packet, ERROR_CODE ); |
954 | } |
907 | } |
955 | // mark the first as fragmented |
908 | // mark the first as fragmented |
956 | header->flags |= IPFLAG_MORE_FRAGMENTS; |
909 | header->flags |= IPFLAG_MORE_FRAGMENTS; |
957 | // create middle framgents |
910 | // create middle framgents |
958 | while( IP_TOTAL_LENGTH( header ) > length ){ |
911 | while( IP_TOTAL_LENGTH( header ) > length ){ |
959 | new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( addrlen >= addr_len ) ? addrlen : addr_len )); |
912 | new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( addrlen >= addr_len ) ? addrlen : addr_len )); |
960 | if( ! new_packet ) return ENOMEM; |
913 | if( ! new_packet ) return ENOMEM; |
961 | middle_header = ip_create_middle_header( new_packet, last_header ); |
914 | middle_header = ip_create_middle_header( new_packet, last_header ); |
962 | if( ! middle_header ){ |
915 | if( ! middle_header ){ |
963 | return ip_release_and_return( packet, ENOMEM ); |
916 | return ip_release_and_return( packet, ENOMEM ); |
964 | } |
917 | } |
965 | if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, middle_header, length - IP_HEADER_LENGTH( middle_header ), src, dest, addrlen ))){ |
918 | if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, middle_header, ( length - IP_HEADER_LENGTH( middle_header )) & ( ~ 0x7 ), src, dest, addrlen ))){ |
966 | return ip_release_and_return( packet, ERROR_CODE ); |
919 | return ip_release_and_return( packet, ERROR_CODE ); |
967 | } |
920 | } |
968 | } |
921 | } |
969 | // finish the first fragment |
922 | // finish the first fragment |
970 | header->header_checksum = IP_HEADER_CHECKSUM( header ); |
923 | header->header_checksum = IP_HEADER_CHECKSUM( header ); |
971 | return EOK; |
924 | return EOK; |
972 | } |
925 | } |
973 | 926 | ||
974 | 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 ){ |
927 | 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 ){ |
975 | ERROR_DECLARE; |
928 | ERROR_DECLARE; |
976 | 929 | ||
977 | void * data; |
930 | void * data; |
- | 931 | size_t offset; |
|
978 | 932 | ||
979 | data = packet_suffix( new_packet, length ); |
933 | data = packet_suffix( new_packet, length ); |
980 | if( ! data ) return ENOMEM; |
934 | if( ! data ) return ENOMEM; |
981 | memcpy( data, (( void * ) header ) + IP_TOTAL_LENGTH( header ) - length, length ); |
935 | memcpy( data, (( void * ) header ) + IP_TOTAL_LENGTH( header ) - length, length ); |
982 | ERROR_PROPAGATE( packet_trim( packet, 0, length )); |
936 | ERROR_PROPAGATE( packet_trim( packet, 0, length )); |
983 | header->total_length = htons( IP_TOTAL_LENGTH( header ) - length ); |
937 | header->total_length = htons( IP_TOTAL_LENGTH( header ) - length ); |
984 | new_header->total_length = htons( IP_HEADER_LENGTH( new_header ) + length ); |
938 | new_header->total_length = htons( IP_HEADER_LENGTH( new_header ) + length ); |
985 | new_header->fragment_offset = header->fragment_offset + IP_HEADER_DATA_LENGTH( header ) / 8; |
939 | offset = IP_FRAGMENT_OFFSET( header ) + IP_HEADER_DATA_LENGTH( header ); |
- | 940 | printf( "offset %d = %d + %d\n", offset, IP_FRAGMENT_OFFSET( header ), IP_HEADER_DATA_LENGTH( header )); |
|
- | 941 | new_header->fragment_offset_high = IP_COMPUTE_FRAGMENT_OFFSET_HIGH( offset ); |
|
- | 942 | new_header->fragment_offset_low = IP_COMPUTE_FRAGMENT_OFFSET_LOW( offset ); |
|
986 | new_header->header_checksum = IP_HEADER_CHECKSUM( new_header ); |
943 | new_header->header_checksum = IP_HEADER_CHECKSUM( new_header ); |
987 | ERROR_PROPAGATE( packet_set_addr( new_packet, ( const uint8_t * ) src, ( const uint8_t * ) dest, addrlen )); |
944 | ERROR_PROPAGATE( packet_set_addr( new_packet, ( const uint8_t * ) src, ( const uint8_t * ) dest, addrlen )); |
988 | return pq_insert_after( packet, new_packet ); |
945 | return pq_insert_after( packet, new_packet ); |
989 | } |
946 | } |
990 | 947 | ||
991 | ip_header_ref ip_create_middle_header( packet_t packet, ip_header_ref last ){ |
948 | ip_header_ref ip_create_middle_header( packet_t packet, ip_header_ref last ){ |
992 | ip_header_ref middle; |
949 | ip_header_ref middle; |
993 | 950 | ||
994 | middle = ( ip_header_ref ) packet_suffix( packet, IP_HEADER_LENGTH( last )); |
951 | middle = ( ip_header_ref ) packet_suffix( packet, IP_HEADER_LENGTH( last )); |
995 | if( ! middle ) return NULL; |
952 | if( ! middle ) return NULL; |
996 | memcpy( middle, last, IP_HEADER_LENGTH( last )); |
953 | memcpy( middle, last, IP_HEADER_LENGTH( last )); |
997 | middle->flags |= IPFLAG_MORE_FRAGMENTS; |
954 | middle->flags |= IPFLAG_MORE_FRAGMENTS; |
998 | return middle; |
955 | return middle; |
999 | } |
956 | } |
1000 | 957 | ||
1001 | void ip_create_last_header( ip_header_ref last, ip_header_ref first ){ |
958 | void ip_create_last_header( ip_header_ref last, ip_header_ref first ){ |
1002 | ip_option_ref option; |
959 | ip_option_ref option; |
1003 | size_t next; |
960 | size_t next; |
1004 | size_t length; |
961 | size_t length; |
1005 | 962 | ||
1006 | // copy first itself |
963 | // copy first itself |
1007 | memcpy( last, first, sizeof( ip_header_t )); |
964 | memcpy( last, first, sizeof( ip_header_t )); |
1008 | length = sizeof( ip_header_t ); |
965 | length = sizeof( ip_header_t ); |
1009 | next = sizeof( ip_header_t ); |
966 | next = sizeof( ip_header_t ); |
1010 | // process all ip options |
967 | // process all ip options |
1011 | while( next < first->header_length ){ |
968 | while( next < first->header_length ){ |
1012 | option = ( ip_option_ref ) ((( uint8_t * ) first ) + next ); |
969 | option = ( ip_option_ref ) ((( uint8_t * ) first ) + next ); |
1013 | // skip end or noop |
970 | // skip end or noop |
1014 | if(( option->type == IPOPT_END ) || ( option->type == IPOPT_NOOP )){ |
971 | if(( option->type == IPOPT_END ) || ( option->type == IPOPT_NOOP )){ |
1015 | ++ next; |
972 | ++ next; |
1016 | }else{ |
973 | }else{ |
1017 | // copy if said so or skip |
974 | // copy if said so or skip |
1018 | if( IPOPT_COPIED( option->type )){ |
975 | if( IPOPT_COPIED( option->type )){ |
1019 | memcpy((( uint8_t * ) last ) + length, (( uint8_t * ) first ) + next, option->length ); |
976 | memcpy((( uint8_t * ) last ) + length, (( uint8_t * ) first ) + next, option->length ); |
1020 | length += option->length; |
977 | length += option->length; |
1021 | } |
978 | } |
1022 | // next option |
979 | // next option |
1023 | next += option->length; |
980 | next += option->length; |
1024 | } |
981 | } |
1025 | } |
982 | } |
1026 | // align 4 byte boundary |
983 | // align 4 byte boundary |
1027 | if( length % 4 ){ |
984 | if( length % 4 ){ |
1028 | bzero((( uint8_t * ) last ) + length, 4 - ( length % 4 )); |
985 | bzero((( uint8_t * ) last ) + length, 4 - ( length % 4 )); |
1029 | last->header_length = length / 4 + 1; |
986 | last->header_length = length / 4 + 1; |
1030 | }else{ |
987 | }else{ |
1031 | last->header_length = length / 4; |
988 | last->header_length = length / 4; |
1032 | } |
989 | } |
1033 | last->header_checksum = 0; |
990 | last->header_checksum = 0; |
1034 | } |
991 | } |
1035 | 992 | ||
1036 | int ip_receive_message( device_id_t device_id, packet_t packet ){ |
993 | int ip_receive_message( device_id_t device_id, packet_t packet ){ |
1037 | packet_t next; |
994 | packet_t next; |
1038 | 995 | ||
1039 | do{ |
996 | do{ |
1040 | next = pq_detach( packet ); |
997 | next = pq_detach( packet ); |
1041 | ip_process_packet( device_id, packet ); |
998 | ip_process_packet( device_id, packet ); |
1042 | packet = next; |
999 | packet = next; |
1043 | }while( packet ); |
1000 | }while( packet ); |
1044 | return EOK; |
1001 | return EOK; |
1045 | } |
1002 | } |
1046 | 1003 | ||
1047 | int ip_process_packet( device_id_t device_id, packet_t packet ){ |
1004 | int ip_process_packet( device_id_t device_id, packet_t packet ){ |
1048 | ERROR_DECLARE; |
1005 | ERROR_DECLARE; |
1049 | 1006 | ||
1050 | ip_header_ref header; |
1007 | ip_header_ref header; |
1051 | in_addr_t dest; |
1008 | in_addr_t dest; |
1052 | ip_route_ref route; |
1009 | ip_route_ref route; |
1053 | int phone; |
1010 | int phone; |
1054 | struct sockaddr * addr; |
1011 | struct sockaddr * addr; |
1055 | struct sockaddr_in addr_in; |
1012 | struct sockaddr_in addr_in; |
1056 | // struct sockaddr_in addr_in6; |
1013 | // struct sockaddr_in addr_in6; |
1057 | socklen_t addrlen; |
1014 | socklen_t addrlen; |
1058 | 1015 | ||
1059 | header = ( ip_header_ref ) packet_get_data( packet ); |
1016 | header = ( ip_header_ref ) packet_get_data( packet ); |
1060 | if( ! header ){ |
1017 | if( ! header ){ |
1061 | return ip_release_and_return( packet, ENOMEM ); |
1018 | return ip_release_and_return( packet, ENOMEM ); |
1062 | } |
1019 | } |
1063 | // checksum |
1020 | // checksum |
1064 | if(( header->header_checksum ) && ( IP_HEADER_CHECKSUM( header ))){ |
1021 | if(( header->header_checksum ) && ( IP_HEADER_CHECKSUM( header ))){ |
- | 1022 | phone = ip_prepare_icmp_and_get_phone( 0, packet, header ); |
|
- | 1023 | if( phone >= 0 ){ |
|
1065 | // TODO checksum error ICMP? |
1024 | // checksum error ICMP |
- | 1025 | icmp_parameter_problem_msg( phone, ICMP_PARAM_POINTER, (( size_t ) (( void * ) & header->header_checksum )) - (( size_t ) (( void * ) header )), packet ); |
|
- | 1026 | } |
|
1066 | return ip_release_and_return( packet, EINVAL ); |
1027 | return EINVAL; |
1067 | } |
1028 | } |
1068 | if( header->ttl <= 1 ){ |
1029 | if( header->ttl <= 1 ){ |
1069 | phone = ip_prepare_icmp_and_get_phone( 0, packet, header ); |
1030 | phone = ip_prepare_icmp_and_get_phone( 0, packet, header ); |
1070 | if( phone >= 0 ){ |
1031 | if( phone >= 0 ){ |
1071 | // ttl oxceeded ICMP |
1032 | // ttl oxceeded ICMP |
1072 | icmp_time_exceeded_msg( phone, ICMP_EXC_TTL, packet ); |
1033 | icmp_time_exceeded_msg( phone, ICMP_EXC_TTL, packet ); |
1073 | } |
1034 | } |
1074 | return EINVAL; |
1035 | return EINVAL; |
1075 | } |
1036 | } |
1076 | // process ipopt and get destination |
1037 | // process ipopt and get destination |
1077 | dest = ip_get_destination( header ); |
1038 | dest = ip_get_destination( header ); |
1078 | // set the addrination address |
1039 | // set the addrination address |
1079 | switch( header->version ){ |
1040 | switch( header->version ){ |
1080 | case IPVERSION: |
1041 | case IPVERSION: |
1081 | addrlen = sizeof( addr_in ); |
1042 | addrlen = sizeof( addr_in ); |
1082 | bzero( & addr_in, addrlen ); |
1043 | bzero( & addr_in, addrlen ); |
1083 | addr_in.sin_family = AF_INET; |
1044 | addr_in.sin_family = AF_INET; |
1084 | memcpy( & addr_in.sin_addr.s_addr, & dest, sizeof( dest )); |
1045 | memcpy( & addr_in.sin_addr.s_addr, & dest, sizeof( dest )); |
1085 | addr = ( struct sockaddr * ) & addr_in; |
1046 | addr = ( struct sockaddr * ) & addr_in; |
1086 | break; |
1047 | break; |
1087 | /* case IPv6VERSION: |
1048 | /* case IPv6VERSION: |
1088 | addrlen = sizeof( dest_in6 ); |
1049 | addrlen = sizeof( dest_in6 ); |
1089 | bzero( & dest_in6, addrlen ); |
1050 | bzero( & dest_in6, addrlen ); |
1090 | dest_in6.sin6_family = AF_INET6; |
1051 | dest_in6.sin6_family = AF_INET6; |
1091 | memcpy( & dest_in6.sin6_addr.s6_addr, ); |
1052 | memcpy( & dest_in6.sin6_addr.s6_addr, ); |
1092 | dest = ( struct sockaddr * ) & dest_in; |
1053 | dest = ( struct sockaddr * ) & dest_in; |
1093 | break; |
1054 | break; |
1094 | */ default: |
1055 | */ default: |
1095 | return EAFNOSUPPORT; |
1056 | return EAFNOSUPPORT; |
1096 | } |
1057 | } |
1097 | ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) & addr, addrlen )); |
1058 | ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) & addr, addrlen )); |
1098 | route = ip_find_route( dest ); |
1059 | route = ip_find_route( dest ); |
1099 | if( ! route ){ |
1060 | if( ! route ){ |
1100 | phone = ip_prepare_icmp_and_get_phone( 0, packet, header ); |
1061 | phone = ip_prepare_icmp_and_get_phone( 0, packet, header ); |
1101 | if( phone >= 0 ){ |
1062 | if( phone >= 0 ){ |
1102 | // unreachable ICMP |
1063 | // unreachable ICMP |
1103 | icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet ); |
1064 | icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet ); |
1104 | } |
1065 | } |
1105 | return ENOENT; |
1066 | return ENOENT; |
1106 | } |
1067 | } |
1107 | if( route->address.s_addr == dest.s_addr ){ |
1068 | if( route->address.s_addr == dest.s_addr ){ |
1108 | // local delivery |
1069 | // local delivery |
1109 | return ip_deliver_local( device_id, packet, header, 0 ); |
1070 | return ip_deliver_local( device_id, packet, header, 0 ); |
1110 | }else{ |
1071 | }else{ |
1111 | // only if routing enabled |
1072 | // only if routing enabled |
1112 | if( route->netif->routing ){ |
1073 | if( route->netif->routing ){ |
1113 | -- header->ttl; |
1074 | -- header->ttl; |
1114 | return ip_send_route( packet, route->netif, route, NULL, dest, 0 ); |
1075 | return ip_send_route( packet, route->netif, route, NULL, dest, 0 ); |
1115 | }else{ |
1076 | }else{ |
1116 | phone = ip_prepare_icmp_and_get_phone( 0, packet, header ); |
1077 | phone = ip_prepare_icmp_and_get_phone( 0, packet, header ); |
1117 | if( phone >= 0 ){ |
1078 | if( phone >= 0 ){ |
1118 | // unreachable ICMP if no routing |
1079 | // unreachable ICMP if no routing |
1119 | icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet ); |
1080 | icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet ); |
1120 | } |
1081 | } |
1121 | return ENOENT; |
1082 | return ENOENT; |
1122 | } |
1083 | } |
1123 | } |
1084 | } |
1124 | } |
1085 | } |
1125 | 1086 | ||
1126 | int ip_received_error_msg( int ip_phone, device_id_t device_id, packet_t packet, services_t target, services_t error ){ |
1087 | int ip_received_error_msg( int ip_phone, device_id_t device_id, packet_t packet, services_t target, services_t error ){ |
1127 | uint8_t * data; |
1088 | uint8_t * data; |
1128 | int offset; |
1089 | int offset; |
1129 | icmp_type_t type; |
1090 | icmp_type_t type; |
1130 | icmp_code_t code; |
1091 | icmp_code_t code; |
1131 | ip_netif_ref netif; |
1092 | ip_netif_ref netif; |
1132 | measured_string_t address; |
1093 | measured_string_t address; |
1133 | ip_route_ref route; |
1094 | ip_route_ref route; |
1134 | ip_header_ref header; |
1095 | ip_header_ref header; |
1135 | 1096 | ||
1136 | switch( error ){ |
1097 | switch( error ){ |
1137 | case SERVICE_ICMP: |
1098 | case SERVICE_ICMP: |
1138 | offset = icmp_client_process_packet( packet, & type, & code, NULL, NULL ); |
1099 | offset = icmp_client_process_packet( packet, & type, & code, NULL, NULL ); |
1139 | if( offset < 0 ){ |
1100 | if( offset < 0 ){ |
1140 | return ip_release_and_return( packet, ENOMEM ); |
1101 | return ip_release_and_return( packet, ENOMEM ); |
1141 | } |
1102 | } |
1142 | data = packet_get_data( packet ); |
1103 | data = packet_get_data( packet ); |
1143 | header = ( ip_header_ref )( data + offset ); |
1104 | header = ( ip_header_ref )( data + offset ); |
1144 | // destination host unreachable? |
1105 | // destination host unreachable? |
1145 | if(( type == ICMP_DEST_UNREACH ) && ( code == ICMP_HOST_UNREACH )){ |
1106 | if(( type == ICMP_DEST_UNREACH ) && ( code == ICMP_HOST_UNREACH )){ |
1146 | fibril_rwlock_read_lock( & ip_globals.netifs_lock ); |
1107 | fibril_rwlock_read_lock( & ip_globals.netifs_lock ); |
1147 | netif = ip_netifs_find( & ip_globals.netifs, device_id ); |
1108 | netif = ip_netifs_find( & ip_globals.netifs, device_id ); |
1148 | if( netif && netif->arp ){ |
1109 | if( netif && netif->arp ){ |
1149 | route = ip_routes_get_index( & netif->routes, 0 ); |
1110 | route = ip_routes_get_index( & netif->routes, 0 ); |
1150 | // from the same network? |
1111 | // from the same network? |
1151 | if( route && (( route->address.s_addr & route->netmask.s_addr ) == ( header->destination_address & route->netmask.s_addr ))){ |
1112 | if( route && (( route->address.s_addr & route->netmask.s_addr ) == ( header->destination_address & route->netmask.s_addr ))){ |
1152 | // clear the ARP mapping if any |
1113 | // clear the ARP mapping if any |
1153 | address.value = ( char * ) & header->destination_address; |
1114 | address.value = ( char * ) & header->destination_address; |
1154 | address.length = CONVERT_SIZE( uint8_t, char, sizeof( header->destination_address )); |
1115 | address.length = CONVERT_SIZE( uint8_t, char, sizeof( header->destination_address )); |
1155 | arp_clear_address_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address ); |
1116 | arp_clear_address_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address ); |
1156 | } |
1117 | } |
1157 | } |
1118 | } |
1158 | fibril_rwlock_read_unlock( & ip_globals.netifs_lock ); |
1119 | fibril_rwlock_read_unlock( & ip_globals.netifs_lock ); |
1159 | } |
1120 | } |
1160 | break; |
1121 | break; |
1161 | default: |
1122 | default: |
1162 | return ip_release_and_return( packet, ENOTSUP ); |
1123 | return ip_release_and_return( packet, ENOTSUP ); |
1163 | } |
1124 | } |
1164 | return ip_deliver_local( device_id, packet, header, error ); |
1125 | return ip_deliver_local( device_id, packet, header, error ); |
1165 | } |
1126 | } |
1166 | 1127 | ||
1167 | int ip_deliver_local( device_id_t device_id, packet_t packet, ip_header_ref header, services_t error ){ |
1128 | int ip_deliver_local( device_id_t device_id, packet_t packet, ip_header_ref header, services_t error ){ |
1168 | ERROR_DECLARE; |
1129 | ERROR_DECLARE; |
1169 | 1130 | ||
1170 | ip_proto_ref proto; |
1131 | ip_proto_ref proto; |
1171 | int phone; |
1132 | int phone; |
1172 | services_t service; |
1133 | services_t service; |
1173 | tl_received_msg_t received_msg; |
1134 | tl_received_msg_t received_msg; |
1174 | struct sockaddr * src; |
1135 | struct sockaddr * src; |
1175 | struct sockaddr * dest; |
1136 | struct sockaddr * dest; |
1176 | struct sockaddr_in src_in; |
1137 | struct sockaddr_in src_in; |
1177 | struct sockaddr_in dest_in; |
1138 | struct sockaddr_in dest_in; |
1178 | // struct sockaddr_in src_in6; |
1139 | // struct sockaddr_in src_in6; |
1179 | // struct sockaddr_in dest_in6; |
1140 | // struct sockaddr_in dest_in6; |
1180 | socklen_t addrlen; |
1141 | socklen_t addrlen; |
1181 | 1142 | ||
1182 | if(( header->flags & IPFLAG_MORE_FRAGMENTS ) || header->fragment_offset ){ |
1143 | if(( header->flags & IPFLAG_MORE_FRAGMENTS ) || IP_FRAGMENT_OFFSET( header )){ |
1183 | // TODO fragmented |
1144 | // TODO fragmented |
1184 | return ENOTSUP; |
1145 | return ENOTSUP; |
1185 | }else{ |
1146 | }else{ |
1186 | switch( header->version ){ |
1147 | switch( header->version ){ |
1187 | case IPVERSION: |
1148 | case IPVERSION: |
1188 | addrlen = sizeof( src_in ); |
1149 | addrlen = sizeof( src_in ); |
1189 | bzero( & src_in, addrlen ); |
1150 | bzero( & src_in, addrlen ); |
1190 | src_in.sin_family = AF_INET; |
1151 | src_in.sin_family = AF_INET; |
1191 | memcpy( & dest_in, & src_in, addrlen ); |
1152 | memcpy( & dest_in, & src_in, addrlen ); |
1192 | memcpy( & src_in.sin_addr.s_addr, & header->source_address, sizeof( header->source_address )); |
1153 | memcpy( & src_in.sin_addr.s_addr, & header->source_address, sizeof( header->source_address )); |
1193 | memcpy( & dest_in.sin_addr.s_addr, & header->destination_address, sizeof( header->destination_address )); |
1154 | memcpy( & dest_in.sin_addr.s_addr, & header->destination_address, sizeof( header->destination_address )); |
1194 | src = ( struct sockaddr * ) & src_in; |
1155 | src = ( struct sockaddr * ) & src_in; |
1195 | dest = ( struct sockaddr * ) & dest_in; |
1156 | dest = ( struct sockaddr * ) & dest_in; |
1196 | break; |
1157 | break; |
1197 | /* case IPv6VERSION: |
1158 | /* case IPv6VERSION: |
1198 | addrlen = sizeof( src_in6 ); |
1159 | addrlen = sizeof( src_in6 ); |
1199 | bzero( & src_in6, addrlen ); |
1160 | bzero( & src_in6, addrlen ); |
1200 | src_in6.sin6_family = AF_INET6; |
1161 | src_in6.sin6_family = AF_INET6; |
1201 | memcpy( & dest_in6, & src_in6, addrlen ); |
1162 | memcpy( & dest_in6, & src_in6, addrlen ); |
1202 | memcpy( & src_in6.sin6_addr.s6_addr, ); |
1163 | memcpy( & src_in6.sin6_addr.s6_addr, ); |
1203 | memcpy( & dest_in6.sin6_addr.s6_addr, ); |
1164 | memcpy( & dest_in6.sin6_addr.s6_addr, ); |
1204 | src = ( struct sockaddr * ) & src_in; |
1165 | src = ( struct sockaddr * ) & src_in; |
1205 | dest = ( struct sockaddr * ) & dest_in; |
1166 | dest = ( struct sockaddr * ) & dest_in; |
1206 | break; |
1167 | break; |
1207 | */ default: |
1168 | */ default: |
1208 | return EAFNOSUPPORT; |
1169 | return EAFNOSUPPORT; |
1209 | } |
1170 | } |
1210 | ERROR_PROPAGATE( packet_set_addr( packet, ( uint8_t * ) src, ( uint8_t * ) dest, addrlen )); |
1171 | ERROR_PROPAGATE( packet_set_addr( packet, ( uint8_t * ) src, ( uint8_t * ) dest, addrlen )); |
1211 | fibril_rwlock_read_lock( & ip_globals.protos_lock ); |
1172 | fibril_rwlock_read_lock( & ip_globals.protos_lock ); |
1212 | proto = ip_protos_find( & ip_globals.protos, header->protocol ); |
1173 | proto = ip_protos_find( & ip_globals.protos, header->protocol ); |
1213 | if( ! proto ){ |
1174 | if( ! proto ){ |
1214 | fibril_rwlock_read_unlock( & ip_globals.protos_lock ); |
1175 | fibril_rwlock_read_unlock( & ip_globals.protos_lock ); |
1215 | phone = ip_prepare_icmp_and_get_phone( error, packet, header ); |
1176 | phone = ip_prepare_icmp_and_get_phone( error, packet, header ); |
1216 | if( phone >= 0 ){ |
1177 | if( phone >= 0 ){ |
1217 | // unreachable ICMP |
1178 | // unreachable ICMP |
1218 | icmp_destination_unreachable_msg( phone, ICMP_PROT_UNREACH, 0, packet ); |
1179 | icmp_destination_unreachable_msg( phone, ICMP_PROT_UNREACH, 0, packet ); |
1219 | } |
1180 | } |
1220 | return ENOENT; |
1181 | return ENOENT; |
1221 | } |
1182 | } |
1222 | if( proto->received_msg ){ |
1183 | if( proto->received_msg ){ |
1223 | service = proto->service; |
1184 | service = proto->service; |
1224 | received_msg = proto->received_msg; |
1185 | received_msg = proto->received_msg; |
1225 | fibril_rwlock_read_unlock( & ip_globals.protos_lock ); |
1186 | fibril_rwlock_read_unlock( & ip_globals.protos_lock ); |
1226 | ERROR_CODE = received_msg( device_id, packet, service, error ); |
1187 | ERROR_CODE = received_msg( device_id, packet, service, error ); |
1227 | }else{ |
1188 | }else{ |
1228 | ERROR_CODE = tl_received_msg( proto->phone, device_id, packet, proto->service, error ); |
1189 | ERROR_CODE = tl_received_msg( proto->phone, device_id, packet, proto->service, error ); |
1229 | fibril_rwlock_read_unlock( & ip_globals.protos_lock ); |
1190 | fibril_rwlock_read_unlock( & ip_globals.protos_lock ); |
1230 | } |
1191 | } |
1231 | return ERROR_CODE; |
1192 | return ERROR_CODE; |
1232 | } |
1193 | } |
1233 | } |
1194 | } |
1234 | 1195 | ||
1235 | in_addr_t ip_get_destination( ip_header_ref header ){ |
1196 | in_addr_t ip_get_destination( ip_header_ref header ){ |
1236 | in_addr_t destination; |
1197 | in_addr_t destination; |
1237 | 1198 | ||
1238 | // TODO search set ipopt route? |
1199 | // TODO search set ipopt route? |
1239 | destination.s_addr = header->destination_address; |
1200 | destination.s_addr = header->destination_address; |
1240 | return destination; |
1201 | return destination; |
1241 | } |
1202 | } |
1242 | 1203 | ||
1243 | int ip_prepare_icmp( packet_t packet, ip_header_ref header ){ |
1204 | int ip_prepare_icmp( packet_t packet, ip_header_ref header ){ |
1244 | packet_t next; |
1205 | packet_t next; |
1245 | struct sockaddr * dest; |
1206 | struct sockaddr * dest; |
1246 | struct sockaddr_in dest_in; |
1207 | struct sockaddr_in dest_in; |
1247 | // struct sockaddr_in dest_in6; |
1208 | // struct sockaddr_in dest_in6; |
1248 | socklen_t addrlen; |
1209 | socklen_t addrlen; |
1249 | 1210 | ||
1250 | // detach the first packet and release the others |
1211 | // detach the first packet and release the others |
1251 | next = pq_detach( packet ); |
1212 | next = pq_detach( packet ); |
1252 | if( next ){ |
1213 | if( next ){ |
1253 | pq_release( ip_globals.net_phone, packet_get_id( next )); |
1214 | pq_release( ip_globals.net_phone, packet_get_id( next )); |
1254 | } |
1215 | } |
1255 | if( ! header ){ |
1216 | if( ! header ){ |
1256 | if( packet_get_data_length( packet ) <= sizeof( ip_header_t )) return ENOMEM; |
1217 | if( packet_get_data_length( packet ) <= sizeof( ip_header_t )) return ENOMEM; |
1257 | // get header |
1218 | // get header |
1258 | header = ( ip_header_ref ) packet_get_data( packet ); |
1219 | header = ( ip_header_ref ) packet_get_data( packet ); |
1259 | if( ! header ) return EINVAL; |
1220 | if( ! header ) return EINVAL; |
1260 | } |
1221 | } |
1261 | // only for the first fragment |
1222 | // only for the first fragment |
1262 | if( header->fragment_offset ) return EINVAL; |
1223 | if( IP_FRAGMENT_OFFSET( header )) return EINVAL; |
1263 | // set the destination address |
1224 | // set the destination address |
1264 | switch( header->version ){ |
1225 | switch( header->version ){ |
1265 | case IPVERSION: |
1226 | case IPVERSION: |
1266 | addrlen = sizeof( dest_in ); |
1227 | addrlen = sizeof( dest_in ); |
1267 | bzero( & dest_in, addrlen ); |
1228 | bzero( & dest_in, addrlen ); |
1268 | dest_in.sin_family = AF_INET; |
1229 | dest_in.sin_family = AF_INET; |
1269 | memcpy( & dest_in.sin_addr.s_addr, & header->source_address, sizeof( header->source_address )); |
1230 | memcpy( & dest_in.sin_addr.s_addr, & header->source_address, sizeof( header->source_address )); |
1270 | dest = ( struct sockaddr * ) & dest_in; |
1231 | dest = ( struct sockaddr * ) & dest_in; |
1271 | break; |
1232 | break; |
1272 | /* case IPv6VERSION: |
1233 | /* case IPv6VERSION: |
1273 | addrlen = sizeof( dest_in6 ); |
1234 | addrlen = sizeof( dest_in6 ); |
1274 | bzero( & dest_in6, addrlen ); |
1235 | bzero( & dest_in6, addrlen ); |
1275 | dest_in6.sin6_family = AF_INET6; |
1236 | dest_in6.sin6_family = AF_INET6; |
1276 | memcpy( & dest_in6.sin6_addr.s6_addr, ); |
1237 | memcpy( & dest_in6.sin6_addr.s6_addr, ); |
1277 | dest = ( struct sockaddr * ) & dest_in; |
1238 | dest = ( struct sockaddr * ) & dest_in; |
1278 | break; |
1239 | break; |
1279 | */ default: |
1240 | */ default: |
1280 | return EAFNOSUPPORT; |
1241 | return EAFNOSUPPORT; |
1281 | } |
1242 | } |
1282 | return packet_set_addr( packet, NULL, ( uint8_t * ) dest, addrlen ); |
1243 | return packet_set_addr( packet, NULL, ( uint8_t * ) dest, addrlen ); |
1283 | } |
1244 | } |
1284 | 1245 | ||
1285 | int ip_get_icmp_phone( void ){ |
1246 | int ip_get_icmp_phone( void ){ |
1286 | ip_proto_ref proto; |
1247 | ip_proto_ref proto; |
1287 | int phone; |
1248 | int phone; |
1288 | 1249 | ||
1289 | fibril_rwlock_read_lock( & ip_globals.protos_lock ); |
1250 | fibril_rwlock_read_lock( & ip_globals.protos_lock ); |
1290 | proto = ip_protos_find( & ip_globals.protos, IPPROTO_ICMP ); |
1251 | proto = ip_protos_find( & ip_globals.protos, IPPROTO_ICMP ); |
1291 | phone = proto ? proto->phone : ENOENT; |
1252 | phone = proto ? proto->phone : ENOENT; |
1292 | fibril_rwlock_read_unlock( & ip_globals.protos_lock ); |
1253 | fibril_rwlock_read_unlock( & ip_globals.protos_lock ); |
1293 | return phone; |
1254 | return phone; |
1294 | } |
1255 | } |
1295 | 1256 | ||
1296 | int ip_prepare_icmp_and_get_phone( services_t error, packet_t packet, ip_header_ref header ){ |
1257 | int ip_prepare_icmp_and_get_phone( services_t error, packet_t packet, ip_header_ref header ){ |
1297 | int phone; |
1258 | int phone; |
1298 | 1259 | ||
1299 | phone = ip_get_icmp_phone(); |
1260 | phone = ip_get_icmp_phone(); |
1300 | if( error || ( phone < 0 ) || ip_prepare_icmp( packet, header )){ |
1261 | if( error || ( phone < 0 ) || ip_prepare_icmp( packet, header )){ |
1301 | return ip_release_and_return( packet, EINVAL ); |
1262 | return ip_release_and_return( packet, EINVAL ); |
1302 | } |
1263 | } |
1303 | return phone; |
1264 | return phone; |
1304 | } |
1265 | } |
1305 | 1266 | ||
1306 | int ip_release_and_return( packet_t packet, int result ){ |
1267 | int ip_release_and_return( packet_t packet, int result ){ |
1307 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
1268 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
1308 | return result; |
1269 | return result; |
1309 | } |
1270 | } |
1310 | 1271 | ||
1311 | 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 ){ |
1272 | 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 ){ |
1312 | struct sockaddr_in * address_in; |
1273 | struct sockaddr_in * address_in; |
1313 | // struct sockaddr_in6 * address_in6; |
1274 | // struct sockaddr_in6 * address_in6; |
1314 | in_addr_t * dest; |
1275 | in_addr_t * dest; |
1315 | in_addr_t * src; |
1276 | in_addr_t * src; |
1316 | ip_route_ref route; |
1277 | ip_route_ref route; |
1317 | ipv4_pseudo_header_ref header_in; |
1278 | ipv4_pseudo_header_ref header_in; |
1318 | 1279 | ||
1319 | if( !( destination && ( addrlen > 0 ))) return EINVAL; |
1280 | if( !( destination && ( addrlen > 0 ))) return EINVAL; |
1320 | if( !( device_id && header && headerlen )) return EBADMEM; |
1281 | if( !( device_id && header && headerlen )) return EBADMEM; |
1321 | if( addrlen < sizeof( struct sockaddr )){ |
1282 | if( addrlen < sizeof( struct sockaddr )){ |
1322 | return EINVAL; |
1283 | return EINVAL; |
1323 | } |
1284 | } |
1324 | switch( destination->sa_family ){ |
1285 | switch( destination->sa_family ){ |
1325 | case AF_INET: |
1286 | case AF_INET: |
1326 | if( addrlen != sizeof( struct sockaddr_in )){ |
1287 | if( addrlen != sizeof( struct sockaddr_in )){ |
1327 | return EINVAL; |
1288 | return EINVAL; |
1328 | } |
1289 | } |
1329 | address_in = ( struct sockaddr_in * ) destination; |
1290 | address_in = ( struct sockaddr_in * ) destination; |
1330 | dest = & address_in->sin_addr; |
1291 | dest = & address_in->sin_addr; |
1331 | break; |
1292 | break; |
1332 | // TODO IPv6 |
1293 | // TODO IPv6 |
1333 | /* case AF_INET6: |
1294 | /* case AF_INET6: |
1334 | if( addrlen != sizeof( struct sockaddr_in6 )) return EINVAL; |
1295 | if( addrlen != sizeof( struct sockaddr_in6 )) return EINVAL; |
1335 | address_in6 = ( struct sockaddr_in6 * ) dest; |
1296 | address_in6 = ( struct sockaddr_in6 * ) dest; |
1336 | address_in6.sin6_addr.s6_addr; |
1297 | address_in6.sin6_addr.s6_addr; |
1337 | */ default: |
1298 | */ default: |
1338 | return EAFNOSUPPORT; |
1299 | return EAFNOSUPPORT; |
1339 | } |
1300 | } |
1340 | fibril_rwlock_read_lock( & ip_globals.lock ); |
1301 | fibril_rwlock_read_lock( & ip_globals.lock ); |
1341 | route = ip_find_route( * dest ); |
1302 | route = ip_find_route( * dest ); |
1342 | if( !( route && route->netif )){ |
1303 | if( !( route && route->netif )){ |
1343 | fibril_rwlock_read_unlock( & ip_globals.lock ); |
1304 | fibril_rwlock_read_unlock( & ip_globals.lock ); |
1344 | return ENOENT; |
1305 | return ENOENT; |
1345 | } |
1306 | } |
1346 | * device_id = route->netif->device_id; |
1307 | * device_id = route->netif->device_id; |
1347 | src = ip_netif_address( route->netif ); |
1308 | src = ip_netif_address( route->netif ); |
1348 | fibril_rwlock_read_unlock( & ip_globals.lock ); |
1309 | fibril_rwlock_read_unlock( & ip_globals.lock ); |
1349 | * headerlen = sizeof( * header_in ); |
1310 | * headerlen = sizeof( * header_in ); |
1350 | header_in = ( ipv4_pseudo_header_ref ) malloc( * headerlen ); |
1311 | header_in = ( ipv4_pseudo_header_ref ) malloc( * headerlen ); |
1351 | if( ! header_in ) return ENOMEM; |
1312 | if( ! header_in ) return ENOMEM; |
1352 | bzero( header_in, * headerlen ); |
1313 | bzero( header_in, * headerlen ); |
1353 | header_in->destination_address = dest->s_addr; |
1314 | header_in->destination_address = dest->s_addr; |
1354 | header_in->source_address = src->s_addr; |
1315 | header_in->source_address = src->s_addr; |
1355 | header_in->protocol = protocol; |
1316 | header_in->protocol = protocol; |
1356 | header_in->data_length = 0; |
1317 | header_in->data_length = 0; |
1357 | * header = ( ip_pseudo_header_ref ) header_in; |
1318 | * header = ( ip_pseudo_header_ref ) header_in; |
1358 | return EOK; |
1319 | return EOK; |
1359 | } |
1320 | } |
1360 | 1321 | ||
1361 | /** @} |
1322 | /** @} |
1362 | */ |
1323 | */ |
1363 | 1324 |