Changeset 80cd7cd in mainline for uspace/srv/net/il
- Timestamp:
- 2011-01-13T20:58:24Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 87e373b
- Parents:
- eaef141 (diff), a613fea1 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- uspace/srv/net/il
- Files:
-
- 5 deleted
- 6 edited
-
arp/Makefile (modified) (1 diff)
-
arp/arp.c (modified) (22 diffs)
-
arp/arp.h (modified) (4 diffs)
-
arp/arp_header.h (deleted)
-
arp/arp_module.c (deleted)
-
arp/arp_oc.h (deleted)
-
ip/Makefile (modified) (1 diff)
-
ip/ip.c (modified) (33 diffs)
-
ip/ip.h (modified) (1 diff)
-
ip/ip_module.c (deleted)
-
ip/ip_module.h (deleted)
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/il/arp/Makefile
reaef141 r80cd7cd 34 34 35 35 SOURCES = \ 36 arp.c \ 37 arp_module.c 36 arp.c 38 37 39 38 include $(USPACE_PREFIX)/Makefile.common -
uspace/srv/net/il/arp/arp.c
reaef141 r80cd7cd 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"42 37 43 38 #include <async.h> … … 54 49 #include <ipc/arp.h> 55 50 #include <ipc/il.h> 51 #include <ipc/nil.h> 56 52 #include <byteorder.h> 57 53 #include <errno.h> 58 59 54 #include <net/modules.h> 60 55 #include <net/device.h> 61 56 #include <net/packet.h> 62 63 #include <nil_interface.h> 57 #include <nil_remote.h> 64 58 #include <protocol_map.h> 65 59 #include <packet_client.h> 66 60 #include <packet_remote.h> 67 #include <il_ interface.h>68 #include <il_ local.h>69 61 #include <il_remote.h> 62 #include <il_skel.h> 63 #include "arp.h" 70 64 71 65 /** ARP module name. */ … … 73 67 74 68 /** Number of microseconds to wait for an ARP reply. */ 75 #define ARP_TRANS_WAIT 1000000 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)); 76 108 77 109 /** ARP global data. */ … … 88 120 trans->hw_addr = NULL; 89 121 } 122 90 123 fibril_condvar_broadcast(&trans->cv); 91 124 } … … 94 127 { 95 128 int count; 96 arp_trans_t *trans; 97 129 98 130 for (count = arp_addr_count(addresses) - 1; count >= 0; count--) { 99 trans = arp_addr_items_get_index(&addresses->values, count); 131 arp_trans_t *trans = arp_addr_items_get_index(&addresses->values, 132 count); 100 133 if (trans) 101 134 arp_clear_trans(trans); … … 103 136 } 104 137 105 106 /** Clears the device specific data. 107 * 108 * @param[in] device The device specific data. 138 /** Clear the device specific data. 139 * 140 * @param[in] device Device specific data. 109 141 */ 110 142 static void arp_clear_device(arp_device_t *device) 111 143 { 112 144 int count; 113 arp_proto_t *proto; 114 145 115 146 for (count = arp_protos_count(&device->protos) - 1; count >= 0; 116 147 count--) { 117 proto = arp_protos_get_index(&device->protos, count); 148 arp_proto_t *proto = arp_protos_get_index(&device->protos, 149 count); 150 118 151 if (proto) { 119 152 if (proto->addr) 120 153 free(proto->addr); 154 121 155 if (proto->addr_data) 122 156 free(proto->addr_data); 157 123 158 arp_clear_addr(&proto->addresses); 124 159 arp_addr_destroy(&proto->addresses); 125 160 } 126 161 } 162 127 163 arp_protos_clear(&device->protos); 128 164 } … … 131 167 { 132 168 int count; 133 arp_device_t *device; 134 169 135 170 fibril_mutex_lock(&arp_globals.lock); 136 171 for (count = arp_cache_count(&arp_globals.cache) - 1; count >= 0; 137 172 count--) { 138 device = arp_cache_get_index(&arp_globals.cache, count); 173 arp_device_t *device = arp_cache_get_index(&arp_globals.cache, 174 count); 175 139 176 if (device) { 140 177 arp_clear_device(device); 141 178 if (device->addr_data) 142 179 free(device->addr_data); 180 143 181 if (device->broadcast_data) 144 182 free(device->broadcast_data); 145 183 } 146 184 } 185 147 186 arp_cache_clear(&arp_globals.cache); 148 187 fibril_mutex_unlock(&arp_globals.lock); 149 printf("Cache cleaned\n");188 150 189 return EOK; 151 190 } … … 154 193 services_t protocol, measured_string_t *address) 155 194 { 156 arp_device_t *device;157 arp_proto_t *proto;158 arp_trans_t *trans;159 160 195 fibril_mutex_lock(&arp_globals.lock); 161 device = arp_cache_find(&arp_globals.cache, device_id); 196 197 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id); 162 198 if (!device) { 163 199 fibril_mutex_unlock(&arp_globals.lock); 164 200 return ENOENT; 165 201 } 166 proto = arp_protos_find(&device->protos, protocol); 202 203 arp_proto_t *proto = arp_protos_find(&device->protos, protocol); 167 204 if (!proto) { 168 205 fibril_mutex_unlock(&arp_globals.lock); 169 206 return ENOENT; 170 207 } 171 trans = arp_addr_find(&proto->addresses, address->value, address->length); 208 209 arp_trans_t *trans = arp_addr_find(&proto->addresses, address->value, 210 address->length); 172 211 if (trans) 173 212 arp_clear_trans(trans); 213 174 214 arp_addr_exclude(&proto->addresses, address->value, address->length); 215 175 216 fibril_mutex_unlock(&arp_globals.lock); 176 217 return EOK; 177 218 } 178 219 179 180 220 static int arp_clear_device_req(int arp_phone, device_id_t device_id) 181 221 { 182 arp_device_t *device;183 184 222 fibril_mutex_lock(&arp_globals.lock); 185 device = arp_cache_find(&arp_globals.cache, device_id); 223 224 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id); 186 225 if (!device) { 187 226 fibril_mutex_unlock(&arp_globals.lock); 188 227 return ENOENT; 189 228 } 229 190 230 arp_clear_device(device); 191 printf("Device %d cleared\n", device_id);231 192 232 fibril_mutex_unlock(&arp_globals.lock); 193 233 return EOK; 194 234 } 195 235 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. 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 * 205 247 */ 206 248 static int arp_proto_create(arp_proto_t **proto, services_t service, 207 249 measured_string_t *address) 208 250 { 209 int rc;210 211 251 *proto = (arp_proto_t *) malloc(sizeof(arp_proto_t)); 212 252 if (!*proto) … … 217 257 (*proto)->addr_data = address->value; 218 258 219 rc = arp_addr_initialize(&(*proto)->addresses);259 int rc = arp_addr_initialize(&(*proto)->addresses); 220 260 if (rc != EOK) { 221 261 free(*proto); … … 226 266 } 227 267 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; 268 /** Process the received ARP packet. 269 * 270 * Update the source hardware address if the source entry exists or the packet 271 * is targeted to my protocol address. 272 * 273 * Respond to the ARP request if the packet is the ARP request and is 274 * targeted to my address. 275 * 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 * 290 */ 291 static int arp_receive_message(device_id_t device_id, packet_t *packet) 292 { 251 293 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 430 * is targeted to my protocol address. 431 * Responses to the ARP request if the packet is the ARP request and is 432 * targeted to my address. 433 * 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. 446 */ 447 static int arp_receive_message(device_id_t device_id, packet_t *packet) 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; 458 int rc; 459 460 length = packet_get_data_length(packet); 294 295 size_t length = packet_get_data_length(packet); 461 296 if (length <= sizeof(arp_header_t)) 462 297 return EINVAL; 463 464 device = arp_cache_find(&arp_globals.cache, device_id);298 299 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id); 465 300 if (!device) 466 301 return ENOENT; 467 468 header = (arp_header_t *) packet_get_data(packet);302 303 arp_header_t *header = (arp_header_t *) packet_get_data(packet); 469 304 if ((ntohs(header->hardware) != device->hardware) || 470 305 (length < sizeof(arp_header_t) + header->hardware_length * 2U + … … 472 307 return EINVAL; 473 308 } 474 475 proto = arp_protos_find(&device->protos,309 310 arp_proto_t *proto = arp_protos_find(&device->protos, 476 311 protocol_unmap(device->service, ntohs(header->protocol))); 477 312 if (!proto) 478 313 return ENOENT; 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, 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, 485 321 header->protocol_length); 486 /* Exists? */ 487 if (trans && trans->hw_addr) { 322 323 if ((trans) && (trans->hw_addr)) { 324 /* Translation exists */ 488 325 if (trans->hw_addr->length != header->hardware_length) 489 326 return EINVAL; 327 490 328 memcpy(trans->hw_addr->value, src_hw, trans->hw_addr->length); 491 329 } 330 492 331 /* Is my protocol address? */ 493 332 if (proto->addr->length != header->protocol_length) 494 333 return EINVAL; 495 if (!str_lcmp(proto->addr->value, (char *) des_proto, 496 proto->addr->length)) { 497 /* Not already updated? */ 334 335 if (!bcmp(proto->addr->value, des_proto, proto->addr->length)) { 498 336 if (!trans) { 337 /* Update the translation */ 499 338 trans = (arp_trans_t *) malloc(sizeof(arp_trans_t)); 500 339 if (!trans) 501 340 return ENOMEM; 341 502 342 trans->hw_addr = NULL; 503 343 fibril_condvar_initialize(&trans->cv); 504 rc = arp_addr_add(&proto->addresses, (char *)src_proto,344 rc = arp_addr_add(&proto->addresses, src_proto, 505 345 header->protocol_length, trans); 506 346 if (rc != EOK) { … … 509 349 } 510 350 } 351 511 352 if (!trans->hw_addr) { 512 trans->hw_addr = measured_string_create_bulk( 513 (char *) src_hw,header->hardware_length);353 trans->hw_addr = measured_string_create_bulk(src_hw, 354 header->hardware_length); 514 355 if (!trans->hw_addr) 515 356 return ENOMEM; 516 357 517 358 /* Notify the fibrils that wait for the translation. */ 518 359 fibril_condvar_broadcast(&trans->cv); 519 360 } 361 520 362 if (ntohs(header->operation) == ARPOP_REQUEST) { 521 363 header->operation = htons(ARPOP_REPLY); … … 538 380 } 539 381 } 540 382 541 383 return EOK; 542 384 } 543 385 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; 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 { 566 422 packet_t *packet; 567 arp_header_t *header;568 bool retry = false;569 423 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) 577 return ENOENT; 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) 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) 594 529 return ENOENT; 595 retry = true; 596 goto restart; 597 } 598 if (retry) 599 return EAGAIN; 600 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 { 601 644 /* ARP packet content size = header + (address + translation) * 2 */ 602 length = 8 + 2 * (proto->addr->length + device->addr->length);645 size_t length = 8 + 2 * (proto->addr->length + device->addr->length); 603 646 if (length > device->packet_dimension.content) 604 647 return ELIMIT; 605 606 packet = packet_get_4_remote(arp_globals.net_phone,648 649 packet_t *packet = packet_get_4_remote(arp_globals.net_phone, 607 650 device->packet_dimension.addr_len, device->packet_dimension.prefix, 608 651 length, device->packet_dimension.suffix); 609 652 if (!packet) 610 653 return ENOMEM; 611 612 header = (arp_header_t *) packet_suffix(packet, length);654 655 arp_header_t *header = (arp_header_t *) packet_suffix(packet, length); 613 656 if (!header) { 614 657 pq_release_remote(arp_globals.net_phone, packet_get_id(packet)); 615 658 return ENOMEM; 616 659 } 617 660 618 661 header->hardware = htons(device->hardware); 619 662 header->hardware_length = (uint8_t) device->addr->length; … … 621 664 header->protocol_length = (uint8_t) proto->addr->length; 622 665 header->operation = htons(ARPOP_REQUEST); 666 623 667 length = sizeof(arp_header_t); 668 624 669 memcpy(((uint8_t *) header) + length, device->addr->value, 625 670 device->addr->length); … … 631 676 length += device->addr->length; 632 677 memcpy(((uint8_t *) header) + length, target->value, target->length); 633 634 rc = packet_set_addr(packet, (uint8_t *) device->addr->value,678 679 int rc = packet_set_addr(packet, (uint8_t *) device->addr->value, 635 680 (uint8_t *) device->broadcast_addr->value, device->addr->length); 636 681 if (rc != EOK) { … … 638 683 return rc; 639 684 } 640 685 641 686 nil_send_msg(device->phone, device_id, packet, SERVICE_ARP); 642 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 643 751 trans = (arp_trans_t *) malloc(sizeof(arp_trans_t)); 644 752 if (!trans) 645 753 return ENOMEM; 754 646 755 trans->hw_addr = NULL; 647 756 fibril_condvar_initialize(&trans->cv); 757 648 758 rc = arp_addr_add(&proto->addresses, target->value, target->length, 649 759 trans); … … 653 763 } 654 764 765 rc = arp_send_request(device_id, protocol, target, device, proto); 766 if (rc != EOK) 767 return rc; 768 655 769 rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock, 656 770 ARP_TRANS_WAIT); 657 771 if (rc == ETIMEOUT) 658 772 return ENOENT; 773 659 774 retry = true; 660 775 goto restart; 661 776 } 662 777 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. 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. 673 787 * 674 788 * @see arp_interface.h 675 789 * @see IS_NET_ARP_MESSAGE() 676 * /677 int 678 arp_message_standalone(ipc_callid_t callid, ipc_call_t *call,679 ipc_call_t *answer, int *answer_count)790 * 791 */ 792 int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer, 793 size_t *count) 680 794 { 681 795 measured_string_t *address; 682 796 measured_string_t *translation; 683 char *data; 684 packet_t *packet; 685 packet_t *next; 797 uint8_t *data; 686 798 int rc; 687 799 688 * answer_count = 0;800 *count = 0; 689 801 switch (IPC_GET_IMETHOD(*call)) { 690 802 case IPC_M_PHONE_HUNGUP: … … 696 808 return rc; 697 809 698 rc = arp_device_message(IPC_GET_DEVICE( call),699 IPC_GET_SERVICE( call), ARP_GET_NETIF(call), address);810 rc = arp_device_message(IPC_GET_DEVICE(*call), 811 IPC_GET_SERVICE(*call), ARP_GET_NETIF(*call), address); 700 812 if (rc != EOK) { 701 813 free(address); 702 814 free(data); 703 815 } 816 704 817 return rc; 705 818 … … 710 823 711 824 fibril_mutex_lock(&arp_globals.lock); 712 rc = arp_translate_message(IPC_GET_DEVICE( call),713 IPC_GET_SERVICE( call), address, &translation);825 rc = arp_translate_message(IPC_GET_DEVICE(*call), 826 IPC_GET_SERVICE(*call), address, &translation); 714 827 free(address); 715 828 free(data); 829 716 830 if (rc != EOK) { 717 831 fibril_mutex_unlock(&arp_globals.lock); 718 832 return rc; 719 833 } 834 720 835 if (!translation) { 721 836 fibril_mutex_unlock(&arp_globals.lock); 722 837 return ENOENT; 723 838 } 839 724 840 rc = measured_strings_reply(translation, 1); 725 841 fibril_mutex_unlock(&arp_globals.lock); 726 842 return rc; 727 843 728 844 case NET_ARP_CLEAR_DEVICE: 729 return arp_clear_device_req(0, IPC_GET_DEVICE( call));730 845 return arp_clear_device_req(0, IPC_GET_DEVICE(*call)); 846 731 847 case NET_ARP_CLEAR_ADDRESS: 732 848 rc = measured_strings_receive(&address, &data, 1); … … 734 850 return rc; 735 851 736 arp_clear_address_req(0, IPC_GET_DEVICE( call),737 IPC_GET_SERVICE( call), address);852 arp_clear_address_req(0, IPC_GET_DEVICE(*call), 853 IPC_GET_SERVICE(*call), address); 738 854 free(address); 739 855 free(data); … … 742 858 case NET_ARP_CLEAN_CACHE: 743 859 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));772 860 } 773 861 … … 775 863 } 776 864 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 connection786 * - 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 processing807 * 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 module822 * start function.823 */824 865 int main(int argc, char *argv[]) 825 866 { 826 int rc;827 828 867 /* Start the module */ 829 rc = il_module_start_standalone(il_client_connection); 830 return rc; 868 return il_module_start(SERVICE_ARP); 831 869 } 832 870 833 871 /** @} 834 872 */ 835 -
uspace/srv/net/il/arp/arp.h
reaef141 r80cd7cd 96 96 measured_string_t *addr; 97 97 /** Actual device hardware address data. */ 98 char*addr_data;98 uint8_t *addr_data; 99 99 /** Broadcast device hardware address. */ 100 100 measured_string_t *broadcast_addr; 101 101 /** Broadcast device hardware address data. */ 102 char*broadcast_data;102 uint8_t *broadcast_data; 103 103 /** Device identifier. */ 104 104 device_id_t device_id; … … 125 125 arp_cache_t cache; 126 126 127 /**128 * The client connection processing function.129 * The module skeleton propagates its own one.130 */131 async_client_conn_t client_connection;132 133 127 /** Networking module phone. */ 134 128 int net_phone; … … 142 136 measured_string_t *addr; 143 137 /** Actual device protocol address data. */ 144 char*addr_data;138 uint8_t *addr_data; 145 139 /** Address map. */ 146 140 arp_addr_t addresses; … … 154 148 * Hardware address for the translation. NULL denotes an incomplete 155 149 * record with possible waiters. 156 */ 150 */ 157 151 measured_string_t *hw_addr; 158 152 /** Condition variable used for waiting for completion of the record. */ -
uspace/srv/net/il/ip/Makefile
reaef141 r80cd7cd 34 34 35 35 SOURCES = \ 36 ip.c \ 37 ip_module.c 36 ip.c 38 37 39 38 include $(USPACE_PREFIX)/Makefile.common -
uspace/srv/net/il/ip/ip.c
reaef141 r80cd7cd 35 35 * @see arp.h 36 36 */ 37 38 #include "ip.h"39 #include "ip_module.h"40 37 41 38 #include <async.h> … … 52 49 #include <sys/types.h> 53 50 #include <byteorder.h> 51 #include "ip.h" 54 52 55 53 #include <adt/measured_strings.h> … … 70 68 #include <icmp_client.h> 71 69 #include <icmp_interface.h> 72 #include <il_interface.h>73 70 #include <ip_client.h> 74 71 #include <ip_interface.h> 75 72 #include <ip_header.h> 76 73 #include <net_interface.h> 77 #include <nil_ interface.h>78 #include <tl_ interface.h>74 #include <nil_remote.h> 75 #include <tl_remote.h> 79 76 #include <packet_remote.h> 80 #include <il_local.h> 77 #include <il_remote.h> 78 #include <il_skel.h> 81 79 82 80 /** IP module name. */ … … 122 120 INT_MAP_IMPLEMENT(ip_protos, ip_proto_t); 123 121 GENERIC_FIELD_IMPLEMENT(ip_routes, ip_route_t); 122 123 static void ip_receiver(ipc_callid_t, ipc_call_t *); 124 124 125 125 /** Releases the packet and returns the result. … … 244 244 } 245 245 246 /** Initializes the IP module. 247 * 248 * @param[in] client_connection The client connection processing function. The 249 * module skeleton propagates its own one. 250 * @return EOK on success. 251 * @return ENOMEM if there is not enough memory left. 252 */ 253 int ip_initialize(async_client_conn_t client_connection) 254 { 255 int rc; 256 246 int il_initialize(int net_phone) 247 { 257 248 fibril_rwlock_initialize(&ip_globals.lock); 258 249 fibril_rwlock_write_lock(&ip_globals.lock); 259 250 fibril_rwlock_initialize(&ip_globals.protos_lock); 260 251 fibril_rwlock_initialize(&ip_globals.netifs_lock); 252 253 ip_globals.net_phone = net_phone; 261 254 ip_globals.packet_counter = 0; 262 255 ip_globals.gateway.address.s_addr = 0; … … 264 257 ip_globals.gateway.gateway.s_addr = 0; 265 258 ip_globals.gateway.netif = NULL; 266 ip_globals.client_connection = client_connection; 267 268 rc = ip_netifs_initialize(&ip_globals.netifs); 259 260 int rc = ip_netifs_initialize(&ip_globals.netifs); 269 261 if (rc != EOK) 270 262 goto out; … … 275 267 if (rc != EOK) 276 268 goto out; 277 rc = add_module(NULL, &ip_globals.modules, ARP_NAME, ARP_FILENAME,278 SERVICE_ARP, 0, arp_connect_module);269 rc = add_module(NULL, &ip_globals.modules, (uint8_t *) ARP_NAME, 270 (uint8_t *) ARP_FILENAME, SERVICE_ARP, 0, arp_connect_module); 279 271 280 272 out: … … 312 304 measured_string_t names[] = { 313 305 { 314 ( char*) "IPV",306 (uint8_t *) "IPV", 315 307 3 316 308 }, 317 309 { 318 ( char*) "IP_CONFIG",310 (uint8_t *) "IP_CONFIG", 319 311 9 320 312 }, 321 313 { 322 ( char*) "IP_ADDR",314 (uint8_t *) "IP_ADDR", 323 315 7 324 316 }, 325 317 { 326 ( char*) "IP_NETMASK",318 (uint8_t *) "IP_NETMASK", 327 319 10 328 320 }, 329 321 { 330 ( char*) "IP_GATEWAY",322 (uint8_t *) "IP_GATEWAY", 331 323 10 332 324 }, 333 325 { 334 ( char*) "IP_BROADCAST",326 (uint8_t *) "IP_BROADCAST", 335 327 12 336 328 }, 337 329 { 338 ( char*) "ARP",330 (uint8_t *) "ARP", 339 331 3 340 332 }, 341 333 { 342 ( char*) "IP_ROUTING",334 (uint8_t *) "IP_ROUTING", 343 335 10 344 336 } … … 346 338 measured_string_t *configuration; 347 339 size_t count = sizeof(names) / sizeof(measured_string_t); 348 char*data;340 uint8_t *data; 349 341 measured_string_t address; 350 342 ip_route_t *route; … … 368 360 if (configuration) { 369 361 if (configuration[0].value) 370 ip_netif->ipv = strtol( configuration[0].value, NULL, 0);371 372 ip_netif->dhcp = !str_lcmp( configuration[1].value, "dhcp",362 ip_netif->ipv = strtol((char *) configuration[0].value, NULL, 0); 363 364 ip_netif->dhcp = !str_lcmp((char *) configuration[1].value, "dhcp", 373 365 configuration[1].length); 374 366 … … 394 386 } 395 387 396 if ((inet_pton(AF_INET, configuration[2].value,388 if ((inet_pton(AF_INET, (char *) configuration[2].value, 397 389 (uint8_t *) &route->address.s_addr) != EOK) || 398 (inet_pton(AF_INET, configuration[3].value,390 (inet_pton(AF_INET, (char *) configuration[3].value, 399 391 (uint8_t *) &route->netmask.s_addr) != EOK) || 400 (inet_pton(AF_INET, configuration[4].value,392 (inet_pton(AF_INET, (char *) configuration[4].value, 401 393 (uint8_t *) &gateway.s_addr) == EINVAL) || 402 (inet_pton(AF_INET, configuration[5].value,394 (inet_pton(AF_INET, (char *) configuration[5].value, 403 395 (uint8_t *) &ip_netif->broadcast.s_addr) == EINVAL)) 404 396 { … … 431 423 ip_netif->phone = nil_bind_service(ip_netif->service, 432 424 (sysarg_t) ip_netif->device_id, SERVICE_IP, 433 ip_ globals.client_connection);425 ip_receiver); 434 426 if (ip_netif->phone < 0) { 435 427 printf("Failed to contact the nil service %d\n", … … 441 433 if (ip_netif->arp) { 442 434 if (route) { 443 address.value = ( char*) &route->address.s_addr;435 address.value = (uint8_t *) &route->address.s_addr; 444 436 address.length = sizeof(in_addr_t); 445 437 … … 477 469 ip_globals.gateway.gateway.s_addr = gateway.s_addr; 478 470 ip_globals.gateway.netif = ip_netif; 471 472 char defgateway[INET_ADDRSTRLEN]; 473 inet_ntop(AF_INET, (uint8_t *) &gateway.s_addr, 474 defgateway, INET_ADDRSTRLEN); 475 printf("%s: Default gateway (%s)\n", NAME, defgateway); 479 476 } 480 477 … … 482 479 } 483 480 484 /** Updates the device content length according to the new MTU value. 485 * 486 * @param[in] device_id The device identifier. 487 * @param[in] mtu The new mtu value. 488 * @return EOK on success. 489 * @return ENOENT if device is not found. 490 */ 491 static int ip_mtu_changed_message(device_id_t device_id, size_t mtu) 492 { 481 static int ip_device_req_local(int il_phone, device_id_t device_id, 482 services_t netif) 483 { 484 ip_netif_t *ip_netif; 485 ip_route_t *route; 486 int index; 487 int rc; 488 489 ip_netif = (ip_netif_t *) malloc(sizeof(ip_netif_t)); 490 if (!ip_netif) 491 return ENOMEM; 492 493 rc = ip_routes_initialize(&ip_netif->routes); 494 if (rc != EOK) { 495 free(ip_netif); 496 return rc; 497 } 498 499 ip_netif->device_id = device_id; 500 ip_netif->service = netif; 501 ip_netif->state = NETIF_STOPPED; 502 503 fibril_rwlock_write_lock(&ip_globals.netifs_lock); 504 505 rc = ip_netif_initialize(ip_netif); 506 if (rc != EOK) { 507 fibril_rwlock_write_unlock(&ip_globals.netifs_lock); 508 ip_routes_destroy(&ip_netif->routes); 509 free(ip_netif); 510 return rc; 511 } 512 if (ip_netif->arp) 513 ip_netif->arp->usage++; 514 515 // print the settings 516 printf("%s: Device registered (id: %d, phone: %d, ipv: %d, conf: %s)\n", 517 NAME, ip_netif->device_id, ip_netif->phone, ip_netif->ipv, 518 ip_netif->dhcp ? "dhcp" : "static"); 519 520 // TODO ipv6 addresses 521 522 char address[INET_ADDRSTRLEN]; 523 char netmask[INET_ADDRSTRLEN]; 524 char gateway[INET_ADDRSTRLEN]; 525 526 for (index = 0; index < ip_routes_count(&ip_netif->routes); index++) { 527 route = ip_routes_get_index(&ip_netif->routes, index); 528 if (route) { 529 inet_ntop(AF_INET, (uint8_t *) &route->address.s_addr, 530 address, INET_ADDRSTRLEN); 531 inet_ntop(AF_INET, (uint8_t *) &route->netmask.s_addr, 532 netmask, INET_ADDRSTRLEN); 533 inet_ntop(AF_INET, (uint8_t *) &route->gateway.s_addr, 534 gateway, INET_ADDRSTRLEN); 535 printf("%s: Route %d (address: %s, netmask: %s, " 536 "gateway: %s)\n", NAME, index, address, netmask, 537 gateway); 538 } 539 } 540 541 inet_ntop(AF_INET, (uint8_t *) &ip_netif->broadcast.s_addr, address, 542 INET_ADDRSTRLEN); 543 fibril_rwlock_write_unlock(&ip_globals.netifs_lock); 544 545 printf("%s: Broadcast (%s)\n", NAME, address); 546 547 return EOK; 548 } 549 550 /** Searches the network interfaces if there is a suitable route. 551 * 552 * @param[in] netif The network interface to be searched for routes. May be 553 * NULL. 554 * @param[in] destination The destination address. 555 * @return The found route. 556 * @return NULL if no route was found. 557 */ 558 static ip_route_t *ip_netif_find_route(ip_netif_t *netif, 559 in_addr_t destination) 560 { 561 int index; 562 ip_route_t *route; 563 564 if (!netif) 565 return NULL; 566 567 /* Start with the first one (the direct route) */ 568 for (index = 0; index < ip_routes_count(&netif->routes); index++) { 569 route = ip_routes_get_index(&netif->routes, index); 570 if ((route) && 571 ((route->address.s_addr & route->netmask.s_addr) == 572 (destination.s_addr & route->netmask.s_addr))) 573 return route; 574 } 575 576 return NULL; 577 } 578 579 /** Searches all network interfaces if there is a suitable route. 580 * 581 * @param[in] destination The destination address. 582 * @return The found route. 583 * @return NULL if no route was found. 584 */ 585 static ip_route_t *ip_find_route(in_addr_t destination) { 586 int index; 587 ip_route_t *route; 493 588 ip_netif_t *netif; 494 589 495 fibril_rwlock_write_lock(&ip_globals.netifs_lock); 496 netif = ip_netifs_find(&ip_globals.netifs, device_id); 497 if (!netif) { 498 fibril_rwlock_write_unlock(&ip_globals.netifs_lock); 499 return ENOENT; 500 } 501 netif->packet_dimension.content = mtu; 502 fibril_rwlock_write_unlock(&ip_globals.netifs_lock); 503 504 printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu); 505 506 return EOK; 507 } 508 509 /** Updates the device state. 510 * 511 * @param[in] device_id The device identifier. 512 * @param[in] state The new state value. 513 * @return EOK on success. 514 * @return ENOENT if device is not found. 515 */ 516 static int ip_device_state_message(device_id_t device_id, device_state_t state) 517 { 518 ip_netif_t *netif; 519 520 fibril_rwlock_write_lock(&ip_globals.netifs_lock); 521 // find the device 522 netif = ip_netifs_find(&ip_globals.netifs, device_id); 523 if (!netif) { 524 fibril_rwlock_write_unlock(&ip_globals.netifs_lock); 525 return ENOENT; 526 } 527 netif->state = state; 528 fibril_rwlock_write_unlock(&ip_globals.netifs_lock); 529 530 printf("%s: Device %d changed state to %d\n", NAME, device_id, state); 531 532 return EOK; 533 } 534 535 536 /** Prefixes a middle fragment header based on the last fragment header to the 537 * packet. 538 * 539 * @param[in] packet The packet to be prefixed. 540 * @param[in] last The last header to be copied. 541 * @return The prefixed middle header. 542 * @return NULL on error. 543 */ 544 static ip_header_t * 545 ip_create_middle_header(packet_t *packet, ip_header_t *last) 546 { 547 ip_header_t *middle; 548 549 middle = (ip_header_t *) packet_suffix(packet, IP_HEADER_LENGTH(last)); 550 if (!middle) 551 return NULL; 552 memcpy(middle, last, IP_HEADER_LENGTH(last)); 553 middle->flags |= IPFLAG_MORE_FRAGMENTS; 554 return middle; 590 // start with the last netif - the newest one 591 index = ip_netifs_count(&ip_globals.netifs) - 1; 592 while (index >= 0) { 593 netif = ip_netifs_get_index(&ip_globals.netifs, index); 594 if (netif && (netif->state == NETIF_ACTIVE)) { 595 route = ip_netif_find_route(netif, destination); 596 if (route) 597 return route; 598 } 599 index--; 600 } 601 602 return &ip_globals.gateway; 603 } 604 605 /** Returns the network interface's IP address. 606 * 607 * @param[in] netif The network interface. 608 * @return The IP address. 609 * @return NULL if no IP address was found. 610 */ 611 static in_addr_t *ip_netif_address(ip_netif_t *netif) 612 { 613 ip_route_t *route; 614 615 route = ip_routes_get_index(&netif->routes, 0); 616 return route ? &route->address : NULL; 555 617 } 556 618 … … 621 683 * function. 622 684 */ 623 static int 624 ip_prepare_packet(in_addr_t *source, in_addr_t dest, packet_t *packet, 625 measured_string_t *destination) 685 static int ip_prepare_packet(in_addr_t *source, in_addr_t dest, 686 packet_t *packet, measured_string_t *destination) 626 687 { 627 688 size_t length; … … 752 813 * function. 753 814 */ 754 static int 755 ip_fragment_packet_data(packet_t *packet, packet_t *new_packet, 815 static int ip_fragment_packet_data(packet_t *packet, packet_t *new_packet, 756 816 ip_header_t *header, ip_header_t *new_header, size_t length, 757 817 const struct sockaddr *src, const struct sockaddr *dest, socklen_t addrlen) … … 787 847 788 848 return pq_insert_after(packet, new_packet); 849 } 850 851 /** Prefixes a middle fragment header based on the last fragment header to the 852 * packet. 853 * 854 * @param[in] packet The packet to be prefixed. 855 * @param[in] last The last header to be copied. 856 * @return The prefixed middle header. 857 * @return NULL on error. 858 */ 859 static ip_header_t *ip_create_middle_header(packet_t *packet, 860 ip_header_t *last) 861 { 862 ip_header_t *middle; 863 864 middle = (ip_header_t *) packet_suffix(packet, IP_HEADER_LENGTH(last)); 865 if (!middle) 866 return NULL; 867 memcpy(middle, last, IP_HEADER_LENGTH(last)); 868 middle->flags |= IPFLAG_MORE_FRAGMENTS; 869 return middle; 789 870 } 790 871 … … 991 1072 * function. 992 1073 */ 993 static int 994 ip_send_route(packet_t *packet, ip_netif_t *netif, ip_route_t *route, 995 in_addr_t *src, in_addr_t dest, services_t error) 1074 static int ip_send_route(packet_t *packet, ip_netif_t *netif, 1075 ip_route_t *route, in_addr_t *src, in_addr_t dest, services_t error) 996 1076 { 997 1077 measured_string_t destination; 998 1078 measured_string_t *translation; 999 char*data;1079 uint8_t *data; 1000 1080 int phone; 1001 1081 int rc; … … 1004 1084 if (netif->arp && (route->address.s_addr != dest.s_addr)) { 1005 1085 destination.value = route->gateway.s_addr ? 1006 ( char *) &route->gateway.s_addr : (char*) &dest.s_addr;1086 (uint8_t *) &route->gateway.s_addr : (uint8_t *) &dest.s_addr; 1007 1087 destination.length = sizeof(dest.s_addr); 1008 1088 … … 1056 1136 } 1057 1137 1058 /** Searches the network interfaces if there is a suitable route. 1059 * 1060 * @param[in] netif The network interface to be searched for routes. May be 1061 * NULL. 1062 * @param[in] destination The destination address. 1063 * @return The found route. 1064 * @return NULL if no route was found. 1065 */ 1066 static ip_route_t * 1067 ip_netif_find_route(ip_netif_t *netif, in_addr_t destination) 1068 { 1069 int index; 1070 ip_route_t *route; 1071 1072 if (!netif) 1073 return NULL; 1074 1075 // start with the first one - the direct route 1076 for (index = 0; index < ip_routes_count(&netif->routes); index++) { 1077 route = ip_routes_get_index(&netif->routes, index); 1078 if (route && 1079 ((route->address.s_addr & route->netmask.s_addr) == 1080 (destination.s_addr & route->netmask.s_addr))) { 1081 return route; 1082 } 1083 } 1084 1085 return NULL; 1086 } 1087 1088 /** Searches all network interfaces if there is a suitable route. 1089 * 1090 * @param[in] destination The destination address. 1091 * @return The found route. 1092 * @return NULL if no route was found. 1093 */ 1094 static ip_route_t *ip_find_route(in_addr_t destination) { 1095 int index; 1096 ip_route_t *route; 1097 ip_netif_t *netif; 1098 1099 // start with the last netif - the newest one 1100 index = ip_netifs_count(&ip_globals.netifs) - 1; 1101 while (index >= 0) { 1102 netif = ip_netifs_get_index(&ip_globals.netifs, index); 1103 if (netif && (netif->state == NETIF_ACTIVE)) { 1104 route = ip_netif_find_route(netif, destination); 1105 if (route) 1106 return route; 1107 } 1108 index--; 1109 } 1110 1111 return &ip_globals.gateway; 1112 } 1113 1114 /** Returns the network interface's IP address. 1115 * 1116 * @param[in] netif The network interface. 1117 * @return The IP address. 1118 * @return NULL if no IP address was found. 1119 */ 1120 static in_addr_t *ip_netif_address(ip_netif_t *netif) 1121 { 1122 ip_route_t *route; 1123 1124 route = ip_routes_get_index(&netif->routes, 0); 1125 return route ? &route->address : NULL; 1126 } 1127 1128 /** Registers the transport layer protocol. 1129 * 1130 * The traffic of this protocol will be supplied using either the receive 1131 * function or IPC message. 1132 * 1133 * @param[in] protocol The transport layer module protocol. 1134 * @param[in] service The transport layer module service. 1135 * @param[in] phone The transport layer module phone. 1136 * @param[in] received_msg The receiving function. 1137 * @return EOK on success. 1138 * @return EINVAL if the protocol parameter and/or the service 1139 * parameter is zero. 1140 * @return EINVAL if the phone parameter is not a positive number 1141 * and the tl_receive_msg is NULL. 1142 * @return ENOMEM if there is not enough memory left. 1143 */ 1144 static int 1145 ip_register(int protocol, services_t service, int phone, 1146 tl_received_msg_t received_msg) 1147 { 1148 ip_proto_t *proto; 1149 int index; 1150 1151 if (!protocol || !service || ((phone < 0) && !received_msg)) 1152 return EINVAL; 1153 1154 proto = (ip_proto_t *) malloc(sizeof(ip_protos_t)); 1155 if (!proto) 1156 return ENOMEM; 1157 1158 proto->protocol = protocol; 1159 proto->service = service; 1160 proto->phone = phone; 1161 proto->received_msg = received_msg; 1162 1163 fibril_rwlock_write_lock(&ip_globals.protos_lock); 1164 index = ip_protos_add(&ip_globals.protos, proto->protocol, proto); 1165 if (index < 0) { 1166 fibril_rwlock_write_unlock(&ip_globals.protos_lock); 1167 free(proto); 1168 return index; 1169 } 1170 fibril_rwlock_write_unlock(&ip_globals.protos_lock); 1171 1172 printf("%s: Protocol registered (protocol: %d, phone: %d)\n", 1173 NAME, proto->protocol, proto->phone); 1174 1175 return EOK; 1176 } 1177 1178 static int 1179 ip_device_req_local(int il_phone, device_id_t device_id, services_t netif) 1180 { 1181 ip_netif_t *ip_netif; 1182 ip_route_t *route; 1183 int index; 1184 int rc; 1185 1186 ip_netif = (ip_netif_t *) malloc(sizeof(ip_netif_t)); 1187 if (!ip_netif) 1188 return ENOMEM; 1189 1190 rc = ip_routes_initialize(&ip_netif->routes); 1191 if (rc != EOK) { 1192 free(ip_netif); 1193 return rc; 1194 } 1195 1196 ip_netif->device_id = device_id; 1197 ip_netif->service = netif; 1198 ip_netif->state = NETIF_STOPPED; 1199 1200 fibril_rwlock_write_lock(&ip_globals.netifs_lock); 1201 1202 rc = ip_netif_initialize(ip_netif); 1203 if (rc != EOK) { 1204 fibril_rwlock_write_unlock(&ip_globals.netifs_lock); 1205 ip_routes_destroy(&ip_netif->routes); 1206 free(ip_netif); 1207 return rc; 1208 } 1209 if (ip_netif->arp) 1210 ip_netif->arp->usage++; 1211 1212 // print the settings 1213 printf("%s: Device registered (id: %d, phone: %d, ipv: %d, conf: %s)\n", 1214 NAME, ip_netif->device_id, ip_netif->phone, ip_netif->ipv, 1215 ip_netif->dhcp ? "dhcp" : "static"); 1216 1217 // TODO ipv6 addresses 1218 1219 char address[INET_ADDRSTRLEN]; 1220 char netmask[INET_ADDRSTRLEN]; 1221 char gateway[INET_ADDRSTRLEN]; 1222 1223 for (index = 0; index < ip_routes_count(&ip_netif->routes); index++) { 1224 route = ip_routes_get_index(&ip_netif->routes, index); 1225 if (route) { 1226 inet_ntop(AF_INET, (uint8_t *) &route->address.s_addr, 1227 address, INET_ADDRSTRLEN); 1228 inet_ntop(AF_INET, (uint8_t *) &route->netmask.s_addr, 1229 netmask, INET_ADDRSTRLEN); 1230 inet_ntop(AF_INET, (uint8_t *) &route->gateway.s_addr, 1231 gateway, INET_ADDRSTRLEN); 1232 printf("%s: Route %d (address: %s, netmask: %s, " 1233 "gateway: %s)\n", NAME, index, address, netmask, 1234 gateway); 1235 } 1236 } 1237 1238 inet_ntop(AF_INET, (uint8_t *) &ip_netif->broadcast.s_addr, address, 1239 INET_ADDRSTRLEN); 1240 fibril_rwlock_write_unlock(&ip_globals.netifs_lock); 1241 1242 printf("%s: Broadcast (%s)\n", NAME, address); 1243 1244 return EOK; 1245 } 1246 1247 static int 1248 ip_send_msg_local(int il_phone, device_id_t device_id, packet_t *packet, 1249 services_t sender, services_t error) 1138 static int ip_send_msg_local(int il_phone, device_id_t device_id, 1139 packet_t *packet, services_t sender, services_t error) 1250 1140 { 1251 1141 int addrlen; … … 1288 1178 if (device_id > 0) { 1289 1179 netif = ip_netifs_find(&ip_globals.netifs, device_id); 1290 route = ip_netif_find_route(netif, * dest);1180 route = ip_netif_find_route(netif, *dest); 1291 1181 if (netif && !route && (ip_globals.gateway.netif == netif)) 1292 1182 route = &ip_globals.gateway; … … 1318 1208 } 1319 1209 } 1320 1210 1321 1211 // if the local host is the destination 1322 1212 if ((route->address.s_addr == dest->s_addr) && … … 1351 1241 } 1352 1242 1243 /** Updates the device state. 1244 * 1245 * @param[in] device_id The device identifier. 1246 * @param[in] state The new state value. 1247 * @return EOK on success. 1248 * @return ENOENT if device is not found. 1249 */ 1250 static int ip_device_state_message(device_id_t device_id, device_state_t state) 1251 { 1252 ip_netif_t *netif; 1253 1254 fibril_rwlock_write_lock(&ip_globals.netifs_lock); 1255 // find the device 1256 netif = ip_netifs_find(&ip_globals.netifs, device_id); 1257 if (!netif) { 1258 fibril_rwlock_write_unlock(&ip_globals.netifs_lock); 1259 return ENOENT; 1260 } 1261 netif->state = state; 1262 fibril_rwlock_write_unlock(&ip_globals.netifs_lock); 1263 1264 printf("%s: Device %d changed state to %d\n", NAME, device_id, state); 1265 1266 return EOK; 1267 } 1268 1269 /** Returns the packet destination address from the IP header. 1270 * 1271 * @param[in] header The packet IP header to be read. 1272 * @return The packet destination address. 1273 */ 1274 static in_addr_t ip_get_destination(ip_header_t *header) 1275 { 1276 in_addr_t destination; 1277 1278 // TODO search set ipopt route? 1279 destination.s_addr = header->destination_address; 1280 return destination; 1281 } 1282 1283 /** Delivers the packet to the local host. 1284 * 1285 * The packet is either passed to another module or released on error. 1286 * The ICMP_PROT_UNREACH error notification may be sent if the protocol is not 1287 * found. 1288 * 1289 * @param[in] device_id The source device identifier. 1290 * @param[in] packet The packet to be delivered. 1291 * @param[in] header The first packet IP header. May be NULL. 1292 * @param[in] error The packet error service. 1293 * @return EOK on success. 1294 * @return ENOTSUP if the packet is a fragment. 1295 * @return EAFNOSUPPORT if the address family is not supported. 1296 * @return ENOENT if the target protocol is not found. 1297 * @return Other error codes as defined for the packet_set_addr() 1298 * function. 1299 * @return Other error codes as defined for the packet_trim() 1300 * function. 1301 * @return Other error codes as defined for the protocol specific 1302 * tl_received_msg() function. 1303 */ 1304 static int ip_deliver_local(device_id_t device_id, packet_t *packet, 1305 ip_header_t *header, services_t error) 1306 { 1307 ip_proto_t *proto; 1308 int phone; 1309 services_t service; 1310 tl_received_msg_t received_msg; 1311 struct sockaddr *src; 1312 struct sockaddr *dest; 1313 struct sockaddr_in src_in; 1314 struct sockaddr_in dest_in; 1315 socklen_t addrlen; 1316 int rc; 1317 1318 if ((header->flags & IPFLAG_MORE_FRAGMENTS) || 1319 IP_FRAGMENT_OFFSET(header)) { 1320 // TODO fragmented 1321 return ENOTSUP; 1322 } 1323 1324 switch (header->version) { 1325 case IPVERSION: 1326 addrlen = sizeof(src_in); 1327 bzero(&src_in, addrlen); 1328 src_in.sin_family = AF_INET; 1329 memcpy(&dest_in, &src_in, addrlen); 1330 memcpy(&src_in.sin_addr.s_addr, &header->source_address, 1331 sizeof(header->source_address)); 1332 memcpy(&dest_in.sin_addr.s_addr, &header->destination_address, 1333 sizeof(header->destination_address)); 1334 src = (struct sockaddr *) &src_in; 1335 dest = (struct sockaddr *) &dest_in; 1336 break; 1337 1338 default: 1339 return ip_release_and_return(packet, EAFNOSUPPORT); 1340 } 1341 1342 rc = packet_set_addr(packet, (uint8_t *) src, (uint8_t *) dest, 1343 addrlen); 1344 if (rc != EOK) 1345 return ip_release_and_return(packet, rc); 1346 1347 // trim padding if present 1348 if (!error && 1349 (IP_TOTAL_LENGTH(header) < packet_get_data_length(packet))) { 1350 rc = packet_trim(packet, 0, 1351 packet_get_data_length(packet) - IP_TOTAL_LENGTH(header)); 1352 if (rc != EOK) 1353 return ip_release_and_return(packet, rc); 1354 } 1355 1356 fibril_rwlock_read_lock(&ip_globals.protos_lock); 1357 1358 proto = ip_protos_find(&ip_globals.protos, header->protocol); 1359 if (!proto) { 1360 fibril_rwlock_read_unlock(&ip_globals.protos_lock); 1361 phone = ip_prepare_icmp_and_get_phone(error, packet, header); 1362 if (phone >= 0) { 1363 // unreachable ICMP 1364 icmp_destination_unreachable_msg(phone, 1365 ICMP_PROT_UNREACH, 0, packet); 1366 } 1367 return ENOENT; 1368 } 1369 1370 if (proto->received_msg) { 1371 service = proto->service; 1372 received_msg = proto->received_msg; 1373 fibril_rwlock_read_unlock(&ip_globals.protos_lock); 1374 rc = received_msg(device_id, packet, service, error); 1375 } else { 1376 rc = tl_received_msg(proto->phone, device_id, packet, 1377 proto->service, error); 1378 fibril_rwlock_read_unlock(&ip_globals.protos_lock); 1379 } 1380 1381 return rc; 1382 } 1383 1384 /** Processes the received packet. 1385 * 1386 * The packet is either passed to another module or released on error. 1387 * 1388 * The ICMP_PARAM_POINTER error notification may be sent if the checksum is 1389 * invalid. 1390 * The ICMP_EXC_TTL error notification may be sent if the TTL is less than two. 1391 * The ICMP_HOST_UNREACH error notification may be sent if no route was found. 1392 * The ICMP_HOST_UNREACH error notification may be sent if the packet is for 1393 * another host and the routing is disabled. 1394 * 1395 * @param[in] device_id The source device identifier. 1396 * @param[in] packet The received packet to be processed. 1397 * @return EOK on success. 1398 * @return EINVAL if the TTL is less than two. 1399 * @return EINVAL if the checksum is invalid. 1400 * @return EAFNOSUPPORT if the address family is not supported. 1401 * @return ENOENT if no route was found. 1402 * @return ENOENT if the packet is for another host and the routing 1403 * is disabled. 1404 */ 1405 static int ip_process_packet(device_id_t device_id, packet_t *packet) 1406 { 1407 ip_header_t *header; 1408 in_addr_t dest; 1409 ip_route_t *route; 1410 int phone; 1411 struct sockaddr *addr; 1412 struct sockaddr_in addr_in; 1413 socklen_t addrlen; 1414 int rc; 1415 1416 header = (ip_header_t *) packet_get_data(packet); 1417 if (!header) 1418 return ip_release_and_return(packet, ENOMEM); 1419 1420 // checksum 1421 if ((header->header_checksum) && 1422 (IP_HEADER_CHECKSUM(header) != IP_CHECKSUM_ZERO)) { 1423 phone = ip_prepare_icmp_and_get_phone(0, packet, header); 1424 if (phone >= 0) { 1425 // checksum error ICMP 1426 icmp_parameter_problem_msg(phone, ICMP_PARAM_POINTER, 1427 ((size_t) ((void *) &header->header_checksum)) - 1428 ((size_t) ((void *) header)), packet); 1429 } 1430 return EINVAL; 1431 } 1432 1433 if (header->ttl <= 1) { 1434 phone = ip_prepare_icmp_and_get_phone(0, packet, header); 1435 if (phone >= 0) { 1436 // ttl exceeded ICMP 1437 icmp_time_exceeded_msg(phone, ICMP_EXC_TTL, packet); 1438 } 1439 return EINVAL; 1440 } 1441 1442 // process ipopt and get destination 1443 dest = ip_get_destination(header); 1444 1445 // set the addrination address 1446 switch (header->version) { 1447 case IPVERSION: 1448 addrlen = sizeof(addr_in); 1449 bzero(&addr_in, addrlen); 1450 addr_in.sin_family = AF_INET; 1451 memcpy(&addr_in.sin_addr.s_addr, &dest, sizeof(dest)); 1452 addr = (struct sockaddr *) &addr_in; 1453 break; 1454 1455 default: 1456 return ip_release_and_return(packet, EAFNOSUPPORT); 1457 } 1458 1459 rc = packet_set_addr(packet, NULL, (uint8_t *) &addr, addrlen); 1460 if (rc != EOK) 1461 return rc; 1462 1463 route = ip_find_route(dest); 1464 if (!route) { 1465 phone = ip_prepare_icmp_and_get_phone(0, packet, header); 1466 if (phone >= 0) { 1467 // unreachable ICMP 1468 icmp_destination_unreachable_msg(phone, 1469 ICMP_HOST_UNREACH, 0, packet); 1470 } 1471 return ENOENT; 1472 } 1473 1474 if (route->address.s_addr == dest.s_addr) { 1475 // local delivery 1476 return ip_deliver_local(device_id, packet, header, 0); 1477 } 1478 1479 if (route->netif->routing) { 1480 header->ttl--; 1481 return ip_send_route(packet, route->netif, route, NULL, dest, 1482 0); 1483 } 1484 1485 phone = ip_prepare_icmp_and_get_phone(0, packet, header); 1486 if (phone >= 0) { 1487 // unreachable ICMP if no routing 1488 icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0, 1489 packet); 1490 } 1491 1492 return ENOENT; 1493 } 1494 1353 1495 /** Returns the device packet dimensions for sending. 1354 1496 * … … 1362 1504 * @return EOK on success. 1363 1505 */ 1364 static int 1365 ip_packet_size_message(device_id_t device_id, size_t *addr_len, size_t *prefix, 1366 size_t *content, size_t *suffix) 1506 static int ip_packet_size_message(device_id_t device_id, size_t *addr_len, 1507 size_t *prefix, size_t *content, size_t *suffix) 1367 1508 { 1368 1509 ip_netif_t *netif; … … 1414 1555 } 1415 1556 1416 /** Returns the packet destination address from the IP header. 1417 * 1418 * @param[in] header The packet IP header to be read. 1419 * @return The packet destination address. 1420 */ 1421 static in_addr_t ip_get_destination(ip_header_t *header) 1422 { 1423 in_addr_t destination; 1424 1425 // TODO search set ipopt route? 1426 destination.s_addr = header->destination_address; 1427 return destination; 1428 } 1429 1430 /** Delivers the packet to the local host. 1431 * 1432 * The packet is either passed to another module or released on error. 1433 * The ICMP_PROT_UNREACH error notification may be sent if the protocol is not 1434 * found. 1435 * 1436 * @param[in] device_id The source device identifier. 1437 * @param[in] packet The packet to be delivered. 1438 * @param[in] header The first packet IP header. May be NULL. 1439 * @param[in] error The packet error service. 1557 /** Updates the device content length according to the new MTU value. 1558 * 1559 * @param[in] device_id The device identifier. 1560 * @param[in] mtu The new mtu value. 1440 1561 * @return EOK on success. 1441 * @return ENOTSUP if the packet is a fragment. 1442 * @return EAFNOSUPPORT if the address family is not supported. 1443 * @return ENOENT if the target protocol is not found. 1444 * @return Other error codes as defined for the packet_set_addr() 1445 * function. 1446 * @return Other error codes as defined for the packet_trim() 1447 * function. 1448 * @return Other error codes as defined for the protocol specific 1449 * tl_received_msg() function. 1562 * @return ENOENT if device is not found. 1563 */ 1564 static int ip_mtu_changed_message(device_id_t device_id, size_t mtu) 1565 { 1566 ip_netif_t *netif; 1567 1568 fibril_rwlock_write_lock(&ip_globals.netifs_lock); 1569 netif = ip_netifs_find(&ip_globals.netifs, device_id); 1570 if (!netif) { 1571 fibril_rwlock_write_unlock(&ip_globals.netifs_lock); 1572 return ENOENT; 1573 } 1574 netif->packet_dimension.content = mtu; 1575 fibril_rwlock_write_unlock(&ip_globals.netifs_lock); 1576 1577 printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu); 1578 1579 return EOK; 1580 } 1581 1582 /** Process IPC messages from the registered device driver modules 1583 * 1584 * @param[in] iid Message identifier. 1585 * @param[in,out] icall Message parameters. 1586 * 1587 */ 1588 static void ip_receiver(ipc_callid_t iid, ipc_call_t *icall) 1589 { 1590 packet_t *packet; 1591 int rc; 1592 1593 while (true) { 1594 switch (IPC_GET_IMETHOD(*icall)) { 1595 case NET_IL_DEVICE_STATE: 1596 rc = ip_device_state_message(IPC_GET_DEVICE(*icall), 1597 IPC_GET_STATE(*icall)); 1598 ipc_answer_0(iid, (sysarg_t) rc); 1599 break; 1600 1601 case NET_IL_RECEIVED: 1602 rc = packet_translate_remote(ip_globals.net_phone, &packet, 1603 IPC_GET_PACKET(*icall)); 1604 if (rc == EOK) { 1605 do { 1606 packet_t *next = pq_detach(packet); 1607 ip_process_packet(IPC_GET_DEVICE(*icall), packet); 1608 packet = next; 1609 } while (packet); 1610 } 1611 1612 ipc_answer_0(iid, (sysarg_t) rc); 1613 break; 1614 1615 case NET_IL_MTU_CHANGED: 1616 rc = ip_mtu_changed_message(IPC_GET_DEVICE(*icall), 1617 IPC_GET_MTU(*icall)); 1618 ipc_answer_0(iid, (sysarg_t) rc); 1619 break; 1620 1621 default: 1622 ipc_answer_0(iid, (sysarg_t) ENOTSUP); 1623 } 1624 1625 iid = async_get_call(icall); 1626 } 1627 } 1628 1629 /** Registers the transport layer protocol. 1630 * 1631 * The traffic of this protocol will be supplied using either the receive 1632 * function or IPC message. 1633 * 1634 * @param[in] protocol The transport layer module protocol. 1635 * @param[in] service The transport layer module service. 1636 * @param[in] phone The transport layer module phone. 1637 * @param[in] received_msg The receiving function. 1638 * @return EOK on success. 1639 * @return EINVAL if the protocol parameter and/or the service 1640 * parameter is zero. 1641 * @return EINVAL if the phone parameter is not a positive number 1642 * and the tl_receive_msg is NULL. 1643 * @return ENOMEM if there is not enough memory left. 1450 1644 */ 1451 1645 static int 1452 ip_ deliver_local(device_id_t device_id, packet_t *packet, ip_header_t *header,1453 services_t error)1646 ip_register(int protocol, services_t service, int phone, 1647 tl_received_msg_t received_msg) 1454 1648 { 1455 1649 ip_proto_t *proto; 1456 int phone; 1457 services_t service; 1458 tl_received_msg_t received_msg; 1459 struct sockaddr *src; 1460 struct sockaddr *dest; 1461 struct sockaddr_in src_in; 1462 struct sockaddr_in dest_in; 1463 socklen_t addrlen; 1464 int rc; 1465 1466 if ((header->flags & IPFLAG_MORE_FRAGMENTS) || 1467 IP_FRAGMENT_OFFSET(header)) { 1468 // TODO fragmented 1469 return ENOTSUP; 1470 } 1471 1472 switch (header->version) { 1473 case IPVERSION: 1474 addrlen = sizeof(src_in); 1475 bzero(&src_in, addrlen); 1476 src_in.sin_family = AF_INET; 1477 memcpy(&dest_in, &src_in, addrlen); 1478 memcpy(&src_in.sin_addr.s_addr, &header->source_address, 1479 sizeof(header->source_address)); 1480 memcpy(&dest_in.sin_addr.s_addr, &header->destination_address, 1481 sizeof(header->destination_address)); 1482 src = (struct sockaddr *) &src_in; 1483 dest = (struct sockaddr *) &dest_in; 1484 break; 1485 1486 default: 1487 return ip_release_and_return(packet, EAFNOSUPPORT); 1488 } 1489 1490 rc = packet_set_addr(packet, (uint8_t *) src, (uint8_t *) dest, 1491 addrlen); 1492 if (rc != EOK) 1493 return ip_release_and_return(packet, rc); 1494 1495 // trim padding if present 1496 if (!error && 1497 (IP_TOTAL_LENGTH(header) < packet_get_data_length(packet))) { 1498 rc = packet_trim(packet, 0, 1499 packet_get_data_length(packet) - IP_TOTAL_LENGTH(header)); 1500 if (rc != EOK) 1501 return ip_release_and_return(packet, rc); 1502 } 1503 1504 fibril_rwlock_read_lock(&ip_globals.protos_lock); 1505 1506 proto = ip_protos_find(&ip_globals.protos, header->protocol); 1507 if (!proto) { 1508 fibril_rwlock_read_unlock(&ip_globals.protos_lock); 1509 phone = ip_prepare_icmp_and_get_phone(error, packet, header); 1510 if (phone >= 0) { 1511 // unreachable ICMP 1512 icmp_destination_unreachable_msg(phone, 1513 ICMP_PROT_UNREACH, 0, packet); 1514 } 1515 return ENOENT; 1516 } 1517 1518 if (proto->received_msg) { 1519 service = proto->service; 1520 received_msg = proto->received_msg; 1521 fibril_rwlock_read_unlock(&ip_globals.protos_lock); 1522 rc = received_msg(device_id, packet, service, error); 1523 } else { 1524 rc = tl_received_msg(proto->phone, device_id, packet, 1525 proto->service, error); 1526 fibril_rwlock_read_unlock(&ip_globals.protos_lock); 1527 } 1528 1529 return rc; 1530 } 1531 1532 /** Processes the received packet. 1533 * 1534 * The packet is either passed to another module or released on error. 1535 * 1536 * The ICMP_PARAM_POINTER error notification may be sent if the checksum is 1537 * invalid. 1538 * The ICMP_EXC_TTL error notification may be sent if the TTL is less than two. 1539 * The ICMP_HOST_UNREACH error notification may be sent if no route was found. 1540 * The ICMP_HOST_UNREACH error notification may be sent if the packet is for 1541 * another host and the routing is disabled. 1542 * 1543 * @param[in] device_id The source device identifier. 1544 * @param[in] packet The received packet to be processed. 1545 * @return EOK on success. 1546 * @return EINVAL if the TTL is less than two. 1547 * @return EINVAL if the checksum is invalid. 1548 * @return EAFNOSUPPORT if the address family is not supported. 1549 * @return ENOENT if no route was found. 1550 * @return ENOENT if the packet is for another host and the routing 1551 * is disabled. 1552 */ 1553 static int 1554 ip_process_packet(device_id_t device_id, packet_t *packet) 1555 { 1556 ip_header_t *header; 1557 in_addr_t dest; 1558 ip_route_t *route; 1559 int phone; 1560 struct sockaddr *addr; 1561 struct sockaddr_in addr_in; 1562 socklen_t addrlen; 1563 int rc; 1564 1565 header = (ip_header_t *) packet_get_data(packet); 1566 if (!header) 1567 return ip_release_and_return(packet, ENOMEM); 1568 1569 // checksum 1570 if ((header->header_checksum) && 1571 (IP_HEADER_CHECKSUM(header) != IP_CHECKSUM_ZERO)) { 1572 phone = ip_prepare_icmp_and_get_phone(0, packet, header); 1573 if (phone >= 0) { 1574 // checksum error ICMP 1575 icmp_parameter_problem_msg(phone, ICMP_PARAM_POINTER, 1576 ((size_t) ((void *) &header->header_checksum)) - 1577 ((size_t) ((void *) header)), packet); 1578 } 1650 int index; 1651 1652 if (!protocol || !service || ((phone < 0) && !received_msg)) 1579 1653 return EINVAL; 1580 } 1581 1582 if (header->ttl <= 1) { 1583 phone = ip_prepare_icmp_and_get_phone(0, packet, header); 1584 if (phone >= 0) { 1585 // ttl exceeded ICMP 1586 icmp_time_exceeded_msg(phone, ICMP_EXC_TTL, packet); 1587 } 1588 return EINVAL; 1589 } 1590 1591 // process ipopt and get destination 1592 dest = ip_get_destination(header); 1593 1594 // set the addrination address 1595 switch (header->version) { 1596 case IPVERSION: 1597 addrlen = sizeof(addr_in); 1598 bzero(&addr_in, addrlen); 1599 addr_in.sin_family = AF_INET; 1600 memcpy(&addr_in.sin_addr.s_addr, &dest, sizeof(dest)); 1601 addr = (struct sockaddr *) &addr_in; 1602 break; 1603 1604 default: 1605 return ip_release_and_return(packet, EAFNOSUPPORT); 1606 } 1607 1608 rc = packet_set_addr(packet, NULL, (uint8_t *) &addr, addrlen); 1609 if (rc != EOK) 1610 return rc; 1611 1612 route = ip_find_route(dest); 1613 if (!route) { 1614 phone = ip_prepare_icmp_and_get_phone(0, packet, header); 1615 if (phone >= 0) { 1616 // unreachable ICMP 1617 icmp_destination_unreachable_msg(phone, 1618 ICMP_HOST_UNREACH, 0, packet); 1619 } 1620 return ENOENT; 1621 } 1622 1623 if (route->address.s_addr == dest.s_addr) { 1624 // local delivery 1625 return ip_deliver_local(device_id, packet, header, 0); 1626 } 1627 1628 if (route->netif->routing) { 1629 header->ttl--; 1630 return ip_send_route(packet, route->netif, route, NULL, dest, 1631 0); 1632 } 1633 1634 phone = ip_prepare_icmp_and_get_phone(0, packet, header); 1635 if (phone >= 0) { 1636 // unreachable ICMP if no routing 1637 icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0, 1638 packet); 1639 } 1640 1641 return ENOENT; 1642 } 1654 1655 proto = (ip_proto_t *) malloc(sizeof(ip_protos_t)); 1656 if (!proto) 1657 return ENOMEM; 1658 1659 proto->protocol = protocol; 1660 proto->service = service; 1661 proto->phone = phone; 1662 proto->received_msg = received_msg; 1663 1664 fibril_rwlock_write_lock(&ip_globals.protos_lock); 1665 index = ip_protos_add(&ip_globals.protos, proto->protocol, proto); 1666 if (index < 0) { 1667 fibril_rwlock_write_unlock(&ip_globals.protos_lock); 1668 free(proto); 1669 return index; 1670 } 1671 fibril_rwlock_write_unlock(&ip_globals.protos_lock); 1672 1673 printf("%s: Protocol registered (protocol: %d, phone: %d)\n", 1674 NAME, proto->protocol, proto->phone); 1675 1676 return EOK; 1677 } 1678 1643 1679 1644 1680 static int … … 1756 1792 (header->destination_address & route->netmask.s_addr))) { 1757 1793 // clear the ARP mapping if any 1758 address.value = ( char*) &header->destination_address;1794 address.value = (uint8_t *) &header->destination_address; 1759 1795 address.length = sizeof(header->destination_address); 1760 1796 arp_clear_address_req(netif->arp->phone, … … 1841 1877 } 1842 1878 1843 /** Processes the received IP packet or the packet queue one by one.1844 *1845 * The packet is either passed to another module or released on error.1846 *1847 * @param[in] device_id The source device identifier.1848 * @param[in,out] packet The received packet.1849 * @return EOK on success and the packet is no longer needed.1850 * @return EINVAL if the packet is too small to carry the IP1851 * packet.1852 * @return EINVAL if the received address lengths differs from the1853 * registered values.1854 * @return ENOENT if the device is not found in the cache.1855 * @return ENOENT if the protocol for the device is not found in1856 * the cache.1857 * @return ENOMEM if there is not enough memory left.1858 */1859 static int ip_receive_message(device_id_t device_id, packet_t *packet)1860 {1861 packet_t *next;1862 1863 do {1864 next = pq_detach(packet);1865 ip_process_packet(device_id, packet);1866 packet = next;1867 } while (packet);1868 1869 return EOK;1870 }1871 1872 1879 /** Processes the IP message. 1873 1880 * … … 1881 1888 * 1882 1889 * @see ip_interface.h 1883 * @see il_ interface.h1890 * @see il_remote.h 1884 1891 * @see IS_NET_IP_MESSAGE() 1885 1892 */ 1886 int 1887 ip_message_standalone(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer, 1888 int *answer_count) 1893 int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer, 1894 size_t *answer_count) 1889 1895 { 1890 1896 packet_t *packet; 1891 1897 struct sockaddr *addr; 1898 void *header; 1899 size_t headerlen; 1892 1900 size_t addrlen; 1893 1901 size_t prefix; 1894 1902 size_t suffix; 1895 1903 size_t content; 1896 void *header;1897 size_t headerlen;1898 1904 device_id_t device_id; 1899 1905 int rc; … … 1905 1911 1906 1912 case IPC_M_CONNECT_TO_ME: 1907 return ip_register(IL_GET_PROTO( call), IL_GET_SERVICE(call),1908 IPC_GET_PHONE( call), NULL);1909 1910 case NET_I L_DEVICE:1911 return ip_device_req_local(0, IPC_GET_DEVICE( call),1912 IPC_GET_SERVICE( call));1913 1914 case NET_I L_SEND:1913 return ip_register(IL_GET_PROTO(*call), IL_GET_SERVICE(*call), 1914 IPC_GET_PHONE(*call), NULL); 1915 1916 case NET_IP_DEVICE: 1917 return ip_device_req_local(0, IPC_GET_DEVICE(*call), 1918 IPC_GET_SERVICE(*call)); 1919 1920 case NET_IP_RECEIVED_ERROR: 1915 1921 rc = packet_translate_remote(ip_globals.net_phone, &packet, 1916 IPC_GET_PACKET( call));1922 IPC_GET_PACKET(*call)); 1917 1923 if (rc != EOK) 1918 1924 return rc; 1919 return ip_send_msg_local(0, IPC_GET_DEVICE(call), packet, 0, 1920 IPC_GET_ERROR(call)); 1921 1922 case NET_IL_DEVICE_STATE: 1923 return ip_device_state_message(IPC_GET_DEVICE(call), 1924 IPC_GET_STATE(call)); 1925 1926 case NET_IL_RECEIVED: 1927 rc = packet_translate_remote(ip_globals.net_phone, &packet, 1928 IPC_GET_PACKET(call)); 1929 if (rc != EOK) 1930 return rc; 1931 return ip_receive_message(IPC_GET_DEVICE(call), packet); 1932 1933 case NET_IP_RECEIVED_ERROR: 1934 rc = packet_translate_remote(ip_globals.net_phone, &packet, 1935 IPC_GET_PACKET(call)); 1936 if (rc != EOK) 1937 return rc; 1938 return ip_received_error_msg_local(0, IPC_GET_DEVICE(call), 1939 packet, IPC_GET_TARGET(call), IPC_GET_ERROR(call)); 1925 return ip_received_error_msg_local(0, IPC_GET_DEVICE(*call), 1926 packet, IPC_GET_TARGET(*call), IPC_GET_ERROR(*call)); 1940 1927 1941 1928 case NET_IP_ADD_ROUTE: 1942 return ip_add_route_req_local(0, IPC_GET_DEVICE( call),1943 IP_GET_ADDRESS( call), IP_GET_NETMASK(call),1944 IP_GET_GATEWAY( call));1929 return ip_add_route_req_local(0, IPC_GET_DEVICE(*call), 1930 IP_GET_ADDRESS(*call), IP_GET_NETMASK(*call), 1931 IP_GET_GATEWAY(*call)); 1945 1932 1946 1933 case NET_IP_SET_GATEWAY: 1947 return ip_set_gateway_req_local(0, IPC_GET_DEVICE( call),1948 IP_GET_GATEWAY( call));1934 return ip_set_gateway_req_local(0, IPC_GET_DEVICE(*call), 1935 IP_GET_GATEWAY(*call)); 1949 1936 1950 1937 case NET_IP_GET_ROUTE: … … 1954 1941 return rc; 1955 1942 1956 rc = ip_get_route_req_local(0, IP_GET_PROTOCOL( call), addr,1943 rc = ip_get_route_req_local(0, IP_GET_PROTOCOL(*call), addr, 1957 1944 (socklen_t) addrlen, &device_id, &header, &headerlen); 1958 1945 if (rc != EOK) 1959 1946 return rc; 1960 1947 1961 IPC_SET_DEVICE( answer, device_id);1962 IP_SET_HEADERLEN( answer, headerlen);1948 IPC_SET_DEVICE(*answer, device_id); 1949 IP_SET_HEADERLEN(*answer, headerlen); 1963 1950 1964 1951 *answer_count = 2; … … 1971 1958 return rc; 1972 1959 1973 case NET_I L_PACKET_SPACE:1974 rc = ip_packet_size_message(IPC_GET_DEVICE( call), &addrlen,1960 case NET_IP_PACKET_SPACE: 1961 rc = ip_packet_size_message(IPC_GET_DEVICE(*call), &addrlen, 1975 1962 &prefix, &content, &suffix); 1976 1963 if (rc != EOK) 1977 1964 return rc; 1978 1965 1979 IPC_SET_ADDR( answer, addrlen);1980 IPC_SET_PREFIX( answer, prefix);1981 IPC_SET_CONTENT( answer, content);1982 IPC_SET_SUFFIX( answer, suffix);1966 IPC_SET_ADDR(*answer, addrlen); 1967 IPC_SET_PREFIX(*answer, prefix); 1968 IPC_SET_CONTENT(*answer, content); 1969 IPC_SET_SUFFIX(*answer, suffix); 1983 1970 *answer_count = 4; 1984 1971 return EOK; 1985 1972 1986 case NET_IL_MTU_CHANGED: 1987 return ip_mtu_changed_message(IPC_GET_DEVICE(call), 1988 IPC_GET_MTU(call)); 1973 case NET_IP_SEND: 1974 rc = packet_translate_remote(ip_globals.net_phone, &packet, 1975 IPC_GET_PACKET(*call)); 1976 if (rc != EOK) 1977 return rc; 1978 1979 return ip_send_msg_local(0, IPC_GET_DEVICE(*call), packet, 0, 1980 IPC_GET_ERROR(*call)); 1989 1981 } 1990 1982 … … 1992 1984 } 1993 1985 1994 /** Default thread for new connections.1995 *1996 * @param[in] iid The initial message identifier.1997 * @param[in] icall The initial message call structure.1998 */1999 static void il_client_connection(ipc_callid_t iid, ipc_call_t *icall)2000 {2001 /*2002 * Accept the connection2003 * - Answer the first IPC_M_CONNECT_ME_TO call.2004 */2005 ipc_answer_0(iid, EOK);2006 2007 while (true) {2008 ipc_call_t answer;2009 int answer_count;2010 2011 /* Clear the answer structure */2012 refresh_answer(&answer, &answer_count);2013 2014 /* Fetch the next message */2015 ipc_call_t call;2016 ipc_callid_t callid = async_get_call(&call);2017 2018 /* Process the message */2019 int res = il_module_message_standalone(callid, &call, &answer,2020 &answer_count);2021 2022 /*2023 * End if told to either by the message or the processing2024 * result.2025 */2026 if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||2027 (res == EHANGUP)) {2028 return;2029 }2030 2031 /* Answer the message */2032 answer_call(callid, res, &answer, answer_count);2033 }2034 }2035 2036 /** Starts the module.2037 *2038 * @return EOK on success.2039 * @return Other error codes as defined for each specific module start function.2040 */2041 1986 int main(int argc, char *argv[]) 2042 1987 { 2043 int rc;2044 2045 1988 /* Start the module */ 2046 rc = il_module_start_standalone(il_client_connection); 2047 return rc; 1989 return il_module_start(SERVICE_IP); 2048 1990 } 2049 1991 -
uspace/srv/net/il/ip/ip.h
reaef141 r80cd7cd 138 138 /** IP global data. */ 139 139 struct ip_globals { 140 /** Default client connection function for support modules. */141 async_client_conn_t client_connection;142 140 /** Default gateway. */ 143 141 ip_route_t gateway;
Note:
See TracChangeset
for help on using the changeset viewer.
