Rev 3992 | Rev 4077 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3992 | Rev 4075 | ||
---|---|---|---|
Line 46... | Line 46... | ||
46 | #include "../../err.h" |
46 | #include "../../err.h" |
47 | #include "../../messages.h" |
47 | #include "../../messages.h" |
48 | #include "../../modules.h" |
48 | #include "../../modules.h" |
49 | 49 | ||
50 | #include "../../include/byteorder.h" |
50 | #include "../../include/byteorder.h" |
- | 51 | #include "../../include/crc.h" |
|
- | 52 | #include "../../include/ethernet_lsap.h" |
|
51 | #include "../../include/ethernet_protocols.h" |
53 | #include "../../include/ethernet_protocols.h" |
52 | #include "../../include/protocol_map.h" |
54 | #include "../../include/protocol_map.h" |
53 | #include "../../netif/device.h" |
55 | #include "../../netif/device.h" |
54 | 56 | ||
55 | #include "../../structures/measured_strings.h" |
57 | #include "../../structures/measured_strings.h" |
Line 60... | Line 62... | ||
60 | #include "eth_header.h" |
62 | #include "eth_header.h" |
61 | //#include "eth_messages.h" |
63 | //#include "eth_messages.h" |
62 | #include "eth_module.h" |
64 | #include "eth_module.h" |
63 | 65 | ||
64 | #define ETH_PREFIX ( sizeof( eth_header_t ) + sizeof( eth_header_lsap_t ) + sizeof( eth_header_snap_t )) |
66 | #define ETH_PREFIX ( sizeof( eth_header_t ) + sizeof( eth_header_lsap_t ) + sizeof( eth_header_snap_t )) |
65 | #define ETH_SUFFIX 4 |
67 | #define ETH_SUFFIX sizeof( eth_fcs_t ) |
66 | #define ETH_MAX_CONTENT ( ETH_MIN_PROTO - 1 ) |
68 | #define ETH_MAX_CONTENT 1500 |
67 | #define ETH_MIN_CONTENT 46 |
69 | #define ETH_MIN_CONTENT 46 |
68 | #define ETH_PADDING ETH_SUFFIX |
- | |
69 | 70 | ||
70 | /** Returns the device identifier message parameter. |
71 | /** Returns the device identifier message parameter. |
71 | */ |
72 | */ |
72 | #define IPC_GET_DEVICE( call ) ( device_id_t ) IPC_GET_ARG1( * call ) |
73 | #define IPC_GET_DEVICE( call ) ( device_id_t ) IPC_GET_ARG1( * call ) |
73 | 74 | ||
Line 120... | Line 121... | ||
120 | int eth_addr_message( device_id_t device_id, eth_addr_type_t type, measured_string_ref * address ); |
121 | int eth_addr_message( device_id_t device_id, eth_addr_type_t type, measured_string_ref * address ); |
121 | int eth_register_message( services_t service, int phone ); |
122 | int eth_register_message( services_t service, int phone ); |
122 | int eth_send_message( device_id_t device_id, packet_t packet, services_t sender ); |
123 | int eth_send_message( device_id_t device_id, packet_t packet, services_t sender ); |
123 | int eth_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ); |
124 | int eth_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ); |
124 | void eth_receiver( ipc_callid_t iid, ipc_call_t * icall ); |
125 | void eth_receiver( ipc_callid_t iid, ipc_call_t * icall ); |
- | 126 | eth_proto_ref eth_proccess_packet( packet_t packet ); |
|
- | 127 | int eth_prepare_packet( packet_t packet, uint8_t * src_addr, int ethertype ); |
|
125 | 128 | ||
126 | int eth_initialize( void ){ |
129 | int eth_initialize( void ){ |
127 | ERROR_DECLARE; |
130 | ERROR_DECLARE; |
128 | 131 | ||
129 | rwlock_initialize( & eth_globals.devices_lock ); |
132 | rwlock_initialize( & eth_globals.devices_lock ); |
Line 199... | Line 202... | ||
199 | } |
202 | } |
200 | rwlock_write_unlock( & eth_globals.devices_lock ); |
203 | rwlock_write_unlock( & eth_globals.devices_lock ); |
201 | return EOK; |
204 | return EOK; |
202 | } |
205 | } |
203 | 206 | ||
204 | int eth_receive_message( device_id_t device_id, packet_t packet ){ |
207 | eth_proto_ref eth_proccess_packet( packet_t packet ){ |
205 | ERROR_DECLARE; |
208 | ERROR_DECLARE; |
206 | 209 | ||
207 | eth_header_ex_ref header; |
210 | eth_header_ex_ref header; |
208 | size_t length; |
211 | size_t length; |
209 | int type; |
212 | int type; |
210 | eth_proto_ref proto; |
213 | size_t prefix; |
211 | size_t size; |
214 | size_t suffix; |
- | 215 | eth_fcs_ref fcs; |
|
212 | 216 | ||
213 | length = packet_get_data_length( packet ); |
217 | length = packet_get_data_length( packet ); |
214 | if( length <= sizeof( eth_header_t ) + ETH_MIN_CONTENT + ETH_PADDING ) return EINVAL; |
218 | if( length <= sizeof( eth_header_t ) + ETH_MIN_CONTENT + ETH_SUFFIX ) return NULL; |
215 | // TODO check CRC padding? |
- | |
216 | header = ( eth_header_ex_ref ) packet_get_data( packet ); |
219 | header = ( eth_header_ex_ref ) packet_get_data( packet ); |
217 | type = ntohs( header->header.ethertype ); |
220 | type = ntohs( header->header.ethertype ); |
218 | if( type >= ETH_MIN_PROTO ){ |
221 | if( type >= ETH_MIN_PROTO ){ |
219 | // DIX Ethernet |
222 | // DIX Ethernet |
220 | size = sizeof( eth_header_t ); |
223 | prefix = sizeof( eth_header_t ); |
221 | }else{ |
224 | suffix = sizeof( eth_fcs_t ); |
222 | // TODO check length? |
225 | fcs = (( void * ) header ) + length - suffix; |
- | 226 | }else if( type <= ETH_MAX_CONTENT ){ |
|
223 | // translate "LSAP" values |
227 | // translate "LSAP" values |
224 | if(( header->lsap.dsap == ETH_RAW ) && ( header->lsap.ssap == ETH_RAW )){ |
228 | if(( header->lsap.dsap == ETH_LSAP_GLSAP ) && ( header->lsap.ssap == ETH_LSAP_GLSAP )){ |
225 | // raw packet |
229 | // raw packet |
226 | // discard |
230 | // discard |
227 | return EINVAL; |
231 | return NULL; |
228 | }else if(( header->lsap.dsap == ETH_LSAP_SNAP ) && ( header->lsap.ssap == ETH_LSAP_SNAP )){ |
232 | }else if(( header->lsap.dsap == ETH_LSAP_SNAP ) && ( header->lsap.ssap == ETH_LSAP_SNAP )){ |
229 | // IEEE 802.3 SNAP |
233 | // IEEE 802.3 + 802.2 + LSAP + SNAP |
230 | // organization code not supported |
234 | // organization code not supported |
231 | type = ntohs( header->snap.ethertype ); |
235 | type = ntohs( header->snap.ethertype ); |
232 | size = sizeof( eth_header_t ) + sizeof( eth_header_lsap_t) + sizeof( eth_header_snap_t); |
236 | prefix = sizeof( eth_header_t ) + sizeof( eth_header_lsap_t) + sizeof( eth_header_snap_t); |
233 | }else{ |
237 | }else{ |
234 | // IEEE 802.3 + 802.2 LSAP |
238 | // IEEE 802.3 + 802.2 LSAP |
235 | // TODO lsap numbers |
- | |
236 | type = header->lsap.dsap; |
239 | type = lsap_map( header->lsap.dsap ); |
237 | size = sizeof( eth_header_t ) + sizeof( eth_header_lsap_t); |
240 | prefix = sizeof( eth_header_t ) + sizeof( eth_header_lsap_t); |
238 | } |
241 | } |
- | 242 | suffix = ( type < ETH_MIN_CONTENT ) ? ETH_MIN_CONTENT - type : 0; |
|
- | 243 | fcs = (( void * ) header ) + prefix + type + suffix; |
|
- | 244 | suffix += length - prefix - type; |
|
- | 245 | }else{ |
|
- | 246 | // invalid length/type, should not occurr |
|
- | 247 | return NULL; |
|
239 | } |
248 | } |
240 | rwlock_write_lock( & eth_globals.protos_lock ); |
249 | // TODO compute crc with fcs to erase? |
241 | proto = eth_protos_find( & eth_globals.protos, type ); |
250 | if(( ~ compute_crc32( ~ 0, & header->header.dest, ((( void * ) fcs ) - (( void * ) & header->header.dest )) * 8 )) != ( * fcs )){ |
242 | if( ! proto ){ |
- | |
243 | rwlock_write_unlock( & eth_globals.protos_lock ); |
- | |
244 | return ENOENT; |
251 | return NULL; |
245 | } |
252 | } |
246 | if( ERROR_OCCURRED( packet_set_addr( packet, header->header.src, header->header.dest, ETH_ADDR )) |
253 | if( ERROR_OCCURRED( packet_set_addr( packet, header->header.src, header->header.dest, ETH_ADDR )) |
247 | || ERROR_OCCURRED( packet_trim( packet, size, ETH_PADDING ))){ |
254 | || ERROR_OCCURRED( packet_trim( packet, prefix, suffix ))){ |
248 | rwlock_write_unlock( & eth_globals.protos_lock ); |
- | |
249 | return ERROR_CODE; |
255 | return NULL; |
250 | } |
256 | } |
- | 257 | return eth_protos_find( & eth_globals.protos, type ); |
|
- | 258 | } |
|
- | 259 | ||
- | 260 | int eth_receive_message( device_id_t device_id, packet_t packet ){ |
|
- | 261 | eth_proto_ref proto; |
|
- | 262 | packet_t next; |
|
- | 263 | ||
- | 264 | rwlock_read_lock( & eth_globals.protos_lock ); |
|
- | 265 | do{ |
|
- | 266 | next = pq_detach( packet ); |
|
- | 267 | proto = eth_proccess_packet( packet ); |
|
- | 268 | if( proto ){ |
|
251 | async_msg_2( proto->phone, NET_IL_RECEIVED, device_id, packet_get_id( packet )); |
269 | async_msg_2( proto->phone, NET_IL_RECEIVED, device_id, packet_get_id( packet )); |
- | 270 | }else{ |
|
- | 271 | // drop invalid/unknown |
|
- | 272 | packet_release( eth_globals.networking_phone, packet_get_id( packet )); |
|
- | 273 | } |
|
- | 274 | packet = next; |
|
- | 275 | }while( packet ); |
|
252 | rwlock_write_unlock( & eth_globals.protos_lock ); |
276 | rwlock_read_unlock( & eth_globals.protos_lock ); |
253 | return EOK; |
277 | return EOK; |
254 | } |
278 | } |
255 | 279 | ||
256 | int eth_packet_space_message( device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix ){ |
280 | int eth_packet_space_message( device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix ){ |
257 | eth_device_ref device; |
281 | eth_device_ref device; |
Line 265... | Line 289... | ||
265 | } |
289 | } |
266 | * content = ( ETH_MAX_CONTENT > device->mtu ) ? device->mtu : ETH_MAX_CONTENT; |
290 | * content = ( ETH_MAX_CONTENT > device->mtu ) ? device->mtu : ETH_MAX_CONTENT; |
267 | rwlock_write_unlock( & eth_globals.devices_lock ); |
291 | rwlock_write_unlock( & eth_globals.devices_lock ); |
268 | * addr_len = ETH_ADDR; |
292 | * addr_len = ETH_ADDR; |
269 | * prefix = ETH_PREFIX; |
293 | * prefix = ETH_PREFIX; |
270 | * suffix = ETH_SUFFIX; |
294 | * suffix = ETH_MIN_CONTENT + ETH_SUFFIX; |
271 | return EOK; |
295 | return EOK; |
272 | } |
296 | } |
273 | 297 | ||
274 | int eth_addr_message( device_id_t device_id, eth_addr_type_t type, measured_string_ref * address ){ |
298 | int eth_addr_message( device_id_t device_id, eth_addr_type_t type, measured_string_ref * address ){ |
275 | eth_device_ref device; |
299 | eth_device_ref device; |
Line 321... | Line 345... | ||
321 | } |
345 | } |
322 | rwlock_write_unlock( & eth_globals.protos_lock ); |
346 | rwlock_write_unlock( & eth_globals.protos_lock ); |
323 | return EOK; |
347 | return EOK; |
324 | } |
348 | } |
325 | 349 | ||
326 | int eth_send_message( device_id_t device_id, packet_t packet, services_t sender ){ |
350 | int eth_prepare_packet( packet_t packet, uint8_t * src_addr, int ethertype ){ |
327 | ERROR_DECLARE; |
- | |
328 | - | ||
329 | eth_device_ref device; |
- | |
330 | eth_header_ex_ref header; |
351 | eth_header_ex_ref header; |
- | 352 | eth_fcs_ref fcs; |
|
331 | uint8_t * src; |
353 | uint8_t * src; |
332 | uint8_t * dest; |
354 | uint8_t * dest; |
333 | int length; |
355 | int length; |
334 | int i; |
356 | int i; |
- | 357 | void * padding; |
|
335 | 358 | ||
336 | header = PACKET_PREFIX( packet, eth_header_ex_t ); |
359 | header = PACKET_PREFIX( packet, eth_header_ex_t ); |
337 | if( ! header ) return ENOMEM; |
360 | if( ! header ) return ENOMEM; |
338 | for( i = 0; i < 7; ++ i ) header->header.preamble[ i ] = ETH_PREAMBLE; |
361 | for( i = 0; i < 7; ++ i ) header->header.preamble[ i ] = ETH_PREAMBLE; |
339 | header->header.sfd = ETH_SFD; |
362 | header->header.sfd = ETH_SFD; |
340 | length = packet_get_addr( packet, & src, & dest ); |
363 | length = packet_get_addr( packet, & src, & dest ); |
341 | if( length < 0 ) return length; |
364 | if( length < 0 ) return length; |
342 | if( length < ETH_ADDR ) return EINVAL; |
365 | if( length < ETH_ADDR ) return EINVAL; |
343 | // TODO src set? |
366 | memcpy( header->header.src, src_addr, ETH_ADDR ); |
344 | // TODO set addresses |
367 | memcpy( & header->header.dest, dest, ETH_ADDR ); |
345 | length = packet_get_data_length( packet ); |
368 | length = packet_get_data_length( packet ); |
346 | if( length > ETH_MAX_CONTENT ) return EINVAL; |
369 | if( length > ETH_MAX_CONTENT ) return EINVAL; |
347 | if( length < ETH_MIN_CONTENT ){ |
370 | if( length < ETH_MIN_CONTENT ){ |
- | 371 | padding = packet_suffix( packet, ETH_MIN_CONTENT - length ); |
|
348 | // TODO pad zeros |
372 | if( ! padding ) return ENOMEM; |
- | 373 | memset( padding, 0, ETH_MIN_CONTENT - length ); |
|
349 | } |
374 | } |
350 | header->header.ethertype = htons( length ); |
375 | header->header.ethertype = htons( length ); |
351 | header->lsap.dsap = 0xAA; |
376 | header->lsap.dsap = 0xAA; |
352 | header->lsap.ssap = header->lsap.dsap; |
377 | header->lsap.ssap = header->lsap.dsap; |
353 | header->lsap.ctrl = 0; |
378 | header->lsap.ctrl = 0; |
354 | for( i = 0; i < 3; ++ i ) header->snap.proto[ i ] = 0; |
379 | for( i = 0; i < 3; ++ i ) header->snap.proto[ i ] = 0; |
355 | header->snap.ethertype = htons( protocol_map( SERVICE_ETHERNET, sender )); |
380 | header->snap.ethertype = ethertype; |
- | 381 | fcs = PACKET_SUFFIX( packet, eth_fcs_t ); |
|
356 | if( ! header ) return ENOENT; |
382 | if( ! fcs ) return ENOMEM; |
- | 383 | * fcs = ~ compute_crc32( ~ 0, & header->header.dest, ((( void * ) fcs ) - (( void * ) & header->header.dest )) * 8 ); |
|
- | 384 | return EOK; |
|
- | 385 | } |
|
- | 386 | ||
- | 387 | int eth_send_message( device_id_t device_id, packet_t packet, services_t sender ){ |
|
- | 388 | ERROR_DECLARE; |
|
- | 389 | ||
- | 390 | eth_device_ref device; |
|
- | 391 | packet_t next; |
|
- | 392 | packet_t tmp; |
|
357 | // TODO eth padding |
393 | int ethertype; |
- | 394 | ||
358 | if( ! packet_suffix( packet, ETH_PADDING )){ |
395 | ethertype = htons( protocol_map( SERVICE_ETHERNET, sender )); |
- | 396 | if( ! ethertype ){ |
|
- | 397 | packet_release( eth_globals.networking_phone, packet_get_id( packet )); |
|
359 | return ENOMEM; |
398 | return EINVAL; |
360 | } |
399 | } |
- | 400 | rwlock_read_lock( & eth_globals.devices_lock ); |
|
- | 401 | device = eth_devices_find( & eth_globals.devices, device_id ); |
|
- | 402 | if( ! device ){ |
|
- | 403 | rwlock_read_unlock( & eth_globals.devices_lock ); |
|
- | 404 | return ENOENT; |
|
361 | 405 | } |
|
- | 406 | // proccess packet queue |
|
- | 407 | next = packet; |
|
- | 408 | do{ |
|
- | 409 | if( ERROR_OCCURRED( eth_prepare_packet( next, ( uint8_t * ) device->addr->value, ethertype ))){ |
|
- | 410 | // release invalid packet |
|
- | 411 | tmp = pq_detach( next ); |
|
362 | rwlock_write_lock( & eth_globals.devices_lock ); |
412 | packet_release( eth_globals.networking_phone, packet_get_id( next )); |
- | 413 | next = tmp; |
|
- | 414 | }else{ |
|
- | 415 | next = pq_next( next ); |
|
- | 416 | } |
|
- | 417 | }while( next ); |
|
- | 418 | // send packet queue |
|
- | 419 | async_msg_2( device->phone, NET_NETIF_SEND, device_id, packet_get_id( packet )); |
|
363 | rwlock_write_unlock( & eth_globals.devices_lock ); |
420 | rwlock_read_unlock( & eth_globals.devices_lock ); |
364 | return EOK; |
421 | return EOK; |
365 | } |
422 | } |
366 | 423 | ||
367 | int eth_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){ |
424 | int eth_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){ |
368 | ERROR_DECLARE; |
425 | ERROR_DECLARE; |