Changes in uspace/srv/net/il/arp/arp.c [ffa2c8ef:7e752b2] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/il/arp/arp.c
rffa2c8ef r7e752b2 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> 45 49 #include <task.h> 46 50 #include <adt/measured_strings.h> 51 #include <ipc/ipc.h> 47 52 #include <ipc/services.h> 48 53 #include <ipc/net.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. */ 66 72 #define NAME "arp" 67 73 68 /** Number of microseconds to wait for an ARP reply. */69 #define ARP_TRANS_WAIT 100000070 71 /** @name ARP operation codes definitions */72 /*@{*/73 74 /** REQUEST operation code. */75 #define ARPOP_REQUEST 176 77 /** REPLY operation code. */78 #define ARPOP_REPLY 279 80 /*@}*/81 82 /** Type definition of an ARP protocol header.83 * @see arp_header84 */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.h92 */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.h105 */106 uint16_t operation;107 } __attribute__ ((packed));108 109 74 /** ARP global data. */ 110 75 arp_globals_t arp_globals; … … 112 77 DEVICE_MAP_IMPLEMENT(arp_cache, arp_device_t); 113 78 INT_MAP_IMPLEMENT(arp_protos, arp_proto_t); 114 GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, arp_trans_t); 115 116 static void arp_clear_trans(arp_trans_t *trans) 117 { 118 if (trans->hw_addr) { 119 free(trans->hw_addr); 120 trans->hw_addr = NULL; 121 } 122 123 fibril_condvar_broadcast(&trans->cv); 124 } 125 126 static void arp_clear_addr(arp_addr_t *addresses) 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. 84 */ 85 static void arp_clear_device(arp_device_t *device) 127 86 { 128 87 int count; 129 130 for (count = arp_addr_count(addresses) - 1; count >= 0; count--) { 131 arp_trans_t *trans = arp_addr_items_get_index(&addresses->values, 132 count); 133 if (trans) 134 arp_clear_trans(trans); 135 } 136 } 137 138 /** Clear the device specific data. 139 * 140 * @param[in] device Device specific data. 141 */ 142 static void arp_clear_device(arp_device_t *device) 143 { 144 int count; 145 88 arp_proto_t *proto; 89 146 90 for (count = arp_protos_count(&device->protos) - 1; count >= 0; 147 91 count--) { 148 arp_proto_t *proto = arp_protos_get_index(&device->protos, 149 count); 150 92 proto = arp_protos_get_index(&device->protos, count); 151 93 if (proto) { 152 94 if (proto->addr) 153 95 free(proto->addr); 154 155 96 if (proto->addr_data) 156 97 free(proto->addr_data); 157 158 arp_clear_addr(&proto->addresses);159 98 arp_addr_destroy(&proto->addresses); 160 99 } 161 100 } 162 163 101 arp_protos_clear(&device->protos); 164 102 } … … 167 105 { 168 106 int count; 169 170 fibril_mutex_lock(&arp_globals.lock); 107 arp_device_t *device; 108 109 fibril_rwlock_write_lock(&arp_globals.lock); 171 110 for (count = arp_cache_count(&arp_globals.cache) - 1; count >= 0; 172 111 count--) { 173 arp_device_t *device = arp_cache_get_index(&arp_globals.cache, 174 count); 175 112 device = arp_cache_get_index(&arp_globals.cache, count); 176 113 if (device) { 177 114 arp_clear_device(device); 178 115 if (device->addr_data) 179 116 free(device->addr_data); 180 181 117 if (device->broadcast_data) 182 118 free(device->broadcast_data); 183 119 } 184 120 } 185 186 121 arp_cache_clear(&arp_globals.cache); 187 fibril_ mutex_unlock(&arp_globals.lock);188 122 fibril_rwlock_write_unlock(&arp_globals.lock); 123 printf("Cache cleaned\n"); 189 124 return EOK; 190 125 } … … 193 128 services_t protocol, measured_string_t *address) 194 129 { 195 fibril_mutex_lock(&arp_globals.lock); 196 197 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id); 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); 198 135 if (!device) { 199 fibril_ mutex_unlock(&arp_globals.lock);136 fibril_rwlock_write_unlock(&arp_globals.lock); 200 137 return ENOENT; 201 138 } 202 203 arp_proto_t *proto = arp_protos_find(&device->protos, protocol); 139 proto = arp_protos_find(&device->protos, protocol); 204 140 if (!proto) { 205 fibril_ mutex_unlock(&arp_globals.lock);141 fibril_rwlock_write_unlock(&arp_globals.lock); 206 142 return ENOENT; 207 143 } 208 209 arp_trans_t *trans = arp_addr_find(&proto->addresses, address->value,210 address->length);211 if (trans)212 arp_clear_trans(trans);213 214 144 arp_addr_exclude(&proto->addresses, address->value, address->length); 215 216 fibril_mutex_unlock(&arp_globals.lock); 145 fibril_rwlock_write_unlock(&arp_globals.lock); 217 146 return EOK; 218 147 } 219 148 149 220 150 static int arp_clear_device_req(int arp_phone, device_id_t device_id) 221 151 { 222 fibril_mutex_lock(&arp_globals.lock); 223 224 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id); 152 arp_device_t *device; 153 154 fibril_rwlock_write_lock(&arp_globals.lock); 155 device = arp_cache_find(&arp_globals.cache, device_id); 225 156 if (!device) { 226 fibril_ mutex_unlock(&arp_globals.lock);157 fibril_rwlock_write_unlock(&arp_globals.lock); 227 158 return ENOENT; 228 159 } 229 230 160 arp_clear_device(device); 231 232 fibril_ mutex_unlock(&arp_globals.lock);161 printf("Device %d cleared\n", device_id); 162 fibril_rwlock_write_unlock(&arp_globals.lock); 233 163 return EOK; 234 164 } 235 165 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 * 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. 247 175 */ 248 176 static int arp_proto_create(arp_proto_t **proto, services_t service, 249 177 measured_string_t *address) 250 178 { 179 int rc; 180 251 181 *proto = (arp_proto_t *) malloc(sizeof(arp_proto_t)); 252 182 if (!*proto) … … 257 187 (*proto)->addr_data = address->value; 258 188 259 intrc = arp_addr_initialize(&(*proto)->addresses);189 rc = arp_addr_initialize(&(*proto)->addresses); 260 190 if (rc != EOK) { 261 191 free(*proto); … … 266 196 } 267 197 268 /** Process the received ARP packet. 269 * 270 * Update the source hardware address if the source entry exists or the packet 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; 221 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 271 400 * is targeted to my protocol address. 272 * 273 * Respond to the ARP request if the packet is the ARP request and is 401 * Responses to the ARP request if the packet is the ARP request and is 274 402 * targeted to my address. 275 403 * 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 * 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. 290 416 */ 291 417 static int arp_receive_message(device_id_t device_id, packet_t *packet) 292 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; 293 428 int rc; 294 295 size_tlength = packet_get_data_length(packet);429 430 length = packet_get_data_length(packet); 296 431 if (length <= sizeof(arp_header_t)) 297 432 return EINVAL; 298 299 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);433 434 device = arp_cache_find(&arp_globals.cache, device_id); 300 435 if (!device) 301 436 return ENOENT; 302 303 arp_header_t *header = (arp_header_t *) packet_get_data(packet);437 438 header = (arp_header_t *) packet_get_data(packet); 304 439 if ((ntohs(header->hardware) != device->hardware) || 305 440 (length < sizeof(arp_header_t) + header->hardware_length * 2U + … … 307 442 return EINVAL; 308 443 } 309 310 arp_proto_t *proto = arp_protos_find(&device->protos,444 445 proto = arp_protos_find(&device->protos, 311 446 protocol_unmap(device->service, ntohs(header->protocol))); 312 447 if (!proto) 313 448 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, 321 header->protocol_length); 322 323 if ((trans) && (trans->hw_addr)) { 324 /* Translation exists */ 325 if (trans->hw_addr->length != header->hardware_length) 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)) { 326 460 return EINVAL; 327 328 memcpy(trans->hw_addr->value, src_hw, trans->hw_addr->length); 329 } 330 461 } 462 memcpy(hw_source->value, src_hw, hw_source->length); 463 } 331 464 /* Is my protocol address? */ 332 if (proto->addr->length != header->protocol_length) 465 if (proto->addr->length != CONVERT_SIZE(uint8_t, char, 466 header->protocol_length)) { 333 467 return EINVAL; 334 335 if (!bcmp(proto->addr->value, des_proto, proto->addr->length)) { 336 if (!trans) { 337 /* Update the translation */ 338 trans = (arp_trans_t *) malloc(sizeof(arp_trans_t)); 339 if (!trans) 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) 340 477 return ENOMEM; 341 342 trans->hw_addr = NULL; 343 fibril_condvar_initialize(&trans->cv); 344 rc = arp_addr_add(&proto->addresses, src_proto, 345 header->protocol_length, trans); 346 if (rc != EOK) { 347 /* The generic char map has already freed trans! */ 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) 348 483 return rc; 349 } 350 } 351 352 if (!trans->hw_addr) { 353 trans->hw_addr = measured_string_create_bulk(src_hw, 354 header->hardware_length); 355 if (!trans->hw_addr) 356 return ENOMEM; 357 358 /* Notify the fibrils that wait for the translation. */ 359 fibril_condvar_broadcast(&trans->cv); 360 } 361 484 } 362 485 if (ntohs(header->operation) == ARPOP_REQUEST) { 363 486 header->operation = htons(ARPOP_REPLY); … … 367 490 memcpy(src_hw, device->addr->value, 368 491 device->packet_dimension.addr_len); 369 memcpy(des_hw, trans->hw_addr->value,492 memcpy(des_hw, hw_source->value, 370 493 header->hardware_length); 371 494 … … 380 503 } 381 504 } 382 505 383 506 return EOK; 384 507 } 385 508 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); 402 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 { 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; 422 533 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 async_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 async_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 async_answer_0(iid, (sysarg_t) rc); 456 break; 457 458 default: 459 async_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) 529 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 { 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 644 551 /* ARP packet content size = header + (address + translation) * 2 */ 645 size_t length = 8 + 2 * (proto->addr->length + device->addr->length); 552 length = 8 + 2 * (CONVERT_SIZE(char, uint8_t, proto->addr->length) + 553 CONVERT_SIZE(char, uint8_t, device->addr->length)); 646 554 if (length > device->packet_dimension.content) 647 return ELIMIT;648 649 packet _t *packet= packet_get_4_remote(arp_globals.net_phone,555 return NULL; 556 557 packet = packet_get_4_remote(arp_globals.net_phone, 650 558 device->packet_dimension.addr_len, device->packet_dimension.prefix, 651 559 length, device->packet_dimension.suffix); 652 560 if (!packet) 653 return ENOMEM;654 655 arp_header_t *header = (arp_header_t *) packet_suffix(packet, length);561 return NULL; 562 563 header = (arp_header_t *) packet_suffix(packet, length); 656 564 if (!header) { 657 565 pq_release_remote(arp_globals.net_phone, packet_get_id(packet)); 658 return ENOMEM;659 } 660 566 return NULL; 567 } 568 661 569 header->hardware = htons(device->hardware); 662 570 header->hardware_length = (uint8_t) device->addr->length; … … 664 572 header->protocol_length = (uint8_t) proto->addr->length; 665 573 header->operation = htons(ARPOP_REQUEST); 666 667 574 length = sizeof(arp_header_t); 668 669 575 memcpy(((uint8_t *) header) + length, device->addr->value, 670 576 device->addr->length); … … 676 582 length += device->addr->length; 677 583 memcpy(((uint8_t *) header) + length, target->value, target->length); 678 679 i nt rc =packet_set_addr(packet, (uint8_t *) device->addr->value,680 (uint8_t *) device->broadcast_addr->value, device->addr->length);681 if (rc!= EOK) {584 585 if (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) { 682 588 pq_release_remote(arp_globals.net_phone, packet_get_id(packet)); 683 return rc;684 } 685 589 return NULL; 590 } 591 686 592 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 assert(fibril_mutex_is_locked(&arp_globals.lock)); 712 713 restart: 714 if ((!target) || (!translation)) 715 return EBADMEM; 716 717 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id); 718 if (!device) 719 return ENOENT; 720 721 arp_proto_t *proto = arp_protos_find(&device->protos, protocol); 722 if ((!proto) || (proto->addr->length != target->length)) 723 return ENOENT; 724 725 arp_trans_t *trans = arp_addr_find(&proto->addresses, target->value, 726 target->length); 727 if (trans) { 728 if (trans->hw_addr) { 729 /* The translation is in place. */ 730 *translation = trans->hw_addr; 731 return EOK; 732 } 733 734 if (retry) { 735 /* 736 * We may get here as a result of being signalled for 737 * some reason while waiting for the translation (e.g. 738 * translation becoming available, record being removed 739 * from the table) and then losing the race for 740 * the arp_globals.lock with someone else who modified 741 * the table. 742 * 743 * Remove the incomplete record so that it is possible 744 * to make new ARP requests. 745 */ 746 arp_clear_trans(trans); 747 arp_addr_exclude(&proto->addresses, target->value, 748 target->length); 749 return EAGAIN; 750 } 751 752 /* 753 * We are a random passer-by who merely joins an already waiting 754 * fibril in waiting for the translation. 755 */ 756 rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock, 757 ARP_TRANS_WAIT); 758 if (rc == ETIMEOUT) 759 return ENOENT; 760 761 /* 762 * Need to recheck because we did not hold the lock while 763 * sleeping on the condition variable. 764 */ 765 retry = true; 766 goto restart; 767 } 768 769 if (retry) 770 return EAGAIN; 771 772 /* 773 * We are under the protection of arp_globals.lock, so we can afford to 774 * first send the ARP request and then insert an incomplete ARP record. 775 * The incomplete record is used to tell any other potential waiter 776 * that this fibril has already sent the request and that it is waiting 777 * for the answer. Lastly, any fibril which sees the incomplete request 778 * can perform a timed wait on its condition variable to wait for the 779 * ARP reply to arrive. 780 */ 781 782 rc = arp_send_request(device_id, protocol, target, device, proto); 783 if (rc != EOK) 784 return rc; 785 786 trans = (arp_trans_t *) malloc(sizeof(arp_trans_t)); 787 if (!trans) 788 return ENOMEM; 789 790 trans->hw_addr = NULL; 791 fibril_condvar_initialize(&trans->cv); 792 793 rc = arp_addr_add(&proto->addresses, target->value, target->length, 794 trans); 795 if (rc != EOK) { 796 /* The generic char map has already freed trans! */ 797 return rc; 798 } 799 800 rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock, 801 ARP_TRANS_WAIT); 802 if (rc == ETIMEOUT) { 803 /* 804 * Remove the incomplete record so that it is possible to make 805 * new ARP requests. 806 */ 807 arp_clear_trans(trans); 808 arp_addr_exclude(&proto->addresses, target->value, 809 target->length); 810 return ENOENT; 811 } 812 813 /* 814 * We need to recheck that the translation has indeed become available, 815 * because we dropped the arp_globals.lock while sleeping on the 816 * condition variable and someone else might have e.g. removed the 817 * translation before we managed to lock arp_globals.lock again. 818 */ 819 820 retry = true; 821 goto restart; 822 } 823 824 /** Process the ARP message. 825 * 826 * @param[in] callid Message identifier. 827 * @param[in] call Message parameters. 828 * @param[out] answer Answer. 829 * @param[out] count Number of arguments of the answer. 830 * 831 * @return EOK on success. 832 * @return ENOTSUP if the message is not known. 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. 833 606 * 834 607 * @see arp_interface.h 835 608 * @see IS_NET_ARP_MESSAGE() 836 * 837 */ 838 int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,839 size_t *count)609 */ 610 int 611 arp_message_standalone(ipc_callid_t callid, ipc_call_t *call, 612 ipc_call_t *answer, int *answer_count) 840 613 { 841 614 measured_string_t *address; 842 615 measured_string_t *translation; 843 uint8_t *data; 616 char *data; 617 packet_t *packet; 618 packet_t *next; 844 619 int rc; 845 620 846 * count = 0;847 switch (IPC_GET_ IMETHOD(*call)) {621 *answer_count = 0; 622 switch (IPC_GET_METHOD(*call)) { 848 623 case IPC_M_PHONE_HUNGUP: 849 624 return EOK; … … 854 629 return rc; 855 630 856 rc = arp_device_message(IPC_GET_DEVICE( *call),857 IPC_GET_SERVICE( *call), ARP_GET_NETIF(*call), address);631 rc = arp_device_message(IPC_GET_DEVICE(call), 632 IPC_GET_SERVICE(call), ARP_GET_NETIF(call), address); 858 633 if (rc != EOK) { 859 634 free(address); 860 635 free(data); 861 636 } 862 863 637 return rc; 864 638 … … 868 642 return rc; 869 643 870 fibril_ mutex_lock(&arp_globals.lock);871 rc = arp_translate_message(IPC_GET_DEVICE(*call),872 IPC_GET_SERVICE( *call), address, &translation);644 fibril_rwlock_read_lock(&arp_globals.lock); 645 translation = arp_translate_message(IPC_GET_DEVICE(call), 646 IPC_GET_SERVICE(call), address); 873 647 free(address); 874 648 free(data); 875 876 if (rc != EOK) {877 fibril_mutex_unlock(&arp_globals.lock);878 return rc;879 }880 881 649 if (!translation) { 882 fibril_ mutex_unlock(&arp_globals.lock);650 fibril_rwlock_read_unlock(&arp_globals.lock); 883 651 return ENOENT; 884 652 } 885 886 653 rc = measured_strings_reply(translation, 1); 887 fibril_ mutex_unlock(&arp_globals.lock);654 fibril_rwlock_read_unlock(&arp_globals.lock); 888 655 return rc; 889 656 890 657 case NET_ARP_CLEAR_DEVICE: 891 return arp_clear_device_req(0, IPC_GET_DEVICE( *call));892 658 return arp_clear_device_req(0, IPC_GET_DEVICE(call)); 659 893 660 case NET_ARP_CLEAR_ADDRESS: 894 661 rc = measured_strings_receive(&address, &data, 1); … … 896 663 return rc; 897 664 898 arp_clear_address_req(0, IPC_GET_DEVICE( *call),899 IPC_GET_SERVICE( *call), address);665 arp_clear_address_req(0, IPC_GET_DEVICE(call), 666 IPC_GET_SERVICE(call), address); 900 667 free(address); 901 668 free(data); … … 904 671 case NET_ARP_CLEAN_CACHE: 905 672 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)); 906 701 } 907 702 … … 909 704 } 910 705 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 connection 715 * - 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 processing 736 * 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 module 751 * start function. 752 */ 911 753 int main(int argc, char *argv[]) 912 754 { 755 int rc; 756 913 757 /* Start the module */ 914 return il_module_start(SERVICE_ARP); 758 rc = il_module_start_standalone(il_client_connection); 759 return rc; 915 760 } 916 761 917 762 /** @} 918 763 */ 764
Note:
See TracChangeset
for help on using the changeset viewer.