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; |