Changeset 357b5f5 in mainline for uspace/srv/net/il/arp/arp.c
- Timestamp:
- 2011-01-23T20:09:13Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- fdb9982c
- Parents:
- cead2aa (diff), 7e36c8d (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/il/arp/arp.c
rcead2aa r357b5f5 36 36 */ 37 37 38 #include "arp.h"39 #include "arp_header.h"40 #include "arp_oc.h"41 #include "arp_module.h"42 43 38 #include <async.h> 44 39 #include <malloc.h> 45 40 #include <mem.h> 46 41 #include <fibril_synch.h> 42 #include <assert.h> 47 43 #include <stdio.h> 48 44 #include <str.h> … … 54 50 #include <ipc/arp.h> 55 51 #include <ipc/il.h> 52 #include <ipc/nil.h> 56 53 #include <byteorder.h> 57 54 #include <errno.h> 58 59 55 #include <net/modules.h> 60 56 #include <net/device.h> 61 57 #include <net/packet.h> 62 63 #include <nil_interface.h> 58 #include <nil_remote.h> 64 59 #include <protocol_map.h> 65 60 #include <packet_client.h> 66 61 #include <packet_remote.h> 67 #include <il_ interface.h>68 #include <il_ local.h>69 62 #include <il_remote.h> 63 #include <il_skel.h> 64 #include "arp.h" 70 65 71 66 /** ARP module name. */ 72 67 #define NAME "arp" 73 68 69 /** Number of microseconds to wait for an ARP reply. */ 70 #define ARP_TRANS_WAIT 1000000 71 72 /** @name ARP operation codes definitions */ 73 /*@{*/ 74 75 /** REQUEST operation code. */ 76 #define ARPOP_REQUEST 1 77 78 /** REPLY operation code. */ 79 #define ARPOP_REPLY 2 80 81 /*@}*/ 82 83 /** Type definition of an ARP protocol header. 84 * @see arp_header 85 */ 86 typedef struct arp_header arp_header_t; 87 88 /** ARP protocol header. */ 89 struct arp_header { 90 /** 91 * Hardware type identifier. 92 * @see hardware.h 93 */ 94 uint16_t hardware; 95 96 /** Protocol identifier. */ 97 uint16_t protocol; 98 /** Hardware address length in bytes. */ 99 uint8_t hardware_length; 100 /** Protocol address length in bytes. */ 101 uint8_t protocol_length; 102 103 /** 104 * ARP packet type. 105 * @see arp_oc.h 106 */ 107 uint16_t operation; 108 } __attribute__ ((packed)); 109 74 110 /** ARP global data. */ 75 111 arp_globals_t arp_globals; … … 77 113 DEVICE_MAP_IMPLEMENT(arp_cache, arp_device_t); 78 114 INT_MAP_IMPLEMENT(arp_protos, arp_proto_t); 79 GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, measured_string_t); 80 81 /** Clears the device specific data. 82 * 83 * @param[in] device The device specific data. 115 GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, arp_trans_t); 116 117 static void arp_clear_trans(arp_trans_t *trans) 118 { 119 if (trans->hw_addr) { 120 free(trans->hw_addr); 121 trans->hw_addr = NULL; 122 } 123 124 fibril_condvar_broadcast(&trans->cv); 125 } 126 127 static void arp_clear_addr(arp_addr_t *addresses) 128 { 129 int count; 130 131 for (count = arp_addr_count(addresses) - 1; count >= 0; count--) { 132 arp_trans_t *trans = arp_addr_items_get_index(&addresses->values, 133 count); 134 if (trans) 135 arp_clear_trans(trans); 136 } 137 } 138 139 /** Clear the device specific data. 140 * 141 * @param[in] device Device specific data. 84 142 */ 85 143 static void arp_clear_device(arp_device_t *device) 86 144 { 87 145 int count; 88 arp_proto_t *proto; 89 146 90 147 for (count = arp_protos_count(&device->protos) - 1; count >= 0; 91 148 count--) { 92 proto = arp_protos_get_index(&device->protos, count); 149 arp_proto_t *proto = arp_protos_get_index(&device->protos, 150 count); 151 93 152 if (proto) { 94 153 if (proto->addr) 95 154 free(proto->addr); 155 96 156 if (proto->addr_data) 97 157 free(proto->addr_data); 158 159 arp_clear_addr(&proto->addresses); 98 160 arp_addr_destroy(&proto->addresses); 99 161 } 100 162 } 163 101 164 arp_protos_clear(&device->protos); 102 165 } … … 105 168 { 106 169 int count; 107 arp_device_t *device; 108 109 fibril_rwlock_write_lock(&arp_globals.lock); 170 171 fibril_mutex_lock(&arp_globals.lock); 110 172 for (count = arp_cache_count(&arp_globals.cache) - 1; count >= 0; 111 173 count--) { 112 device = arp_cache_get_index(&arp_globals.cache, count); 174 arp_device_t *device = arp_cache_get_index(&arp_globals.cache, 175 count); 176 113 177 if (device) { 114 178 arp_clear_device(device); 115 179 if (device->addr_data) 116 180 free(device->addr_data); 181 117 182 if (device->broadcast_data) 118 183 free(device->broadcast_data); 119 184 } 120 185 } 186 121 187 arp_cache_clear(&arp_globals.cache); 122 fibril_ rwlock_write_unlock(&arp_globals.lock);123 printf("Cache cleaned\n");188 fibril_mutex_unlock(&arp_globals.lock); 189 124 190 return EOK; 125 191 } … … 128 194 services_t protocol, measured_string_t *address) 129 195 { 130 arp_device_t *device; 131 arp_proto_t *proto; 132 133 fibril_rwlock_write_lock(&arp_globals.lock); 134 device = arp_cache_find(&arp_globals.cache, device_id); 196 fibril_mutex_lock(&arp_globals.lock); 197 198 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id); 135 199 if (!device) { 136 fibril_ rwlock_write_unlock(&arp_globals.lock);200 fibril_mutex_unlock(&arp_globals.lock); 137 201 return ENOENT; 138 202 } 139 proto = arp_protos_find(&device->protos, protocol); 203 204 arp_proto_t *proto = arp_protos_find(&device->protos, protocol); 140 205 if (!proto) { 141 fibril_ rwlock_write_unlock(&arp_globals.lock);206 fibril_mutex_unlock(&arp_globals.lock); 142 207 return ENOENT; 143 208 } 209 210 arp_trans_t *trans = arp_addr_find(&proto->addresses, address->value, 211 address->length); 212 if (trans) 213 arp_clear_trans(trans); 214 144 215 arp_addr_exclude(&proto->addresses, address->value, address->length); 145 fibril_rwlock_write_unlock(&arp_globals.lock); 216 217 fibril_mutex_unlock(&arp_globals.lock); 146 218 return EOK; 147 219 } 148 220 149 150 221 static int arp_clear_device_req(int arp_phone, device_id_t device_id) 151 222 { 152 arp_device_t *device; 153 154 fibril_rwlock_write_lock(&arp_globals.lock); 155 device = arp_cache_find(&arp_globals.cache, device_id); 223 fibril_mutex_lock(&arp_globals.lock); 224 225 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id); 156 226 if (!device) { 157 fibril_ rwlock_write_unlock(&arp_globals.lock);227 fibril_mutex_unlock(&arp_globals.lock); 158 228 return ENOENT; 159 229 } 230 160 231 arp_clear_device(device); 161 printf("Device %d cleared\n", device_id);162 fibril_ rwlock_write_unlock(&arp_globals.lock);232 233 fibril_mutex_unlock(&arp_globals.lock); 163 234 return EOK; 164 235 } 165 236 166 /** Creates new protocol specific data. 167 * 168 * Allocates and returns the needed memory block as the proto parameter. 169 * 170 * @param[out] proto The allocated protocol specific data. 171 * @param[in] service The protocol module service. 172 * @param[in] address The actual protocol device address. 173 * @return EOK on success. 174 * @return ENOMEM if there is not enough memory left. 237 /** Create new protocol specific data. 238 * 239 * Allocate and return the needed memory block as the proto parameter. 240 * 241 * @param[out] proto Allocated protocol specific data. 242 * @param[in] service Protocol module service. 243 * @param[in] address Actual protocol device address. 244 * 245 * @return EOK on success. 246 * @return ENOMEM if there is not enough memory left. 247 * 175 248 */ 176 249 static int arp_proto_create(arp_proto_t **proto, services_t service, 177 250 measured_string_t *address) 178 251 { 179 int rc;180 181 252 *proto = (arp_proto_t *) malloc(sizeof(arp_proto_t)); 182 253 if (!*proto) … … 187 258 (*proto)->addr_data = address->value; 188 259 189 rc = arp_addr_initialize(&(*proto)->addresses);260 int rc = arp_addr_initialize(&(*proto)->addresses); 190 261 if (rc != EOK) { 191 262 free(*proto); … … 196 267 } 197 268 198 /** Registers the device. 199 * 200 * Creates new device entry in the cache or updates the protocol address if the 201 * device with the device identifier and the driver service exists. 202 * 203 * @param[in] device_id The device identifier. 204 * @param[in] service The device driver service. 205 * @param[in] protocol The protocol service. 206 * @param[in] address The actual device protocol address. 207 * @return EOK on success. 208 * @return EEXIST if another device with the same device identifier 209 * and different driver service exists. 210 * @return ENOMEM if there is not enough memory left. 211 * @return Other error codes as defined for the 212 * measured_strings_return() function. 213 */ 214 static int arp_device_message(device_id_t device_id, services_t service, 215 services_t protocol, measured_string_t *address) 216 { 217 arp_device_t *device; 218 arp_proto_t *proto; 219 hw_type_t hardware; 220 int index; 269 /** Process the received ARP packet. 270 * 271 * Update the source hardware address if the source entry exists or the packet 272 * is targeted to my protocol address. 273 * 274 * Respond to the ARP request if the packet is the ARP request and is 275 * targeted to my address. 276 * 277 * @param[in] device_id Source device identifier. 278 * @param[in,out] packet Received packet. 279 * 280 * @return EOK on success and the packet is no longer needed. 281 * @return One on success and the packet has been reused. 282 * @return EINVAL if the packet is too small to carry an ARP 283 * packet. 284 * @return EINVAL if the received address lengths differs from 285 * the registered values. 286 * @return ENOENT if the device is not found in the cache. 287 * @return ENOENT if the protocol for the device is not found in 288 * the cache. 289 * @return ENOMEM if there is not enough memory left. 290 * 291 */ 292 static int arp_receive_message(device_id_t device_id, packet_t *packet) 293 { 221 294 int rc; 222 223 fibril_rwlock_write_lock(&arp_globals.lock); 224 225 /* An existing device? */ 226 device = arp_cache_find(&arp_globals.cache, device_id); 227 228 if (device) { 229 if (device->service != service) { 230 printf("Device %d already exists\n", device->device_id); 231 fibril_rwlock_write_unlock(&arp_globals.lock); 232 return EEXIST; 233 } 234 proto = arp_protos_find(&device->protos, protocol); 235 if (proto) { 236 free(proto->addr); 237 free(proto->addr_data); 238 proto->addr = address; 239 proto->addr_data = address->value; 240 } else { 241 rc = arp_proto_create(&proto, protocol, address); 242 if (rc != EOK) { 243 fibril_rwlock_write_unlock(&arp_globals.lock); 244 return rc; 245 } 246 index = arp_protos_add(&device->protos, proto->service, 247 proto); 248 if (index < 0) { 249 fibril_rwlock_write_unlock(&arp_globals.lock); 250 free(proto); 251 return index; 252 } 253 printf("New protocol added:\n\tdevice id\t= " 254 "%d\n\tproto\t= %d", device_id, protocol); 255 } 256 } else { 257 hardware = hardware_map(service); 258 if (!hardware) 259 return ENOENT; 260 261 /* Create a new device */ 262 device = (arp_device_t *) malloc(sizeof(arp_device_t)); 263 if (!device) { 264 fibril_rwlock_write_unlock(&arp_globals.lock); 265 return ENOMEM; 266 } 267 device->hardware = hardware; 268 device->device_id = device_id; 269 rc = arp_protos_initialize(&device->protos); 270 if (rc != EOK) { 271 fibril_rwlock_write_unlock(&arp_globals.lock); 272 free(device); 273 return rc; 274 } 275 rc = arp_proto_create(&proto, protocol, address); 276 if (rc != EOK) { 277 fibril_rwlock_write_unlock(&arp_globals.lock); 278 free(device); 279 return rc; 280 } 281 index = arp_protos_add(&device->protos, proto->service, proto); 282 if (index < 0) { 283 fibril_rwlock_write_unlock(&arp_globals.lock); 284 arp_protos_destroy(&device->protos); 285 free(device); 286 return index; 287 } 288 device->service = service; 289 290 /* Bind the new one */ 291 device->phone = nil_bind_service(device->service, 292 (ipcarg_t) device->device_id, SERVICE_ARP, 293 arp_globals.client_connection); 294 if (device->phone < 0) { 295 fibril_rwlock_write_unlock(&arp_globals.lock); 296 arp_protos_destroy(&device->protos); 297 free(device); 298 return EREFUSED; 299 } 300 301 /* Get packet dimensions */ 302 rc = nil_packet_size_req(device->phone, device_id, 303 &device->packet_dimension); 304 if (rc != EOK) { 305 fibril_rwlock_write_unlock(&arp_globals.lock); 306 arp_protos_destroy(&device->protos); 307 free(device); 308 return rc; 309 } 310 311 /* Get hardware address */ 312 rc = nil_get_addr_req(device->phone, device_id, &device->addr, 313 &device->addr_data); 314 if (rc != EOK) { 315 fibril_rwlock_write_unlock(&arp_globals.lock); 316 arp_protos_destroy(&device->protos); 317 free(device); 318 return rc; 319 } 320 321 /* Get broadcast address */ 322 rc = nil_get_broadcast_addr_req(device->phone, device_id, 323 &device->broadcast_addr, &device->broadcast_data); 324 if (rc != EOK) { 325 fibril_rwlock_write_unlock(&arp_globals.lock); 326 free(device->addr); 327 free(device->addr_data); 328 arp_protos_destroy(&device->protos); 329 free(device); 330 return rc; 331 } 332 333 rc = arp_cache_add(&arp_globals.cache, device->device_id, 334 device); 335 if (rc != EOK) { 336 fibril_rwlock_write_unlock(&arp_globals.lock); 337 free(device->addr); 338 free(device->addr_data); 339 free(device->broadcast_addr); 340 free(device->broadcast_data); 341 arp_protos_destroy(&device->protos); 342 free(device); 343 return rc; 344 } 345 printf("%s: Device registered (id: %d, type: 0x%x, service: %d," 346 " proto: %d)\n", NAME, device->device_id, device->hardware, 347 device->service, protocol); 348 } 349 fibril_rwlock_write_unlock(&arp_globals.lock); 350 351 return EOK; 352 } 353 354 /** Initializes the ARP module. 355 * 356 * @param[in] client_connection The client connection processing function. 357 * The module skeleton propagates its own one. 358 * @return EOK on success. 359 * @return ENOMEM if there is not enough memory left. 360 */ 361 int arp_initialize(async_client_conn_t client_connection) 362 { 363 int rc; 364 365 fibril_rwlock_initialize(&arp_globals.lock); 366 fibril_rwlock_write_lock(&arp_globals.lock); 367 arp_globals.client_connection = client_connection; 368 rc = arp_cache_initialize(&arp_globals.cache); 369 fibril_rwlock_write_unlock(&arp_globals.lock); 370 371 return rc; 372 } 373 374 /** Updates the device content length according to the new MTU value. 375 * 376 * @param[in] device_id The device identifier. 377 * @param[in] mtu The new mtu value. 378 * @return ENOENT if device is not found. 379 * @return EOK on success. 380 */ 381 static int arp_mtu_changed_message(device_id_t device_id, size_t mtu) 382 { 383 arp_device_t *device; 384 385 fibril_rwlock_write_lock(&arp_globals.lock); 386 device = arp_cache_find(&arp_globals.cache, device_id); 387 if (!device) { 388 fibril_rwlock_write_unlock(&arp_globals.lock); 389 return ENOENT; 390 } 391 device->packet_dimension.content = mtu; 392 fibril_rwlock_write_unlock(&arp_globals.lock); 393 printf("arp - device %d changed mtu to %zu\n\n", device_id, mtu); 394 return EOK; 395 } 396 397 /** Processes the received ARP packet. 398 * 399 * Updates the source hardware address if the source entry exists or the packet 400 * is targeted to my protocol address. 401 * Responses to the ARP request if the packet is the ARP request and is 402 * targeted to my address. 403 * 404 * @param[in] device_id The source device identifier. 405 * @param[in,out] packet The received packet. 406 * @return EOK on success and the packet is no longer needed. 407 * @return One on success and the packet has been reused. 408 * @return EINVAL if the packet is too small to carry an ARP 409 * packet. 410 * @return EINVAL if the received address lengths differs from 411 * the registered values. 412 * @return ENOENT if the device is not found in the cache. 413 * @return ENOENT if the protocol for the device is not found in 414 * the cache. 415 * @return ENOMEM if there is not enough memory left. 416 */ 417 static int arp_receive_message(device_id_t device_id, packet_t *packet) 418 { 419 size_t length; 420 arp_header_t *header; 421 arp_device_t *device; 422 arp_proto_t *proto; 423 measured_string_t *hw_source; 424 uint8_t *src_hw; 425 uint8_t *src_proto; 426 uint8_t *des_hw; 427 uint8_t *des_proto; 428 int rc; 429 430 length = packet_get_data_length(packet); 295 296 size_t length = packet_get_data_length(packet); 431 297 if (length <= sizeof(arp_header_t)) 432 298 return EINVAL; 433 434 device = arp_cache_find(&arp_globals.cache, device_id);299 300 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id); 435 301 if (!device) 436 302 return ENOENT; 437 438 header = (arp_header_t *) packet_get_data(packet);303 304 arp_header_t *header = (arp_header_t *) packet_get_data(packet); 439 305 if ((ntohs(header->hardware) != device->hardware) || 440 306 (length < sizeof(arp_header_t) + header->hardware_length * 2U + … … 442 308 return EINVAL; 443 309 } 444 445 proto = arp_protos_find(&device->protos,310 311 arp_proto_t *proto = arp_protos_find(&device->protos, 446 312 protocol_unmap(device->service, ntohs(header->protocol))); 447 313 if (!proto) 448 314 return ENOENT; 449 450 src_hw = ((uint8_t *) header) + sizeof(arp_header_t); 451 src_proto = src_hw + header->hardware_length; 452 des_hw = src_proto + header->protocol_length; 453 des_proto = des_hw + header->hardware_length; 454 hw_source = arp_addr_find(&proto->addresses, (char *) src_proto, 455 CONVERT_SIZE(uint8_t, char, header->protocol_length)); 456 /* Exists? */ 457 if (hw_source) { 458 if (hw_source->length != CONVERT_SIZE(uint8_t, char, 459 header->hardware_length)) { 315 316 uint8_t *src_hw = ((uint8_t *) header) + sizeof(arp_header_t); 317 uint8_t *src_proto = src_hw + header->hardware_length; 318 uint8_t *des_hw = src_proto + header->protocol_length; 319 uint8_t *des_proto = des_hw + header->hardware_length; 320 321 arp_trans_t *trans = arp_addr_find(&proto->addresses, src_proto, 322 header->protocol_length); 323 324 if ((trans) && (trans->hw_addr)) { 325 /* Translation exists */ 326 if (trans->hw_addr->length != header->hardware_length) 460 327 return EINVAL; 461 } 462 memcpy(hw_source->value, src_hw, hw_source->length); 463 } 328 329 memcpy(trans->hw_addr->value, src_hw, trans->hw_addr->length); 330 } 331 464 332 /* Is my protocol address? */ 465 if (proto->addr->length != CONVERT_SIZE(uint8_t, char, 466 header->protocol_length)) { 333 if (proto->addr->length != header->protocol_length) 467 334 return EINVAL; 468 } 469 if (!str_lcmp(proto->addr->value, (char *) des_proto, 470 proto->addr->length)) { 471 /* Not already updated? */ 472 if (!hw_source) { 473 hw_source = measured_string_create_bulk((char *) src_hw, 474 CONVERT_SIZE(uint8_t, char, 475 header->hardware_length)); 476 if (!hw_source) 335 336 if (!bcmp(proto->addr->value, des_proto, proto->addr->length)) { 337 if (!trans) { 338 /* Update the translation */ 339 trans = (arp_trans_t *) malloc(sizeof(arp_trans_t)); 340 if (!trans) 477 341 return ENOMEM; 478 479 rc = arp_addr_add(&proto->addresses, (char *) src_proto, 480 CONVERT_SIZE(uint8_t, char, 481 header->protocol_length), hw_source); 482 if (rc != EOK) 342 343 trans->hw_addr = NULL; 344 fibril_condvar_initialize(&trans->cv); 345 rc = arp_addr_add(&proto->addresses, src_proto, 346 header->protocol_length, trans); 347 if (rc != EOK) { 348 /* The generic char map has already freed trans! */ 483 349 return rc; 484 } 350 } 351 } 352 353 if (!trans->hw_addr) { 354 trans->hw_addr = measured_string_create_bulk(src_hw, 355 header->hardware_length); 356 if (!trans->hw_addr) 357 return ENOMEM; 358 359 /* Notify the fibrils that wait for the translation. */ 360 fibril_condvar_broadcast(&trans->cv); 361 } 362 485 363 if (ntohs(header->operation) == ARPOP_REQUEST) { 486 364 header->operation = htons(ARPOP_REPLY); … … 490 368 memcpy(src_hw, device->addr->value, 491 369 device->packet_dimension.addr_len); 492 memcpy(des_hw, hw_source->value,370 memcpy(des_hw, trans->hw_addr->value, 493 371 header->hardware_length); 494 372 … … 503 381 } 504 382 } 505 383 506 384 return EOK; 507 385 } 508 386 509 510 /** Returns the hardware address for the given protocol address. 511 * 512 * Sends the ARP request packet if the hardware address is not found in the 513 * cache. 514 * 515 * @param[in] device_id The device identifier. 516 * @param[in] protocol The protocol service. 517 * @param[in] target The target protocol address. 518 * @return The hardware address of the target. 519 * @return NULL if the target parameter is NULL. 520 * @return NULL if the device is not found. 521 * @return NULL if the device packet is too small to send a 522 * request. 523 * @return NULL if the hardware address is not found in the cache. 524 */ 525 static measured_string_t * 526 arp_translate_message(device_id_t device_id, services_t protocol, 527 measured_string_t *target) 528 { 529 arp_device_t *device; 530 arp_proto_t *proto; 531 measured_string_t *addr; 532 size_t length; 387 /** Update the device content length according to the new MTU value. 388 * 389 * @param[in] device_id Device identifier. 390 * @param[in] mtu New MTU value. 391 * 392 * @return ENOENT if device is not found. 393 * @return EOK on success. 394 * 395 */ 396 static int arp_mtu_changed_message(device_id_t device_id, size_t mtu) 397 { 398 fibril_mutex_lock(&arp_globals.lock); 399 400 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id); 401 if (!device) { 402 fibril_mutex_unlock(&arp_globals.lock); 403 return ENOENT; 404 } 405 406 device->packet_dimension.content = mtu; 407 408 fibril_mutex_unlock(&arp_globals.lock); 409 410 printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu); 411 412 return EOK; 413 } 414 415 /** Process IPC messages from the registered device driver modules 416 * 417 * @param[in] iid Message identifier. 418 * @param[in,out] icall Message parameters. 419 * 420 */ 421 static void arp_receiver(ipc_callid_t iid, ipc_call_t *icall) 422 { 533 423 packet_t *packet; 534 arp_header_t *header; 535 536 if (!target) 537 return NULL; 538 539 device = arp_cache_find(&arp_globals.cache, device_id); 540 if (!device) 541 return NULL; 542 543 proto = arp_protos_find(&device->protos, protocol); 544 if (!proto || (proto->addr->length != target->length)) 545 return NULL; 546 547 addr = arp_addr_find(&proto->addresses, target->value, target->length); 548 if (addr) 549 return addr; 550 424 int rc; 425 426 while (true) { 427 switch (IPC_GET_IMETHOD(*icall)) { 428 case NET_IL_DEVICE_STATE: 429 /* Do nothing - keep the cache */ 430 ipc_answer_0(iid, (sysarg_t) EOK); 431 break; 432 433 case NET_IL_RECEIVED: 434 rc = packet_translate_remote(arp_globals.net_phone, &packet, 435 IPC_GET_PACKET(*icall)); 436 if (rc == EOK) { 437 fibril_mutex_lock(&arp_globals.lock); 438 do { 439 packet_t *next = pq_detach(packet); 440 rc = arp_receive_message(IPC_GET_DEVICE(*icall), packet); 441 if (rc != 1) { 442 pq_release_remote(arp_globals.net_phone, 443 packet_get_id(packet)); 444 } 445 446 packet = next; 447 } while (packet); 448 fibril_mutex_unlock(&arp_globals.lock); 449 } 450 ipc_answer_0(iid, (sysarg_t) rc); 451 break; 452 453 case NET_IL_MTU_CHANGED: 454 rc = arp_mtu_changed_message(IPC_GET_DEVICE(*icall), 455 IPC_GET_MTU(*icall)); 456 ipc_answer_0(iid, (sysarg_t) rc); 457 break; 458 459 default: 460 ipc_answer_0(iid, (sysarg_t) ENOTSUP); 461 } 462 463 iid = async_get_call(icall); 464 } 465 } 466 467 /** Register the device. 468 * 469 * Create new device entry in the cache or update the protocol address if the 470 * device with the device identifier and the driver service exists. 471 * 472 * @param[in] device_id Device identifier. 473 * @param[in] service Device driver service. 474 * @param[in] protocol Protocol service. 475 * @param[in] address Actual device protocol address. 476 * 477 * @return EOK on success. 478 * @return EEXIST if another device with the same device identifier 479 * and different driver service exists. 480 * @return ENOMEM if there is not enough memory left. 481 * @return Other error codes as defined for the 482 * measured_strings_return() function. 483 * 484 */ 485 static int arp_device_message(device_id_t device_id, services_t service, 486 services_t protocol, measured_string_t *address) 487 { 488 int index; 489 int rc; 490 491 fibril_mutex_lock(&arp_globals.lock); 492 493 /* An existing device? */ 494 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id); 495 if (device) { 496 if (device->service != service) { 497 printf("%s: Device %d already exists\n", NAME, 498 device->device_id); 499 fibril_mutex_unlock(&arp_globals.lock); 500 return EEXIST; 501 } 502 503 arp_proto_t *proto = arp_protos_find(&device->protos, protocol); 504 if (proto) { 505 free(proto->addr); 506 free(proto->addr_data); 507 proto->addr = address; 508 proto->addr_data = address->value; 509 } else { 510 rc = arp_proto_create(&proto, protocol, address); 511 if (rc != EOK) { 512 fibril_mutex_unlock(&arp_globals.lock); 513 return rc; 514 } 515 516 index = arp_protos_add(&device->protos, proto->service, 517 proto); 518 if (index < 0) { 519 fibril_mutex_unlock(&arp_globals.lock); 520 free(proto); 521 return index; 522 } 523 524 printf("%s: New protocol added (id: %d, proto: %d)\n", NAME, 525 device_id, protocol); 526 } 527 } else { 528 hw_type_t hardware = hardware_map(service); 529 if (!hardware) 530 return ENOENT; 531 532 /* Create new device */ 533 device = (arp_device_t *) malloc(sizeof(arp_device_t)); 534 if (!device) { 535 fibril_mutex_unlock(&arp_globals.lock); 536 return ENOMEM; 537 } 538 539 device->hardware = hardware; 540 device->device_id = device_id; 541 rc = arp_protos_initialize(&device->protos); 542 if (rc != EOK) { 543 fibril_mutex_unlock(&arp_globals.lock); 544 free(device); 545 return rc; 546 } 547 548 arp_proto_t *proto; 549 rc = arp_proto_create(&proto, protocol, address); 550 if (rc != EOK) { 551 fibril_mutex_unlock(&arp_globals.lock); 552 free(device); 553 return rc; 554 } 555 556 index = arp_protos_add(&device->protos, proto->service, proto); 557 if (index < 0) { 558 fibril_mutex_unlock(&arp_globals.lock); 559 arp_protos_destroy(&device->protos); 560 free(device); 561 return index; 562 } 563 564 device->service = service; 565 566 /* Bind */ 567 device->phone = nil_bind_service(device->service, 568 (sysarg_t) device->device_id, SERVICE_ARP, 569 arp_receiver); 570 if (device->phone < 0) { 571 fibril_mutex_unlock(&arp_globals.lock); 572 arp_protos_destroy(&device->protos); 573 free(device); 574 return EREFUSED; 575 } 576 577 /* Get packet dimensions */ 578 rc = nil_packet_size_req(device->phone, device_id, 579 &device->packet_dimension); 580 if (rc != EOK) { 581 fibril_mutex_unlock(&arp_globals.lock); 582 arp_protos_destroy(&device->protos); 583 free(device); 584 return rc; 585 } 586 587 /* Get hardware address */ 588 rc = nil_get_addr_req(device->phone, device_id, &device->addr, 589 &device->addr_data); 590 if (rc != EOK) { 591 fibril_mutex_unlock(&arp_globals.lock); 592 arp_protos_destroy(&device->protos); 593 free(device); 594 return rc; 595 } 596 597 /* Get broadcast address */ 598 rc = nil_get_broadcast_addr_req(device->phone, device_id, 599 &device->broadcast_addr, &device->broadcast_data); 600 if (rc != EOK) { 601 fibril_mutex_unlock(&arp_globals.lock); 602 free(device->addr); 603 free(device->addr_data); 604 arp_protos_destroy(&device->protos); 605 free(device); 606 return rc; 607 } 608 609 rc = arp_cache_add(&arp_globals.cache, device->device_id, 610 device); 611 if (rc != EOK) { 612 fibril_mutex_unlock(&arp_globals.lock); 613 free(device->addr); 614 free(device->addr_data); 615 free(device->broadcast_addr); 616 free(device->broadcast_data); 617 arp_protos_destroy(&device->protos); 618 free(device); 619 return rc; 620 } 621 printf("%s: Device registered (id: %d, type: 0x%x, service: %d," 622 " proto: %d)\n", NAME, device->device_id, device->hardware, 623 device->service, protocol); 624 } 625 626 fibril_mutex_unlock(&arp_globals.lock); 627 return EOK; 628 } 629 630 int il_initialize(int net_phone) 631 { 632 fibril_mutex_initialize(&arp_globals.lock); 633 634 fibril_mutex_lock(&arp_globals.lock); 635 arp_globals.net_phone = net_phone; 636 int rc = arp_cache_initialize(&arp_globals.cache); 637 fibril_mutex_unlock(&arp_globals.lock); 638 639 return rc; 640 } 641 642 static int arp_send_request(device_id_t device_id, services_t protocol, 643 measured_string_t *target, arp_device_t *device, arp_proto_t *proto) 644 { 551 645 /* ARP packet content size = header + (address + translation) * 2 */ 552 length = 8 + 2 * (CONVERT_SIZE(char, uint8_t, proto->addr->length) + 553 CONVERT_SIZE(char, uint8_t, device->addr->length)); 646 size_t length = 8 + 2 * (proto->addr->length + device->addr->length); 554 647 if (length > device->packet_dimension.content) 555 return NULL;556 557 packet = packet_get_4_remote(arp_globals.net_phone,648 return ELIMIT; 649 650 packet_t *packet = packet_get_4_remote(arp_globals.net_phone, 558 651 device->packet_dimension.addr_len, device->packet_dimension.prefix, 559 652 length, device->packet_dimension.suffix); 560 653 if (!packet) 561 return NULL;562 563 header = (arp_header_t *) packet_suffix(packet, length);654 return ENOMEM; 655 656 arp_header_t *header = (arp_header_t *) packet_suffix(packet, length); 564 657 if (!header) { 565 658 pq_release_remote(arp_globals.net_phone, packet_get_id(packet)); 566 return NULL;567 } 568 659 return ENOMEM; 660 } 661 569 662 header->hardware = htons(device->hardware); 570 663 header->hardware_length = (uint8_t) device->addr->length; … … 572 665 header->protocol_length = (uint8_t) proto->addr->length; 573 666 header->operation = htons(ARPOP_REQUEST); 667 574 668 length = sizeof(arp_header_t); 669 575 670 memcpy(((uint8_t *) header) + length, device->addr->value, 576 671 device->addr->length); … … 582 677 length += device->addr->length; 583 678 memcpy(((uint8_t *) header) + length, target->value, target->length); 584 585 i f (packet_set_addr(packet, (uint8_t *) device->addr->value,586 (uint8_t *) device->broadcast_addr->value, 587 CONVERT_SIZE(char, uint8_t, device->addr->length))!= EOK) {679 680 int rc = packet_set_addr(packet, (uint8_t *) device->addr->value, 681 (uint8_t *) device->broadcast_addr->value, device->addr->length); 682 if (rc != EOK) { 588 683 pq_release_remote(arp_globals.net_phone, packet_get_id(packet)); 589 return NULL;590 } 591 684 return rc; 685 } 686 592 687 nil_send_msg(device->phone, device_id, packet, SERVICE_ARP); 593 return NULL; 594 } 595 596 597 /** Processes the ARP message. 598 * 599 * @param[in] callid The message identifier. 600 * @param[in] call The message parameters. 601 * @param[out] answer The message answer parameters. 602 * @param[out] answer_count The last parameter for the actual answer in the 603 * answer parameter. 604 * @return EOK on success. 605 * @return ENOTSUP if the message is not known. 688 return EOK; 689 } 690 691 /** Return the hardware address for the given protocol address. 692 * 693 * Send the ARP request packet if the hardware address is not found in the 694 * cache. 695 * 696 * @param[in] device_id Device identifier. 697 * @param[in] protocol Protocol service. 698 * @param[in] target Target protocol address. 699 * @param[out] translation Where the hardware address of the target is stored. 700 * 701 * @return EOK on success. 702 * @return EAGAIN if the caller should try again. 703 * @return Other error codes in case of error. 704 * 705 */ 706 static int arp_translate_message(device_id_t device_id, services_t protocol, 707 measured_string_t *target, measured_string_t **translation) 708 { 709 bool retry = false; 710 int rc; 711 712 assert(fibril_mutex_is_locked(&arp_globals.lock)); 713 714 restart: 715 if ((!target) || (!translation)) 716 return EBADMEM; 717 718 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id); 719 if (!device) 720 return ENOENT; 721 722 arp_proto_t *proto = arp_protos_find(&device->protos, protocol); 723 if ((!proto) || (proto->addr->length != target->length)) 724 return ENOENT; 725 726 arp_trans_t *trans = arp_addr_find(&proto->addresses, target->value, 727 target->length); 728 if (trans) { 729 if (trans->hw_addr) { 730 /* The translation is in place. */ 731 *translation = trans->hw_addr; 732 return EOK; 733 } 734 735 if (retry) { 736 /* 737 * We may get here as a result of being signalled for 738 * some reason while waiting for the translation (e.g. 739 * translation becoming available, record being removed 740 * from the table) and then losing the race for 741 * the arp_globals.lock with someone else who modified 742 * the table. 743 * 744 * Remove the incomplete record so that it is possible 745 * to make new ARP requests. 746 */ 747 arp_clear_trans(trans); 748 arp_addr_exclude(&proto->addresses, target->value, 749 target->length); 750 return EAGAIN; 751 } 752 753 /* 754 * We are a random passer-by who merely joins an already waiting 755 * fibril in waiting for the translation. 756 */ 757 rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock, 758 ARP_TRANS_WAIT); 759 if (rc == ETIMEOUT) 760 return ENOENT; 761 762 /* 763 * Need to recheck because we did not hold the lock while 764 * sleeping on the condition variable. 765 */ 766 retry = true; 767 goto restart; 768 } 769 770 if (retry) 771 return EAGAIN; 772 773 /* 774 * We are under the protection of arp_globals.lock, so we can afford to 775 * first send the ARP request and then insert an incomplete ARP record. 776 * The incomplete record is used to tell any other potential waiter 777 * that this fibril has already sent the request and that it is waiting 778 * for the answer. Lastly, any fibril which sees the incomplete request 779 * can perform a timed wait on its condition variable to wait for the 780 * ARP reply to arrive. 781 */ 782 783 rc = arp_send_request(device_id, protocol, target, device, proto); 784 if (rc != EOK) 785 return rc; 786 787 trans = (arp_trans_t *) malloc(sizeof(arp_trans_t)); 788 if (!trans) 789 return ENOMEM; 790 791 trans->hw_addr = NULL; 792 fibril_condvar_initialize(&trans->cv); 793 794 rc = arp_addr_add(&proto->addresses, target->value, target->length, 795 trans); 796 if (rc != EOK) { 797 /* The generic char map has already freed trans! */ 798 return rc; 799 } 800 801 rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock, 802 ARP_TRANS_WAIT); 803 if (rc == ETIMEOUT) { 804 /* 805 * Remove the incomplete record so that it is possible to make 806 * new ARP requests. 807 */ 808 arp_clear_trans(trans); 809 arp_addr_exclude(&proto->addresses, target->value, 810 target->length); 811 return ENOENT; 812 } 813 814 /* 815 * We need to recheck that the translation has indeed become available, 816 * because we dropped the arp_globals.lock while sleeping on the 817 * condition variable and someone else might have e.g. removed the 818 * translation before we managed to lock arp_globals.lock again. 819 */ 820 821 retry = true; 822 goto restart; 823 } 824 825 /** Process the ARP message. 826 * 827 * @param[in] callid Message identifier. 828 * @param[in] call Message parameters. 829 * @param[out] answer Answer. 830 * @param[out] count Number of arguments of the answer. 831 * 832 * @return EOK on success. 833 * @return ENOTSUP if the message is not known. 606 834 * 607 835 * @see arp_interface.h 608 836 * @see IS_NET_ARP_MESSAGE() 609 * /610 int 611 arp_message_standalone(ipc_callid_t callid, ipc_call_t *call,612 ipc_call_t *answer, int *answer_count)837 * 838 */ 839 int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer, 840 size_t *count) 613 841 { 614 842 measured_string_t *address; 615 843 measured_string_t *translation; 616 char *data; 617 packet_t *packet; 618 packet_t *next; 844 uint8_t *data; 619 845 int rc; 620 846 621 * answer_count = 0;622 switch (IPC_GET_ METHOD(*call)) {847 *count = 0; 848 switch (IPC_GET_IMETHOD(*call)) { 623 849 case IPC_M_PHONE_HUNGUP: 624 850 return EOK; … … 629 855 return rc; 630 856 631 rc = arp_device_message(IPC_GET_DEVICE( call),632 IPC_GET_SERVICE( call), ARP_GET_NETIF(call), address);857 rc = arp_device_message(IPC_GET_DEVICE(*call), 858 IPC_GET_SERVICE(*call), ARP_GET_NETIF(*call), address); 633 859 if (rc != EOK) { 634 860 free(address); 635 861 free(data); 636 862 } 863 637 864 return rc; 638 865 … … 642 869 return rc; 643 870 644 fibril_ rwlock_read_lock(&arp_globals.lock);645 translation = arp_translate_message(IPC_GET_DEVICE(call),646 IPC_GET_SERVICE( call), address);871 fibril_mutex_lock(&arp_globals.lock); 872 rc = arp_translate_message(IPC_GET_DEVICE(*call), 873 IPC_GET_SERVICE(*call), address, &translation); 647 874 free(address); 648 875 free(data); 876 877 if (rc != EOK) { 878 fibril_mutex_unlock(&arp_globals.lock); 879 return rc; 880 } 881 649 882 if (!translation) { 650 fibril_ rwlock_read_unlock(&arp_globals.lock);883 fibril_mutex_unlock(&arp_globals.lock); 651 884 return ENOENT; 652 885 } 886 653 887 rc = measured_strings_reply(translation, 1); 654 fibril_ rwlock_read_unlock(&arp_globals.lock);888 fibril_mutex_unlock(&arp_globals.lock); 655 889 return rc; 656 890 657 891 case NET_ARP_CLEAR_DEVICE: 658 return arp_clear_device_req(0, IPC_GET_DEVICE( call));659 892 return arp_clear_device_req(0, IPC_GET_DEVICE(*call)); 893 660 894 case NET_ARP_CLEAR_ADDRESS: 661 895 rc = measured_strings_receive(&address, &data, 1); … … 663 897 return rc; 664 898 665 arp_clear_address_req(0, IPC_GET_DEVICE( call),666 IPC_GET_SERVICE( call), address);899 arp_clear_address_req(0, IPC_GET_DEVICE(*call), 900 IPC_GET_SERVICE(*call), address); 667 901 free(address); 668 902 free(data); … … 671 905 case NET_ARP_CLEAN_CACHE: 672 906 return arp_clean_cache_req(0); 673 674 case NET_IL_DEVICE_STATE:675 /* Do nothing - keep the cache */676 return EOK;677 678 case NET_IL_RECEIVED:679 rc = packet_translate_remote(arp_globals.net_phone, &packet,680 IPC_GET_PACKET(call));681 if (rc != EOK)682 return rc;683 684 fibril_rwlock_read_lock(&arp_globals.lock);685 do {686 next = pq_detach(packet);687 rc = arp_receive_message(IPC_GET_DEVICE(call), packet);688 if (rc != 1) {689 pq_release_remote(arp_globals.net_phone,690 packet_get_id(packet));691 }692 packet = next;693 } while (packet);694 fibril_rwlock_read_unlock(&arp_globals.lock);695 696 return EOK;697 698 case NET_IL_MTU_CHANGED:699 return arp_mtu_changed_message(IPC_GET_DEVICE(call),700 IPC_GET_MTU(call));701 907 } 702 908 … … 704 910 } 705 911 706 /** Default thread for new connections.707 *708 * @param[in] iid The initial message identifier.709 * @param[in] icall The initial message call structure.710 */711 static void il_client_connection(ipc_callid_t iid, ipc_call_t *icall)712 {713 /*714 * Accept the connection715 * - Answer the first IPC_M_CONNECT_ME_TO call.716 */717 ipc_answer_0(iid, EOK);718 719 while (true) {720 ipc_call_t answer;721 int answer_count;722 723 /* Clear the answer structure */724 refresh_answer(&answer, &answer_count);725 726 /* Fetch the next message */727 ipc_call_t call;728 ipc_callid_t callid = async_get_call(&call);729 730 /* Process the message */731 int res = il_module_message_standalone(callid, &call, &answer,732 &answer_count);733 734 /*735 * End if told to either by the message or the processing736 * result.737 */738 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||739 (res == EHANGUP))740 return;741 742 /* Answer the message */743 answer_call(callid, res, &answer, answer_count);744 }745 }746 747 /** Starts the module.748 *749 * @return EOK on success.750 * @return Other error codes as defined for each specific module751 * start function.752 */753 912 int main(int argc, char *argv[]) 754 913 { 755 int rc;756 757 914 /* Start the module */ 758 rc = il_module_start_standalone(il_client_connection); 759 return rc; 915 return il_module_start(SERVICE_ARP); 760 916 } 761 917 762 918 /** @} 763 919 */ 764
Note:
See TracChangeset
for help on using the changeset viewer.