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