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