Changeset 357b5f5 in mainline for uspace/srv/net
- Timestamp:
- 2011-01-23T20:09:13Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- fdb9982c
- Parents:
- cead2aa (diff), 7e36c8d (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- uspace/srv/net
- Files:
-
- 14 deleted
- 23 edited
- 2 moved
-
cfg/lo (moved) (moved from uspace/srv/net/cfg/lo.netif_standalone )
-
cfg/lo.netif_nil_bundle (deleted)
-
cfg/ne2k (moved) (moved from uspace/srv/net/cfg/ne2k.netif_standalone ) (2 diffs)
-
cfg/ne2k.netif_nil_bundle (deleted)
-
il/arp/Makefile (modified) (1 diff)
-
il/arp/arp.c (modified) (17 diffs)
-
il/arp/arp.h (modified) (6 diffs)
-
il/arp/arp_header.h (deleted)
-
il/arp/arp_module.c (deleted)
-
il/ip/Makefile (modified) (1 diff)
-
il/ip/ip.c (modified) (34 diffs)
-
il/ip/ip.h (modified) (1 diff)
-
il/ip/ip_module.c (deleted)
-
il/ip/ip_module.h (deleted)
-
net/net.c (modified) (32 diffs)
-
net/net.h (modified) (3 diffs)
-
net/net_standalone.c (modified) (2 diffs)
-
netif/lo/Makefile (modified) (1 diff)
-
netif/lo/lo.c (modified) (7 diffs)
-
nil/eth/Makefile (modified) (1 diff)
-
nil/eth/eth.c (modified) (15 diffs)
-
nil/eth/eth.h (modified) (2 diffs)
-
nil/eth/eth_header.h (deleted)
-
nil/nildummy/Makefile (modified) (1 diff)
-
nil/nildummy/nildummy.c (modified) (20 diffs)
-
nil/nildummy/nildummy.h (modified) (4 diffs)
-
nil/nildummy/nildummy_module.c (deleted)
-
tl/icmp/Makefile (modified) (1 diff)
-
tl/icmp/icmp.c (modified) (12 diffs)
-
tl/icmp/icmp.h (deleted)
-
tl/icmp/icmp_module.c (deleted)
-
tl/icmp/icmp_module.h (deleted)
-
tl/tcp/Makefile (modified) (1 diff)
-
tl/tcp/tcp.c (modified) (30 diffs)
-
tl/tcp/tcp_module.h (deleted)
-
tl/udp/Makefile (modified) (1 diff)
-
tl/udp/udp.c (modified) (14 diffs)
-
tl/udp/udp_module.c (deleted)
-
tl/udp/udp_module.h (deleted)
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/cfg/ne2k
rcead2aa r357b5f5 3 3 NAME=ne2k 4 4 5 NETIF= dp83905 NETIF=ne2000 6 6 NIL=eth 7 7 IL=ip 8 8 9 IRQ= 99 IRQ=5 10 10 IO=300 11 11 … … 17 17 IP_ADDR=10.0.2.15 18 18 IP_ROUTING=yes 19 IP_NETMASK=255.255.255. 24019 IP_NETMASK=255.255.255.0 20 20 IP_BROADCAST=10.0.2.255 21 21 IP_GATEWAY=10.0.2.2 22 22 ARP=arp 23 23 24 MTU=1 49224 MTU=1500 -
uspace/srv/net/il/arp/Makefile
rcead2aa r357b5f5 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
rcead2aa r357b5f5 36 36 */ 37 37 38 #include "arp.h"39 #include "arp_header.h"40 #include "arp_oc.h"41 #include "arp_module.h"42 43 38 #include <async.h> 44 39 #include <malloc.h> 45 40 #include <mem.h> 46 41 #include <fibril_synch.h> 42 #include <assert.h> 47 43 #include <stdio.h> 48 44 #include <str.h> … … 54 50 #include <ipc/arp.h> 55 51 #include <ipc/il.h> 52 #include <ipc/nil.h> 56 53 #include <byteorder.h> 57 54 #include <errno.h> 58 59 55 #include <net/modules.h> 60 56 #include <net/device.h> 61 57 #include <net/packet.h> 62 63 #include <nil_interface.h> 58 #include <nil_remote.h> 64 59 #include <protocol_map.h> 65 60 #include <packet_client.h> 66 61 #include <packet_remote.h> 67 #include <il_ interface.h>68 #include <il_ local.h>69 62 #include <il_remote.h> 63 #include <il_skel.h> 64 #include "arp.h" 70 65 71 66 /** ARP module name. */ 72 67 #define NAME "arp" 73 68 69 /** Number of microseconds to wait for an ARP reply. */ 70 #define ARP_TRANS_WAIT 1000000 71 72 /** @name ARP operation codes definitions */ 73 /*@{*/ 74 75 /** REQUEST operation code. */ 76 #define ARPOP_REQUEST 1 77 78 /** REPLY operation code. */ 79 #define ARPOP_REPLY 2 80 81 /*@}*/ 82 83 /** Type definition of an ARP protocol header. 84 * @see arp_header 85 */ 86 typedef struct arp_header arp_header_t; 87 88 /** ARP protocol header. */ 89 struct arp_header { 90 /** 91 * Hardware type identifier. 92 * @see hardware.h 93 */ 94 uint16_t hardware; 95 96 /** Protocol identifier. */ 97 uint16_t protocol; 98 /** Hardware address length in bytes. */ 99 uint8_t hardware_length; 100 /** Protocol address length in bytes. */ 101 uint8_t protocol_length; 102 103 /** 104 * ARP packet type. 105 * @see arp_oc.h 106 */ 107 uint16_t operation; 108 } __attribute__ ((packed)); 109 74 110 /** ARP global data. */ 75 111 arp_globals_t arp_globals; … … 77 113 DEVICE_MAP_IMPLEMENT(arp_cache, arp_device_t); 78 114 INT_MAP_IMPLEMENT(arp_protos, arp_proto_t); 79 GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, measured_string_t); 80 81 /** Clears the device specific data. 82 * 83 * @param[in] device The device specific data. 115 GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, arp_trans_t); 116 117 static void arp_clear_trans(arp_trans_t *trans) 118 { 119 if (trans->hw_addr) { 120 free(trans->hw_addr); 121 trans->hw_addr = NULL; 122 } 123 124 fibril_condvar_broadcast(&trans->cv); 125 } 126 127 static void arp_clear_addr(arp_addr_t *addresses) 128 { 129 int count; 130 131 for (count = arp_addr_count(addresses) - 1; count >= 0; count--) { 132 arp_trans_t *trans = arp_addr_items_get_index(&addresses->values, 133 count); 134 if (trans) 135 arp_clear_trans(trans); 136 } 137 } 138 139 /** Clear the device specific data. 140 * 141 * @param[in] device Device specific data. 84 142 */ 85 143 static void arp_clear_device(arp_device_t *device) 86 144 { 87 145 int count; 88 arp_proto_t *proto; 89 146 90 147 for (count = arp_protos_count(&device->protos) - 1; count >= 0; 91 148 count--) { 92 proto = arp_protos_get_index(&device->protos, count); 149 arp_proto_t *proto = arp_protos_get_index(&device->protos, 150 count); 151 93 152 if (proto) { 94 153 if (proto->addr) 95 154 free(proto->addr); 155 96 156 if (proto->addr_data) 97 157 free(proto->addr_data); 158 159 arp_clear_addr(&proto->addresses); 98 160 arp_addr_destroy(&proto->addresses); 99 161 } 100 162 } 163 101 164 arp_protos_clear(&device->protos); 102 165 } … … 105 168 { 106 169 int count; 107 arp_device_t *device; 108 109 fibril_rwlock_write_lock(&arp_globals.lock); 170 171 fibril_mutex_lock(&arp_globals.lock); 110 172 for (count = arp_cache_count(&arp_globals.cache) - 1; count >= 0; 111 173 count--) { 112 device = arp_cache_get_index(&arp_globals.cache, count); 174 arp_device_t *device = arp_cache_get_index(&arp_globals.cache, 175 count); 176 113 177 if (device) { 114 178 arp_clear_device(device); 115 179 if (device->addr_data) 116 180 free(device->addr_data); 181 117 182 if (device->broadcast_data) 118 183 free(device->broadcast_data); 119 184 } 120 185 } 186 121 187 arp_cache_clear(&arp_globals.cache); 122 fibril_ rwlock_write_unlock(&arp_globals.lock);123 printf("Cache cleaned\n");188 fibril_mutex_unlock(&arp_globals.lock); 189 124 190 return EOK; 125 191 } … … 128 194 services_t protocol, measured_string_t *address) 129 195 { 130 arp_device_t *device; 131 arp_proto_t *proto; 132 133 fibril_rwlock_write_lock(&arp_globals.lock); 134 device = arp_cache_find(&arp_globals.cache, device_id); 196 fibril_mutex_lock(&arp_globals.lock); 197 198 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id); 135 199 if (!device) { 136 fibril_ rwlock_write_unlock(&arp_globals.lock);200 fibril_mutex_unlock(&arp_globals.lock); 137 201 return ENOENT; 138 202 } 139 proto = arp_protos_find(&device->protos, protocol); 203 204 arp_proto_t *proto = arp_protos_find(&device->protos, protocol); 140 205 if (!proto) { 141 fibril_ rwlock_write_unlock(&arp_globals.lock);206 fibril_mutex_unlock(&arp_globals.lock); 142 207 return ENOENT; 143 208 } 209 210 arp_trans_t *trans = arp_addr_find(&proto->addresses, address->value, 211 address->length); 212 if (trans) 213 arp_clear_trans(trans); 214 144 215 arp_addr_exclude(&proto->addresses, address->value, address->length); 145 fibril_rwlock_write_unlock(&arp_globals.lock); 216 217 fibril_mutex_unlock(&arp_globals.lock); 146 218 return EOK; 147 219 } 148 220 149 150 221 static int arp_clear_device_req(int arp_phone, device_id_t device_id) 151 222 { 152 arp_device_t *device; 153 154 fibril_rwlock_write_lock(&arp_globals.lock); 155 device = arp_cache_find(&arp_globals.cache, device_id); 223 fibril_mutex_lock(&arp_globals.lock); 224 225 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id); 156 226 if (!device) { 157 fibril_ rwlock_write_unlock(&arp_globals.lock);227 fibril_mutex_unlock(&arp_globals.lock); 158 228 return ENOENT; 159 229 } 230 160 231 arp_clear_device(device); 161 printf("Device %d cleared\n", device_id);162 fibril_ rwlock_write_unlock(&arp_globals.lock);232 233 fibril_mutex_unlock(&arp_globals.lock); 163 234 return EOK; 164 235 } 165 236 166 /** Creates new protocol specific data. 167 * 168 * Allocates and returns the needed memory block as the proto parameter. 169 * 170 * @param[out] proto The allocated protocol specific data. 171 * @param[in] service The protocol module service. 172 * @param[in] address The actual protocol device address. 173 * @return EOK on success. 174 * @return ENOMEM if there is not enough memory left. 237 /** Create new protocol specific data. 238 * 239 * Allocate and return the needed memory block as the proto parameter. 240 * 241 * @param[out] proto Allocated protocol specific data. 242 * @param[in] service Protocol module service. 243 * @param[in] address Actual protocol device address. 244 * 245 * @return EOK on success. 246 * @return ENOMEM if there is not enough memory left. 247 * 175 248 */ 176 249 static int arp_proto_create(arp_proto_t **proto, services_t service, 177 250 measured_string_t *address) 178 251 { 179 int rc;180 181 252 *proto = (arp_proto_t *) malloc(sizeof(arp_proto_t)); 182 253 if (!*proto) … … 187 258 (*proto)->addr_data = address->value; 188 259 189 rc = arp_addr_initialize(&(*proto)->addresses);260 int rc = arp_addr_initialize(&(*proto)->addresses); 190 261 if (rc != EOK) { 191 262 free(*proto); … … 196 267 } 197 268 198 /** Registers the device. 199 * 200 * Creates new device entry in the cache or updates the protocol address if the 201 * device with the device identifier and the driver service exists. 202 * 203 * @param[in] device_id The device identifier. 204 * @param[in] service The device driver service. 205 * @param[in] protocol The protocol service. 206 * @param[in] address The actual device protocol address. 207 * @return EOK on success. 208 * @return EEXIST if another device with the same device identifier 209 * and different driver service exists. 210 * @return ENOMEM if there is not enough memory left. 211 * @return Other error codes as defined for the 212 * measured_strings_return() function. 213 */ 214 static int arp_device_message(device_id_t device_id, services_t service, 215 services_t protocol, measured_string_t *address) 216 { 217 arp_device_t *device; 218 arp_proto_t *proto; 219 hw_type_t hardware; 220 int index; 269 /** Process the received ARP packet. 270 * 271 * Update the source hardware address if the source entry exists or the packet 272 * is targeted to my protocol address. 273 * 274 * Respond to the ARP request if the packet is the ARP request and is 275 * targeted to my address. 276 * 277 * @param[in] device_id Source device identifier. 278 * @param[in,out] packet Received packet. 279 * 280 * @return EOK on success and the packet is no longer needed. 281 * @return One on success and the packet has been reused. 282 * @return EINVAL if the packet is too small to carry an ARP 283 * packet. 284 * @return EINVAL if the received address lengths differs from 285 * the registered values. 286 * @return ENOENT if the device is not found in the cache. 287 * @return ENOENT if the protocol for the device is not found in 288 * the cache. 289 * @return ENOMEM if there is not enough memory left. 290 * 291 */ 292 static int arp_receive_message(device_id_t device_id, packet_t *packet) 293 { 221 294 int rc; 222 223 fibril_rwlock_write_lock(&arp_globals.lock); 224 225 /* An existing device? */ 226 device = arp_cache_find(&arp_globals.cache, device_id); 227 228 if (device) { 229 if (device->service != service) { 230 printf("Device %d already exists\n", device->device_id); 231 fibril_rwlock_write_unlock(&arp_globals.lock); 232 return EEXIST; 233 } 234 proto = arp_protos_find(&device->protos, protocol); 235 if (proto) { 236 free(proto->addr); 237 free(proto->addr_data); 238 proto->addr = address; 239 proto->addr_data = address->value; 240 } else { 241 rc = arp_proto_create(&proto, protocol, address); 242 if (rc != EOK) { 243 fibril_rwlock_write_unlock(&arp_globals.lock); 244 return rc; 245 } 246 index = arp_protos_add(&device->protos, proto->service, 247 proto); 248 if (index < 0) { 249 fibril_rwlock_write_unlock(&arp_globals.lock); 250 free(proto); 251 return index; 252 } 253 printf("New protocol added:\n\tdevice id\t= " 254 "%d\n\tproto\t= %d", device_id, protocol); 255 } 256 } else { 257 hardware = hardware_map(service); 258 if (!hardware) 259 return ENOENT; 260 261 /* Create a new device */ 262 device = (arp_device_t *) malloc(sizeof(arp_device_t)); 263 if (!device) { 264 fibril_rwlock_write_unlock(&arp_globals.lock); 265 return ENOMEM; 266 } 267 device->hardware = hardware; 268 device->device_id = device_id; 269 rc = arp_protos_initialize(&device->protos); 270 if (rc != EOK) { 271 fibril_rwlock_write_unlock(&arp_globals.lock); 272 free(device); 273 return rc; 274 } 275 rc = arp_proto_create(&proto, protocol, address); 276 if (rc != EOK) { 277 fibril_rwlock_write_unlock(&arp_globals.lock); 278 free(device); 279 return rc; 280 } 281 index = arp_protos_add(&device->protos, proto->service, proto); 282 if (index < 0) { 283 fibril_rwlock_write_unlock(&arp_globals.lock); 284 arp_protos_destroy(&device->protos); 285 free(device); 286 return index; 287 } 288 device->service = service; 289 290 /* Bind the new one */ 291 device->phone = nil_bind_service(device->service, 292 (ipcarg_t) device->device_id, SERVICE_ARP, 293 arp_globals.client_connection); 294 if (device->phone < 0) { 295 fibril_rwlock_write_unlock(&arp_globals.lock); 296 arp_protos_destroy(&device->protos); 297 free(device); 298 return EREFUSED; 299 } 300 301 /* Get packet dimensions */ 302 rc = nil_packet_size_req(device->phone, device_id, 303 &device->packet_dimension); 304 if (rc != EOK) { 305 fibril_rwlock_write_unlock(&arp_globals.lock); 306 arp_protos_destroy(&device->protos); 307 free(device); 308 return rc; 309 } 310 311 /* Get hardware address */ 312 rc = nil_get_addr_req(device->phone, device_id, &device->addr, 313 &device->addr_data); 314 if (rc != EOK) { 315 fibril_rwlock_write_unlock(&arp_globals.lock); 316 arp_protos_destroy(&device->protos); 317 free(device); 318 return rc; 319 } 320 321 /* Get broadcast address */ 322 rc = nil_get_broadcast_addr_req(device->phone, device_id, 323 &device->broadcast_addr, &device->broadcast_data); 324 if (rc != EOK) { 325 fibril_rwlock_write_unlock(&arp_globals.lock); 326 free(device->addr); 327 free(device->addr_data); 328 arp_protos_destroy(&device->protos); 329 free(device); 330 return rc; 331 } 332 333 rc = arp_cache_add(&arp_globals.cache, device->device_id, 334 device); 335 if (rc != EOK) { 336 fibril_rwlock_write_unlock(&arp_globals.lock); 337 free(device->addr); 338 free(device->addr_data); 339 free(device->broadcast_addr); 340 free(device->broadcast_data); 341 arp_protos_destroy(&device->protos); 342 free(device); 343 return rc; 344 } 345 printf("%s: Device registered (id: %d, type: 0x%x, service: %d," 346 " proto: %d)\n", NAME, device->device_id, device->hardware, 347 device->service, protocol); 348 } 349 fibril_rwlock_write_unlock(&arp_globals.lock); 350 351 return EOK; 352 } 353 354 /** Initializes the ARP module. 355 * 356 * @param[in] client_connection The client connection processing function. 357 * The module skeleton propagates its own one. 358 * @return EOK on success. 359 * @return ENOMEM if there is not enough memory left. 360 */ 361 int arp_initialize(async_client_conn_t client_connection) 362 { 363 int rc; 364 365 fibril_rwlock_initialize(&arp_globals.lock); 366 fibril_rwlock_write_lock(&arp_globals.lock); 367 arp_globals.client_connection = client_connection; 368 rc = arp_cache_initialize(&arp_globals.cache); 369 fibril_rwlock_write_unlock(&arp_globals.lock); 370 371 return rc; 372 } 373 374 /** Updates the device content length according to the new MTU value. 375 * 376 * @param[in] device_id The device identifier. 377 * @param[in] mtu The new mtu value. 378 * @return ENOENT if device is not found. 379 * @return EOK on success. 380 */ 381 static int arp_mtu_changed_message(device_id_t device_id, size_t mtu) 382 { 383 arp_device_t *device; 384 385 fibril_rwlock_write_lock(&arp_globals.lock); 386 device = arp_cache_find(&arp_globals.cache, device_id); 387 if (!device) { 388 fibril_rwlock_write_unlock(&arp_globals.lock); 389 return ENOENT; 390 } 391 device->packet_dimension.content = mtu; 392 fibril_rwlock_write_unlock(&arp_globals.lock); 393 printf("arp - device %d changed mtu to %zu\n\n", device_id, mtu); 394 return EOK; 395 } 396 397 /** Processes the received ARP packet. 398 * 399 * Updates the source hardware address if the source entry exists or the packet 400 * is targeted to my protocol address. 401 * Responses to the ARP request if the packet is the ARP request and is 402 * targeted to my address. 403 * 404 * @param[in] device_id The source device identifier. 405 * @param[in,out] packet The received packet. 406 * @return EOK on success and the packet is no longer needed. 407 * @return One on success and the packet has been reused. 408 * @return EINVAL if the packet is too small to carry an ARP 409 * packet. 410 * @return EINVAL if the received address lengths differs from 411 * the registered values. 412 * @return ENOENT if the device is not found in the cache. 413 * @return ENOENT if the protocol for the device is not found in 414 * the cache. 415 * @return ENOMEM if there is not enough memory left. 416 */ 417 static int arp_receive_message(device_id_t device_id, packet_t *packet) 418 { 419 size_t length; 420 arp_header_t *header; 421 arp_device_t *device; 422 arp_proto_t *proto; 423 measured_string_t *hw_source; 424 uint8_t *src_hw; 425 uint8_t *src_proto; 426 uint8_t *des_hw; 427 uint8_t *des_proto; 428 int rc; 429 430 length = packet_get_data_length(packet); 295 296 size_t length = packet_get_data_length(packet); 431 297 if (length <= sizeof(arp_header_t)) 432 298 return EINVAL; 433 434 device = arp_cache_find(&arp_globals.cache, device_id);299 300 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id); 435 301 if (!device) 436 302 return ENOENT; 437 438 header = (arp_header_t *) packet_get_data(packet);303 304 arp_header_t *header = (arp_header_t *) packet_get_data(packet); 439 305 if ((ntohs(header->hardware) != device->hardware) || 440 306 (length < sizeof(arp_header_t) + header->hardware_length * 2U + … … 442 308 return EINVAL; 443 309 } 444 445 proto = arp_protos_find(&device->protos,310 311 arp_proto_t *proto = arp_protos_find(&device->protos, 446 312 protocol_unmap(device->service, ntohs(header->protocol))); 447 313 if (!proto) 448 314 return ENOENT; 449 450 src_hw = ((uint8_t *) header) + sizeof(arp_header_t); 451 src_proto = src_hw + header->hardware_length; 452 des_hw = src_proto + header->protocol_length; 453 des_proto = des_hw + header->hardware_length; 454 hw_source = arp_addr_find(&proto->addresses, (char *) src_proto, 455 CONVERT_SIZE(uint8_t, char, header->protocol_length)); 456 /* Exists? */ 457 if (hw_source) { 458 if (hw_source->length != CONVERT_SIZE(uint8_t, char, 459 header->hardware_length)) { 315 316 uint8_t *src_hw = ((uint8_t *) header) + sizeof(arp_header_t); 317 uint8_t *src_proto = src_hw + header->hardware_length; 318 uint8_t *des_hw = src_proto + header->protocol_length; 319 uint8_t *des_proto = des_hw + header->hardware_length; 320 321 arp_trans_t *trans = arp_addr_find(&proto->addresses, src_proto, 322 header->protocol_length); 323 324 if ((trans) && (trans->hw_addr)) { 325 /* Translation exists */ 326 if (trans->hw_addr->length != header->hardware_length) 460 327 return EINVAL; 461 } 462 memcpy(hw_source->value, src_hw, hw_source->length); 463 } 328 329 memcpy(trans->hw_addr->value, src_hw, trans->hw_addr->length); 330 } 331 464 332 /* Is my protocol address? */ 465 if (proto->addr->length != CONVERT_SIZE(uint8_t, char, 466 header->protocol_length)) { 333 if (proto->addr->length != header->protocol_length) 467 334 return EINVAL; 468 } 469 if (!str_lcmp(proto->addr->value, (char *) des_proto, 470 proto->addr->length)) { 471 /* Not already updated? */ 472 if (!hw_source) { 473 hw_source = measured_string_create_bulk((char *) src_hw, 474 CONVERT_SIZE(uint8_t, char, 475 header->hardware_length)); 476 if (!hw_source) 335 336 if (!bcmp(proto->addr->value, des_proto, proto->addr->length)) { 337 if (!trans) { 338 /* Update the translation */ 339 trans = (arp_trans_t *) malloc(sizeof(arp_trans_t)); 340 if (!trans) 477 341 return ENOMEM; 478 479 rc = arp_addr_add(&proto->addresses, (char *) src_proto, 480 CONVERT_SIZE(uint8_t, char, 481 header->protocol_length), hw_source); 482 if (rc != EOK) 342 343 trans->hw_addr = NULL; 344 fibril_condvar_initialize(&trans->cv); 345 rc = arp_addr_add(&proto->addresses, src_proto, 346 header->protocol_length, trans); 347 if (rc != EOK) { 348 /* The generic char map has already freed trans! */ 483 349 return rc; 484 } 350 } 351 } 352 353 if (!trans->hw_addr) { 354 trans->hw_addr = measured_string_create_bulk(src_hw, 355 header->hardware_length); 356 if (!trans->hw_addr) 357 return ENOMEM; 358 359 /* Notify the fibrils that wait for the translation. */ 360 fibril_condvar_broadcast(&trans->cv); 361 } 362 485 363 if (ntohs(header->operation) == ARPOP_REQUEST) { 486 364 header->operation = htons(ARPOP_REPLY); … … 490 368 memcpy(src_hw, device->addr->value, 491 369 device->packet_dimension.addr_len); 492 memcpy(des_hw, hw_source->value,370 memcpy(des_hw, trans->hw_addr->value, 493 371 header->hardware_length); 494 372 … … 503 381 } 504 382 } 505 383 506 384 return EOK; 507 385 } 508 386 509 510 /** Returns the hardware address for the given protocol address. 511 * 512 * Sends the ARP request packet if the hardware address is not found in the 513 * cache. 514 * 515 * @param[in] device_id The device identifier. 516 * @param[in] protocol The protocol service. 517 * @param[in] target The target protocol address. 518 * @return The hardware address of the target. 519 * @return NULL if the target parameter is NULL. 520 * @return NULL if the device is not found. 521 * @return NULL if the device packet is too small to send a 522 * request. 523 * @return NULL if the hardware address is not found in the cache. 524 */ 525 static measured_string_t * 526 arp_translate_message(device_id_t device_id, services_t protocol, 527 measured_string_t *target) 528 { 529 arp_device_t *device; 530 arp_proto_t *proto; 531 measured_string_t *addr; 532 size_t length; 387 /** Update the device content length according to the new MTU value. 388 * 389 * @param[in] device_id Device identifier. 390 * @param[in] mtu New MTU value. 391 * 392 * @return ENOENT if device is not found. 393 * @return EOK on success. 394 * 395 */ 396 static int arp_mtu_changed_message(device_id_t device_id, size_t mtu) 397 { 398 fibril_mutex_lock(&arp_globals.lock); 399 400 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id); 401 if (!device) { 402 fibril_mutex_unlock(&arp_globals.lock); 403 return ENOENT; 404 } 405 406 device->packet_dimension.content = mtu; 407 408 fibril_mutex_unlock(&arp_globals.lock); 409 410 printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu); 411 412 return EOK; 413 } 414 415 /** Process IPC messages from the registered device driver modules 416 * 417 * @param[in] iid Message identifier. 418 * @param[in,out] icall Message parameters. 419 * 420 */ 421 static void arp_receiver(ipc_callid_t iid, ipc_call_t *icall) 422 { 533 423 packet_t *packet; 534 arp_header_t *header; 535 536 if (!target) 537 return NULL; 538 539 device = arp_cache_find(&arp_globals.cache, device_id); 540 if (!device) 541 return NULL; 542 543 proto = arp_protos_find(&device->protos, protocol); 544 if (!proto || (proto->addr->length != target->length)) 545 return NULL; 546 547 addr = arp_addr_find(&proto->addresses, target->value, target->length); 548 if (addr) 549 return addr; 550 424 int rc; 425 426 while (true) { 427 switch (IPC_GET_IMETHOD(*icall)) { 428 case NET_IL_DEVICE_STATE: 429 /* Do nothing - keep the cache */ 430 ipc_answer_0(iid, (sysarg_t) EOK); 431 break; 432 433 case NET_IL_RECEIVED: 434 rc = packet_translate_remote(arp_globals.net_phone, &packet, 435 IPC_GET_PACKET(*icall)); 436 if (rc == EOK) { 437 fibril_mutex_lock(&arp_globals.lock); 438 do { 439 packet_t *next = pq_detach(packet); 440 rc = arp_receive_message(IPC_GET_DEVICE(*icall), packet); 441 if (rc != 1) { 442 pq_release_remote(arp_globals.net_phone, 443 packet_get_id(packet)); 444 } 445 446 packet = next; 447 } while (packet); 448 fibril_mutex_unlock(&arp_globals.lock); 449 } 450 ipc_answer_0(iid, (sysarg_t) rc); 451 break; 452 453 case NET_IL_MTU_CHANGED: 454 rc = arp_mtu_changed_message(IPC_GET_DEVICE(*icall), 455 IPC_GET_MTU(*icall)); 456 ipc_answer_0(iid, (sysarg_t) rc); 457 break; 458 459 default: 460 ipc_answer_0(iid, (sysarg_t) ENOTSUP); 461 } 462 463 iid = async_get_call(icall); 464 } 465 } 466 467 /** Register the device. 468 * 469 * Create new device entry in the cache or update the protocol address if the 470 * device with the device identifier and the driver service exists. 471 * 472 * @param[in] device_id Device identifier. 473 * @param[in] service Device driver service. 474 * @param[in] protocol Protocol service. 475 * @param[in] address Actual device protocol address. 476 * 477 * @return EOK on success. 478 * @return EEXIST if another device with the same device identifier 479 * and different driver service exists. 480 * @return ENOMEM if there is not enough memory left. 481 * @return Other error codes as defined for the 482 * measured_strings_return() function. 483 * 484 */ 485 static int arp_device_message(device_id_t device_id, services_t service, 486 services_t protocol, measured_string_t *address) 487 { 488 int index; 489 int rc; 490 491 fibril_mutex_lock(&arp_globals.lock); 492 493 /* An existing device? */ 494 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id); 495 if (device) { 496 if (device->service != service) { 497 printf("%s: Device %d already exists\n", NAME, 498 device->device_id); 499 fibril_mutex_unlock(&arp_globals.lock); 500 return EEXIST; 501 } 502 503 arp_proto_t *proto = arp_protos_find(&device->protos, protocol); 504 if (proto) { 505 free(proto->addr); 506 free(proto->addr_data); 507 proto->addr = address; 508 proto->addr_data = address->value; 509 } else { 510 rc = arp_proto_create(&proto, protocol, address); 511 if (rc != EOK) { 512 fibril_mutex_unlock(&arp_globals.lock); 513 return rc; 514 } 515 516 index = arp_protos_add(&device->protos, proto->service, 517 proto); 518 if (index < 0) { 519 fibril_mutex_unlock(&arp_globals.lock); 520 free(proto); 521 return index; 522 } 523 524 printf("%s: New protocol added (id: %d, proto: %d)\n", NAME, 525 device_id, protocol); 526 } 527 } else { 528 hw_type_t hardware = hardware_map(service); 529 if (!hardware) 530 return ENOENT; 531 532 /* Create new device */ 533 device = (arp_device_t *) malloc(sizeof(arp_device_t)); 534 if (!device) { 535 fibril_mutex_unlock(&arp_globals.lock); 536 return ENOMEM; 537 } 538 539 device->hardware = hardware; 540 device->device_id = device_id; 541 rc = arp_protos_initialize(&device->protos); 542 if (rc != EOK) { 543 fibril_mutex_unlock(&arp_globals.lock); 544 free(device); 545 return rc; 546 } 547 548 arp_proto_t *proto; 549 rc = arp_proto_create(&proto, protocol, address); 550 if (rc != EOK) { 551 fibril_mutex_unlock(&arp_globals.lock); 552 free(device); 553 return rc; 554 } 555 556 index = arp_protos_add(&device->protos, proto->service, proto); 557 if (index < 0) { 558 fibril_mutex_unlock(&arp_globals.lock); 559 arp_protos_destroy(&device->protos); 560 free(device); 561 return index; 562 } 563 564 device->service = service; 565 566 /* Bind */ 567 device->phone = nil_bind_service(device->service, 568 (sysarg_t) device->device_id, SERVICE_ARP, 569 arp_receiver); 570 if (device->phone < 0) { 571 fibril_mutex_unlock(&arp_globals.lock); 572 arp_protos_destroy(&device->protos); 573 free(device); 574 return EREFUSED; 575 } 576 577 /* Get packet dimensions */ 578 rc = nil_packet_size_req(device->phone, device_id, 579 &device->packet_dimension); 580 if (rc != EOK) { 581 fibril_mutex_unlock(&arp_globals.lock); 582 arp_protos_destroy(&device->protos); 583 free(device); 584 return rc; 585 } 586 587 /* Get hardware address */ 588 rc = nil_get_addr_req(device->phone, device_id, &device->addr, 589 &device->addr_data); 590 if (rc != EOK) { 591 fibril_mutex_unlock(&arp_globals.lock); 592 arp_protos_destroy(&device->protos); 593 free(device); 594 return rc; 595 } 596 597 /* Get broadcast address */ 598 rc = nil_get_broadcast_addr_req(device->phone, device_id, 599 &device->broadcast_addr, &device->broadcast_data); 600 if (rc != EOK) { 601 fibril_mutex_unlock(&arp_globals.lock); 602 free(device->addr); 603 free(device->addr_data); 604 arp_protos_destroy(&device->protos); 605 free(device); 606 return rc; 607 } 608 609 rc = arp_cache_add(&arp_globals.cache, device->device_id, 610 device); 611 if (rc != EOK) { 612 fibril_mutex_unlock(&arp_globals.lock); 613 free(device->addr); 614 free(device->addr_data); 615 free(device->broadcast_addr); 616 free(device->broadcast_data); 617 arp_protos_destroy(&device->protos); 618 free(device); 619 return rc; 620 } 621 printf("%s: Device registered (id: %d, type: 0x%x, service: %d," 622 " proto: %d)\n", NAME, device->device_id, device->hardware, 623 device->service, protocol); 624 } 625 626 fibril_mutex_unlock(&arp_globals.lock); 627 return EOK; 628 } 629 630 int il_initialize(int net_phone) 631 { 632 fibril_mutex_initialize(&arp_globals.lock); 633 634 fibril_mutex_lock(&arp_globals.lock); 635 arp_globals.net_phone = net_phone; 636 int rc = arp_cache_initialize(&arp_globals.cache); 637 fibril_mutex_unlock(&arp_globals.lock); 638 639 return rc; 640 } 641 642 static int arp_send_request(device_id_t device_id, services_t protocol, 643 measured_string_t *target, arp_device_t *device, arp_proto_t *proto) 644 { 551 645 /* ARP packet content size = header + (address + translation) * 2 */ 552 length = 8 + 2 * (CONVERT_SIZE(char, uint8_t, proto->addr->length) + 553 CONVERT_SIZE(char, uint8_t, device->addr->length)); 646 size_t length = 8 + 2 * (proto->addr->length + device->addr->length); 554 647 if (length > device->packet_dimension.content) 555 return NULL;556 557 packet = packet_get_4_remote(arp_globals.net_phone,648 return ELIMIT; 649 650 packet_t *packet = packet_get_4_remote(arp_globals.net_phone, 558 651 device->packet_dimension.addr_len, device->packet_dimension.prefix, 559 652 length, device->packet_dimension.suffix); 560 653 if (!packet) 561 return NULL;562 563 header = (arp_header_t *) packet_suffix(packet, length);654 return ENOMEM; 655 656 arp_header_t *header = (arp_header_t *) packet_suffix(packet, length); 564 657 if (!header) { 565 658 pq_release_remote(arp_globals.net_phone, packet_get_id(packet)); 566 return NULL;567 } 568 659 return ENOMEM; 660 } 661 569 662 header->hardware = htons(device->hardware); 570 663 header->hardware_length = (uint8_t) device->addr->length; … … 572 665 header->protocol_length = (uint8_t) proto->addr->length; 573 666 header->operation = htons(ARPOP_REQUEST); 667 574 668 length = sizeof(arp_header_t); 669 575 670 memcpy(((uint8_t *) header) + length, device->addr->value, 576 671 device->addr->length); … … 582 677 length += device->addr->length; 583 678 memcpy(((uint8_t *) header) + length, target->value, target->length); 584 585 i f (packet_set_addr(packet, (uint8_t *) device->addr->value,586 (uint8_t *) device->broadcast_addr->value, 587 CONVERT_SIZE(char, uint8_t, device->addr->length))!= EOK) {679 680 int rc = packet_set_addr(packet, (uint8_t *) device->addr->value, 681 (uint8_t *) device->broadcast_addr->value, device->addr->length); 682 if (rc != EOK) { 588 683 pq_release_remote(arp_globals.net_phone, packet_get_id(packet)); 589 return NULL;590 } 591 684 return rc; 685 } 686 592 687 nil_send_msg(device->phone, device_id, packet, SERVICE_ARP); 593 return NULL; 594 } 595 596 597 /** Processes the ARP message. 598 * 599 * @param[in] callid The message identifier. 600 * @param[in] call The message parameters. 601 * @param[out] answer The message answer parameters. 602 * @param[out] answer_count The last parameter for the actual answer in the 603 * answer parameter. 604 * @return EOK on success. 605 * @return ENOTSUP if the message is not known. 688 return EOK; 689 } 690 691 /** Return the hardware address for the given protocol address. 692 * 693 * Send the ARP request packet if the hardware address is not found in the 694 * cache. 695 * 696 * @param[in] device_id Device identifier. 697 * @param[in] protocol Protocol service. 698 * @param[in] target Target protocol address. 699 * @param[out] translation Where the hardware address of the target is stored. 700 * 701 * @return EOK on success. 702 * @return EAGAIN if the caller should try again. 703 * @return Other error codes in case of error. 704 * 705 */ 706 static int arp_translate_message(device_id_t device_id, services_t protocol, 707 measured_string_t *target, measured_string_t **translation) 708 { 709 bool retry = false; 710 int rc; 711 712 assert(fibril_mutex_is_locked(&arp_globals.lock)); 713 714 restart: 715 if ((!target) || (!translation)) 716 return EBADMEM; 717 718 arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id); 719 if (!device) 720 return ENOENT; 721 722 arp_proto_t *proto = arp_protos_find(&device->protos, protocol); 723 if ((!proto) || (proto->addr->length != target->length)) 724 return ENOENT; 725 726 arp_trans_t *trans = arp_addr_find(&proto->addresses, target->value, 727 target->length); 728 if (trans) { 729 if (trans->hw_addr) { 730 /* The translation is in place. */ 731 *translation = trans->hw_addr; 732 return EOK; 733 } 734 735 if (retry) { 736 /* 737 * We may get here as a result of being signalled for 738 * some reason while waiting for the translation (e.g. 739 * translation becoming available, record being removed 740 * from the table) and then losing the race for 741 * the arp_globals.lock with someone else who modified 742 * the table. 743 * 744 * Remove the incomplete record so that it is possible 745 * to make new ARP requests. 746 */ 747 arp_clear_trans(trans); 748 arp_addr_exclude(&proto->addresses, target->value, 749 target->length); 750 return EAGAIN; 751 } 752 753 /* 754 * We are a random passer-by who merely joins an already waiting 755 * fibril in waiting for the translation. 756 */ 757 rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock, 758 ARP_TRANS_WAIT); 759 if (rc == ETIMEOUT) 760 return ENOENT; 761 762 /* 763 * Need to recheck because we did not hold the lock while 764 * sleeping on the condition variable. 765 */ 766 retry = true; 767 goto restart; 768 } 769 770 if (retry) 771 return EAGAIN; 772 773 /* 774 * We are under the protection of arp_globals.lock, so we can afford to 775 * first send the ARP request and then insert an incomplete ARP record. 776 * The incomplete record is used to tell any other potential waiter 777 * that this fibril has already sent the request and that it is waiting 778 * for the answer. Lastly, any fibril which sees the incomplete request 779 * can perform a timed wait on its condition variable to wait for the 780 * ARP reply to arrive. 781 */ 782 783 rc = arp_send_request(device_id, protocol, target, device, proto); 784 if (rc != EOK) 785 return rc; 786 787 trans = (arp_trans_t *) malloc(sizeof(arp_trans_t)); 788 if (!trans) 789 return ENOMEM; 790 791 trans->hw_addr = NULL; 792 fibril_condvar_initialize(&trans->cv); 793 794 rc = arp_addr_add(&proto->addresses, target->value, target->length, 795 trans); 796 if (rc != EOK) { 797 /* The generic char map has already freed trans! */ 798 return rc; 799 } 800 801 rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock, 802 ARP_TRANS_WAIT); 803 if (rc == ETIMEOUT) { 804 /* 805 * Remove the incomplete record so that it is possible to make 806 * new ARP requests. 807 */ 808 arp_clear_trans(trans); 809 arp_addr_exclude(&proto->addresses, target->value, 810 target->length); 811 return ENOENT; 812 } 813 814 /* 815 * We need to recheck that the translation has indeed become available, 816 * because we dropped the arp_globals.lock while sleeping on the 817 * condition variable and someone else might have e.g. removed the 818 * translation before we managed to lock arp_globals.lock again. 819 */ 820 821 retry = true; 822 goto restart; 823 } 824 825 /** Process the ARP message. 826 * 827 * @param[in] callid Message identifier. 828 * @param[in] call Message parameters. 829 * @param[out] answer Answer. 830 * @param[out] count Number of arguments of the answer. 831 * 832 * @return EOK on success. 833 * @return ENOTSUP if the message is not known. 606 834 * 607 835 * @see arp_interface.h 608 836 * @see IS_NET_ARP_MESSAGE() 609 * /610 int 611 arp_message_standalone(ipc_callid_t callid, ipc_call_t *call,612 ipc_call_t *answer, int *answer_count)837 * 838 */ 839 int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer, 840 size_t *count) 613 841 { 614 842 measured_string_t *address; 615 843 measured_string_t *translation; 616 char *data; 617 packet_t *packet; 618 packet_t *next; 844 uint8_t *data; 619 845 int rc; 620 846 621 * answer_count = 0;622 switch (IPC_GET_ METHOD(*call)) {847 *count = 0; 848 switch (IPC_GET_IMETHOD(*call)) { 623 849 case IPC_M_PHONE_HUNGUP: 624 850 return EOK; … … 629 855 return rc; 630 856 631 rc = arp_device_message(IPC_GET_DEVICE( call),632 IPC_GET_SERVICE( call), ARP_GET_NETIF(call), address);857 rc = arp_device_message(IPC_GET_DEVICE(*call), 858 IPC_GET_SERVICE(*call), ARP_GET_NETIF(*call), address); 633 859 if (rc != EOK) { 634 860 free(address); 635 861 free(data); 636 862 } 863 637 864 return rc; 638 865 … … 642 869 return rc; 643 870 644 fibril_ rwlock_read_lock(&arp_globals.lock);645 translation = arp_translate_message(IPC_GET_DEVICE(call),646 IPC_GET_SERVICE( call), address);871 fibril_mutex_lock(&arp_globals.lock); 872 rc = arp_translate_message(IPC_GET_DEVICE(*call), 873 IPC_GET_SERVICE(*call), address, &translation); 647 874 free(address); 648 875 free(data); 876 877 if (rc != EOK) { 878 fibril_mutex_unlock(&arp_globals.lock); 879 return rc; 880 } 881 649 882 if (!translation) { 650 fibril_ rwlock_read_unlock(&arp_globals.lock);883 fibril_mutex_unlock(&arp_globals.lock); 651 884 return ENOENT; 652 885 } 886 653 887 rc = measured_strings_reply(translation, 1); 654 fibril_ rwlock_read_unlock(&arp_globals.lock);888 fibril_mutex_unlock(&arp_globals.lock); 655 889 return rc; 656 890 657 891 case NET_ARP_CLEAR_DEVICE: 658 return arp_clear_device_req(0, IPC_GET_DEVICE( call));659 892 return arp_clear_device_req(0, IPC_GET_DEVICE(*call)); 893 660 894 case NET_ARP_CLEAR_ADDRESS: 661 895 rc = measured_strings_receive(&address, &data, 1); … … 663 897 return rc; 664 898 665 arp_clear_address_req(0, IPC_GET_DEVICE( call),666 IPC_GET_SERVICE( call), address);899 arp_clear_address_req(0, IPC_GET_DEVICE(*call), 900 IPC_GET_SERVICE(*call), address); 667 901 free(address); 668 902 free(data); … … 671 905 case NET_ARP_CLEAN_CACHE: 672 906 return arp_clean_cache_req(0); 673 674 case NET_IL_DEVICE_STATE:675 /* Do nothing - keep the cache */676 return EOK;677 678 case NET_IL_RECEIVED:679 rc = packet_translate_remote(arp_globals.net_phone, &packet,680 IPC_GET_PACKET(call));681 if (rc != EOK)682 return rc;683 684 fibril_rwlock_read_lock(&arp_globals.lock);685 do {686 next = pq_detach(packet);687 rc = arp_receive_message(IPC_GET_DEVICE(call), packet);688 if (rc != 1) {689 pq_release_remote(arp_globals.net_phone,690 packet_get_id(packet));691 }692 packet = next;693 } while (packet);694 fibril_rwlock_read_unlock(&arp_globals.lock);695 696 return EOK;697 698 case NET_IL_MTU_CHANGED:699 return arp_mtu_changed_message(IPC_GET_DEVICE(call),700 IPC_GET_MTU(call));701 907 } 702 908 … … 704 910 } 705 911 706 /** Default thread for new connections.707 *708 * @param[in] iid The initial message identifier.709 * @param[in] icall The initial message call structure.710 */711 static void il_client_connection(ipc_callid_t iid, ipc_call_t *icall)712 {713 /*714 * Accept the connection715 * - Answer the first IPC_M_CONNECT_ME_TO call.716 */717 ipc_answer_0(iid, EOK);718 719 while (true) {720 ipc_call_t answer;721 int answer_count;722 723 /* Clear the answer structure */724 refresh_answer(&answer, &answer_count);725 726 /* Fetch the next message */727 ipc_call_t call;728 ipc_callid_t callid = async_get_call(&call);729 730 /* Process the message */731 int res = il_module_message_standalone(callid, &call, &answer,732 &answer_count);733 734 /*735 * End if told to either by the message or the processing736 * result.737 */738 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||739 (res == EHANGUP))740 return;741 742 /* Answer the message */743 answer_call(callid, res, &answer, answer_count);744 }745 }746 747 /** Starts the module.748 *749 * @return EOK on success.750 * @return Other error codes as defined for each specific module751 * start function.752 */753 912 int main(int argc, char *argv[]) 754 913 { 755 int rc;756 757 914 /* Start the module */ 758 rc = il_module_start_standalone(il_client_connection); 759 return rc; 915 return il_module_start(SERVICE_ARP); 760 916 } 761 917 762 918 /** @} 763 919 */ 764 -
uspace/srv/net/il/arp/arp.h
rcead2aa r357b5f5 65 65 typedef struct arp_proto arp_proto_t; 66 66 67 /** Type definition of the ARP address translation record. 68 * @see arp_trans 69 */ 70 typedef struct arp_trans arp_trans_t; 71 67 72 /** ARP address map. 68 73 * … … 70 75 * @see generic_char_map.h 71 76 */ 72 GENERIC_CHAR_MAP_DECLARE(arp_addr, measured_string_t);77 GENERIC_CHAR_MAP_DECLARE(arp_addr, arp_trans_t); 73 78 74 79 /** ARP address cache. … … 89 94 struct arp_device { 90 95 /** Actual device hardware address. */ 91 measured_string_t * addr;96 measured_string_t *addr; 92 97 /** Actual device hardware address data. */ 93 char*addr_data;98 uint8_t *addr_data; 94 99 /** Broadcast device hardware address. */ 95 measured_string_t * broadcast_addr;100 measured_string_t *broadcast_addr; 96 101 /** Broadcast device hardware address data. */ 97 char*broadcast_data;102 uint8_t *broadcast_data; 98 103 /** Device identifier. */ 99 104 device_id_t device_id; … … 120 125 arp_cache_t cache; 121 126 122 /**123 * The client connection processing function.124 * The module skeleton propagates its own one.125 */126 async_client_conn_t client_connection;127 128 127 /** Networking module phone. */ 129 128 int net_phone; 130 129 /** Safety lock. */ 131 fibril_ rwlock_t lock;130 fibril_mutex_t lock; 132 131 }; 133 132 … … 137 136 measured_string_t *addr; 138 137 /** Actual device protocol address data. */ 139 char*addr_data;138 uint8_t *addr_data; 140 139 /** Address map. */ 141 140 arp_addr_t addresses; … … 144 143 }; 145 144 145 /** ARP address translation record. */ 146 struct arp_trans { 147 /** 148 * Hardware address for the translation. NULL denotes an incomplete 149 * record with possible waiters. 150 */ 151 measured_string_t *hw_addr; 152 /** Condition variable used for waiting for completion of the record. */ 153 fibril_condvar_t cv; 154 }; 155 146 156 #endif 147 157 148 158 /** @} 149 159 */ 160 -
uspace/srv/net/il/ip/Makefile
rcead2aa r357b5f5 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
rcead2aa r357b5f5 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> … … 69 67 #include <net_checksum.h> 70 68 #include <icmp_client.h> 71 #include <icmp_interface.h> 72 #include <il_interface.h> 69 #include <icmp_remote.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 { … … 430 422 // binds the netif service which also initializes the device 431 423 ip_netif->phone = nil_bind_service(ip_netif->service, 432 ( ipcarg_t) ip_netif->device_id, SERVICE_IP,433 ip_ globals.client_connection);424 (sysarg_t) ip_netif->device_id, SERVICE_IP, 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;444 address.length = CONVERT_SIZE(in_addr_t, char, 1);435 address.value = (uint8_t *) &route->address.s_addr; 436 address.length = sizeof(in_addr_t); 445 437 446 438 rc = arp_device_req(ip_netif->arp->phone, … … 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; … … 639 700 if (destination) { 640 701 rc = packet_set_addr(packet, NULL, (uint8_t *) destination->value, 641 CONVERT_SIZE(char, uint8_t, destination->length));702 destination->length); 642 703 } else { 643 704 rc = packet_set_addr(packet, NULL, NULL, 0); … … 687 748 rc = packet_set_addr(next, NULL, 688 749 (uint8_t *) destination->value, 689 CONVERT_SIZE(char, uint8_t, 690 destination->length)); 750 destination->length); 691 751 if (rc != EOK) { 692 752 free(last_header); … … 718 778 rc = packet_set_addr(next, NULL, 719 779 (uint8_t *) destination->value, 720 CONVERT_SIZE(char, uint8_t, destination->length));780 destination->length); 721 781 if (rc != EOK) { 722 782 free(last_header); … … 753 813 * function. 754 814 */ 755 static int 756 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, 757 816 ip_header_t *header, ip_header_t *new_header, size_t length, 758 817 const struct sockaddr *src, const struct sockaddr *dest, socklen_t addrlen) … … 788 847 789 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; 790 870 } 791 871 … … 992 1072 * function. 993 1073 */ 994 static int 995 ip_send_route(packet_t *packet, ip_netif_t *netif, ip_route_t *route, 996 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) 997 1076 { 998 1077 measured_string_t destination; 999 1078 measured_string_t *translation; 1000 char*data;1079 uint8_t *data; 1001 1080 int phone; 1002 1081 int rc; … … 1005 1084 if (netif->arp && (route->address.s_addr != dest.s_addr)) { 1006 1085 destination.value = route->gateway.s_addr ? 1007 ( char *) &route->gateway.s_addr : (char*) &dest.s_addr;1008 destination.length = CONVERT_SIZE(dest.s_addr, char, 1);1086 (uint8_t *) &route->gateway.s_addr : (uint8_t *) &dest.s_addr; 1087 destination.length = sizeof(dest.s_addr); 1009 1088 1010 1089 rc = arp_translate_req(netif->arp->phone, netif->device_id, … … 1057 1136 } 1058 1137 1059 /** Searches the network interfaces if there is a suitable route. 1060 * 1061 * @param[in] netif The network interface to be searched for routes. May be 1062 * NULL. 1063 * @param[in] destination The destination address. 1064 * @return The found route. 1065 * @return NULL if no route was found. 1066 */ 1067 static ip_route_t * 1068 ip_netif_find_route(ip_netif_t *netif, in_addr_t destination) 1069 { 1070 int index; 1071 ip_route_t *route; 1072 1073 if (!netif) 1074 return NULL; 1075 1076 // start with the first one - the direct route 1077 for (index = 0; index < ip_routes_count(&netif->routes); index++) { 1078 route = ip_routes_get_index(&netif->routes, index); 1079 if (route && 1080 ((route->address.s_addr & route->netmask.s_addr) == 1081 (destination.s_addr & route->netmask.s_addr))) { 1082 return route; 1083 } 1084 } 1085 1086 return NULL; 1087 } 1088 1089 /** Searches all network interfaces if there is a suitable route. 1090 * 1091 * @param[in] destination The destination address. 1092 * @return The found route. 1093 * @return NULL if no route was found. 1094 */ 1095 static ip_route_t *ip_find_route(in_addr_t destination) { 1096 int index; 1097 ip_route_t *route; 1098 ip_netif_t *netif; 1099 1100 // start with the last netif - the newest one 1101 index = ip_netifs_count(&ip_globals.netifs) - 1; 1102 while (index >= 0) { 1103 netif = ip_netifs_get_index(&ip_globals.netifs, index); 1104 if (netif && (netif->state == NETIF_ACTIVE)) { 1105 route = ip_netif_find_route(netif, destination); 1106 if (route) 1107 return route; 1108 } 1109 index--; 1110 } 1111 1112 return &ip_globals.gateway; 1113 } 1114 1115 /** Returns the network interface's IP address. 1116 * 1117 * @param[in] netif The network interface. 1118 * @return The IP address. 1119 * @return NULL if no IP address was found. 1120 */ 1121 static in_addr_t *ip_netif_address(ip_netif_t *netif) 1122 { 1123 ip_route_t *route; 1124 1125 route = ip_routes_get_index(&netif->routes, 0); 1126 return route ? &route->address : NULL; 1127 } 1128 1129 /** Registers the transport layer protocol. 1130 * 1131 * The traffic of this protocol will be supplied using either the receive 1132 * function or IPC message. 1133 * 1134 * @param[in] protocol The transport layer module protocol. 1135 * @param[in] service The transport layer module service. 1136 * @param[in] phone The transport layer module phone. 1137 * @param[in] received_msg The receiving function. 1138 * @return EOK on success. 1139 * @return EINVAL if the protocol parameter and/or the service 1140 * parameter is zero. 1141 * @return EINVAL if the phone parameter is not a positive number 1142 * and the tl_receive_msg is NULL. 1143 * @return ENOMEM if there is not enough memory left. 1144 */ 1145 static int 1146 ip_register(int protocol, services_t service, int phone, 1147 tl_received_msg_t received_msg) 1148 { 1149 ip_proto_t *proto; 1150 int index; 1151 1152 if (!protocol || !service || ((phone < 0) && !received_msg)) 1153 return EINVAL; 1154 1155 proto = (ip_proto_t *) malloc(sizeof(ip_protos_t)); 1156 if (!proto) 1157 return ENOMEM; 1158 1159 proto->protocol = protocol; 1160 proto->service = service; 1161 proto->phone = phone; 1162 proto->received_msg = received_msg; 1163 1164 fibril_rwlock_write_lock(&ip_globals.protos_lock); 1165 index = ip_protos_add(&ip_globals.protos, proto->protocol, proto); 1166 if (index < 0) { 1167 fibril_rwlock_write_unlock(&ip_globals.protos_lock); 1168 free(proto); 1169 return index; 1170 } 1171 fibril_rwlock_write_unlock(&ip_globals.protos_lock); 1172 1173 printf("%s: Protocol registered (protocol: %d, phone: %d)\n", 1174 NAME, proto->protocol, proto->phone); 1175 1176 return EOK; 1177 } 1178 1179 static int 1180 ip_device_req_local(int il_phone, device_id_t device_id, services_t netif) 1181 { 1182 ip_netif_t *ip_netif; 1183 ip_route_t *route; 1184 int index; 1185 int rc; 1186 1187 ip_netif = (ip_netif_t *) malloc(sizeof(ip_netif_t)); 1188 if (!ip_netif) 1189 return ENOMEM; 1190 1191 rc = ip_routes_initialize(&ip_netif->routes); 1192 if (rc != EOK) { 1193 free(ip_netif); 1194 return rc; 1195 } 1196 1197 ip_netif->device_id = device_id; 1198 ip_netif->service = netif; 1199 ip_netif->state = NETIF_STOPPED; 1200 1201 fibril_rwlock_write_lock(&ip_globals.netifs_lock); 1202 1203 rc = ip_netif_initialize(ip_netif); 1204 if (rc != EOK) { 1205 fibril_rwlock_write_unlock(&ip_globals.netifs_lock); 1206 ip_routes_destroy(&ip_netif->routes); 1207 free(ip_netif); 1208 return rc; 1209 } 1210 if (ip_netif->arp) 1211 ip_netif->arp->usage++; 1212 1213 // print the settings 1214 printf("%s: Device registered (id: %d, phone: %d, ipv: %d, conf: %s)\n", 1215 NAME, ip_netif->device_id, ip_netif->phone, ip_netif->ipv, 1216 ip_netif->dhcp ? "dhcp" : "static"); 1217 1218 // TODO ipv6 addresses 1219 1220 char address[INET_ADDRSTRLEN]; 1221 char netmask[INET_ADDRSTRLEN]; 1222 char gateway[INET_ADDRSTRLEN]; 1223 1224 for (index = 0; index < ip_routes_count(&ip_netif->routes); index++) { 1225 route = ip_routes_get_index(&ip_netif->routes, index); 1226 if (route) { 1227 inet_ntop(AF_INET, (uint8_t *) &route->address.s_addr, 1228 address, INET_ADDRSTRLEN); 1229 inet_ntop(AF_INET, (uint8_t *) &route->netmask.s_addr, 1230 netmask, INET_ADDRSTRLEN); 1231 inet_ntop(AF_INET, (uint8_t *) &route->gateway.s_addr, 1232 gateway, INET_ADDRSTRLEN); 1233 printf("%s: Route %d (address: %s, netmask: %s, " 1234 "gateway: %s)\n", NAME, index, address, netmask, 1235 gateway); 1236 } 1237 } 1238 1239 inet_ntop(AF_INET, (uint8_t *) &ip_netif->broadcast.s_addr, address, 1240 INET_ADDRSTRLEN); 1241 fibril_rwlock_write_unlock(&ip_globals.netifs_lock); 1242 1243 printf("%s: Broadcast (%s)\n", NAME, address); 1244 1245 return EOK; 1246 } 1247 1248 static int 1249 ip_send_msg_local(int il_phone, device_id_t device_id, packet_t *packet, 1250 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) 1251 1140 { 1252 1141 int addrlen; … … 1289 1178 if (device_id > 0) { 1290 1179 netif = ip_netifs_find(&ip_globals.netifs, device_id); 1291 route = ip_netif_find_route(netif, * dest);1180 route = ip_netif_find_route(netif, *dest); 1292 1181 if (netif && !route && (ip_globals.gateway.netif == netif)) 1293 1182 route = &ip_globals.gateway; … … 1319 1208 } 1320 1209 } 1321 1210 1322 1211 // if the local host is the destination 1323 1212 if ((route->address.s_addr == dest->s_addr) && … … 1352 1241 } 1353 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 1354 1495 /** Returns the device packet dimensions for sending. 1355 1496 * … … 1363 1504 * @return EOK on success. 1364 1505 */ 1365 static int 1366 ip_packet_size_message(device_id_t device_id, size_t *addr_len, size_t *prefix, 1367 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) 1368 1508 { 1369 1509 ip_netif_t *netif; … … 1415 1555 } 1416 1556 1417 /** Returns the packet destination address from the IP header. 1418 * 1419 * @param[in] header The packet IP header to be read. 1420 * @return The packet destination address. 1421 */ 1422 static in_addr_t ip_get_destination(ip_header_t *header) 1423 { 1424 in_addr_t destination; 1425 1426 // TODO search set ipopt route? 1427 destination.s_addr = header->destination_address; 1428 return destination; 1429 } 1430 1431 /** Delivers the packet to the local host. 1432 * 1433 * The packet is either passed to another module or released on error. 1434 * The ICMP_PROT_UNREACH error notification may be sent if the protocol is not 1435 * found. 1436 * 1437 * @param[in] device_id The source device identifier. 1438 * @param[in] packet The packet to be delivered. 1439 * @param[in] header The first packet IP header. May be NULL. 1440 * @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. 1441 1561 * @return EOK on success. 1442 * @return ENOTSUP if the packet is a fragment. 1443 * @return EAFNOSUPPORT if the address family is not supported. 1444 * @return ENOENT if the target protocol is not found. 1445 * @return Other error codes as defined for the packet_set_addr() 1446 * function. 1447 * @return Other error codes as defined for the packet_trim() 1448 * function. 1449 * @return Other error codes as defined for the protocol specific 1450 * 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. 1451 1644 */ 1452 1645 static int 1453 ip_ deliver_local(device_id_t device_id, packet_t *packet, ip_header_t *header,1454 services_t error)1646 ip_register(int protocol, services_t service, int phone, 1647 tl_received_msg_t received_msg) 1455 1648 { 1456 1649 ip_proto_t *proto; 1457 int phone; 1458 services_t service; 1459 tl_received_msg_t received_msg; 1460 struct sockaddr *src; 1461 struct sockaddr *dest; 1462 struct sockaddr_in src_in; 1463 struct sockaddr_in dest_in; 1464 socklen_t addrlen; 1465 int rc; 1466 1467 if ((header->flags & IPFLAG_MORE_FRAGMENTS) || 1468 IP_FRAGMENT_OFFSET(header)) { 1469 // TODO fragmented 1470 return ENOTSUP; 1471 } 1472 1473 switch (header->version) { 1474 case IPVERSION: 1475 addrlen = sizeof(src_in); 1476 bzero(&src_in, addrlen); 1477 src_in.sin_family = AF_INET; 1478 memcpy(&dest_in, &src_in, addrlen); 1479 memcpy(&src_in.sin_addr.s_addr, &header->source_address, 1480 sizeof(header->source_address)); 1481 memcpy(&dest_in.sin_addr.s_addr, &header->destination_address, 1482 sizeof(header->destination_address)); 1483 src = (struct sockaddr *) &src_in; 1484 dest = (struct sockaddr *) &dest_in; 1485 break; 1486 1487 default: 1488 return ip_release_and_return(packet, EAFNOSUPPORT); 1489 } 1490 1491 rc = packet_set_addr(packet, (uint8_t *) src, (uint8_t *) dest, 1492 addrlen); 1493 if (rc != EOK) 1494 return ip_release_and_return(packet, rc); 1495 1496 // trim padding if present 1497 if (!error && 1498 (IP_TOTAL_LENGTH(header) < packet_get_data_length(packet))) { 1499 rc = packet_trim(packet, 0, 1500 packet_get_data_length(packet) - IP_TOTAL_LENGTH(header)); 1501 if (rc != EOK) 1502 return ip_release_and_return(packet, rc); 1503 } 1504 1505 fibril_rwlock_read_lock(&ip_globals.protos_lock); 1506 1507 proto = ip_protos_find(&ip_globals.protos, header->protocol); 1508 if (!proto) { 1509 fibril_rwlock_read_unlock(&ip_globals.protos_lock); 1510 phone = ip_prepare_icmp_and_get_phone(error, packet, header); 1511 if (phone >= 0) { 1512 // unreachable ICMP 1513 icmp_destination_unreachable_msg(phone, 1514 ICMP_PROT_UNREACH, 0, packet); 1515 } 1516 return ENOENT; 1517 } 1518 1519 if (proto->received_msg) { 1520 service = proto->service; 1521 received_msg = proto->received_msg; 1522 fibril_rwlock_read_unlock(&ip_globals.protos_lock); 1523 rc = received_msg(device_id, packet, service, error); 1524 } else { 1525 rc = tl_received_msg(proto->phone, device_id, packet, 1526 proto->service, error); 1527 fibril_rwlock_read_unlock(&ip_globals.protos_lock); 1528 } 1529 1530 return rc; 1531 } 1532 1533 /** Processes the received packet. 1534 * 1535 * The packet is either passed to another module or released on error. 1536 * 1537 * The ICMP_PARAM_POINTER error notification may be sent if the checksum is 1538 * invalid. 1539 * The ICMP_EXC_TTL error notification may be sent if the TTL is less than two. 1540 * The ICMP_HOST_UNREACH error notification may be sent if no route was found. 1541 * The ICMP_HOST_UNREACH error notification may be sent if the packet is for 1542 * another host and the routing is disabled. 1543 * 1544 * @param[in] device_id The source device identifier. 1545 * @param[in] packet The received packet to be processed. 1546 * @return EOK on success. 1547 * @return EINVAL if the TTL is less than two. 1548 * @return EINVAL if the checksum is invalid. 1549 * @return EAFNOSUPPORT if the address family is not supported. 1550 * @return ENOENT if no route was found. 1551 * @return ENOENT if the packet is for another host and the routing 1552 * is disabled. 1553 */ 1554 static int 1555 ip_process_packet(device_id_t device_id, packet_t *packet) 1556 { 1557 ip_header_t *header; 1558 in_addr_t dest; 1559 ip_route_t *route; 1560 int phone; 1561 struct sockaddr *addr; 1562 struct sockaddr_in addr_in; 1563 socklen_t addrlen; 1564 int rc; 1565 1566 header = (ip_header_t *) packet_get_data(packet); 1567 if (!header) 1568 return ip_release_and_return(packet, ENOMEM); 1569 1570 // checksum 1571 if ((header->header_checksum) && 1572 (IP_HEADER_CHECKSUM(header) != IP_CHECKSUM_ZERO)) { 1573 phone = ip_prepare_icmp_and_get_phone(0, packet, header); 1574 if (phone >= 0) { 1575 // checksum error ICMP 1576 icmp_parameter_problem_msg(phone, ICMP_PARAM_POINTER, 1577 ((size_t) ((void *) &header->header_checksum)) - 1578 ((size_t) ((void *) header)), packet); 1579 } 1650 int index; 1651 1652 if (!protocol || !service || ((phone < 0) && !received_msg)) 1580 1653 return EINVAL; 1581 } 1582 1583 if (header->ttl <= 1) { 1584 phone = ip_prepare_icmp_and_get_phone(0, packet, header); 1585 if (phone >= 0) { 1586 // ttl exceeded ICMP 1587 icmp_time_exceeded_msg(phone, ICMP_EXC_TTL, packet); 1588 } 1589 return EINVAL; 1590 } 1591 1592 // process ipopt and get destination 1593 dest = ip_get_destination(header); 1594 1595 // set the addrination address 1596 switch (header->version) { 1597 case IPVERSION: 1598 addrlen = sizeof(addr_in); 1599 bzero(&addr_in, addrlen); 1600 addr_in.sin_family = AF_INET; 1601 memcpy(&addr_in.sin_addr.s_addr, &dest, sizeof(dest)); 1602 addr = (struct sockaddr *) &addr_in; 1603 break; 1604 1605 default: 1606 return ip_release_and_return(packet, EAFNOSUPPORT); 1607 } 1608 1609 rc = packet_set_addr(packet, NULL, (uint8_t *) &addr, addrlen); 1610 if (rc != EOK) 1611 return rc; 1612 1613 route = ip_find_route(dest); 1614 if (!route) { 1615 phone = ip_prepare_icmp_and_get_phone(0, packet, header); 1616 if (phone >= 0) { 1617 // unreachable ICMP 1618 icmp_destination_unreachable_msg(phone, 1619 ICMP_HOST_UNREACH, 0, packet); 1620 } 1621 return ENOENT; 1622 } 1623 1624 if (route->address.s_addr == dest.s_addr) { 1625 // local delivery 1626 return ip_deliver_local(device_id, packet, header, 0); 1627 } 1628 1629 if (route->netif->routing) { 1630 header->ttl--; 1631 return ip_send_route(packet, route->netif, route, NULL, dest, 1632 0); 1633 } 1634 1635 phone = ip_prepare_icmp_and_get_phone(0, packet, header); 1636 if (phone >= 0) { 1637 // unreachable ICMP if no routing 1638 icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0, 1639 packet); 1640 } 1641 1642 return ENOENT; 1643 } 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 1644 1679 1645 1680 static int … … 1757 1792 (header->destination_address & route->netmask.s_addr))) { 1758 1793 // clear the ARP mapping if any 1759 address.value = (char *) &header->destination_address; 1760 address.length = CONVERT_SIZE(uint8_t, char, 1761 sizeof(header->destination_address)); 1794 address.value = (uint8_t *) &header->destination_address; 1795 address.length = sizeof(header->destination_address); 1762 1796 arp_clear_address_req(netif->arp->phone, 1763 1797 netif->device_id, SERVICE_IP, &address); … … 1843 1877 } 1844 1878 1845 /** Processes the received IP packet or the packet queue one by one.1846 *1847 * The packet is either passed to another module or released on error.1848 *1849 * @param[in] device_id The source device identifier.1850 * @param[in,out] packet The received packet.1851 * @return EOK on success and the packet is no longer needed.1852 * @return EINVAL if the packet is too small to carry the IP1853 * packet.1854 * @return EINVAL if the received address lengths differs from the1855 * registered values.1856 * @return ENOENT if the device is not found in the cache.1857 * @return ENOENT if the protocol for the device is not found in1858 * the cache.1859 * @return ENOMEM if there is not enough memory left.1860 */1861 static int ip_receive_message(device_id_t device_id, packet_t *packet)1862 {1863 packet_t *next;1864 1865 do {1866 next = pq_detach(packet);1867 ip_process_packet(device_id, packet);1868 packet = next;1869 } while (packet);1870 1871 return EOK;1872 }1873 1874 1879 /** Processes the IP message. 1875 1880 * … … 1883 1888 * 1884 1889 * @see ip_interface.h 1885 * @see il_ interface.h1890 * @see il_remote.h 1886 1891 * @see IS_NET_IP_MESSAGE() 1887 1892 */ 1888 int 1889 ip_message_standalone(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer, 1890 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) 1891 1895 { 1892 1896 packet_t *packet; 1893 1897 struct sockaddr *addr; 1898 void *header; 1899 size_t headerlen; 1894 1900 size_t addrlen; 1895 1901 size_t prefix; 1896 1902 size_t suffix; 1897 1903 size_t content; 1898 void *header;1899 size_t headerlen;1900 1904 device_id_t device_id; 1901 1905 int rc; 1902 1906 1903 1907 *answer_count = 0; 1904 switch (IPC_GET_ METHOD(*call)) {1908 switch (IPC_GET_IMETHOD(*call)) { 1905 1909 case IPC_M_PHONE_HUNGUP: 1906 1910 return EOK; 1907 1911 1908 1912 case IPC_M_CONNECT_TO_ME: 1909 return ip_register(IL_GET_PROTO( call), IL_GET_SERVICE(call),1910 IPC_GET_PHONE( call), NULL);1911 1912 case NET_I L_DEVICE:1913 return ip_device_req_local(0, IPC_GET_DEVICE( call),1914 IPC_GET_SERVICE( call));1915 1916 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: 1917 1921 rc = packet_translate_remote(ip_globals.net_phone, &packet, 1918 IPC_GET_PACKET( call));1922 IPC_GET_PACKET(*call)); 1919 1923 if (rc != EOK) 1920 1924 return rc; 1921 return ip_send_msg_local(0, IPC_GET_DEVICE(call), packet, 0, 1922 IPC_GET_ERROR(call)); 1923 1924 case NET_IL_DEVICE_STATE: 1925 return ip_device_state_message(IPC_GET_DEVICE(call), 1926 IPC_GET_STATE(call)); 1927 1928 case NET_IL_RECEIVED: 1929 rc = packet_translate_remote(ip_globals.net_phone, &packet, 1930 IPC_GET_PACKET(call)); 1931 if (rc != EOK) 1932 return rc; 1933 return ip_receive_message(IPC_GET_DEVICE(call), packet); 1934 1935 case NET_IP_RECEIVED_ERROR: 1936 rc = packet_translate_remote(ip_globals.net_phone, &packet, 1937 IPC_GET_PACKET(call)); 1938 if (rc != EOK) 1939 return rc; 1940 return ip_received_error_msg_local(0, IPC_GET_DEVICE(call), 1941 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)); 1942 1927 1943 1928 case NET_IP_ADD_ROUTE: 1944 return ip_add_route_req_local(0, IPC_GET_DEVICE( call),1945 IP_GET_ADDRESS( call), IP_GET_NETMASK(call),1946 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)); 1947 1932 1948 1933 case NET_IP_SET_GATEWAY: 1949 return ip_set_gateway_req_local(0, IPC_GET_DEVICE( call),1950 IP_GET_GATEWAY( call));1934 return ip_set_gateway_req_local(0, IPC_GET_DEVICE(*call), 1935 IP_GET_GATEWAY(*call)); 1951 1936 1952 1937 case NET_IP_GET_ROUTE: 1953 rc = data_receive((void **) &addr, &addrlen); 1938 rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, 1939 &addrlen); 1954 1940 if (rc != EOK) 1955 1941 return rc; 1956 1942 1957 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, 1958 1944 (socklen_t) addrlen, &device_id, &header, &headerlen); 1959 1945 if (rc != EOK) 1960 1946 return rc; 1961 1947 1962 IPC_SET_DEVICE( answer, device_id);1963 IP_SET_HEADERLEN( answer, headerlen);1948 IPC_SET_DEVICE(*answer, device_id); 1949 IP_SET_HEADERLEN(*answer, headerlen); 1964 1950 1965 1951 *answer_count = 2; … … 1972 1958 return rc; 1973 1959 1974 case NET_I L_PACKET_SPACE:1975 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, 1976 1962 &prefix, &content, &suffix); 1977 1963 if (rc != EOK) 1978 1964 return rc; 1979 1965 1980 IPC_SET_ADDR( answer, addrlen);1981 IPC_SET_PREFIX( answer, prefix);1982 IPC_SET_CONTENT( answer, content);1983 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); 1984 1970 *answer_count = 4; 1985 1971 return EOK; 1986 1972 1987 case NET_IL_MTU_CHANGED: 1988 return ip_mtu_changed_message(IPC_GET_DEVICE(call), 1989 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)); 1990 1981 } 1991 1982 … … 1993 1984 } 1994 1985 1995 /** Default thread for new connections.1996 *1997 * @param[in] iid The initial message identifier.1998 * @param[in] icall The initial message call structure.1999 */2000 static void il_client_connection(ipc_callid_t iid, ipc_call_t *icall)2001 {2002 /*2003 * Accept the connection2004 * - Answer the first IPC_M_CONNECT_ME_TO call.2005 */2006 ipc_answer_0(iid, EOK);2007 2008 while (true) {2009 ipc_call_t answer;2010 int answer_count;2011 2012 /* Clear the answer structure */2013 refresh_answer(&answer, &answer_count);2014 2015 /* Fetch the next message */2016 ipc_call_t call;2017 ipc_callid_t callid = async_get_call(&call);2018 2019 /* Process the message */2020 int res = il_module_message_standalone(callid, &call, &answer,2021 &answer_count);2022 2023 /*2024 * End if told to either by the message or the processing2025 * result.2026 */2027 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||2028 (res == EHANGUP)) {2029 return;2030 }2031 2032 /* Answer the message */2033 answer_call(callid, res, &answer, answer_count);2034 }2035 }2036 2037 /** Starts the module.2038 *2039 * @return EOK on success.2040 * @return Other error codes as defined for each specific module start function.2041 */2042 1986 int main(int argc, char *argv[]) 2043 1987 { 2044 int rc;2045 2046 1988 /* Start the module */ 2047 rc = il_module_start_standalone(il_client_connection); 2048 return rc; 1989 return il_module_start(SERVICE_IP); 2049 1990 } 2050 1991 -
uspace/srv/net/il/ip/ip.h
rcead2aa r357b5f5 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; -
uspace/srv/net/net/net.c
rcead2aa r357b5f5 45 45 #include <stdio.h> 46 46 #include <str.h> 47 #include <str_error.h> 47 48 48 49 #include <ipc/ipc.h> … … 51 52 #include <ipc/net_net.h> 52 53 #include <ipc/il.h> 54 #include <ipc/nil.h> 53 55 54 56 #include <net/modules.h> … … 62 64 63 65 #include <netif_remote.h> 64 #include <nil_ interface.h>66 #include <nil_remote.h> 65 67 #include <net_interface.h> 66 68 #include <ip_interface.h> … … 90 92 * 91 93 */ 92 int add_configuration(measured_strings_t *configuration, const char*name,93 const char*value)94 int add_configuration(measured_strings_t *configuration, const uint8_t *name, 95 const uint8_t *value) 94 96 { 95 97 int rc; … … 119 121 } 120 122 121 static int parse_line(measured_strings_t *configuration, char*line)123 static int parse_line(measured_strings_t *configuration, uint8_t *line) 122 124 { 123 125 int rc; 124 126 125 127 /* From the beginning */ 126 char*name = line;128 uint8_t *name = line; 127 129 128 130 /* Skip comments and blank lines */ … … 135 137 136 138 /* Remember the name start */ 137 char*value = name;139 uint8_t *value = name; 138 140 139 141 /* Skip the name */ … … 186 188 187 189 /* Construct the full filename */ 188 char line[BUFFER_SIZE];189 if (snprintf( line, BUFFER_SIZE, "%s/%s", directory, filename) > BUFFER_SIZE)190 char fname[BUFFER_SIZE]; 191 if (snprintf(fname, BUFFER_SIZE, "%s/%s", directory, filename) > BUFFER_SIZE) 190 192 return EOVERFLOW; 191 193 192 194 /* Open the file */ 193 FILE *cfg = fopen( line, "r");195 FILE *cfg = fopen(fname, "r"); 194 196 if (!cfg) 195 197 return ENOENT; … … 201 203 unsigned int line_number = 0; 202 204 size_t index = 0; 205 uint8_t line[BUFFER_SIZE]; 206 203 207 while (!ferror(cfg) && !feof(cfg)) { 204 208 int read = fgetc(cfg); … … 207 211 line[BUFFER_SIZE - 1] = '\0'; 208 212 fprintf(stderr, "%s: Configuration line %u too " 209 "long: %s\n", NAME, line_number, line);213 "long: %s\n", NAME, line_number, (char *) line); 210 214 211 215 /* No space left in the line buffer */ … … 213 217 } 214 218 /* Append the character */ 215 line[index] = ( char) read;219 line[index] = (uint8_t) read; 216 220 index++; 217 221 } else { … … 221 225 if (parse_line(configuration, line) != EOK) { 222 226 fprintf(stderr, "%s: Configuration error on " 223 "line %u: %s\n", NAME, line_number, line);227 "line %u: %s\n", NAME, line_number, (char *) line); 224 228 } 225 229 … … 282 286 return rc; 283 287 284 rc = add_module(NULL, &net_globals.modules, LO_NAME, LO_FILENAME,285 SERVICE_LO, 0, connect_to_service);286 if (rc != EOK) 287 return rc; 288 rc = add_module(NULL, &net_globals.modules, DP8390_NAME,289 DP8390_FILENAME, SERVICE_DP8390, 0, connect_to_service);290 if (rc != EOK) 291 return rc; 292 rc = add_module(NULL, &net_globals.modules, ETHERNET_NAME,293 ETHERNET_FILENAME, SERVICE_ETHERNET, 0, connect_to_service);294 if (rc != EOK) 295 return rc; 296 rc = add_module(NULL, &net_globals.modules, NILDUMMY_NAME,297 NILDUMMY_FILENAME, SERVICE_NILDUMMY, 0, connect_to_service);288 rc = add_module(NULL, &net_globals.modules, (uint8_t *) LO_NAME, 289 (uint8_t *) LO_FILENAME, SERVICE_LO, 0, connect_to_service); 290 if (rc != EOK) 291 return rc; 292 rc = add_module(NULL, &net_globals.modules, (uint8_t *) NE2000_NAME, 293 (uint8_t *) NE2000_FILENAME, SERVICE_NE2000, 0, connect_to_service); 294 if (rc != EOK) 295 return rc; 296 rc = add_module(NULL, &net_globals.modules, (uint8_t *) ETHERNET_NAME, 297 (uint8_t *) ETHERNET_FILENAME, SERVICE_ETHERNET, 0, connect_to_service); 298 if (rc != EOK) 299 return rc; 300 rc = add_module(NULL, &net_globals.modules, (uint8_t *) NILDUMMY_NAME, 301 (uint8_t *) NILDUMMY_FILENAME, SERVICE_NILDUMMY, 0, connect_to_service); 298 302 if (rc != EOK) 299 303 return rc; … … 322 326 static int net_module_start(async_client_conn_t client_connection) 323 327 { 324 ipcarg_t phonehash;328 sysarg_t phonehash; 325 329 int rc; 326 330 … … 330 334 return rc; 331 335 332 333 336 rc = net_initialize(client_connection); 334 337 if (rc != EOK) 335 338 goto out; 336 339 337 rc = REGISTER_ME(SERVICE_NETWORKING, &phonehash);340 rc = ipc_connect_to_me(PHONE_NS, SERVICE_NETWORKING, 0, 0, &phonehash); 338 341 if (rc != EOK) 339 342 goto out; … … 364 367 */ 365 368 static int net_get_conf(measured_strings_t *netif_conf, 366 measured_string_t *configuration, size_t count, char**data)369 measured_string_t *configuration, size_t count, uint8_t **data) 367 370 { 368 371 if (data) … … 390 393 391 394 int net_get_conf_req(int net_phone, measured_string_t **configuration, 392 size_t count, char**data)395 size_t count, uint8_t **data) 393 396 { 394 397 if (!configuration || (count <= 0)) … … 399 402 400 403 int net_get_device_conf_req(int net_phone, device_id_t device_id, 401 measured_string_t **configuration, size_t count, char**data)404 measured_string_t **configuration, size_t count, uint8_t **data) 402 405 { 403 406 if ((!configuration) || (count == 0)) … … 411 414 } 412 415 413 void net_free_settings(measured_string_t *settings, char*data)416 void net_free_settings(measured_string_t *settings, uint8_t *data) 414 417 { 415 418 } … … 437 440 /* Mandatory netif */ 438 441 measured_string_t *setting = 439 measured_strings_find(&netif->configuration, CONF_NETIF, 0);442 measured_strings_find(&netif->configuration, (uint8_t *) CONF_NETIF, 0); 440 443 441 444 netif->driver = get_running_module(&net_globals.modules, setting->value); … … 447 450 448 451 /* Optional network interface layer */ 449 setting = measured_strings_find(&netif->configuration, CONF_NIL, 0);452 setting = measured_strings_find(&netif->configuration, (uint8_t *) CONF_NIL, 0); 450 453 if (setting) { 451 454 netif->nil = get_running_module(&net_globals.modules, setting->value); … … 459 462 460 463 /* Mandatory internet layer */ 461 setting = measured_strings_find(&netif->configuration, CONF_IL, 0);464 setting = measured_strings_find(&netif->configuration, (uint8_t *) CONF_IL, 0); 462 465 netif->il = get_running_module(&net_globals.modules, setting->value); 463 466 if (!netif->il) { … … 468 471 469 472 /* Hardware configuration */ 470 setting = measured_strings_find(&netif->configuration, CONF_IRQ, 0);471 int irq = setting ? strtol( setting->value, NULL, 10) : 0;472 473 setting = measured_strings_find(&netif->configuration, CONF_IO, 0);474 int io = setting ? strtol(setting->value, NULL, 16) : 0;475 476 rc = netif_probe_req _remote(netif->driver->phone, netif->id, irq,io);473 setting = measured_strings_find(&netif->configuration, (uint8_t *) CONF_IRQ, 0); 474 int irq = setting ? strtol((char *) setting->value, NULL, 10) : 0; 475 476 setting = measured_strings_find(&netif->configuration, (uint8_t *) CONF_IO, 0); 477 uintptr_t io = setting ? strtol((char *) setting->value, NULL, 16) : 0; 478 479 rc = netif_probe_req(netif->driver->phone, netif->id, irq, (void *) io); 477 480 if (rc != EOK) 478 481 return rc; … … 481 484 services_t internet_service; 482 485 if (netif->nil) { 483 setting = measured_strings_find(&netif->configuration, CONF_MTU, 0);486 setting = measured_strings_find(&netif->configuration, (uint8_t *) CONF_MTU, 0); 484 487 if (!setting) 485 488 setting = measured_strings_find(&net_globals.configuration, 486 CONF_MTU, 0);487 488 int mtu = setting ? strtol( setting->value, NULL, 10) : 0;489 (uint8_t *) CONF_MTU, 0); 490 491 int mtu = setting ? strtol((char *) setting->value, NULL, 10) : 0; 489 492 490 493 rc = nil_device_req(netif->nil->phone, netif->id, mtu, … … 509 512 } 510 513 511 return netif_start_req _remote(netif->driver->phone, netif->id);514 return netif_start_req(netif->driver->phone, netif->id); 512 515 } 513 516 … … 558 561 /* Mandatory name */ 559 562 measured_string_t *setting = 560 measured_strings_find(&netif->configuration, CONF_NAME, 0);563 measured_strings_find(&netif->configuration, (uint8_t *) CONF_NAME, 0); 561 564 if (!setting) { 562 565 fprintf(stderr, "%s: Network interface name is missing\n", NAME); … … 589 592 rc = start_device(netif); 590 593 if (rc != EOK) { 594 printf("%s: Error starting interface %s (%s)\n", NAME, 595 netif->name, str_error(rc)); 591 596 measured_strings_destroy(&netif->configuration); 592 597 netifs_exclude_index(&net_globals.netifs, index); 598 593 599 return rc; 594 600 } … … 602 608 printf("%s: Network interface started (name: %s, id: %d, driver: %s, " 603 609 "nil: %s, il: %s)\n", NAME, netif->name, netif->id, 604 netif->driver->name, netif->nil ?netif->nil->name : "[none]",610 netif->driver->name, netif->nil ? (char *) netif->nil->name : "[none]", 605 611 netif->il->name); 606 612 } … … 611 617 /** Process the networking message. 612 618 * 613 * @param[in] callidThe message identifier.614 * @param[in] callThe message parameters.619 * @param[in] callid The message identifier. 620 * @param[in] call The message parameters. 615 621 * @param[out] answer The message answer parameters. 616 622 * @param[out] answer_count The last parameter for the actual answer … … 625 631 */ 626 632 int net_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer, 627 int *answer_count)633 size_t *answer_count) 628 634 { 629 635 measured_string_t *strings; 630 char*data;636 uint8_t *data; 631 637 int rc; 632 638 633 639 *answer_count = 0; 634 switch (IPC_GET_ METHOD(*call)) {640 switch (IPC_GET_IMETHOD(*call)) { 635 641 case IPC_M_PHONE_HUNGUP: 636 642 return EOK; 637 643 case NET_NET_GET_DEVICE_CONF: 638 644 rc = measured_strings_receive(&strings, &data, 639 IPC_GET_COUNT( call));645 IPC_GET_COUNT(*call)); 640 646 if (rc != EOK) 641 647 return rc; 642 net_get_device_conf_req(0, IPC_GET_DEVICE( call), &strings,643 IPC_GET_COUNT( call), NULL);648 net_get_device_conf_req(0, IPC_GET_DEVICE(*call), &strings, 649 IPC_GET_COUNT(*call), NULL); 644 650 645 651 /* Strings should not contain received data anymore */ 646 652 free(data); 647 653 648 rc = measured_strings_reply(strings, IPC_GET_COUNT( call));654 rc = measured_strings_reply(strings, IPC_GET_COUNT(*call)); 649 655 free(strings); 650 656 return rc; 651 657 case NET_NET_GET_CONF: 652 658 rc = measured_strings_receive(&strings, &data, 653 IPC_GET_COUNT( call));659 IPC_GET_COUNT(*call)); 654 660 if (rc != EOK) 655 661 return rc; 656 net_get_conf_req(0, &strings, IPC_GET_COUNT( call), NULL);662 net_get_conf_req(0, &strings, IPC_GET_COUNT(*call), NULL); 657 663 658 664 /* Strings should not contain received data anymore */ 659 665 free(data); 660 666 661 rc = measured_strings_reply(strings, IPC_GET_COUNT( call));667 rc = measured_strings_reply(strings, IPC_GET_COUNT(*call)); 662 668 free(strings); 663 669 return rc; … … 686 692 /* Clear the answer structure */ 687 693 ipc_call_t answer; 688 int answer_count;694 size_t answer_count; 689 695 refresh_answer(&answer, &answer_count); 690 696 … … 697 703 698 704 /* End if told to either by the message or the processing result */ 699 if ((IPC_GET_ METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))705 if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP)) 700 706 return; 701 707 … … 707 713 int main(int argc, char *argv[]) 708 714 { 709 int rc; 710 711 rc = net_module_start(net_client_connection); 712 if (rc != EOK) { 713 fprintf(stderr, "%s: net_module_start error %i\n", NAME, rc); 714 return rc; 715 } 716 717 return EOK; 715 return net_module_start(net_client_connection); 718 716 } 719 717 -
uspace/srv/net/net/net.h
rcead2aa r357b5f5 52 52 */ 53 53 54 #define DP8390_FILENAME "/srv/dp8390"55 #define DP8390_NAME "dp8390"54 #define NE2000_FILENAME "/srv/ne2000" 55 #define NE2000_NAME "ne2000" 56 56 57 57 #define ETHERNET_FILENAME "/srv/eth" … … 105 105 module_t *driver; 106 106 107 device_id_t id; /**< System-unique network interface identifier. */108 module_t *il; /**< Serving internet layer module index. */109 char *name;/**< System-unique network interface name. */110 module_t *nil; /**< Serving link layer module index. */107 device_id_t id; /**< System-unique network interface identifier. */ 108 module_t *il; /**< Serving internet layer module index. */ 109 uint8_t *name; /**< System-unique network interface name. */ 110 module_t *nil; /**< Serving link layer module index. */ 111 111 } netif_t; 112 112 … … 133 133 } net_globals_t; 134 134 135 extern int add_configuration(measured_strings_t *, const char *, const char *); 136 extern int net_module_message(ipc_callid_t, ipc_call_t *, ipc_call_t *, int *); 135 extern int add_configuration(measured_strings_t *, const uint8_t *, 136 const uint8_t *); 137 extern int net_module_message(ipc_callid_t, ipc_call_t *, ipc_call_t *, size_t *); 137 138 extern int net_initialize_build(async_client_conn_t); 138 extern int net_message(ipc_callid_t, ipc_call_t *, ipc_call_t *, int *);139 extern int net_message(ipc_callid_t, ipc_call_t *, ipc_call_t *, size_t *); 139 140 140 141 #endif -
uspace/srv/net/net/net_standalone.c
rcead2aa r357b5f5 63 63 int rc; 64 64 65 task_id_t task_id = spawn("/srv/ip");65 task_id_t task_id = net_spawn((uint8_t *) "/srv/ip"); 66 66 if (!task_id) 67 67 return EINVAL; 68 68 69 rc = add_module(NULL, &net_globals.modules, IP_NAME,70 IP_FILENAME, SERVICE_IP, task_id, ip_connect_module);69 rc = add_module(NULL, &net_globals.modules, (uint8_t *) IP_NAME, 70 (uint8_t *) IP_FILENAME, SERVICE_IP, task_id, ip_connect_module); 71 71 if (rc != EOK) 72 72 return rc; 73 73 74 if (! spawn("/srv/icmp"))74 if (!net_spawn((uint8_t *) "/srv/icmp")) 75 75 return EINVAL; 76 76 77 if (! spawn("/srv/udp"))77 if (!net_spawn((uint8_t *) "/srv/udp")) 78 78 return EINVAL; 79 79 80 if (! spawn("/srv/tcp"))80 if (!net_spawn((uint8_t *) "/srv/tcp")) 81 81 return EINVAL; 82 82 … … 100 100 */ 101 101 int net_module_message(ipc_callid_t callid, ipc_call_t *call, 102 ipc_call_t *answer, int *answer_count)102 ipc_call_t *answer, size_t *count) 103 103 { 104 if (IS_NET_PACKET_MESSAGE( call))105 return packet_server_message(callid, call, answer, answer_count);104 if (IS_NET_PACKET_MESSAGE(*call)) 105 return packet_server_message(callid, call, answer, count); 106 106 107 return net_message(callid, call, answer, answer_count);107 return net_message(callid, call, answer, count); 108 108 } 109 109 -
uspace/srv/net/netif/lo/Makefile
rcead2aa r357b5f5 39 39 -include $(CONFIG_MAKEFILE) 40 40 41 ifeq ($(CONFIG_NETIF_NIL_BUNDLE),y)42 LIBS += $(USPACE_PREFIX)/srv/net/nil/nildummy/libnildummy.a43 endif44 45 41 BINARY = lo 46 42 -
uspace/srv/net/netif/lo/lo.c
rcead2aa r357b5f5 48 48 #include <packet_client.h> 49 49 #include <net/device.h> 50 #include <nil_interface.h> 51 #include <netif_interface.h> 52 #include <netif_local.h> 53 54 /** Default hardware address. */ 55 #define DEFAULT_ADDR "\0\0\0\0\0\0" 50 #include <netif_skel.h> 51 #include <nil_remote.h> 56 52 57 53 /** Default address length. */ 58 #define DEFAULT_ADDR_LEN (sizeof(DEFAULT_ADDR) / sizeof(char))54 #define DEFAULT_ADDR_LEN 6 59 55 60 56 /** Loopback module name. */ 61 57 #define NAME "lo" 62 58 63 /** Network interface global data. */ 64 netif_globals_t netif_globals;59 static uint8_t default_addr[DEFAULT_ADDR_LEN] = 60 {0, 0, 0, 0, 0, 0}; 65 61 66 62 int netif_specific_message(ipc_callid_t callid, ipc_call_t *call, 67 ipc_call_t *answer, int *answer_count)63 ipc_call_t *answer, size_t *count) 68 64 { 69 65 return ENOTSUP; … … 74 70 if (!address) 75 71 return EBADMEM; 76 77 address->value = str_dup(DEFAULT_ADDR);72 73 address->value = default_addr; 78 74 address->length = DEFAULT_ADDR_LEN; 79 75 80 76 return EOK; 81 77 } … … 83 79 int netif_get_device_stats(device_id_t device_id, device_stats_t *stats) 84 80 { 85 netif_device_t *device;86 int rc;87 88 81 if (!stats) 89 82 return EBADMEM; 90 91 rc = find_device(device_id, &device); 83 84 netif_device_t *device; 85 int rc = find_device(device_id, &device); 92 86 if (rc != EOK) 93 87 return rc; 94 88 95 89 memcpy(stats, (device_stats_t *) device->specific, 96 90 sizeof(device_stats_t)); 97 98 return EOK; 99 } 100 101 /** Changes the loopback state. 102 * 103 * @param[in] device The device structure. 104 * @param[in] state The new device state. 105 * @return The new state if changed. 106 * @return EOK otherwise. 107 */ 108 static int change_state_message(netif_device_t *device, device_state_t state) 91 92 return EOK; 93 } 94 95 /** Change the loopback state. 96 * 97 * @param[in] device The device structure. 98 * @param[in] state The new device state. 99 * 100 * @return New state if changed. 101 * @return EOK otherwise. 102 * 103 */ 104 static void change_state_message(netif_device_t *device, device_state_t state) 109 105 { 110 106 if (device->state != state) { 111 107 device->state = state; 112 108 113 printf("%s: State changed to %s\n", NAME, 114 (state == NETIF_ACTIVE) ? "active" : "stopped"); 109 const char *desc; 110 switch (state) { 111 case NETIF_ACTIVE: 112 desc = "active"; 113 break; 114 case NETIF_STOPPED: 115 desc = "stopped"; 116 break; 117 default: 118 desc = "unknown"; 119 } 115 120 116 return state; 117 } 118 119 return EOK; 120 } 121 122 /** Creates and returns the loopback network interface structure. 123 * 124 * @param[in] device_id The new devce identifier. 125 * @param[out] device The device structure. 126 * @return EOK on success. 127 * @return EXDEV if one loopback network interface already exists. 128 * @return ENOMEM if there is not enough memory left. 129 */ 130 static int create(device_id_t device_id, netif_device_t **device) 131 { 132 int index; 133 121 printf("%s: State changed to %s\n", NAME, desc); 122 } 123 } 124 125 /** Create and return the loopback network interface structure. 126 * 127 * @param[in] device_id New devce identifier. 128 * @param[out] device Device structure. 129 * 130 * @return EOK on success. 131 * @return EXDEV if one loopback network interface already exists. 132 * @return ENOMEM if there is not enough memory left. 133 * 134 */ 135 static int lo_create(device_id_t device_id, netif_device_t **device) 136 { 134 137 if (netif_device_map_count(&netif_globals.device_map) > 0) 135 138 return EXDEV; 136 139 137 140 *device = (netif_device_t *) malloc(sizeof(netif_device_t)); 138 141 if (!*device) 139 142 return ENOMEM; 140 143 141 144 (*device)->specific = (device_stats_t *) malloc(sizeof(device_stats_t)); 142 145 if (!(*device)->specific) { … … 144 147 return ENOMEM; 145 148 } 146 149 147 150 null_device_stats((device_stats_t *) (*device)->specific); 148 151 (*device)->device_id = device_id; 149 152 (*device)->nil_phone = -1; 150 153 (*device)->state = NETIF_STOPPED; 151 in dex = netif_device_map_add(&netif_globals.device_map,154 int index = netif_device_map_add(&netif_globals.device_map, 152 155 (*device)->device_id, *device); 153 156 154 157 if (index < 0) { 155 158 free(*device); … … 164 167 int netif_initialize(void) 165 168 { 166 ipcarg_t phonehash;167 168 return REGISTER_ME(SERVICE_LO, &phonehash); 169 } 170 171 int netif_probe_message(device_id_t device_id, int irq, uintptr_t io) 172 { 169 sysarg_t phonehash; 170 return ipc_connect_to_me(PHONE_NS, SERVICE_LO, 0, 0, &phonehash); 171 } 172 173 int netif_probe_message(device_id_t device_id, int irq, void *io) 174 { 175 /* Create a new device */ 173 176 netif_device_t *device; 174 int rc; 175 176 /* Create a new device */ 177 rc = create(device_id, &device); 177 int rc = lo_create(device_id, &device); 178 178 if (rc != EOK) 179 179 return rc; 180 181 /* Print the settings */ 180 182 181 printf("%s: Device created (id: %d)\n", NAME, device->device_id); 183 184 182 return EOK; 185 183 } … … 188 186 { 189 187 netif_device_t *device; 190 size_t length; 191 packet_t *next; 192 int phone; 193 int rc; 194 195 rc = find_device(device_id, &device); 188 int rc = find_device(device_id, &device); 196 189 if (rc != EOK) 197 190 return EOK; 198 191 199 192 if (device->state != NETIF_ACTIVE) { 200 193 netif_pq_release(packet_get_id(packet)); 201 194 return EFORWARD; 202 195 } 203 204 next = packet;196 197 packet_t *next = packet; 205 198 do { 206 199 ((device_stats_t *) device->specific)->send_packets++; 207 200 ((device_stats_t *) device->specific)->receive_packets++; 208 length = packet_get_data_length(next);201 size_t length = packet_get_data_length(next); 209 202 ((device_stats_t *) device->specific)->send_bytes += length; 210 203 ((device_stats_t *) device->specific)->receive_bytes += length; 211 204 next = pq_next(next); 212 } while (next);213 214 phone = device->nil_phone;205 } while (next); 206 207 int phone = device->nil_phone; 215 208 fibril_rwlock_write_unlock(&netif_globals.lock); 209 216 210 nil_received_msg(phone, device_id, packet, sender); 211 217 212 fibril_rwlock_write_lock(&netif_globals.lock); 218 219 213 return EOK; 220 214 } … … 222 216 int netif_start_message(netif_device_t *device) 223 217 { 224 return change_state_message(device, NETIF_ACTIVE); 218 change_state_message(device, NETIF_ACTIVE); 219 return device->state; 225 220 } 226 221 227 222 int netif_stop_message(netif_device_t *device) 228 223 { 229 return change_state_message(device, NETIF_STOPPED); 230 } 231 232 /** Default thread for new connections. 233 * 234 * @param[in] iid The initial message identifier. 235 * @param[in] icall The initial message call structure. 236 */ 237 static void netif_client_connection(ipc_callid_t iid, ipc_call_t *icall) 238 { 239 /* 240 * Accept the connection 241 * - Answer the first IPC_M_CONNECT_ME_TO call. 242 */ 243 ipc_answer_0(iid, EOK); 244 245 while (true) { 246 ipc_call_t answer; 247 int answer_count; 248 249 /* Clear the answer structure */ 250 refresh_answer(&answer, &answer_count); 251 252 /* Fetch the next message */ 253 ipc_call_t call; 254 ipc_callid_t callid = async_get_call(&call); 255 256 /* Process the message */ 257 int res = netif_module_message(NAME, callid, &call, &answer, 258 &answer_count); 259 260 /* 261 * End if told to either by the message or the processing 262 * result. 263 */ 264 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || 265 (res == EHANGUP)) 266 return; 267 268 /* Answer the message */ 269 answer_call(callid, res, &answer, answer_count); 270 } 224 change_state_message(device, NETIF_STOPPED); 225 return device->state; 271 226 } 272 227 273 228 int main(int argc, char *argv[]) 274 229 { 275 int rc;276 277 230 /* Start the module */ 278 rc = netif_module_start(netif_client_connection); 279 return rc; 231 return netif_module_start(); 280 232 } 281 233 -
uspace/srv/net/nil/eth/Makefile
rcead2aa r357b5f5 39 39 -include $(CONFIG_MAKEFILE) 40 40 41 ifeq ($(CONFIG_NETIF_NIL_BUNDLE),y) 42 LIBRARY = libeth 43 else 44 BINARY = eth 45 endif 41 BINARY = eth 46 42 47 43 SOURCES = \ 48 eth.c \ 49 eth_module.c 44 eth.c 50 45 51 46 include $(USPACE_PREFIX)/Makefile.common -
uspace/srv/net/nil/eth/eth.c
rcead2aa r357b5f5 45 45 46 46 #include <ipc/ipc.h> 47 #include <ipc/nil.h> 47 48 #include <ipc/net.h> 48 49 #include <ipc/services.h> … … 54 55 #include <protocol_map.h> 55 56 #include <net/device.h> 56 #include <netif_ interface.h>57 #include <netif_remote.h> 57 58 #include <net_interface.h> 58 #include <nil_interface.h> 59 #include <il_interface.h> 59 #include <il_remote.h> 60 60 #include <adt/measured_strings.h> 61 61 #include <packet_client.h> 62 62 #include <packet_remote.h> 63 #include <nil_ local.h>63 #include <nil_skel.h> 64 64 65 65 #include "eth.h" 66 #include "eth_header.h"67 66 68 67 /** The module name. */ … … 72 71 #define ETH_PREFIX \ 73 72 (sizeof(eth_header_t) + sizeof(eth_header_lsap_t) + \ 74 sizeof(eth_header_snap_t))73 sizeof(eth_header_snap_t)) 75 74 76 75 /** Reserved packet suffix length. */ 77 #define ETH_SUFFIX \ 78 sizeof(eth_fcs_t) 76 #define ETH_SUFFIX (sizeof(eth_fcs_t)) 79 77 80 78 /** Maximum packet content length. */ 81 #define ETH_MAX_CONTENT 1500u79 #define ETH_MAX_CONTENT 1500u 82 80 83 81 /** Minimum packet content length. */ 84 #define ETH_MIN_CONTENT 46u82 #define ETH_MIN_CONTENT 46u 85 83 86 84 /** Maximum tagged packet content length. */ 87 85 #define ETH_MAX_TAGGED_CONTENT(flags) \ 88 86 (ETH_MAX_CONTENT - \ 89 ((IS_8023_2_LSAP(flags) || IS_8023_2_SNAP(flags)) ? \90 sizeof(eth_header_lsap_t) : 0) - \91 (IS_8023_2_SNAP(flags) ? sizeof(eth_header_snap_t) : 0))87 ((IS_8023_2_LSAP(flags) || IS_8023_2_SNAP(flags)) ? \ 88 sizeof(eth_header_lsap_t) : 0) - \ 89 (IS_8023_2_SNAP(flags) ? sizeof(eth_header_snap_t) : 0)) 92 90 93 91 /** Minimum tagged packet content length. */ 94 92 #define ETH_MIN_TAGGED_CONTENT(flags) \ 95 93 (ETH_MIN_CONTENT - \ 96 ((IS_8023_2_LSAP(flags) || IS_8023_2_SNAP(flags)) ? \97 sizeof(eth_header_lsap_t) : 0) - \98 (IS_8023_2_SNAP(flags) ? sizeof(eth_header_snap_t) : 0))94 ((IS_8023_2_LSAP(flags) || IS_8023_2_SNAP(flags)) ? \ 95 sizeof(eth_header_lsap_t) : 0) - \ 96 (IS_8023_2_SNAP(flags) ? sizeof(eth_header_snap_t) : 0)) 99 97 100 98 /** Dummy flag shift value. */ 101 #define ETH_DUMMY_SHIFT 099 #define ETH_DUMMY_SHIFT 0 102 100 103 101 /** Mode flag shift value. */ 104 #define ETH_MODE_SHIFT 1102 #define ETH_MODE_SHIFT 1 105 103 106 104 /** Dummy device flag. 107 105 * Preamble and FCS are mandatory part of the packets. 108 106 */ 109 #define ETH_DUMMY (1 << ETH_DUMMY_SHIFT)107 #define ETH_DUMMY (1 << ETH_DUMMY_SHIFT) 110 108 111 109 /** Returns the dummy flag. 112 110 * @see ETH_DUMMY 113 111 */ 114 #define IS_DUMMY(flags) ((flags) & ETH_DUMMY)112 #define IS_DUMMY(flags) ((flags) & ETH_DUMMY) 115 113 116 114 /** Device mode flags. … … 119 117 * @see ETH_8023_2_SNAP 120 118 */ 121 #define ETH_MODE_MASK (3 << ETH_MODE_SHIFT)119 #define ETH_MODE_MASK (3 << ETH_MODE_SHIFT) 122 120 123 121 /** DIX Ethernet mode flag. */ 124 #define ETH_DIX (1 << ETH_MODE_SHIFT)125 126 /** Return swhether the DIX Ethernet mode flag is set.127 * 128 * @param[in] flags The ethernet flags.122 #define ETH_DIX (1 << ETH_MODE_SHIFT) 123 124 /** Return whether the DIX Ethernet mode flag is set. 125 * 126 * @param[in] flags Ethernet flags. 129 127 * @see ETH_DIX 130 */ 131 #define IS_DIX(flags) (((flags) & ETH_MODE_MASK) == ETH_DIX) 128 * 129 */ 130 #define IS_DIX(flags) (((flags) & ETH_MODE_MASK) == ETH_DIX) 132 131 133 132 /** 802.3 + 802.2 + LSAP mode flag. */ 134 #define ETH_8023_2_LSAP (2 << ETH_MODE_SHIFT)135 136 /** Return swhether the 802.3 + 802.2 + LSAP mode flag is set.137 * 138 * @param[in] flags The ethernet flags.133 #define ETH_8023_2_LSAP (2 << ETH_MODE_SHIFT) 134 135 /** Return whether the 802.3 + 802.2 + LSAP mode flag is set. 136 * 137 * @param[in] flags Ethernet flags. 139 138 * @see ETH_8023_2_LSAP 140 */ 141 #define IS_8023_2_LSAP(flags) (((flags) & ETH_MODE_MASK) == ETH_8023_2_LSAP) 139 * 140 */ 141 #define IS_8023_2_LSAP(flags) (((flags) & ETH_MODE_MASK) == ETH_8023_2_LSAP) 142 142 143 143 /** 802.3 + 802.2 + LSAP + SNAP mode flag. */ 144 #define ETH_8023_2_SNAP (3 << ETH_MODE_SHIFT)145 146 /** Return swhether the 802.3 + 802.2 + LSAP + SNAP mode flag is set.147 * 148 * @param[in] flags The ethernet flags.144 #define ETH_8023_2_SNAP (3 << ETH_MODE_SHIFT) 145 146 /** Return whether the 802.3 + 802.2 + LSAP + SNAP mode flag is set. 147 * 148 * @param[in] flags Ethernet flags. 149 149 * @see ETH_8023_2_SNAP 150 */ 151 #define IS_8023_2_SNAP(flags) (((flags) & ETH_MODE_MASK) == ETH_8023_2_SNAP) 150 * 151 */ 152 #define IS_8023_2_SNAP(flags) (((flags) & ETH_MODE_MASK) == ETH_8023_2_SNAP) 152 153 153 154 /** Type definition of the ethernet address type. … … 201 202 202 203 eth_globals.broadcast_addr = 203 measured_string_create_bulk("\xFF\xFF\xFF\xFF\xFF\xFF", 204 CONVERT_SIZE(uint8_t, char, ETH_ADDR)); 204 measured_string_create_bulk((uint8_t *) "\xFF\xFF\xFF\xFF\xFF\xFF", ETH_ADDR); 205 205 if (!eth_globals.broadcast_addr) { 206 206 rc = ENOMEM; … … 238 238 239 239 while (true) { 240 switch (IPC_GET_ METHOD(*icall)) {240 switch (IPC_GET_IMETHOD(*icall)) { 241 241 case NET_NIL_DEVICE_STATE: 242 nil_device_state_msg_local(0, IPC_GET_DEVICE( icall),243 IPC_GET_STATE( icall));242 nil_device_state_msg_local(0, IPC_GET_DEVICE(*icall), 243 IPC_GET_STATE(*icall)); 244 244 ipc_answer_0(iid, EOK); 245 245 break; 246 246 case NET_NIL_RECEIVED: 247 247 rc = packet_translate_remote(eth_globals.net_phone, 248 &packet, IPC_GET_PACKET( icall));249 if (rc == EOK) {248 &packet, IPC_GET_PACKET(*icall)); 249 if (rc == EOK) 250 250 rc = nil_received_msg_local(0, 251 IPC_GET_DEVICE( icall), packet, 0);252 }253 ipc_answer_0(iid, ( ipcarg_t) rc);251 IPC_GET_DEVICE(*icall), packet, 0); 252 253 ipc_answer_0(iid, (sysarg_t) rc); 254 254 break; 255 255 default: 256 ipc_answer_0(iid, ( ipcarg_t) ENOTSUP);256 ipc_answer_0(iid, (sysarg_t) ENOTSUP); 257 257 } 258 258 … … 285 285 measured_string_t names[2] = { 286 286 { 287 ( char*) "ETH_MODE",287 (uint8_t *) "ETH_MODE", 288 288 8 289 289 }, 290 290 { 291 ( char*) "ETH_DUMMY",291 (uint8_t *) "ETH_DUMMY", 292 292 9 293 293 } … … 295 295 measured_string_t *configuration; 296 296 size_t count = sizeof(names) / sizeof(measured_string_t); 297 char*data;297 uint8_t *data; 298 298 eth_proto_t *proto; 299 299 int rc; … … 359 359 360 360 if (configuration) { 361 if (!str_lcmp( configuration[0].value, "DIX",361 if (!str_lcmp((char *) configuration[0].value, "DIX", 362 362 configuration[0].length)) { 363 363 device->flags |= ETH_DIX; 364 } else if(!str_lcmp( configuration[0].value, "8023_2_LSAP",364 } else if(!str_lcmp((char *) configuration[0].value, "8023_2_LSAP", 365 365 configuration[0].length)) { 366 366 device->flags |= ETH_8023_2_LSAP; … … 408 408 409 409 printf("%s: Device registered (id: %d, service: %d: mtu: %zu, " 410 "mac: % x:%x:%x:%x:%x:%x, flags: 0x%x)\n",410 "mac: %02x:%02x:%02x:%02x:%02x:%02x, flags: 0x%x)\n", 411 411 NAME, device->device_id, device->service, device->mtu, 412 412 device->addr_data[0], device->addr_data[1], … … 837 837 } 838 838 839 int nil_m essage_standalone(const char *name, ipc_callid_t callid,840 ipc_call_t * call, ipc_call_t *answer, int *answer_count)839 int nil_module_message(ipc_callid_t callid, ipc_call_t *call, 840 ipc_call_t *answer, size_t *answer_count) 841 841 { 842 842 measured_string_t *address; … … 849 849 850 850 *answer_count = 0; 851 switch (IPC_GET_ METHOD(*call)) {851 switch (IPC_GET_IMETHOD(*call)) { 852 852 case IPC_M_PHONE_HUNGUP: 853 853 return EOK; 854 854 855 855 case NET_NIL_DEVICE: 856 return eth_device_message(IPC_GET_DEVICE( call),857 IPC_GET_SERVICE( call), IPC_GET_MTU(call));856 return eth_device_message(IPC_GET_DEVICE(*call), 857 IPC_GET_SERVICE(*call), IPC_GET_MTU(*call)); 858 858 case NET_NIL_SEND: 859 859 rc = packet_translate_remote(eth_globals.net_phone, &packet, 860 IPC_GET_PACKET( call));860 IPC_GET_PACKET(*call)); 861 861 if (rc != EOK) 862 862 return rc; 863 return eth_send_message(IPC_GET_DEVICE( call), packet,864 IPC_GET_SERVICE( call));863 return eth_send_message(IPC_GET_DEVICE(*call), packet, 864 IPC_GET_SERVICE(*call)); 865 865 case NET_NIL_PACKET_SPACE: 866 rc = eth_packet_space_message(IPC_GET_DEVICE( call), &addrlen,866 rc = eth_packet_space_message(IPC_GET_DEVICE(*call), &addrlen, 867 867 &prefix, &content, &suffix); 868 868 if (rc != EOK) 869 869 return rc; 870 IPC_SET_ADDR( answer, addrlen);871 IPC_SET_PREFIX( answer, prefix);872 IPC_SET_CONTENT( answer, content);873 IPC_SET_SUFFIX( answer, suffix);870 IPC_SET_ADDR(*answer, addrlen); 871 IPC_SET_PREFIX(*answer, prefix); 872 IPC_SET_CONTENT(*answer, content); 873 IPC_SET_SUFFIX(*answer, suffix); 874 874 *answer_count = 4; 875 875 return EOK; 876 876 case NET_NIL_ADDR: 877 rc = eth_addr_message(IPC_GET_DEVICE( call), ETH_LOCAL_ADDR,877 rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_LOCAL_ADDR, 878 878 &address); 879 879 if (rc != EOK) … … 881 881 return measured_strings_reply(address, 1); 882 882 case NET_NIL_BROADCAST_ADDR: 883 rc = eth_addr_message(IPC_GET_DEVICE( call), ETH_BROADCAST_ADDR,883 rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_BROADCAST_ADDR, 884 884 &address); 885 885 if (rc != EOK) … … 887 887 return measured_strings_reply(address, 1); 888 888 case IPC_M_CONNECT_TO_ME: 889 return eth_register_message(NIL_GET_PROTO( call),890 IPC_GET_PHONE( call));889 return eth_register_message(NIL_GET_PROTO(*call), 890 IPC_GET_PHONE(*call)); 891 891 } 892 892 … … 894 894 } 895 895 896 /** Default thread for new connections.897 *898 * @param[in] iid The initial message identifier.899 * @param[in] icall The initial message call structure.900 */901 static void nil_client_connection(ipc_callid_t iid, ipc_call_t *icall)902 {903 /*904 * Accept the connection905 * - Answer the first IPC_M_CONNECT_ME_TO call.906 */907 ipc_answer_0(iid, EOK);908 909 while (true) {910 ipc_call_t answer;911 int answer_count;912 913 /* Clear the answer structure */914 refresh_answer(&answer, &answer_count);915 916 /* Fetch the next message */917 ipc_call_t call;918 ipc_callid_t callid = async_get_call(&call);919 920 /* Process the message */921 int res = nil_module_message_standalone(NAME, callid, &call,922 &answer, &answer_count);923 924 /*925 * End if told to either by the message or the processing926 * result.927 */928 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||929 (res == EHANGUP))930 return;931 932 /* Answer the message */933 answer_call(callid, res, &answer, answer_count);934 }935 }936 937 896 int main(int argc, char *argv[]) 938 897 { 939 int rc;940 941 898 /* Start the module */ 942 rc = nil_module_start_standalone(nil_client_connection); 943 return rc; 899 return nil_module_start(SERVICE_ETHERNET); 944 900 } 945 901 -
uspace/srv/net/nil/eth/eth.h
rcead2aa r357b5f5 44 44 #include <adt/measured_strings.h> 45 45 46 /** Ethernet address length. */ 47 #define ETH_ADDR 6 48 49 /** Ethernet header preamble value. */ 50 #define ETH_PREAMBLE 0x55 51 52 /** Ethernet header start of frame value. */ 53 #define ETH_SFD 0xD5 54 55 /** IEEE 802.2 unordered information control field. */ 56 #define IEEE_8023_2_UI 0x03 57 58 /** Type definition of the Ethernet header IEEE 802.3 + 802.2 + SNAP extensions. 59 * @see eth_header_snap 60 */ 61 typedef struct eth_header_snap eth_header_snap_t; 62 63 /** Type definition of the Ethernet header IEEE 802.3 + 802.2 + SNAP extensions. 64 * @see eth_header_lsap 65 */ 66 typedef struct eth_header_lsap eth_header_lsap_t; 67 68 /** Type definition of the Ethernet header LSAP extension. 69 * @see eth_ieee_lsap 70 */ 71 typedef struct eth_ieee_lsap eth_ieee_lsap_t; 72 73 /** Type definition of the Ethernet header SNAP extension. 74 * @see eth_snap 75 */ 76 typedef struct eth_snap eth_snap_t; 77 78 /** Type definition of the Ethernet header preamble. 79 * @see preamble 80 */ 81 typedef struct eth_preamble eth_preamble_t; 82 83 /** Type definition of the Ethernet header. 84 * @see eth_header 85 */ 86 typedef struct eth_header eth_header_t; 87 88 /** Ethernet header Link Service Access Point extension. */ 89 struct eth_ieee_lsap { 90 /** 91 * Destination Service Access Point identifier. 92 * The possible values are assigned by an IEEE committee. 93 */ 94 uint8_t dsap; 95 96 /** 97 * Source Service Access Point identifier. 98 * The possible values are assigned by an IEEE committee. 99 */ 100 uint8_t ssap; 101 102 /** 103 * Control parameter. 104 * The possible values are assigned by an IEEE committee. 105 */ 106 uint8_t ctrl; 107 } __attribute__ ((packed)); 108 109 /** Ethernet header SNAP extension. */ 110 struct eth_snap { 111 /** Protocol identifier or organization code. */ 112 uint8_t protocol[3]; 113 114 /** 115 * Ethernet protocol identifier in the network byte order (big endian). 116 * @see ethernet_protocols.h 117 */ 118 uint16_t ethertype; 119 } __attribute__ ((packed)); 120 121 /** Ethernet header preamble. 122 * 123 * Used for dummy devices. 124 */ 125 struct eth_preamble { 126 /** 127 * Controlling preamble used for the frame transmission synchronization. 128 * All should be set to ETH_PREAMBLE. 129 */ 130 uint8_t preamble[7]; 131 132 /** 133 * Start of Frame Delimiter used for the frame transmission 134 * synchronization. 135 * Should be set to ETH_SFD. 136 */ 137 uint8_t sfd; 138 } __attribute__ ((packed)); 139 140 /** Ethernet header. */ 141 struct eth_header { 142 /** Destination host Ethernet address (MAC address). */ 143 uint8_t destination_address[ETH_ADDR]; 144 /** Source host Ethernet address (MAC address). */ 145 uint8_t source_address[ETH_ADDR]; 146 147 /** 148 * Ethernet protocol identifier in the network byte order (big endian). 149 * @see ethernet_protocols.h 150 */ 151 uint16_t ethertype; 152 } __attribute__ ((packed)); 153 154 /** Ethernet header IEEE 802.3 + 802.2 extension. */ 155 struct eth_header_lsap { 156 /** Ethernet header. */ 157 eth_header_t header; 158 159 /** 160 * LSAP extension. 161 * If DSAP and SSAP are set to ETH_LSAP_SNAP the SNAP extension is being 162 * used. 163 * If DSAP and SSAP fields are equal to ETH_RAW the raw Ethernet packet 164 * without any extensions is being used and the frame content starts 165 * rigth after the two fields. 166 */ 167 eth_ieee_lsap_t lsap; 168 } __attribute__ ((packed)); 169 170 /** Ethernet header IEEE 802.3 + 802.2 + SNAP extensions. */ 171 struct eth_header_snap { 172 /** Ethernet header. */ 173 eth_header_t header; 174 175 /** 176 * LSAP extension. 177 * If DSAP and SSAP are set to ETH_LSAP_SNAP the SNAP extension is being 178 * used. 179 * If DSAP and SSAP fields are equal to ETH_RAW the raw Ethernet packet 180 * without any extensions is being used and the frame content starts 181 * rigth after the two fields. 182 */ 183 eth_ieee_lsap_t lsap; 184 185 /** SNAP extension. */ 186 eth_snap_t snap; 187 } __attribute__ ((packed)); 188 189 /** Ethernet Frame Check Sequence. */ 190 typedef uint32_t eth_fcs_t; 191 46 192 /** Type definition of the Ethernet global data. 47 193 * @see eth_globals … … 91 237 /** Actual device hardware address. */ 92 238 measured_string_t *addr; 239 93 240 /** Actual device hardware address data. */ 94 char*addr_data;241 uint8_t *addr_data; 95 242 }; 96 243 -
uspace/srv/net/nil/nildummy/Makefile
rcead2aa r357b5f5 39 39 -include $(CONFIG_MAKEFILE) 40 40 41 ifeq ($(CONFIG_NETIF_NIL_BUNDLE),y) 42 LIBRARY = libnildummy 43 else 44 BINARY = nildummy 45 endif 41 BINARY = nildummy 46 42 47 43 SOURCES = \ 48 nildummy.c \ 49 nildummy_module.c 44 nildummy.c 50 45 51 46 include $(USPACE_PREFIX)/Makefile.common -
uspace/srv/net/nil/nildummy/nildummy.c
rcead2aa r357b5f5 42 42 #include <str.h> 43 43 #include <ipc/ipc.h> 44 #include <ipc/nil.h> 44 45 #include <ipc/net.h> 45 46 #include <ipc/services.h> … … 47 48 #include <net/modules.h> 48 49 #include <net/device.h> 49 #include <netif_interface.h> 50 #include <nil_interface.h> 51 #include <il_interface.h> 50 #include <il_remote.h> 52 51 #include <adt/measured_strings.h> 53 52 #include <net/packet.h> 54 53 #include <packet_remote.h> 55 #include <nil_local.h> 54 #include <netif_remote.h> 55 #include <nil_skel.h> 56 56 57 57 #include "nildummy.h" … … 81 81 int nil_initialize(int net_phone) 82 82 { 83 int rc;84 85 83 fibril_rwlock_initialize(&nildummy_globals.devices_lock); 86 84 fibril_rwlock_initialize(&nildummy_globals.protos_lock); … … 90 88 nildummy_globals.net_phone = net_phone; 91 89 nildummy_globals.proto.phone = 0; 92 rc = nildummy_devices_initialize(&nildummy_globals.devices);90 int rc = nildummy_devices_initialize(&nildummy_globals.devices); 93 91 94 92 fibril_rwlock_write_unlock(&nildummy_globals.protos_lock); … … 98 96 } 99 97 100 /** Process IPC messages from the registered device driver modules in an101 * infinite loop.102 * 103 * @param[in ] iid The message identifier.104 * @param[in,out] icall The message parameters.98 /** Process IPC messages from the registered device driver modules 99 * 100 * @param[in] iid Message identifier. 101 * @param[in,out] icall Message parameters. 102 * 105 103 */ 106 104 static void nildummy_receiver(ipc_callid_t iid, ipc_call_t *icall) … … 108 106 packet_t *packet; 109 107 int rc; 110 108 111 109 while (true) { 112 switch (IPC_GET_ METHOD(*icall)) {110 switch (IPC_GET_IMETHOD(*icall)) { 113 111 case NET_NIL_DEVICE_STATE: 114 112 rc = nil_device_state_msg_local(0, 115 IPC_GET_DEVICE( icall), IPC_GET_STATE(icall));116 ipc_answer_0(iid, ( ipcarg_t) rc);113 IPC_GET_DEVICE(*icall), IPC_GET_STATE(*icall)); 114 ipc_answer_0(iid, (sysarg_t) rc); 117 115 break; 118 116 119 117 case NET_NIL_RECEIVED: 120 118 rc = packet_translate_remote(nildummy_globals.net_phone, 121 &packet, IPC_GET_PACKET( icall));122 if (rc == EOK) {119 &packet, IPC_GET_PACKET(*icall)); 120 if (rc == EOK) 123 121 rc = nil_received_msg_local(0, 124 IPC_GET_DEVICE( icall), packet, 0);125 }126 ipc_answer_0(iid, ( ipcarg_t) rc);122 IPC_GET_DEVICE(*icall), packet, 0); 123 124 ipc_answer_0(iid, (sysarg_t) rc); 127 125 break; 128 126 129 127 default: 130 ipc_answer_0(iid, ( ipcarg_t) ENOTSUP);128 ipc_answer_0(iid, (sysarg_t) ENOTSUP); 131 129 } 132 130 … … 139 137 * Determine the device local hardware address. 140 138 * 141 * @param[in] device_id The new device identifier. 142 * @param[in] service The device driver service. 143 * @param[in] mtu The device maximum transmission unit. 144 * @return EOK on success. 145 * @return EEXIST if the device with the different service exists. 146 * @return ENOMEM if there is not enough memory left. 147 * @return Other error codes as defined for the 148 * netif_bind_service() function. 149 * @return Other error codes as defined for the 150 * netif_get_addr_req() function. 139 * @param[in] device_id New device identifier. 140 * @param[in] service Device driver service. 141 * @param[in] mtu Device maximum transmission unit. 142 * 143 * @return EOK on success. 144 * @return EEXIST if the device with the different service exists. 145 * @return ENOMEM if there is not enough memory left. 146 * @return Other error codes as defined for the 147 * netif_bind_service() function. 148 * @return Other error codes as defined for the 149 * netif_get_addr_req() function. 150 * 151 151 */ 152 152 static int nildummy_device_message(device_id_t device_id, services_t service, 153 153 size_t mtu) 154 154 { 155 nildummy_device_t *device;156 int index;157 int rc;158 159 155 fibril_rwlock_write_lock(&nildummy_globals.devices_lock); 160 156 161 157 /* An existing device? */ 162 device = nildummy_devices_find(&nildummy_globals.devices, device_id); 158 nildummy_device_t *device = 159 nildummy_devices_find(&nildummy_globals.devices, device_id); 163 160 if (device) { 164 161 if (device->service != service) { … … 213 210 214 211 /* Get hardware address */ 215 rc = netif_get_addr_req(device->phone, device->device_id, &device->addr,216 &device->addr _data);212 int rc = netif_get_addr_req(device->phone, device->device_id, 213 &device->addr, &device->addr_data); 217 214 if (rc != EOK) { 218 215 fibril_rwlock_write_unlock(&nildummy_globals.devices_lock); … … 222 219 223 220 /* Add to the cache */ 224 in dex = nildummy_devices_add(&nildummy_globals.devices,221 int index = nildummy_devices_add(&nildummy_globals.devices, 225 222 device->device_id, device); 226 223 if (index < 0) { … … 240 237 /** Return the device hardware address. 241 238 * 242 * @param[in] device_id The device identifier. 243 * @param[out] address The device hardware address. 244 * @return EOK on success. 245 * @return EBADMEM if the address parameter is NULL. 246 * @return ENOENT if there no such device. 239 * @param[in] device_id Device identifier. 240 * @param[out] address Device hardware address. 241 * 242 * @return EOK on success. 243 * @return EBADMEM if the address parameter is NULL. 244 * @return ENOENT if there no such device. 247 245 * 248 246 */ … … 250 248 measured_string_t **address) 251 249 { 252 nildummy_device_t *device;253 254 250 if (!address) 255 251 return EBADMEM; 256 252 257 253 fibril_rwlock_read_lock(&nildummy_globals.devices_lock); 258 device = nildummy_devices_find(&nildummy_globals.devices, device_id); 254 255 nildummy_device_t *device = 256 nildummy_devices_find(&nildummy_globals.devices, device_id); 259 257 if (!device) { 260 258 fibril_rwlock_read_unlock(&nildummy_globals.devices_lock); 261 259 return ENOENT; 262 260 } 261 263 262 *address = device->addr; 263 264 264 fibril_rwlock_read_unlock(&nildummy_globals.devices_lock); 265 265 … … 269 269 /** Return the device packet dimensions for sending. 270 270 * 271 * @param[in] device_id The device identifier. 272 * @param[out] addr_len The minimum reserved address length. 273 * @param[out] prefix The minimum reserved prefix size. 274 * @param[out] content The maximum content size. 275 * @param[out] suffix The minimum reserved suffix size. 276 * @return EOK on success. 277 * @return EBADMEM if either one of the parameters is NULL. 278 * @return ENOENT if there is no such device. 271 * @param[in] device_id Device identifier. 272 * @param[out] addr_len Minimum reserved address length. 273 * @param[out] prefix Minimum reserved prefix size. 274 * @param[out] content Maximum content size. 275 * @param[out] suffix Minimum reserved suffix size. 276 * 277 * @return EOK on success. 278 * @return EBADMEM if either one of the parameters is NULL. 279 * @return ENOENT if there is no such device. 279 280 * 280 281 */ … … 282 283 size_t *prefix, size_t *content, size_t *suffix) 283 284 { 284 nildummy_device_t *device; 285 286 if (!addr_len || !prefix || !content || !suffix) 285 if ((!addr_len) || (!prefix) || (!content) || (!suffix)) 287 286 return EBADMEM; 288 287 289 288 fibril_rwlock_read_lock(&nildummy_globals.devices_lock); 290 device = nildummy_devices_find(&nildummy_globals.devices, device_id); 289 290 nildummy_device_t *device = 291 nildummy_devices_find(&nildummy_globals.devices, device_id); 291 292 if (!device) { 292 293 fibril_rwlock_read_unlock(&nildummy_globals.devices_lock); 293 294 return ENOENT; 294 295 } 295 296 296 297 *content = device->mtu; 298 297 299 fibril_rwlock_read_unlock(&nildummy_globals.devices_lock); 298 300 … … 306 308 packet_t *packet, services_t target) 307 309 { 308 packet_t *next;309 310 310 fibril_rwlock_read_lock(&nildummy_globals.protos_lock); 311 311 312 if (nildummy_globals.proto.phone) { 312 313 do { 313 next = pq_detach(packet);314 packet_t *next = pq_detach(packet); 314 315 il_received_msg(nildummy_globals.proto.phone, device_id, 315 316 packet, nildummy_globals.proto.service); 316 317 packet = next; 317 } while(packet); 318 } 318 } while (packet); 319 } 320 319 321 fibril_rwlock_read_unlock(&nildummy_globals.protos_lock); 320 322 … … 326 328 * Pass received packets for this service. 327 329 * 328 * @param[in] service The module service. 329 * @param[in] phone The service phone. 330 * @return EOK on success. 331 * @return ENOENT if the service is not known. 332 * @return ENOMEM if there is not enough memory left. 330 * @param[in] service Module service. 331 * @param[in] phone Service phone. 332 * 333 * @return EOK on success. 334 * @return ENOENT if the service is not known. 335 * @return ENOMEM if there is not enough memory left. 336 * 333 337 */ 334 338 static int nildummy_register_message(services_t service, int phone) … … 347 351 /** Send the packet queue. 348 352 * 349 * @param[in] device_id The device identifier. 350 * @param[in] packet The packet queue. 351 * @param[in] sender The sending module service. 352 * @return EOK on success. 353 * @return ENOENT if there no such device. 354 * @return EINVAL if the service parameter is not known. 353 * @param[in] device_id Device identifier. 354 * @param[in] packet Packet queue. 355 * @param[in] sender Sending module service. 356 * 357 * @return EOK on success. 358 * @return ENOENT if there no such device. 359 * @return EINVAL if the service parameter is not known. 360 * 355 361 */ 356 362 static int nildummy_send_message(device_id_t device_id, packet_t *packet, 357 363 services_t sender) 358 364 { 359 nildummy_device_t *device;360 361 365 fibril_rwlock_read_lock(&nildummy_globals.devices_lock); 362 device = nildummy_devices_find(&nildummy_globals.devices, device_id); 366 367 nildummy_device_t *device = 368 nildummy_devices_find(&nildummy_globals.devices, device_id); 363 369 if (!device) { 364 370 fibril_rwlock_read_unlock(&nildummy_globals.devices_lock); 365 371 return ENOENT; 366 372 } 367 373 368 374 /* Send packet queue */ 369 375 if (packet) 370 376 netif_send_msg(device->phone, device_id, packet, 371 377 SERVICE_NILDUMMY); 378 372 379 fibril_rwlock_read_unlock(&nildummy_globals.devices_lock); 373 return EOK; 374 } 375 376 int nil_message_standalone(const char *name, ipc_callid_t callid, 377 ipc_call_t *call, ipc_call_t *answer, int *answer_count) 380 381 return EOK; 382 } 383 384 int nil_module_message(ipc_callid_t callid, ipc_call_t *call, 385 ipc_call_t *answer, size_t *answer_count) 378 386 { 379 387 measured_string_t *address; … … 386 394 387 395 *answer_count = 0; 388 switch (IPC_GET_ METHOD(*call)) {396 switch (IPC_GET_IMETHOD(*call)) { 389 397 case IPC_M_PHONE_HUNGUP: 390 398 return EOK; 391 399 392 400 case NET_NIL_DEVICE: 393 return nildummy_device_message(IPC_GET_DEVICE( call),394 IPC_GET_SERVICE( call), IPC_GET_MTU(call));401 return nildummy_device_message(IPC_GET_DEVICE(*call), 402 IPC_GET_SERVICE(*call), IPC_GET_MTU(*call)); 395 403 396 404 case NET_NIL_SEND: 397 405 rc = packet_translate_remote(nildummy_globals.net_phone, 398 &packet, IPC_GET_PACKET( call));406 &packet, IPC_GET_PACKET(*call)); 399 407 if (rc != EOK) 400 408 return rc; 401 return nildummy_send_message(IPC_GET_DEVICE( call), packet,402 IPC_GET_SERVICE( call));409 return nildummy_send_message(IPC_GET_DEVICE(*call), packet, 410 IPC_GET_SERVICE(*call)); 403 411 404 412 case NET_NIL_PACKET_SPACE: 405 rc = nildummy_packet_space_message(IPC_GET_DEVICE( call),413 rc = nildummy_packet_space_message(IPC_GET_DEVICE(*call), 406 414 &addrlen, &prefix, &content, &suffix); 407 415 if (rc != EOK) 408 416 return rc; 409 IPC_SET_ADDR( answer, addrlen);410 IPC_SET_PREFIX( answer, prefix);411 IPC_SET_CONTENT( answer, content);412 IPC_SET_SUFFIX( answer, suffix);417 IPC_SET_ADDR(*answer, addrlen); 418 IPC_SET_PREFIX(*answer, prefix); 419 IPC_SET_CONTENT(*answer, content); 420 IPC_SET_SUFFIX(*answer, suffix); 413 421 *answer_count = 4; 414 422 return EOK; 415 423 416 424 case NET_NIL_ADDR: 417 rc = nildummy_addr_message(IPC_GET_DEVICE( call), &address);425 rc = nildummy_addr_message(IPC_GET_DEVICE(*call), &address); 418 426 if (rc != EOK) 419 427 return rc; … … 421 429 422 430 case NET_NIL_BROADCAST_ADDR: 423 rc = nildummy_addr_message(IPC_GET_DEVICE( call), &address);431 rc = nildummy_addr_message(IPC_GET_DEVICE(*call), &address); 424 432 if (rc != EOK) 425 433 return rc; … … 427 435 428 436 case IPC_M_CONNECT_TO_ME: 429 return nildummy_register_message(NIL_GET_PROTO( call),430 IPC_GET_PHONE( call));437 return nildummy_register_message(NIL_GET_PROTO(*call), 438 IPC_GET_PHONE(*call)); 431 439 } 432 440 … … 434 442 } 435 443 436 /** Default thread for new connections.437 *438 * @param[in] iid The initial message identifier.439 * @param[in] icall The initial message call structure.440 */441 static void nil_client_connection(ipc_callid_t iid, ipc_call_t *icall)442 {443 /*444 * Accept the connection445 * - Answer the first IPC_M_CONNECT_ME_TO call.446 */447 ipc_answer_0(iid, EOK);448 449 while (true) {450 ipc_call_t answer;451 int answer_count;452 453 /* Clear the answer structure */454 refresh_answer(&answer, &answer_count);455 456 /* Fetch the next message */457 ipc_call_t call;458 ipc_callid_t callid = async_get_call(&call);459 460 /* Process the message */461 int res = nil_module_message_standalone(NAME, callid, &call,462 &answer, &answer_count);463 464 /*465 * End if told to either by the message or the processing466 * result.467 */468 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||469 (res == EHANGUP))470 return;471 472 /* Answer the message */473 answer_call(callid, res, &answer, answer_count);474 }475 }476 477 444 int main(int argc, char *argv[]) 478 445 { 479 int rc;480 481 446 /* Start the module */ 482 rc = nil_module_start_standalone(nil_client_connection); 483 return rc; 447 return nil_module_start(SERVICE_NILDUMMY); 484 448 } 485 449 -
uspace/srv/net/nil/nildummy/nildummy.h
rcead2aa r357b5f5 45 45 46 46 /** Type definition of the dummy nil global data. 47 * 47 48 * @see nildummy_globals 49 * 48 50 */ 49 51 typedef struct nildummy_globals nildummy_globals_t; 50 52 51 53 /** Type definition of the dummy nil device specific data. 54 * 52 55 * @see nildummy_device 56 * 53 57 */ 54 58 typedef struct nildummy_device nildummy_device_t; 55 59 56 60 /** Type definition of the dummy nil protocol specific data. 61 * 57 62 * @see nildummy_proto 63 * 58 64 */ 59 65 typedef struct nildummy_proto nildummy_proto_t; 60 66 61 67 /** Dummy nil device map. 62 * Maps devices to the dummy nil device specific data. 68 * 69 * Map devices to the dummy nil device specific data. 63 70 * @see device.h 71 * 64 72 */ 65 73 DEVICE_MAP_DECLARE(nildummy_devices, nildummy_device_t); … … 69 77 /** Device identifier. */ 70 78 device_id_t device_id; 79 71 80 /** Device driver service. */ 72 81 services_t service; 82 73 83 /** Driver phone. */ 74 84 int phone; 85 75 86 /** Maximal transmission unit. */ 76 87 size_t mtu; 88 77 89 /** Actual device hardware address. */ 78 90 measured_string_t *addr; 91 79 92 /** Actual device hardware address data. */ 80 char*addr_data;93 uint8_t *addr_data; 81 94 }; 82 95 … … 85 98 /** Protocol service. */ 86 99 services_t service; 100 87 101 /** Protocol module phone. */ 88 102 int phone; … … 93 107 /** Networking module phone. */ 94 108 int net_phone; 95 /** Safety lock for devices. */ 109 110 /** Lock for devices. */ 96 111 fibril_rwlock_t devices_lock; 112 97 113 /** All known Ethernet devices. */ 98 114 nildummy_devices_t devices; 115 99 116 /** Safety lock for protocols. */ 100 117 fibril_rwlock_t protos_lock; 118 101 119 /** Default protocol. */ 102 120 nildummy_proto_t proto; -
uspace/srv/net/tl/icmp/Makefile
rcead2aa r357b5f5 34 34 35 35 SOURCES = \ 36 icmp.c \ 37 icmp_module.c 36 icmp.c 38 37 39 38 include $(USPACE_PREFIX)/Makefile.common -
uspace/srv/net/tl/icmp/icmp.c
rcead2aa r357b5f5 33 33 /** @file 34 34 * ICMP module implementation. 35 * @see icmp.h 36 */ 37 38 #include "icmp.h" 39 #include "icmp_module.h" 35 */ 40 36 41 37 #include <async.h> … … 54 50 #include <byteorder.h> 55 51 #include <errno.h> 52 #include <adt/hash_table.h> 56 53 57 54 #include <net/socket_codes.h> … … 67 64 #include <net_checksum.h> 68 65 #include <icmp_client.h> 69 #include <icmp_ interface.h>70 #include <il_ interface.h>66 #include <icmp_remote.h> 67 #include <il_remote.h> 71 68 #include <ip_client.h> 72 69 #include <ip_interface.h> 73 70 #include <net_interface.h> 74 #include <tl_ interface.h>75 #include <tl_ local.h>71 #include <tl_remote.h> 72 #include <tl_skel.h> 76 73 #include <icmp_header.h> 77 74 78 /** ICMP module name. */ 79 #define NAME "ICMP protocol" 80 81 /** Default ICMP error reporting. */ 82 #define NET_DEFAULT_ICMP_ERROR_REPORTING true 83 84 /** Default ICMP echo replying. */ 85 #define NET_DEFAULT_ICMP_ECHO_REPLYING true 86 87 /** Original datagram length in bytes transfered to the error notification 88 * message. 89 */ 90 #define ICMP_KEEP_LENGTH 8 91 92 /** Free identifier numbers pool start. */ 93 #define ICMP_FREE_IDS_START 1 94 95 /** Free identifier numbers pool end. */ 96 #define ICMP_FREE_IDS_END UINT16_MAX 97 98 /** Computes the ICMP datagram checksum. 99 * 100 * @param[in,out] header The ICMP datagram header. 101 * @param[in] length The total datagram length. 102 * @return The computed checksum. 75 /** ICMP module name */ 76 #define NAME "icmp" 77 78 /** Number of replies hash table keys */ 79 #define REPLY_KEYS 2 80 81 /** Number of replies hash table buckets */ 82 #define REPLY_BUCKETS 1024 83 84 /** 85 * Original datagram length in bytes transfered to the error 86 * notification message. 87 */ 88 #define ICMP_KEEP_LENGTH 8 89 90 /** Compute the ICMP datagram checksum. 91 * 92 * @param[in,out] header ICMP datagram header. 93 * @param[in] length Total datagram length. 94 * 95 * @return Computed checksum. 96 * 103 97 */ 104 98 #define ICMP_CHECKSUM(header, length) \ … … 106 100 107 101 /** An echo request datagrams pattern. */ 108 #define ICMP_ECHO_TEXT "Hello from HelenOS." 109 110 /** Computes an ICMP reply data key. 111 * 112 * @param[in] id The message identifier. 113 * @param[in] sequence The message sequence number. 114 * @return The computed ICMP reply data key. 115 */ 116 #define ICMP_GET_REPLY_KEY(id, sequence) \ 117 (((id) << 16) | (sequence & 0xFFFF)) 118 119 120 /** ICMP global data. */ 121 icmp_globals_t icmp_globals; 122 123 INT_MAP_IMPLEMENT(icmp_replies, icmp_reply_t); 124 INT_MAP_IMPLEMENT(icmp_echo_data, icmp_echo_t); 125 126 /** Releases the packet and returns the result. 127 * 128 * @param[in] packet The packet queue to be released. 129 * @param[in] result The result to be returned. 130 * @return The result parameter. 131 */ 132 static int icmp_release_and_return(packet_t *packet, int result) 133 { 134 pq_release_remote(icmp_globals.net_phone, packet_get_id(packet)); 135 return result; 136 } 137 138 /** Sends the ICMP message. 139 * 140 * Sets the message type and code and computes the checksum. 102 #define ICMP_ECHO_TEXT "ICMP hello from HelenOS." 103 104 /** ICMP reply data. */ 105 typedef struct { 106 /** Hash table link */ 107 link_t link; 108 109 /** Reply identification and sequence */ 110 icmp_param_t id; 111 icmp_param_t sequence; 112 113 /** Reply signaling */ 114 fibril_condvar_t condvar; 115 116 /** Reply result */ 117 int result; 118 } icmp_reply_t; 119 120 /** Global data */ 121 static int phone_net = -1; 122 static int phone_ip = -1; 123 static bool error_reporting = true; 124 static bool echo_replying = true; 125 static packet_dimension_t icmp_dimension; 126 127 /** ICMP client identification counter */ 128 static atomic_t icmp_client; 129 130 /** ICMP identifier and sequence number (client-specific) */ 131 static fibril_local icmp_param_t icmp_id; 132 static fibril_local icmp_param_t icmp_seq; 133 134 /** Reply hash table */ 135 static fibril_mutex_t reply_lock; 136 static hash_table_t replies; 137 138 static hash_index_t replies_hash(unsigned long key[]) 139 { 140 /* 141 * ICMP identifier and sequence numbers 142 * are 16-bit values. 143 */ 144 hash_index_t index = ((key[0] & 0xffff) << 16) | (key[1] & 0xffff); 145 return (index % REPLY_BUCKETS); 146 } 147 148 static int replies_compare(unsigned long key[], hash_count_t keys, link_t *item) 149 { 150 icmp_reply_t *reply = 151 hash_table_get_instance(item, icmp_reply_t, link); 152 153 if (keys == 1) 154 return (reply->id == key[0]); 155 else 156 return ((reply->id == key[0]) && (reply->sequence == key[1])); 157 } 158 159 static void replies_remove_callback(link_t *item) 160 { 161 } 162 163 static hash_table_operations_t reply_ops = { 164 .hash = replies_hash, 165 .compare = replies_compare, 166 .remove_callback = replies_remove_callback 167 }; 168 169 /** Release the packet and return the result. 170 * 171 * @param[in] packet Packet queue to be released. 172 * 173 */ 174 static void icmp_release(packet_t *packet) 175 { 176 pq_release_remote(phone_net, packet_get_id(packet)); 177 } 178 179 /** Send the ICMP message. 180 * 181 * Set the message type and code and compute the checksum. 141 182 * Error messages are sent only if allowed in the configuration. 142 * Releases the packet on errors. 143 * 144 * @param[in] type The message type. 145 * @param[in] code The message code. 146 * @param[in] packet The message packet to be sent. 147 * @param[in] header The ICMP header. 148 * @param[in] error The error service to be announced. Should be 149 * SERVICE_ICMP or zero. 150 * @param[in] ttl The time to live. 151 * @param[in] tos The type of service. 152 * @param[in] dont_fragment The value indicating whether the datagram must not 153 * be fragmented. Is used as a MTU discovery. 154 * @return EOK on success. 155 * @return EPERM if the error message is not allowed. 156 */ 157 static int icmp_send_packet(icmp_type_t type, icmp_code_t code, packet_t *packet, 158 icmp_header_t *header, services_t error, ip_ttl_t ttl, ip_tos_t tos, 159 int dont_fragment) 160 { 161 int rc; 162 183 * Release the packet on errors. 184 * 185 * @param[in] type Message type. 186 * @param[in] code Message code. 187 * @param[in] packet Message packet to be sent. 188 * @param[in] header ICMP header. 189 * @param[in] error Error service to be announced. Should be 190 * SERVICE_ICMP or zero. 191 * @param[in] ttl Time to live. 192 * @param[in] tos Type of service. 193 * @param[in] dont_fragment Disable fragmentation. 194 * 195 * @return EOK on success. 196 * @return EPERM if the error message is not allowed. 197 * 198 */ 199 static int icmp_send_packet(icmp_type_t type, icmp_code_t code, 200 packet_t *packet, icmp_header_t *header, services_t error, ip_ttl_t ttl, 201 ip_tos_t tos, bool dont_fragment) 202 { 163 203 /* Do not send an error if disabled */ 164 if (error && !icmp_globals.error_reporting) 165 return icmp_release_and_return(packet, EPERM); 166 204 if ((error) && (!error_reporting)) { 205 icmp_release(packet); 206 return EPERM; 207 } 208 167 209 header->type = type; 168 210 header->code = code; 211 212 /* 213 * The checksum needs to be calculated 214 * with a virtual checksum field set to 215 * zero. 216 */ 169 217 header->checksum = 0; 170 218 header->checksum = ICMP_CHECKSUM(header, 171 219 packet_get_data_length(packet)); 172 220 173 rc = ip_client_prepare_packet(packet, IPPROTO_ICMP, ttl, tos,221 int rc = ip_client_prepare_packet(packet, IPPROTO_ICMP, ttl, tos, 174 222 dont_fragment, 0); 175 if (rc != EOK) 176 return icmp_release_and_return(packet, rc); 177 178 return ip_send_msg(icmp_globals.ip_phone, -1, packet, SERVICE_ICMP, 179 error); 180 } 181 182 /** Prepares the ICMP error packet. 183 * 184 * Truncates the original packet if longer than ICMP_KEEP_LENGTH bytes. 185 * Prefixes and returns the ICMP header. 186 * 187 * @param[in,out] packet The original packet. 223 if (rc != EOK) { 224 icmp_release(packet); 225 return rc; 226 } 227 228 return ip_send_msg(phone_ip, -1, packet, SERVICE_ICMP, error); 229 } 230 231 /** Prepare the ICMP error packet. 232 * 233 * Truncate the original packet if longer than ICMP_KEEP_LENGTH bytes. 234 * Prefix and return the ICMP header. 235 * 236 * @param[in,out] packet Original packet. 237 * 188 238 * @return The prefixed ICMP header. 189 239 * @return NULL on errors. 240 * 190 241 */ 191 242 static icmp_header_t *icmp_prepare_packet(packet_t *packet) 192 243 { 193 icmp_header_t *header; 194 size_t header_length; 195 size_t total_length; 196 197 total_length = packet_get_data_length(packet); 244 size_t total_length = packet_get_data_length(packet); 198 245 if (total_length <= 0) 199 246 return NULL; 200 201 header_length = ip_client_header_length(packet);247 248 size_t header_length = ip_client_header_length(packet); 202 249 if (header_length <= 0) 203 250 return NULL; 204 251 205 252 /* Truncate if longer than 64 bits (without the IP header) */ 206 253 if ((total_length > header_length + ICMP_KEEP_LENGTH) && 207 254 (packet_trim(packet, 0, 208 total_length - header_length - ICMP_KEEP_LENGTH) != EOK)) {255 total_length - header_length - ICMP_KEEP_LENGTH) != EOK)) 209 256 return NULL; 210 } 211 212 header = PACKET_PREFIX(packet, icmp_header_t); 257 258 icmp_header_t *header = PACKET_PREFIX(packet, icmp_header_t); 213 259 if (!header) 214 260 return NULL; 215 261 216 262 bzero(header, sizeof(*header)); 217 263 return header; 218 264 } 219 265 220 /** Request san echo message.221 * 222 * Send s a packet with specified parameters to the target host and waits for223 * the reply upto the given timeout.224 * Block sthe caller until the reply or the timeout occurs.225 * 226 * @param[in] id The message identifier.227 * @param[in] sequence The message sequence parameter.228 * @param[in] size The message data length in bytes.229 * @param[in] timeout The timeout in miliseconds.230 * @param[in] ttl The time to live.231 * @param[in] tos The type of service.232 * @param[in] dont_fragment The value indicating whether the datagram must not233 * be fragmented. Is used as a MTU discovery.234 * @param[in] addr The target host address.235 * @param[in] addrlen The torget host address length.236 * @return ICMP_ECHO on success.237 * @return ETIMEOUT if the reply has not arrived before the238 * timeout.239 * @return ICMP type of the received error notification.240 * @return EINVAL if the addrlen parameter is less or equal to241 * zero.242 * @return ENOMEM if there is not enough memory left.243 * @return EPARTY if there was an internal error.266 /** Request an echo message. 267 * 268 * Send a packet with specified parameters to the target host 269 * and wait for the reply upto the given timeout. 270 * Block the caller until the reply or the timeout occurs. 271 * 272 * @param[in] id Message identifier. 273 * @param[in] sequence Message sequence parameter. 274 * @param[in] size Message data length in bytes. 275 * @param[in] timeout Timeout in miliseconds. 276 * @param[in] ttl Time to live. 277 * @param[in] tos Type of service. 278 * @param[in] dont_fragment Disable fragmentation. 279 * @param[in] addr Target host address. 280 * @param[in] addrlen Torget host address length. 281 * 282 * @return ICMP_ECHO on success. 283 * @return ETIMEOUT if the reply has not arrived before the 284 * timeout. 285 * @return ICMP type of the received error notification. 286 * @return EINVAL if the addrlen parameter is less or equal to 287 * zero. 288 * @return ENOMEM if there is not enough memory left. 289 * 244 290 */ 245 291 static int icmp_echo(icmp_param_t id, icmp_param_t sequence, size_t size, 246 mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, 247 const struct sockaddr * addr, socklen_t addrlen) 248 { 249 icmp_header_t *header; 250 packet_t *packet; 251 size_t length; 252 uint8_t *data; 253 icmp_reply_t *reply; 254 int reply_key; 255 int index; 256 int rc; 257 292 mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, bool dont_fragment, 293 const struct sockaddr *addr, socklen_t addrlen) 294 { 258 295 if (addrlen <= 0) 259 296 return EINVAL; 260 261 length = (size_t) addrlen; 262 /* TODO do not ask all the time */ 263 rc = ip_packet_size_req(icmp_globals.ip_phone, -1, 264 &icmp_globals.packet_dimension); 265 if (rc != EOK) 266 return rc; 267 268 packet = packet_get_4_remote(icmp_globals.net_phone, size, 269 icmp_globals.packet_dimension.addr_len, 270 ICMP_HEADER_SIZE + icmp_globals.packet_dimension.prefix, 271 icmp_globals.packet_dimension.suffix); 297 298 size_t length = (size_t) addrlen; 299 300 packet_t *packet = packet_get_4_remote(phone_net, size, 301 icmp_dimension.addr_len, ICMP_HEADER_SIZE + icmp_dimension.prefix, 302 icmp_dimension.suffix); 272 303 if (!packet) 273 304 return ENOMEM; 274 305 275 306 /* Prepare the requesting packet, set the destination address. */ 276 rc = packet_set_addr(packet, NULL, (const uint8_t *) addr, length); 277 if (rc != EOK) 278 return icmp_release_and_return(packet, rc); 279 307 int rc = packet_set_addr(packet, NULL, (const uint8_t *) addr, length); 308 if (rc != EOK) { 309 icmp_release(packet); 310 return rc; 311 } 312 280 313 /* Allocate space in the packet */ 281 data = (uint8_t *) packet_suffix(packet, size); 282 if (!data) 283 return icmp_release_and_return(packet, ENOMEM); 284 314 uint8_t *data = (uint8_t *) packet_suffix(packet, size); 315 if (!data) { 316 icmp_release(packet); 317 return ENOMEM; 318 } 319 285 320 /* Fill the data */ 286 321 length = 0; … … 290 325 } 291 326 memcpy(data + length, ICMP_ECHO_TEXT, size - length); 292 327 293 328 /* Prefix the header */ 294 header = PACKET_PREFIX(packet, icmp_header_t); 295 if (!header) 296 return icmp_release_and_return(packet, ENOMEM); 297 298 bzero(header, sizeof(*header)); 329 icmp_header_t *header = PACKET_PREFIX(packet, icmp_header_t); 330 if (!header) { 331 icmp_release(packet); 332 return ENOMEM; 333 } 334 335 bzero(header, sizeof(icmp_header_t)); 299 336 header->un.echo.identifier = id; 300 337 header->un.echo.sequence_number = sequence; 301 338 302 339 /* Prepare the reply structure */ 303 reply = malloc(sizeof(*reply)); 304 if (!reply) 305 return icmp_release_and_return(packet, ENOMEM); 306 307 fibril_mutex_initialize(&reply->mutex); 308 fibril_mutex_lock(&reply->mutex); 340 icmp_reply_t *reply = malloc(sizeof(icmp_reply_t)); 341 if (!reply) { 342 icmp_release(packet); 343 return ENOMEM; 344 } 345 346 reply->id = id; 347 reply->sequence = sequence; 309 348 fibril_condvar_initialize(&reply->condvar); 310 reply_key = ICMP_GET_REPLY_KEY(header->un.echo.identifier, 311 header->un.echo.sequence_number); 312 index = icmp_replies_add(&icmp_globals.replies, reply_key, reply); 313 if (index < 0) { 314 free(reply); 315 return icmp_release_and_return(packet, index); 316 } 317 318 /* Unlock the globals so that we can wait for the reply */ 319 fibril_rwlock_write_unlock(&icmp_globals.lock); 320 349 350 /* Add the reply to the replies hash table */ 351 fibril_mutex_lock(&reply_lock); 352 353 unsigned long key[REPLY_KEYS] = {id, sequence}; 354 hash_table_insert(&replies, key, &reply->link); 355 321 356 /* Send the request */ 322 357 icmp_send_packet(ICMP_ECHO, 0, packet, header, 0, ttl, tos, 323 358 dont_fragment); 324 359 325 360 /* Wait for the reply. Timeout in microseconds. */ 326 rc = fibril_condvar_wait_timeout(&reply->condvar, &reply ->mutex,361 rc = fibril_condvar_wait_timeout(&reply->condvar, &reply_lock, 327 362 timeout * 1000); 328 363 if (rc == EOK) 329 364 rc = reply->result; 330 331 /* Drop the reply mutex before locking the globals again*/332 fibril_mutex_unlock(&reply->mutex);333 fibril_rwlock_write_lock(&icmp_globals.lock);334 335 /* Destroy the reply structure */336 icmp_replies_exclude_index(&icmp_globals.replies, index);337 365 366 /* Remove the reply from the replies hash table */ 367 hash_table_remove(&replies, key, REPLY_KEYS); 368 369 fibril_mutex_unlock(&reply_lock); 370 371 free(reply); 372 338 373 return rc; 339 374 } 340 375 341 static int icmp_destination_unreachable _msg_local(int icmp_phone,342 icmp_code_t code, icmp_param_t mtu,packet_t *packet)343 { 344 icmp_header_t *header ;345 346 header = icmp_prepare_packet(packet);347 if (!header)348 return icmp_release_and_return(packet, ENOMEM);349 376 static int icmp_destination_unreachable(icmp_code_t code, icmp_param_t mtu, 377 packet_t *packet) 378 { 379 icmp_header_t *header = icmp_prepare_packet(packet); 380 if (!header) { 381 icmp_release(packet); 382 return ENOMEM; 383 } 384 350 385 if (mtu) 351 386 header->un.frag.mtu = mtu; 352 387 353 388 return icmp_send_packet(ICMP_DEST_UNREACH, code, packet, header, 354 SERVICE_ICMP, 0, 0, 0);355 } 356 357 static int icmp_source_quench _msg_local(int icmp_phone,packet_t *packet)358 { 359 icmp_header_t *header ;360 361 header = icmp_prepare_packet(packet);362 if (!header)363 return icmp_release_and_return(packet, ENOMEM);364 389 SERVICE_ICMP, 0, 0, false); 390 } 391 392 static int icmp_source_quench(packet_t *packet) 393 { 394 icmp_header_t *header = icmp_prepare_packet(packet); 395 if (!header) { 396 icmp_release(packet); 397 return ENOMEM; 398 } 399 365 400 return icmp_send_packet(ICMP_SOURCE_QUENCH, 0, packet, header, 366 SERVICE_ICMP, 0, 0, 0); 367 } 368 369 static int icmp_time_exceeded_msg_local(int icmp_phone, icmp_code_t code, 401 SERVICE_ICMP, 0, 0, false); 402 } 403 404 static int icmp_time_exceeded(icmp_code_t code, packet_t *packet) 405 { 406 icmp_header_t *header = icmp_prepare_packet(packet); 407 if (!header) { 408 icmp_release(packet); 409 return ENOMEM; 410 } 411 412 return icmp_send_packet(ICMP_TIME_EXCEEDED, code, packet, header, 413 SERVICE_ICMP, 0, 0, false); 414 } 415 416 static int icmp_parameter_problem(icmp_code_t code, icmp_param_t pointer, 370 417 packet_t *packet) 371 418 { 372 icmp_header_t *header; 373 374 header = icmp_prepare_packet(packet); 375 if (!header) 376 return icmp_release_and_return(packet, ENOMEM); 377 378 return icmp_send_packet(ICMP_TIME_EXCEEDED, code, packet, header, 379 SERVICE_ICMP, 0, 0, 0); 380 } 381 382 static int icmp_parameter_problem_msg_local(int icmp_phone, icmp_code_t code, 383 icmp_param_t pointer, packet_t *packet) 384 { 385 icmp_header_t *header; 386 387 header = icmp_prepare_packet(packet); 388 if (!header) 389 return icmp_release_and_return(packet, ENOMEM); 390 419 icmp_header_t *header = icmp_prepare_packet(packet); 420 if (!header) { 421 icmp_release(packet); 422 return ENOMEM; 423 } 424 391 425 header->un.param.pointer = pointer; 392 426 return icmp_send_packet(ICMP_PARAMETERPROB, code, packet, header, 393 SERVICE_ICMP, 0, 0, 0); 394 } 395 396 /** Initializes the ICMP module. 397 * 398 * @param[in] client_connection The client connection processing function. The 399 * module skeleton propagates its own one. 400 * @return EOK on success. 401 * @return ENOMEM if there is not enough memory left. 402 */ 403 int icmp_initialize(async_client_conn_t client_connection) 404 { 405 measured_string_t names[] = { 406 { 407 (char *) "ICMP_ERROR_REPORTING", 408 20 409 }, 410 { 411 (char *) "ICMP_ECHO_REPLYING", 412 18 413 } 414 }; 415 measured_string_t *configuration; 416 size_t count = sizeof(names) / sizeof(measured_string_t); 417 char *data; 418 int rc; 419 420 fibril_rwlock_initialize(&icmp_globals.lock); 421 fibril_rwlock_write_lock(&icmp_globals.lock); 422 icmp_replies_initialize(&icmp_globals.replies); 423 icmp_echo_data_initialize(&icmp_globals.echo_data); 424 425 icmp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_ICMP, 426 SERVICE_ICMP, client_connection); 427 if (icmp_globals.ip_phone < 0) { 428 fibril_rwlock_write_unlock(&icmp_globals.lock); 429 return icmp_globals.ip_phone; 430 } 431 432 rc = ip_packet_size_req(icmp_globals.ip_phone, -1, 433 &icmp_globals.packet_dimension); 434 if (rc != EOK) { 435 fibril_rwlock_write_unlock(&icmp_globals.lock); 436 return rc; 437 } 438 439 icmp_globals.packet_dimension.prefix += ICMP_HEADER_SIZE; 440 icmp_globals.packet_dimension.content -= ICMP_HEADER_SIZE; 441 442 icmp_globals.error_reporting = NET_DEFAULT_ICMP_ERROR_REPORTING; 443 icmp_globals.echo_replying = NET_DEFAULT_ICMP_ECHO_REPLYING; 444 445 /* Get configuration */ 446 configuration = &names[0]; 447 rc = net_get_conf_req(icmp_globals.net_phone, &configuration, count, 448 &data); 449 if (rc != EOK) { 450 fibril_rwlock_write_unlock(&icmp_globals.lock); 451 return rc; 452 } 453 454 if (configuration) { 455 if (configuration[0].value) { 456 icmp_globals.error_reporting = 457 (configuration[0].value[0] == 'y'); 458 } 459 if (configuration[1].value) { 460 icmp_globals.echo_replying = 461 (configuration[1].value[0] == 'y'); 462 } 463 net_free_settings(configuration, data); 464 } 465 466 fibril_rwlock_write_unlock(&icmp_globals.lock); 467 return EOK; 468 } 469 470 /** Tries to set the pending reply result as the received message type. 427 SERVICE_ICMP, 0, 0, false); 428 } 429 430 /** Try to set the pending reply result as the received message type. 471 431 * 472 432 * If the reply data is not present, the reply timed out and the other fibril 473 * is already awake. 474 * Releases the packet.475 * 476 * @param[in] packet The received reply message.477 * @param[in] header The ICMP message header.478 * @param[in] type The received reply message type.479 * @param[in] code The received reply message code.480 */ 481 static void icmp_process_echo_reply(packet_t *packet, icmp_header_t *header,433 * is already awake. The packet is released. 434 * 435 * @param[in] packet The received reply message. 436 * @param[in] header The ICMP message header. 437 * @param[in] type The received reply message type. 438 * @param[in] code The received reply message code. 439 * 440 */ 441 static void icmp_process_echo_reply(packet_t *packet, icmp_header_t *header, 482 442 icmp_type_t type, icmp_code_t code) 483 443 { 484 int reply_key; 485 icmp_reply_t *reply; 486 487 /* Compute the reply key */ 488 reply_key = ICMP_GET_REPLY_KEY(header->un.echo.identifier, 489 header->un.echo.sequence_number); 490 pq_release_remote(icmp_globals.net_phone, packet_get_id(packet)); 491 444 unsigned long key[REPLY_KEYS] = 445 {header->un.echo.identifier, header->un.echo.sequence_number}; 446 447 /* The packet is no longer needed */ 448 icmp_release(packet); 449 492 450 /* Find the pending reply */ 493 fibril_rwlock_write_lock(&icmp_globals.lock); 494 reply = icmp_replies_find(&icmp_globals.replies, reply_key); 495 if (reply) { 451 fibril_mutex_lock(&reply_lock); 452 453 link_t *link = hash_table_find(&replies, key); 454 if (link != NULL) { 455 icmp_reply_t *reply = 456 hash_table_get_instance(link, icmp_reply_t, link); 457 496 458 reply->result = type; 497 459 fibril_condvar_signal(&reply->condvar); 498 460 } 499 fibril_rwlock_write_unlock(&icmp_globals.lock); 500 } 501 502 /** Processes the received ICMP packet. 503 * 504 * Notifies the destination socket application. 505 * 506 * @param[in,out] packet The received packet. 507 * @param[in] error The packet error reporting service. Prefixes the 508 * received packet. 509 * @return EOK on success. 510 * @return EINVAL if the packet is not valid. 511 * @return EINVAL if the stored packet address is not the an_addr_t. 512 * @return EINVAL if the packet does not contain any data. 513 * @return NO_DATA if the packet content is shorter than the user 514 * datagram header. 515 * @return ENOMEM if there is not enough memory left. 516 * @return EADDRNOTAVAIL if the destination socket does not exist. 517 * @return Other error codes as defined for the 518 * ip_client_process_packet() function. 461 462 fibril_mutex_unlock(&reply_lock); 463 } 464 465 /** Process the received ICMP packet. 466 * 467 * Notify the destination socket application. 468 * 469 * @param[in,out] packet Received packet. 470 * @param[in] error Packet error reporting service to prefix 471 * the received packet. 472 * 473 * @return EOK on success. 474 * @return EINVAL if the packet is not valid. 475 * @return EINVAL if the stored packet address is not the an_addr_t. 476 * @return EINVAL if the packet does not contain any data. 477 * @return NO_DATA if the packet content is shorter than the user 478 * datagram header. 479 * @return ENOMEM if there is not enough memory left. 480 * @return EADDRNOTAVAIL if the destination socket does not exist. 481 * @return Other error codes as defined for the 482 * ip_client_process_packet() function. 483 * 519 484 */ 520 485 static int icmp_process_packet(packet_t *packet, services_t error) 521 486 { 522 size_t length;523 uint8_t *src;524 int addrlen;525 int result;526 void *data;527 icmp_header_t *header;528 487 icmp_type_t type; 529 488 icmp_code_t code; 530 489 int rc; 531 490 532 491 switch (error) { 533 492 case SERVICE_NONE: … … 535 494 case SERVICE_ICMP: 536 495 /* Process error */ 537 result = icmp_client_process_packet(packet, &type, &code, NULL, 538 NULL); 539 if (result < 0) 540 return result; 541 length = (size_t) result; 496 rc = icmp_client_process_packet(packet, &type, &code, NULL, NULL); 497 if (rc < 0) 498 return rc; 499 542 500 /* Remove the error header */ 543 rc = packet_trim(packet, length, 0);501 rc = packet_trim(packet, (size_t) rc, 0); 544 502 if (rc != EOK) 545 503 return rc; 504 546 505 break; 547 506 default: 548 507 return ENOTSUP; 549 508 } 550 509 551 510 /* Get rid of the IP header */ 552 length = ip_client_header_length(packet);511 size_t length = ip_client_header_length(packet); 553 512 rc = packet_trim(packet, length, 0); 554 513 if (rc != EOK) 555 514 return rc; 556 515 557 516 length = packet_get_data_length(packet); 558 517 if (length <= 0) 559 518 return EINVAL; 560 519 561 520 if (length < ICMP_HEADER_SIZE) 562 521 return EINVAL; 563 564 data = packet_get_data(packet);522 523 void *data = packet_get_data(packet); 565 524 if (!data) 566 525 return EINVAL; 567 526 568 527 /* Get ICMP header */ 569 header = (icmp_header_t *) data;570 528 icmp_header_t *header = (icmp_header_t *) data; 529 571 530 if (header->checksum) { 572 531 while (ICMP_CHECKSUM(header, length) != IP_CHECKSUM_ZERO) { … … 582 541 } 583 542 } 543 584 544 return EINVAL; 585 545 } 586 546 } 587 547 588 548 switch (header->type) { 589 549 case ICMP_ECHOREPLY: … … 592 552 else 593 553 icmp_process_echo_reply(packet, header, ICMP_ECHO, 0); 594 554 595 555 return EOK; 596 556 597 557 case ICMP_ECHO: 598 558 if (error) { … … 602 562 603 563 /* Do not send a reply if disabled */ 604 if (icmp_globals.echo_replying) { 605 addrlen = packet_get_addr(packet, &src, NULL); 606 564 if (echo_replying) { 565 uint8_t *src; 566 int addrlen = packet_get_addr(packet, &src, NULL); 567 607 568 /* 608 * Set both addresses to the source one (avoid sthe569 * Set both addresses to the source one (avoid the 609 570 * source address deletion before setting the 610 571 * destination one). … … 617 578 return EOK; 618 579 } 619 580 620 581 return EINVAL; 621 582 } 622 583 623 584 return EPERM; 624 585 625 586 case ICMP_DEST_UNREACH: 626 587 case ICMP_SOURCE_QUENCH: … … 635 596 case ICMP_SKIP: 636 597 case ICMP_PHOTURIS: 637 ip_received_error_msg( icmp_globals.ip_phone, -1, packet,598 ip_received_error_msg(phone_ip, -1, packet, 638 599 SERVICE_IP, SERVICE_ICMP); 639 600 return EOK; 640 601 641 602 default: 642 603 return ENOTSUP; … … 644 605 } 645 606 646 /** Processes the received ICMP packet. 647 * 648 * Is used as an entry point from the underlying IP module. 649 * Releases the packet on error. 650 * 651 * @param device_id The device identifier. Ignored parameter. 652 * @param[in,out] packet The received packet. 653 * @param receiver The target service. Ignored parameter. 654 * @param[in] error The packet error reporting service. Prefixes the 655 * received packet. 656 * @return EOK on success. 657 * @return Other error codes as defined for the 658 * icmp_process_packet() function. 659 */ 660 static int icmp_received_msg_local(device_id_t device_id, packet_t *packet, 661 services_t receiver, services_t error) 662 { 663 int rc; 664 665 rc = icmp_process_packet(packet, error); 666 if (rc != EOK) 667 return icmp_release_and_return(packet, rc); 668 669 return EOK; 670 } 671 672 /** Processes the generic client messages. 673 * 674 * @param[in] call The message parameters. 675 * @return EOK on success. 676 * @return ENOTSUP if the message is not known. 677 * @return Other error codes as defined for the packet_translate() 678 * function. 679 * @return Other error codes as defined for the 680 * icmp_destination_unreachable_msg_local() function. 681 * @return Other error codes as defined for the 682 * icmp_source_quench_msg_local() function. 683 * @return Other error codes as defined for the 684 * icmp_time_exceeded_msg_local() function. 685 * @return Other error codes as defined for the 686 * icmp_parameter_problem_msg_local() function. 687 * 688 * @see icmp_interface.h 689 */ 690 static int icmp_process_message(ipc_call_t *call) 691 { 607 /** Process IPC messages from the IP module 608 * 609 * @param[in] iid Message identifier. 610 * @param[in,out] icall Message parameters. 611 * 612 */ 613 static void icmp_receiver(ipc_callid_t iid, ipc_call_t *icall) 614 { 615 bool loop = true; 692 616 packet_t *packet; 693 617 int rc; 694 695 switch (IPC_GET_METHOD(*call)) { 696 case NET_ICMP_DEST_UNREACH: 697 rc = packet_translate_remote(icmp_globals.net_phone, &packet, 698 IPC_GET_PACKET(call)); 618 619 while (loop) { 620 switch (IPC_GET_IMETHOD(*icall)) { 621 case NET_TL_RECEIVED: 622 rc = packet_translate_remote(phone_net, &packet, 623 IPC_GET_PACKET(*icall)); 624 if (rc == EOK) { 625 rc = icmp_process_packet(packet, IPC_GET_ERROR(*icall)); 626 if (rc != EOK) 627 icmp_release(packet); 628 } 629 630 ipc_answer_0(iid, (sysarg_t) rc); 631 break; 632 case IPC_M_PHONE_HUNGUP: 633 loop = false; 634 continue; 635 default: 636 ipc_answer_0(iid, (sysarg_t) ENOTSUP); 637 } 638 639 iid = async_get_call(icall); 640 } 641 } 642 643 /** Initialize the ICMP module. 644 * 645 * @param[in] net_phone Network module phone. 646 * 647 * @return EOK on success. 648 * @return ENOMEM if there is not enough memory left. 649 * 650 */ 651 int tl_initialize(int net_phone) 652 { 653 measured_string_t names[] = { 654 { 655 (uint8_t *) "ICMP_ERROR_REPORTING", 656 20 657 }, 658 { 659 (uint8_t *) "ICMP_ECHO_REPLYING", 660 18 661 } 662 }; 663 measured_string_t *configuration; 664 size_t count = sizeof(names) / sizeof(measured_string_t); 665 uint8_t *data; 666 667 if (!hash_table_create(&replies, REPLY_BUCKETS, REPLY_KEYS, &reply_ops)) 668 return ENOMEM; 669 670 fibril_mutex_initialize(&reply_lock); 671 atomic_set(&icmp_client, 0); 672 673 phone_net = net_phone; 674 phone_ip = ip_bind_service(SERVICE_IP, IPPROTO_ICMP, SERVICE_ICMP, 675 icmp_receiver); 676 if (phone_ip < 0) 677 return phone_ip; 678 679 int rc = ip_packet_size_req(phone_ip, -1, &icmp_dimension); 680 if (rc != EOK) 681 return rc; 682 683 icmp_dimension.prefix += ICMP_HEADER_SIZE; 684 icmp_dimension.content -= ICMP_HEADER_SIZE; 685 686 /* Get configuration */ 687 configuration = &names[0]; 688 rc = net_get_conf_req(phone_net, &configuration, count, &data); 689 if (rc != EOK) 690 return rc; 691 692 if (configuration) { 693 if (configuration[0].value) 694 error_reporting = (configuration[0].value[0] == 'y'); 695 696 if (configuration[1].value) 697 echo_replying = (configuration[1].value[0] == 'y'); 698 699 net_free_settings(configuration, data); 700 } 701 702 return EOK; 703 } 704 705 /** Per-connection initialization 706 * 707 * Initialize client-specific global variables. 708 * 709 */ 710 void tl_connection(void) 711 { 712 icmp_id = (icmp_param_t) atomic_postinc(&icmp_client); 713 icmp_seq = 1; 714 } 715 716 /** Process the ICMP message. 717 * 718 * @param[in] callid Message identifier. 719 * @param[in] call Message parameters. 720 * @param[out] answer Answer. 721 * @param[out] count Number of arguments of the answer. 722 * 723 * @return EOK on success. 724 * @return ENOTSUP if the message is not known. 725 * @return Other error codes as defined for the packet_translate() 726 * function. 727 * @return Other error codes as defined for the 728 * icmp_destination_unreachable() function. 729 * @return Other error codes as defined for the 730 * icmp_source_quench() function. 731 * @return Other error codes as defined for the 732 * icmp_time_exceeded() function. 733 * @return Other error codes as defined for the 734 * icmp_parameter_problem() function. 735 * 736 * @see icmp_remote.h 737 * @see IS_NET_ICMP_MESSAGE() 738 * 739 */ 740 int tl_message(ipc_callid_t callid, ipc_call_t *call, 741 ipc_call_t *answer, size_t *count) 742 { 743 struct sockaddr *addr; 744 size_t size; 745 packet_t *packet; 746 int rc; 747 748 *count = 0; 749 750 switch (IPC_GET_IMETHOD(*call)) { 751 case NET_ICMP_ECHO: 752 rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, &size); 699 753 if (rc != EOK) 700 754 return rc; 701 return icmp_destination_unreachable_msg_local(0, 702 ICMP_GET_CODE(call), ICMP_GET_MTU(call), packet); 703 case NET_ICMP_SOURCE_QUENCH: 704 rc = packet_translate_remote(icmp_globals.net_phone, &packet, 705 IPC_GET_PACKET(call)); 755 756 rc = icmp_echo(icmp_id, icmp_seq, ICMP_GET_SIZE(*call), 757 ICMP_GET_TIMEOUT(*call), ICMP_GET_TTL(*call), 758 ICMP_GET_TOS(*call), ICMP_GET_DONT_FRAGMENT(*call), 759 addr, (socklen_t) size); 760 761 free(addr); 762 icmp_seq++; 763 return rc; 764 765 case NET_ICMP_DEST_UNREACH: 766 rc = packet_translate_remote(phone_net, &packet, 767 IPC_GET_PACKET(*call)); 706 768 if (rc != EOK) 707 769 return rc; 708 return icmp_source_quench_msg_local(0, packet); 709 case NET_ICMP_TIME_EXCEEDED: 710 rc = packet_translate_remote(icmp_globals.net_phone, &packet, 711 IPC_GET_PACKET(call)); 770 771 return icmp_destination_unreachable(ICMP_GET_CODE(*call), 772 ICMP_GET_MTU(*call), packet); 773 774 case NET_ICMP_SOURCE_QUENCH: 775 rc = packet_translate_remote(phone_net, &packet, 776 IPC_GET_PACKET(*call)); 712 777 if (rc != EOK) 713 778 return rc; 714 return icmp_time_exceeded_msg_local(0, ICMP_GET_CODE(call), 715 packet); 716 case NET_ICMP_PARAMETERPROB: 717 rc = packet_translate_remote(icmp_globals.net_phone, &packet, 718 IPC_GET_PACKET(call)); 779 780 return icmp_source_quench(packet); 781 782 case NET_ICMP_TIME_EXCEEDED: 783 rc = packet_translate_remote(phone_net, &packet, 784 IPC_GET_PACKET(*call)); 719 785 if (rc != EOK) 720 786 return rc; 721 return icmp_parameter_problem_msg_local(0, ICMP_GET_CODE(call), 722 ICMP_GET_POINTER(call), packet); 723 default: 724 return ENOTSUP; 725 } 726 } 727 728 /** Assigns a new identifier for the connection. 729 * 730 * Fills the echo data parameter with the assigned values. 731 * 732 * @param[in,out] echo_data The echo data to be bound. 733 * @return Index of the inserted echo data. 734 * @return EBADMEM if the echo_data parameter is NULL. 735 * @return ENOTCONN if no free identifier have been found. 736 */ 737 static int icmp_bind_free_id(icmp_echo_t *echo_data) 738 { 739 icmp_param_t index; 740 741 if (!echo_data) 742 return EBADMEM; 743 744 /* From the last used one */ 745 index = icmp_globals.last_used_id; 746 do { 747 index++; 748 /* til the range end */ 749 if (index >= ICMP_FREE_IDS_END) { 750 /* start from the range beginning */ 751 index = ICMP_FREE_IDS_START - 1; 752 do { 753 index++; 754 /* til the last used one */ 755 if (index >= icmp_globals.last_used_id) { 756 /* none found */ 757 return ENOTCONN; 758 } 759 } while(icmp_echo_data_find(&icmp_globals.echo_data, 760 index) != NULL); 761 762 /* Found, break immediately */ 763 break; 764 } 765 } while (icmp_echo_data_find(&icmp_globals.echo_data, index) != NULL); 766 767 echo_data->identifier = index; 768 echo_data->sequence_number = 0; 769 770 return icmp_echo_data_add(&icmp_globals.echo_data, index, echo_data); 771 } 772 773 /** Processes the client messages. 774 * 775 * Remembers the assigned identifier and sequence numbers. 776 * Runs until the client module disconnects. 777 * 778 * @param[in] callid The message identifier. 779 * @param[in] call The message parameters. 780 * @return EOK. 781 * 782 * @see icmp_interface.h 783 * @see icmp_api.h 784 */ 785 static int icmp_process_client_messages(ipc_callid_t callid, ipc_call_t call) 786 { 787 bool keep_on_going = true; 788 ipc_call_t answer; 789 int answer_count; 790 size_t length; 791 struct sockaddr *addr; 792 ipc_callid_t data_callid; 793 icmp_echo_t *echo_data; 794 int rc = EOK; 795 796 /* 797 * Accept the connection 798 * - Answer the first NET_ICMP_INIT call. 799 */ 800 answer_count = 0; 801 802 echo_data = (icmp_echo_t *) malloc(sizeof(*echo_data)); 803 if (!echo_data) 804 return ENOMEM; 805 806 /* Assign a new identifier */ 807 fibril_rwlock_write_lock(&icmp_globals.lock); 808 rc = icmp_bind_free_id(echo_data); 809 fibril_rwlock_write_unlock(&icmp_globals.lock); 810 if (rc < 0) { 811 free(echo_data); 812 return rc; 813 } 814 815 while (keep_on_going) { 816 /* Answer the call */ 817 answer_call(callid, rc, &answer, answer_count); 818 819 /* Refresh data */ 820 refresh_answer(&answer, &answer_count); 821 822 /* Get the next call */ 823 callid = async_get_call(&call); 824 825 /* Process the call */ 826 switch (IPC_GET_METHOD(call)) { 827 case IPC_M_PHONE_HUNGUP: 828 keep_on_going = false; 829 rc = EHANGUP; 830 break; 831 832 case NET_ICMP_ECHO: 833 if (!async_data_write_receive(&data_callid, &length)) { 834 rc = EINVAL; 835 break; 836 } 837 838 addr = malloc(length); 839 if (!addr) { 840 rc = ENOMEM; 841 break; 842 } 843 844 rc = async_data_write_finalize(data_callid, addr, 845 length); 846 if (rc != EOK) { 847 free(addr); 848 break; 849 } 850 851 fibril_rwlock_write_lock(&icmp_globals.lock); 852 rc = icmp_echo(echo_data->identifier, 853 echo_data->sequence_number, ICMP_GET_SIZE(call), 854 ICMP_GET_TIMEOUT(call), ICMP_GET_TTL(call), 855 ICMP_GET_TOS(call), ICMP_GET_DONT_FRAGMENT(call), 856 addr, (socklen_t) length); 857 fibril_rwlock_write_unlock(&icmp_globals.lock); 858 859 free(addr); 860 861 if (echo_data->sequence_number < UINT16_MAX) 862 echo_data->sequence_number++; 863 else 864 echo_data->sequence_number = 0; 865 866 break; 867 868 default: 869 rc = icmp_process_message(&call); 870 } 871 872 } 873 874 /* Release the identifier */ 875 fibril_rwlock_write_lock(&icmp_globals.lock); 876 icmp_echo_data_exclude(&icmp_globals.echo_data, echo_data->identifier); 877 fibril_rwlock_write_unlock(&icmp_globals.lock); 878 879 return rc; 880 } 881 882 /** Processes the ICMP message. 883 * 884 * @param[in] callid The message identifier. 885 * @param[in] call The message parameters. 886 * @param[out] answer The message answer parameters. 887 * @param[out] answer_count The last parameter for the actual answer in the 888 * answer parameter. 889 * @return EOK on success. 890 * @return ENOTSUP if the message is not known. 891 * 892 * @see icmp_interface.h 893 * @see IS_NET_ICMP_MESSAGE() 894 */ 895 int icmp_message_standalone(ipc_callid_t callid, ipc_call_t *call, 896 ipc_call_t *answer, int *answer_count) 897 { 898 packet_t *packet; 899 int rc; 900 901 *answer_count = 0; 902 switch (IPC_GET_METHOD(*call)) { 903 case NET_TL_RECEIVED: 904 rc = packet_translate_remote(icmp_globals.net_phone, &packet, 905 IPC_GET_PACKET(call)); 787 788 return icmp_time_exceeded(ICMP_GET_CODE(*call), packet); 789 790 case NET_ICMP_PARAMETERPROB: 791 rc = packet_translate_remote(phone_net, &packet, 792 IPC_GET_PACKET(*call)); 906 793 if (rc != EOK) 907 794 return rc; 908 return icmp_received_msg_local(IPC_GET_DEVICE(call), packet, 909 SERVICE_ICMP, IPC_GET_ERROR(call)); 910 911 case NET_ICMP_INIT: 912 return icmp_process_client_messages(callid, * call); 913 914 default: 915 return icmp_process_message(call); 916 } 917 795 796 return icmp_parameter_problem(ICMP_GET_CODE(*call), 797 ICMP_GET_POINTER(*call), packet); 798 } 799 918 800 return ENOTSUP; 919 801 } 920 802 921 922 /** Default thread for new connections.923 *924 * @param[in] iid The initial message identifier.925 * @param[in] icall The initial message call structure.926 *927 */928 static void tl_client_connection(ipc_callid_t iid, ipc_call_t *icall)929 {930 /*931 * Accept the connection932 * - Answer the first IPC_M_CONNECT_ME_TO call.933 */934 ipc_answer_0(iid, EOK);935 936 while (true) {937 ipc_call_t answer;938 int answer_count;939 940 /* Clear the answer structure */941 refresh_answer(&answer, &answer_count);942 943 /* Fetch the next message */944 ipc_call_t call;945 ipc_callid_t callid = async_get_call(&call);946 947 /* Process the message */948 int res = tl_module_message_standalone(callid, &call, &answer,949 &answer_count);950 951 /*952 * End if told to either by the message or the processing953 * result.954 */955 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||956 (res == EHANGUP))957 return;958 959 /* Answer the message */960 answer_call(callid, res, &answer, answer_count);961 }962 }963 964 /** Starts the module.965 *966 * @return EOK on success.967 * @return Other error codes as defined for each specific module968 * start function.969 */970 803 int main(int argc, char *argv[]) 971 804 { 972 int rc;973 974 805 /* Start the module */ 975 rc = tl_module_start_standalone(tl_client_connection); 976 return rc; 806 return tl_module_start(SERVICE_ICMP); 977 807 } 978 808 979 809 /** @} 980 810 */ 981 -
uspace/srv/net/tl/tcp/Makefile
rcead2aa r357b5f5 34 34 35 35 SOURCES = \ 36 tcp.c \ 37 tcp_module.c 36 tcp.c 38 37 39 38 include $(USPACE_PREFIX)/Makefile.common -
uspace/srv/net/tl/tcp/tcp.c
rcead2aa r357b5f5 36 36 */ 37 37 38 #include "tcp.h"39 #include "tcp_header.h"40 #include "tcp_module.h"41 42 38 #include <assert.h> 43 39 #include <async.h> … … 68 64 #include <ip_interface.h> 69 65 #include <icmp_client.h> 70 #include <icmp_ interface.h>66 #include <icmp_remote.h> 71 67 #include <net_interface.h> 72 68 #include <socket_core.h> 73 69 #include <tl_common.h> 74 #include <tl_local.h> 75 #include <tl_interface.h> 70 #include <tl_remote.h> 71 #include <tl_skel.h> 72 73 #include "tcp.h" 74 #include "tcp_header.h" 76 75 77 76 /** TCP module name. */ 78 #define NAME "TCP protocol"77 #define NAME "tcp" 79 78 80 79 /** The TCP window default value. */ … … 154 153 155 154 /** Port map key. */ 156 char*key;155 uint8_t *key; 157 156 158 157 /** Port map key length. */ … … 205 204 static int tcp_queue_received_packet(socket_core_t *, tcp_socket_data_t *, 206 205 packet_t *, int, size_t); 206 static void tcp_queue_received_end_of_data(socket_core_t *socket); 207 207 208 208 static int tcp_received_msg(device_id_t, packet_t *, services_t, services_t); … … 219 219 /** TCP global data. */ 220 220 tcp_globals_t tcp_globals; 221 222 /** Initializes the TCP module.223 *224 * @param[in] client_connection The client connection processing function. The225 * module skeleton propagates its own one.226 * @return EOK on success.227 * @return ENOMEM if there is not enough memory left.228 */229 int tcp_initialize(async_client_conn_t client_connection)230 {231 int rc;232 233 assert(client_connection);234 235 fibril_rwlock_initialize(&tcp_globals.lock);236 fibril_rwlock_write_lock(&tcp_globals.lock);237 238 tcp_globals.icmp_phone = icmp_connect_module(SERVICE_ICMP,239 ICMP_CONNECT_TIMEOUT);240 tcp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_TCP,241 SERVICE_TCP, client_connection);242 if (tcp_globals.ip_phone < 0) {243 fibril_rwlock_write_unlock(&tcp_globals.lock);244 return tcp_globals.ip_phone;245 }246 247 rc = socket_ports_initialize(&tcp_globals.sockets);248 if (rc != EOK)249 goto out;250 251 rc = packet_dimensions_initialize(&tcp_globals.dimensions);252 if (rc != EOK) {253 socket_ports_destroy(&tcp_globals.sockets);254 goto out;255 }256 257 tcp_globals.last_used_port = TCP_FREE_PORTS_START - 1;258 259 out:260 fibril_rwlock_write_unlock(&tcp_globals.lock);261 return rc;262 }263 221 264 222 int tcp_received_msg(device_id_t device_id, packet_t *packet, … … 357 315 /* Find the destination socket */ 358 316 socket = socket_port_find(&tcp_globals.sockets, 359 ntohs(header->destination_port), ( const char*) src, addrlen);317 ntohs(header->destination_port), (uint8_t *) src, addrlen); 360 318 if (!socket) { 361 319 /* Find the listening destination socket */ 362 320 socket = socket_port_find(&tcp_globals.sockets, 363 ntohs(header->destination_port), SOCKET_MAP_KEY_LISTENING,364 0);321 ntohs(header->destination_port), 322 (uint8_t *) SOCKET_MAP_KEY_LISTENING, 0); 365 323 } 366 324 … … 453 411 454 412 has_error_service: 455 fibril_rwlock_ read_unlock(&tcp_globals.lock);413 fibril_rwlock_write_unlock(&tcp_globals.lock); 456 414 457 415 /* TODO error reporting/handling */ … … 504 462 size_t offset; 505 463 uint32_t new_sequence_number; 464 bool forced_ack; 506 465 int rc; 507 466 … … 512 471 assert(packet); 513 472 473 forced_ack = false; 474 514 475 new_sequence_number = ntohl(header->sequence_number); 515 476 old_incoming = socket_data->next_incoming; 516 477 517 if (header->finalize) 518 socket_data->fin_incoming = new_sequence_number; 478 if (header->finalize) { 479 socket_data->fin_incoming = new_sequence_number + 480 total_length - TCP_HEADER_LENGTH(header); 481 } 519 482 520 483 /* Trim begining if containing expected data */ … … 760 723 /* Release duplicite or restricted */ 761 724 pq_release_remote(tcp_globals.net_phone, packet_get_id(packet)); 762 } 763 764 /* Change state according to the acknowledging incoming fin */ 765 if (IS_IN_INTERVAL_OVERFLOW(old_incoming, socket_data->fin_incoming, 766 socket_data->next_incoming)) { 725 forced_ack = true; 726 } 727 728 /* If next in sequence is an incoming FIN */ 729 if (socket_data->next_incoming == socket_data->fin_incoming) { 730 /* Advance sequence number */ 731 socket_data->next_incoming += 1; 732 733 /* Handle FIN */ 767 734 switch (socket_data->state) { 768 735 case TCP_SOCKET_FIN_WAIT_1: … … 771 738 socket_data->state = TCP_SOCKET_CLOSING; 772 739 break; 773 /*case TCP_ESTABLISHED:*/ 740 case TCP_SOCKET_ESTABLISHED: 741 /* Queue end-of-data marker on the socket. */ 742 tcp_queue_received_end_of_data(socket); 743 socket_data->state = TCP_SOCKET_CLOSE_WAIT; 744 break; 774 745 default: 775 746 socket_data->state = TCP_SOCKET_CLOSE_WAIT; … … 779 750 780 751 packet = tcp_get_packets_to_send(socket, socket_data); 781 if (!packet ) {752 if (!packet && (socket_data->next_incoming != old_incoming || forced_ack)) { 782 753 /* Create the notification packet */ 783 754 rc = tcp_create_notification_packet(&packet, socket, … … 829 800 /* Notify the destination socket */ 830 801 async_msg_5(socket->phone, NET_SOCKET_RECEIVED, 831 ( ipcarg_t) socket->socket_id,802 (sysarg_t) socket->socket_id, 832 803 ((packet_dimension->content < socket_data->data_fragment_size) ? 833 804 packet_dimension->content : socket_data->data_fragment_size), 0, 0, 834 ( ipcarg_t) fragments);805 (sysarg_t) fragments); 835 806 836 807 return EOK; 808 } 809 810 /** Queue end-of-data marker on the socket. 811 * 812 * Next element in the sequence space is FIN. Queue end-of-data marker 813 * on the socket. 814 * 815 * @param socket Socket 816 */ 817 static void tcp_queue_received_end_of_data(socket_core_t *socket) 818 { 819 assert(socket != NULL); 820 821 /* Notify the destination socket */ 822 async_msg_5(socket->phone, NET_SOCKET_RECEIVED, 823 (sysarg_t) socket->socket_id, 824 0, 0, 0, 825 (sysarg_t) 0 /* 0 fragments == no more data */); 837 826 } 838 827 … … 966 955 /* Find the destination socket */ 967 956 listening_socket = socket_port_find(&tcp_globals.sockets, 968 listening_port, SOCKET_MAP_KEY_LISTENING, 0);957 listening_port, (uint8_t *) SOCKET_MAP_KEY_LISTENING, 0); 969 958 if (!listening_socket || 970 959 (listening_socket->socket_id != listening_socket_id)) { … … 990 979 991 980 rc = socket_port_add(&tcp_globals.sockets, listening_port, socket, 992 ( const char*) socket_data->addr, socket_data->addrlen);981 (uint8_t *) socket_data->addr, socket_data->addrlen); 993 982 assert(socket == socket_port_find(&tcp_globals.sockets, listening_port, 994 ( const char*) socket_data->addr, socket_data->addrlen));983 (uint8_t *) socket_data->addr, socket_data->addrlen)); 995 984 996 985 // rc = socket_bind_free_port(&tcp_globals.sockets, socket, … … 1090 1079 /* Notify the destination socket */ 1091 1080 async_msg_5(socket->phone, NET_SOCKET_ACCEPTED, 1092 ( ipcarg_t) listening_socket->socket_id,1081 (sysarg_t) listening_socket->socket_id, 1093 1082 socket_data->data_fragment_size, TCP_HEADER_SIZE, 1094 0, ( ipcarg_t) socket->socket_id);1083 0, (sysarg_t) socket->socket_id); 1095 1084 1096 1085 fibril_rwlock_write_unlock(socket_data->local_lock); … … 1215 1204 } 1216 1205 1206 /** Per-connection initialization 1207 * 1208 */ 1209 void tl_connection(void) 1210 { 1211 } 1212 1217 1213 /** Processes the TCP message. 1218 1214 * … … 1228 1224 * @see IS_NET_TCP_MESSAGE() 1229 1225 */ 1230 int 1231 tcp_message_standalone(ipc_callid_t callid, ipc_call_t *call, 1232 ipc_call_t *answer, int *answer_count) 1233 { 1234 packet_t *packet; 1235 int rc; 1236 1226 int tl_message(ipc_callid_t callid, ipc_call_t *call, 1227 ipc_call_t *answer, size_t *answer_count) 1228 { 1237 1229 assert(call); 1238 1230 assert(answer); … … 1240 1232 1241 1233 *answer_count = 0; 1242 switch (IPC_GET_METHOD(*call)) { 1243 case NET_TL_RECEIVED: 1244 // fibril_rwlock_read_lock(&tcp_globals.lock); 1245 rc = packet_translate_remote(tcp_globals.net_phone, &packet, 1246 IPC_GET_PACKET(call)); 1247 if (rc != EOK) { 1248 // fibril_rwlock_read_unlock(&tcp_globals.lock); 1249 return rc; 1250 } 1251 rc = tcp_received_msg(IPC_GET_DEVICE(call), packet, SERVICE_TCP, 1252 IPC_GET_ERROR(call)); 1253 // fibril_rwlock_read_unlock(&tcp_globals.lock); 1254 return rc; 1234 switch (IPC_GET_IMETHOD(*call)) { 1255 1235 case IPC_M_CONNECT_TO_ME: 1256 1236 return tcp_process_client_messages(callid, *call); … … 1291 1271 bool keep_on_going = true; 1292 1272 socket_cores_t local_sockets; 1293 int app_phone = IPC_GET_PHONE( &call);1273 int app_phone = IPC_GET_PHONE(call); 1294 1274 struct sockaddr *addr; 1295 1275 int socket_id; … … 1298 1278 fibril_rwlock_t lock; 1299 1279 ipc_call_t answer; 1300 int answer_count;1280 size_t answer_count; 1301 1281 tcp_socket_data_t *socket_data; 1302 1282 socket_core_t *socket; … … 1323 1303 1324 1304 /* Process the call */ 1325 switch (IPC_GET_ METHOD(call)) {1305 switch (IPC_GET_IMETHOD(call)) { 1326 1306 case IPC_M_PHONE_HUNGUP: 1327 1307 keep_on_going = false; … … 1365 1345 1366 1346 case NET_SOCKET_BIND: 1367 res = data_receive((void **) &addr, &addrlen); 1347 res = async_data_write_accept((void **) &addr, false, 1348 0, 0, 0, &addrlen); 1368 1349 if (res != EOK) 1369 1350 break; … … 1402 1383 1403 1384 case NET_SOCKET_CONNECT: 1404 res = data_receive((void **) &addr, &addrlen); 1385 res = async_data_write_accept((void **) &addr, false, 1386 0, 0, 0, &addrlen); 1405 1387 if (res != EOK) 1406 1388 break; … … 1453 1435 1454 1436 case NET_SOCKET_SENDTO: 1455 res = data_receive((void **) &addr, &addrlen); 1437 res = async_data_write_accept((void **) &addr, false, 1438 0, 0, 0, &addrlen); 1456 1439 if (res != EOK) 1457 1440 break; … … 1800 1783 fibril_rwlock_write_unlock(socket_data->local_lock); 1801 1784 1785 socket_data->state = TCP_SOCKET_SYN_SENT; 1786 1802 1787 /* Send the packet */ 1803 1788 printf("connecting %d\n", packet_get_id(packet)); … … 2072 2057 2073 2058 /* Copy the key */ 2074 operation_timeout->key = (( char*) operation_timeout) +2059 operation_timeout->key = ((uint8_t *) operation_timeout) + 2075 2060 sizeof(*operation_timeout); 2076 2061 operation_timeout->key_length = socket->key_length; … … 2082 2067 if (!fibril) { 2083 2068 free(operation_timeout); 2084 return EPARTY; /* FIXME: use another EC */ 2085 } 2069 return ENOMEM; 2070 } 2071 2086 2072 // fibril_mutex_lock(&socket_data->operation.mutex); 2087 2073 /* Start the timeout fibril */ … … 2206 2192 2207 2193 tcp_prepare_operation_header(socket, socket_data, header, 0, 0); 2208 rc = tcp_queue_packet(socket, socket_data, packet, 0);2194 rc = tcp_queue_packet(socket, socket_data, packet, total_length); 2209 2195 if (rc != EOK) 2210 2196 return rc; … … 2448 2434 } 2449 2435 2450 /** Default thread for new connections.2436 /** Process IPC messages from the IP module 2451 2437 * 2452 * @param[in] iid The initial message identifier.2453 * @param[in ] icall The initial message call structure.2438 * @param[in] iid Message identifier. 2439 * @param[in,out] icall Message parameters. 2454 2440 * 2455 2441 */ 2456 static void tl_client_connection(ipc_callid_t iid, ipc_call_t * icall) 2457 { 2458 /* 2459 * Accept the connection 2460 * - Answer the first IPC_M_CONNECT_ME_TO call. 2461 */ 2462 ipc_answer_0(iid, EOK); 2463 2442 static void tcp_receiver(ipc_callid_t iid, ipc_call_t *icall) 2443 { 2444 packet_t *packet; 2445 int rc; 2446 2464 2447 while (true) { 2465 ipc_call_t answer; 2466 int answer_count; 2467 2468 /* Clear the answer structure */ 2469 refresh_answer(&answer, &answer_count); 2470 2471 /* Fetch the next message */ 2472 ipc_call_t call; 2473 ipc_callid_t callid = async_get_call(&call); 2474 2475 /* Process the message */ 2476 int res = tl_module_message_standalone(callid, &call, &answer, 2477 &answer_count); 2478 2479 /* 2480 * End if told to either by the message or the processing 2481 * result. 2482 */ 2483 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || 2484 (res == EHANGUP)) 2485 return; 2486 2487 /* 2488 * Answer the message 2489 */ 2490 answer_call(callid, res, &answer, answer_count); 2491 } 2492 } 2493 2494 /** Starts the module. 2448 switch (IPC_GET_IMETHOD(*icall)) { 2449 case NET_TL_RECEIVED: 2450 rc = packet_translate_remote(tcp_globals.net_phone, &packet, 2451 IPC_GET_PACKET(*icall)); 2452 if (rc == EOK) 2453 rc = tcp_received_msg(IPC_GET_DEVICE(*icall), packet, 2454 SERVICE_TCP, IPC_GET_ERROR(*icall)); 2455 2456 ipc_answer_0(iid, (sysarg_t) rc); 2457 break; 2458 default: 2459 ipc_answer_0(iid, (sysarg_t) ENOTSUP); 2460 } 2461 2462 iid = async_get_call(icall); 2463 } 2464 } 2465 2466 /** Initialize the TCP module. 2495 2467 * 2496 * @return EOK on success. 2497 * @return Other error codes as defined for each specific module 2498 * start function. 2468 * @param[in] net_phone Network module phone. 2469 * 2470 * @return EOK on success. 2471 * @return ENOMEM if there is not enough memory left. 2472 * 2499 2473 */ 2500 int 2501 main(int argc, char *argv[]) 2502 { 2503 int rc; 2504 2505 rc = tl_module_start_standalone(tl_client_connection); 2474 int tl_initialize(int net_phone) 2475 { 2476 fibril_rwlock_initialize(&tcp_globals.lock); 2477 fibril_rwlock_write_lock(&tcp_globals.lock); 2478 2479 tcp_globals.net_phone = net_phone; 2480 2481 tcp_globals.icmp_phone = icmp_connect_module(ICMP_CONNECT_TIMEOUT); 2482 tcp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_TCP, 2483 SERVICE_TCP, tcp_receiver); 2484 if (tcp_globals.ip_phone < 0) { 2485 fibril_rwlock_write_unlock(&tcp_globals.lock); 2486 return tcp_globals.ip_phone; 2487 } 2488 2489 int rc = socket_ports_initialize(&tcp_globals.sockets); 2490 if (rc != EOK) 2491 goto out; 2492 2493 rc = packet_dimensions_initialize(&tcp_globals.dimensions); 2494 if (rc != EOK) { 2495 socket_ports_destroy(&tcp_globals.sockets); 2496 goto out; 2497 } 2498 2499 tcp_globals.last_used_port = TCP_FREE_PORTS_START - 1; 2500 2501 out: 2502 fibril_rwlock_write_unlock(&tcp_globals.lock); 2506 2503 return rc; 2504 } 2505 2506 int main(int argc, char *argv[]) 2507 { 2508 return tl_module_start(SERVICE_TCP); 2507 2509 } 2508 2510 -
uspace/srv/net/tl/udp/Makefile
rcead2aa r357b5f5 34 34 35 35 SOURCES = \ 36 udp.c \ 37 udp_module.c 36 udp.c 38 37 39 38 include $(USPACE_PREFIX)/Makefile.common -
uspace/srv/net/tl/udp/udp.c
rcead2aa r357b5f5 35 35 * @see udp.h 36 36 */ 37 38 #include "udp.h"39 #include "udp_header.h"40 #include "udp_module.h"41 37 42 38 #include <async.h> … … 65 61 #include <ip_interface.h> 66 62 #include <icmp_client.h> 67 #include <icmp_ interface.h>63 #include <icmp_remote.h> 68 64 #include <net_interface.h> 69 65 #include <socket_core.h> 70 66 #include <tl_common.h> 71 #include <tl_local.h> 72 #include <tl_interface.h> 67 #include <tl_remote.h> 68 #include <tl_skel.h> 69 70 #include "udp.h" 71 #include "udp_header.h" 73 72 74 73 /** UDP module name. */ 75 #define NAME "UDP protocol"74 #define NAME "udp" 76 75 77 76 /** Default UDP checksum computing. */ … … 92 91 /** UDP global data. */ 93 92 udp_globals_t udp_globals; 94 95 /** Initializes the UDP module.96 *97 * @param[in] client_connection The client connection processing function. The98 * module skeleton propagates its own one.99 * @return EOK on success.100 * @return ENOMEM if there is not enough memory left.101 */102 int udp_initialize(async_client_conn_t client_connection)103 {104 measured_string_t names[] = {105 {106 (char *) "UDP_CHECKSUM_COMPUTING",107 22108 },109 {110 (char *) "UDP_AUTOBINDING",111 15112 }113 };114 measured_string_t *configuration;115 size_t count = sizeof(names) / sizeof(measured_string_t);116 char *data;117 int rc;118 119 fibril_rwlock_initialize(&udp_globals.lock);120 fibril_rwlock_write_lock(&udp_globals.lock);121 122 udp_globals.icmp_phone = icmp_connect_module(SERVICE_ICMP,123 ICMP_CONNECT_TIMEOUT);124 125 udp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_UDP,126 SERVICE_UDP, client_connection);127 if (udp_globals.ip_phone < 0) {128 fibril_rwlock_write_unlock(&udp_globals.lock);129 return udp_globals.ip_phone;130 }131 132 /* Read default packet dimensions */133 rc = ip_packet_size_req(udp_globals.ip_phone, -1,134 &udp_globals.packet_dimension);135 if (rc != EOK) {136 fibril_rwlock_write_unlock(&udp_globals.lock);137 return rc;138 }139 140 rc = socket_ports_initialize(&udp_globals.sockets);141 if (rc != EOK) {142 fibril_rwlock_write_unlock(&udp_globals.lock);143 return rc;144 }145 146 rc = packet_dimensions_initialize(&udp_globals.dimensions);147 if (rc != EOK) {148 socket_ports_destroy(&udp_globals.sockets);149 fibril_rwlock_write_unlock(&udp_globals.lock);150 return rc;151 }152 153 udp_globals.packet_dimension.prefix += sizeof(udp_header_t);154 udp_globals.packet_dimension.content -= sizeof(udp_header_t);155 udp_globals.last_used_port = UDP_FREE_PORTS_START - 1;156 157 udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING;158 udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING;159 160 /* Get configuration */161 configuration = &names[0];162 rc = net_get_conf_req(udp_globals.net_phone, &configuration, count,163 &data);164 if (rc != EOK) {165 socket_ports_destroy(&udp_globals.sockets);166 fibril_rwlock_write_unlock(&udp_globals.lock);167 return rc;168 }169 170 if (configuration) {171 if (configuration[0].value)172 udp_globals.checksum_computing =173 (configuration[0].value[0] == 'y');174 175 if (configuration[1].value)176 udp_globals.autobinding =177 (configuration[1].value[0] == 'y');178 179 net_free_settings(configuration, data);180 }181 182 fibril_rwlock_write_unlock(&udp_globals.lock);183 return EOK;184 }185 93 186 94 /** Releases the packet and returns the result. … … 283 191 /* Find the destination socket */ 284 192 socket = socket_port_find(&udp_globals.sockets, 285 ntohs(header->destination_port),SOCKET_MAP_KEY_LISTENING, 0);193 ntohs(header->destination_port), (uint8_t *) SOCKET_MAP_KEY_LISTENING, 0); 286 194 if (!socket) { 287 195 if (tl_prepare_icmp_packet(udp_globals.net_phone, … … 393 301 fibril_rwlock_write_unlock(&udp_globals.lock); 394 302 async_msg_5(socket->phone, NET_SOCKET_RECEIVED, 395 ( ipcarg_t) socket->socket_id, packet_dimension->content, 0, 0,396 ( ipcarg_t) fragments);303 (sysarg_t) socket->socket_id, packet_dimension->content, 0, 0, 304 (sysarg_t) fragments); 397 305 398 306 return EOK; … … 424 332 425 333 return result; 334 } 335 336 /** Process IPC messages from the IP module 337 * 338 * @param[in] iid Message identifier. 339 * @param[in,out] icall Message parameters. 340 * 341 */ 342 static void udp_receiver(ipc_callid_t iid, ipc_call_t *icall) 343 { 344 packet_t *packet; 345 int rc; 346 347 while (true) { 348 switch (IPC_GET_IMETHOD(*icall)) { 349 case NET_TL_RECEIVED: 350 rc = packet_translate_remote(udp_globals.net_phone, &packet, 351 IPC_GET_PACKET(*icall)); 352 if (rc == EOK) 353 rc = udp_received_msg(IPC_GET_DEVICE(*icall), packet, 354 SERVICE_UDP, IPC_GET_ERROR(*icall)); 355 356 ipc_answer_0(iid, (sysarg_t) rc); 357 break; 358 default: 359 ipc_answer_0(iid, (sysarg_t) ENOTSUP); 360 } 361 362 iid = async_get_call(icall); 363 } 364 } 365 366 /** Initialize the UDP module. 367 * 368 * @param[in] net_phone Network module phone. 369 * 370 * @return EOK on success. 371 * @return ENOMEM if there is not enough memory left. 372 * 373 */ 374 int tl_initialize(int net_phone) 375 { 376 measured_string_t names[] = { 377 { 378 (uint8_t *) "UDP_CHECKSUM_COMPUTING", 379 22 380 }, 381 { 382 (uint8_t *) "UDP_AUTOBINDING", 383 15 384 } 385 }; 386 measured_string_t *configuration; 387 size_t count = sizeof(names) / sizeof(measured_string_t); 388 uint8_t *data; 389 390 fibril_rwlock_initialize(&udp_globals.lock); 391 fibril_rwlock_write_lock(&udp_globals.lock); 392 393 udp_globals.net_phone = net_phone; 394 395 udp_globals.icmp_phone = icmp_connect_module(ICMP_CONNECT_TIMEOUT); 396 397 udp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_UDP, 398 SERVICE_UDP, udp_receiver); 399 if (udp_globals.ip_phone < 0) { 400 fibril_rwlock_write_unlock(&udp_globals.lock); 401 return udp_globals.ip_phone; 402 } 403 404 /* Read default packet dimensions */ 405 int rc = ip_packet_size_req(udp_globals.ip_phone, -1, 406 &udp_globals.packet_dimension); 407 if (rc != EOK) { 408 fibril_rwlock_write_unlock(&udp_globals.lock); 409 return rc; 410 } 411 412 rc = socket_ports_initialize(&udp_globals.sockets); 413 if (rc != EOK) { 414 fibril_rwlock_write_unlock(&udp_globals.lock); 415 return rc; 416 } 417 418 rc = packet_dimensions_initialize(&udp_globals.dimensions); 419 if (rc != EOK) { 420 socket_ports_destroy(&udp_globals.sockets); 421 fibril_rwlock_write_unlock(&udp_globals.lock); 422 return rc; 423 } 424 425 udp_globals.packet_dimension.prefix += sizeof(udp_header_t); 426 udp_globals.packet_dimension.content -= sizeof(udp_header_t); 427 udp_globals.last_used_port = UDP_FREE_PORTS_START - 1; 428 429 udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING; 430 udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING; 431 432 /* Get configuration */ 433 configuration = &names[0]; 434 rc = net_get_conf_req(udp_globals.net_phone, &configuration, count, 435 &data); 436 if (rc != EOK) { 437 socket_ports_destroy(&udp_globals.sockets); 438 fibril_rwlock_write_unlock(&udp_globals.lock); 439 return rc; 440 } 441 442 if (configuration) { 443 if (configuration[0].value) 444 udp_globals.checksum_computing = 445 (configuration[0].value[0] == 'y'); 446 447 if (configuration[1].value) 448 udp_globals.autobinding = 449 (configuration[1].value[0] == 'y'); 450 451 net_free_settings(configuration, data); 452 } 453 454 fibril_rwlock_write_unlock(&udp_globals.lock); 455 return EOK; 426 456 } 427 457 … … 707 737 bool keep_on_going = true; 708 738 socket_cores_t local_sockets; 709 int app_phone = IPC_GET_PHONE( &call);739 int app_phone = IPC_GET_PHONE(call); 710 740 struct sockaddr *addr; 711 741 int socket_id; … … 713 743 size_t size; 714 744 ipc_call_t answer; 715 int answer_count;745 size_t answer_count; 716 746 packet_dimension_t *packet_dimension; 717 747 … … 742 772 743 773 /* Process the call */ 744 switch (IPC_GET_ METHOD(call)) {774 switch (IPC_GET_IMETHOD(call)) { 745 775 case IPC_M_PHONE_HUNGUP: 746 776 keep_on_going = false; … … 771 801 772 802 case NET_SOCKET_BIND: 773 res = data_receive((void **) &addr, &addrlen); 803 res = async_data_write_accept((void **) &addr, false, 804 0, 0, 0, &addrlen); 774 805 if (res != EOK) 775 806 break; … … 784 815 785 816 case NET_SOCKET_SENDTO: 786 res = data_receive((void **) &addr, &addrlen); 817 res = async_data_write_accept((void **) &addr, false, 818 0, 0, 0, &addrlen); 787 819 if (res != EOK) 788 820 break; … … 845 877 } 846 878 879 /** Per-connection initialization 880 * 881 */ 882 void tl_connection(void) 883 { 884 } 885 847 886 /** Processes the UDP message. 848 887 * … … 858 897 * @see IS_NET_UDP_MESSAGE() 859 898 */ 860 int udp_message_standalone(ipc_callid_t callid, ipc_call_t *call, 861 ipc_call_t *answer, int *answer_count) 862 { 863 packet_t *packet; 864 int rc; 865 899 int tl_message(ipc_callid_t callid, ipc_call_t *call, 900 ipc_call_t *answer, size_t *answer_count) 901 { 866 902 *answer_count = 0; 867 903 868 switch (IPC_GET_METHOD(*call)) { 869 case NET_TL_RECEIVED: 870 rc = packet_translate_remote(udp_globals.net_phone, &packet, 871 IPC_GET_PACKET(call)); 872 if (rc != EOK) 873 return rc; 874 return udp_received_msg(IPC_GET_DEVICE(call), packet, 875 SERVICE_UDP, IPC_GET_ERROR(call)); 904 switch (IPC_GET_IMETHOD(*call)) { 876 905 case IPC_M_CONNECT_TO_ME: 877 return udp_process_client_messages(callid, * call);906 return udp_process_client_messages(callid, *call); 878 907 } 879 908 … … 881 910 } 882 911 883 /** Default thread for new connections.884 *885 * @param[in] iid The initial message identifier.886 * @param[in] icall The initial message call structure.887 */888 static void tl_client_connection(ipc_callid_t iid, ipc_call_t * icall)889 {890 /*891 * Accept the connection892 * - Answer the first IPC_M_CONNECT_ME_TO call.893 */894 ipc_answer_0(iid, EOK);895 896 while (true) {897 ipc_call_t answer;898 int answer_count;899 900 /* Clear the answer structure */901 refresh_answer(&answer, &answer_count);902 903 /* Fetch the next message */904 ipc_call_t call;905 ipc_callid_t callid = async_get_call(&call);906 907 /* Process the message */908 int res = tl_module_message_standalone(callid, &call, &answer,909 &answer_count);910 911 /*912 * End if told to either by the message or the processing913 * result.914 */915 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||916 (res == EHANGUP))917 return;918 919 /* Answer the message */920 answer_call(callid, res, &answer, answer_count);921 }922 }923 924 /** Starts the module.925 *926 * @return EOK on success.927 * @return Other error codes as defined for each specific module928 * start function.929 */930 912 int main(int argc, char *argv[]) 931 913 { 932 int rc;933 934 914 /* Start the module */ 935 rc = tl_module_start_standalone(tl_client_connection); 936 return rc; 915 return tl_module_start(SERVICE_UDP); 937 916 } 938 917
Note:
See TracChangeset
for help on using the changeset viewer.
