Changeset 330df83 in mainline for uspace/srv/net/inetsrv/pdu.c
- Timestamp:
- 2013-07-19T20:42:57Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f4cbf9dd
- Parents:
- 8a8a08d1 (diff), cd18cd1 (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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/inetsrv/pdu.c
r8a8a08d1 r330df83 49 49 #include "pdu.h" 50 50 51 static FIBRIL_MUTEX_INITIALIZE(ip_ident_lock);52 static uint16_t ip_ident = 0;53 54 51 /** One's complement addition. 55 52 * … … 107 104 */ 108 105 int inet_pdu_encode(inet_packet_t *packet, addr32_t src, addr32_t dest, 109 size_t offs, size_t mtu, void **rdata, size_t *rsize, size_t *roffs)106 size_t offs, size_t mtu, void **rdata, size_t *rsize, size_t *roffs) 110 107 { 111 108 /* Upper bound for fragment offset field */ … … 117 114 118 115 size_t hdr_size = sizeof(ip_header_t); 119 120 size_t data_offs = ROUND_UP(hdr_size, 4); 121 116 if (hdr_size >= mtu) 117 return EINVAL; 118 119 assert(hdr_size % 4 == 0); 122 120 assert(offs % FRAG_OFFS_UNIT == 0); 123 121 assert(offs / FRAG_OFFS_UNIT < fragoff_limit); … … 125 123 /* Value for the fragment offset field */ 126 124 uint16_t foff = offs / FRAG_OFFS_UNIT; 127 128 if (hdr_size >= mtu)129 return EINVAL;130 125 131 126 /* Amount of space in the PDU available for payload */ … … 152 147 return ENOMEM; 153 148 154 /* Allocate identifier */155 fibril_mutex_lock(&ip_ident_lock);156 uint16_t ident = ++ip_ident;157 fibril_mutex_unlock(&ip_ident_lock);158 159 149 /* Encode header fields */ 160 150 ip_header_t *hdr = (ip_header_t *) data; … … 164 154 hdr->tos = packet->tos; 165 155 hdr->tot_len = host2uint16_t_be(size); 166 hdr->id = host2uint16_t_be( ident);156 hdr->id = host2uint16_t_be(packet->ident); 167 157 hdr->flags_foff = host2uint16_t_be(flags_foff); 168 158 hdr->ttl = packet->ttl; … … 178 168 179 169 /* Copy payload */ 180 memcpy((uint8_t *) data + data_offs, packet->data + offs, xfer_size);170 memcpy((uint8_t *) data + hdr_size, packet->data + offs, xfer_size); 181 171 182 172 *rdata = data; … … 202 192 * @param rdata Place to store pointer to allocated data buffer 203 193 * @param rsize Place to store size of allocated data buffer 204 * @param roffs Place to store offset of remaning data194 * @param roffs Place to store offset of remaning data 205 195 * 206 196 */ … … 208 198 size_t offs, size_t mtu, void **rdata, size_t *rsize, size_t *roffs) 209 199 { 200 /* IPv6 mandates a minimal MTU of 1280 bytes */ 201 if (mtu < 1280) 202 return ELIMIT; 203 210 204 /* Upper bound for fragment offset field */ 211 size_t fragoff_limit = 1 << ( FF_FRAGOFF_h - FF_FRAGOFF_l);205 size_t fragoff_limit = 1 << (OF_FRAGOFF_h - OF_FRAGOFF_l); 212 206 213 207 /* Verify that total size of datagram is within reasonable bounds */ … … 215 209 return ELIMIT; 216 210 217 size_t hdr_size = sizeof(ip6_header_t); 218 219 size_t data_offs = ROUND_UP(hdr_size, 4); 220 211 /* Determine whether we need the Fragment extension header */ 212 bool fragment; 213 if (offs == 0) 214 fragment = (packet->size + sizeof(ip6_header_t) > mtu); 215 else 216 fragment = true; 217 218 size_t hdr_size; 219 if (fragment) 220 hdr_size = sizeof(ip6_header_t) + sizeof(ip6_header_fragment_t); 221 else 222 hdr_size = sizeof(ip6_header_t); 223 224 if (hdr_size >= mtu) 225 return EINVAL; 226 227 assert(sizeof(ip6_header_t) % 8 == 0); 228 assert(hdr_size % 8 == 0); 221 229 assert(offs % FRAG_OFFS_UNIT == 0); 222 230 assert(offs / FRAG_OFFS_UNIT < fragoff_limit); 223 231 224 #if 0225 // FIXME TODO fragmentation226 227 232 /* Value for the fragment offset field */ 228 233 uint16_t foff = offs / FRAG_OFFS_UNIT; 229 #endif230 231 if (hdr_size >= mtu)232 return EINVAL;233 234 234 235 /* Amount of space in the PDU available for payload */ … … 245 246 size_t rem_offs = offs + xfer_size; 246 247 247 #if 0248 // FIXME TODO fragmentation249 250 248 /* Flags */ 251 uint16_t flags_foff = 252 (packet->df ? BIT_V(uint16_t, FF_FLAG_DF) : 0) + 253 (rem_offs < packet->size ? BIT_V(uint16_t, FF_FLAG_MF) : 0) + 254 (foff << FF_FRAGOFF_l); 255 #endif 249 uint16_t offsmf = 250 (rem_offs < packet->size ? BIT_V(uint16_t, OF_FLAG_M) : 0) + 251 (foff << OF_FRAGOFF_l); 256 252 257 253 void *data = calloc(size, 1); … … 259 255 return ENOMEM; 260 256 261 #if 0262 // FIXME TODO fragmentation263 264 /* Allocate identifier */265 fibril_mutex_lock(&ip_ident_lock);266 uint16_t ident = ++ip_ident;267 fibril_mutex_unlock(&ip_ident_lock);268 #endif269 270 257 /* Encode header fields */ 271 258 ip6_header_t *hdr6 = (ip6_header_t *) data; … … 273 260 hdr6->ver_tc = (6 << (VI_VERSION_l)); 274 261 memset(hdr6->tc_fl, 0, 3); 275 hdr6->payload_len = host2uint16_t_be(packet->size);276 hdr6->next = packet->proto;277 262 hdr6->hop_limit = packet->ttl; 278 263 … … 280 265 host2addr128_t_be(dest, hdr6->dest_addr); 281 266 267 /* Optionally encode Fragment extension header fields */ 268 if (fragment) { 269 assert(offsmf != 0); 270 271 hdr6->payload_len = host2uint16_t_be(packet->size + 272 sizeof(ip6_header_fragment_t)); 273 hdr6->next = IP6_NEXT_FRAGMENT; 274 275 ip6_header_fragment_t *hdr6f = (ip6_header_fragment_t *) 276 (hdr6 + 1); 277 278 hdr6f->next = packet->proto; 279 hdr6f->reserved = 0; 280 hdr6f->offsmf = host2uint16_t_be(offsmf); 281 hdr6f->id = host2uint32_t_be(packet->ident); 282 } else { 283 assert(offsmf == 0); 284 285 hdr6->payload_len = host2uint16_t_be(packet->size); 286 hdr6->next = packet->proto; 287 } 288 282 289 /* Copy payload */ 283 memcpy((uint8_t *) data + data_offs, packet->data + offs, xfer_size);290 memcpy((uint8_t *) data + hdr_size, packet->data + offs, xfer_size); 284 291 285 292 *rdata = data; … … 290 297 } 291 298 299 /** Decode IPv4 datagram 300 * 301 * @param data Serialized IPv4 datagram 302 * @param size Length of serialized IPv4 datagram 303 * @param packet IP datagram structure to be filled 304 * 305 * @return EOK on success 306 * @return EINVAL if the datagram is invalid or damaged 307 * @return ENOMEM if not enough memory 308 * 309 */ 292 310 int inet_pdu_decode(void *data, size_t size, inet_packet_t *packet) 293 311 { … … 353 371 } 354 372 373 /** Decode IPv6 datagram 374 * 375 * @param data Serialized IPv6 datagram 376 * @param size Length of serialized IPv6 datagram 377 * @param packet IP datagram structure to be filled 378 * 379 * @return EOK on success 380 * @return EINVAL if the datagram is invalid or damaged 381 * @return ENOMEM if not enough memory 382 * 383 */ 355 384 int inet_pdu_decode6(void *data, size_t size, inet_packet_t *packet) 356 385 { … … 373 402 size_t payload_len = uint16_t_be2host(hdr6->payload_len); 374 403 if (payload_len + sizeof(ip6_header_t) > size) { 375 log_msg(LOG_DEFAULT, LVL_DEBUG, " TotalLength = %zu > PDU size = %zu",404 log_msg(LOG_DEFAULT, LVL_DEBUG, "Payload Length = %zu > PDU size = %zu", 376 405 payload_len + sizeof(ip6_header_t), size); 377 406 return EINVAL; 378 407 } 379 408 380 #if 0 381 // FIXME TODO fragmentation 382 383 uint16_t ident = uint16_t_be2host(hdr->id); 384 uint16_t flags_foff = uint16_t_be2host(hdr->flags_foff); 385 uint16_t foff = BIT_RANGE_EXTRACT(uint16_t, FF_FRAGOFF_h, FF_FRAGOFF_l, 386 flags_foff); 387 #endif 388 389 /* XXX Checksum */ 409 uint32_t ident; 410 uint16_t offsmf; 411 uint16_t foff; 412 uint16_t next; 413 size_t data_offs = sizeof(ip6_header_t); 414 415 /* Fragment extension header */ 416 if (hdr6->next == IP6_NEXT_FRAGMENT) { 417 ip6_header_fragment_t *hdr6f = (ip6_header_fragment_t *) 418 (hdr6 + 1); 419 420 ident = uint32_t_be2host(hdr6f->id); 421 offsmf = uint16_t_be2host(hdr6f->offsmf); 422 foff = BIT_RANGE_EXTRACT(uint16_t, OF_FRAGOFF_h, OF_FRAGOFF_l, 423 offsmf); 424 next = hdr6f->next; 425 data_offs += sizeof(ip6_header_fragment_t); 426 payload_len -= sizeof(ip6_header_fragment_t); 427 } else { 428 ident = 0; 429 offsmf = 0; 430 foff = 0; 431 next = hdr6->next; 432 } 390 433 391 434 addr128_t src; … … 399 442 400 443 packet->tos = 0; 401 packet->proto = hdr6->next;444 packet->proto = next; 402 445 packet->ttl = hdr6->hop_limit; 403 404 #if 0405 // FIXME TODO fragmentation406 407 446 packet->ident = ident; 408 packet->df = (flags_foff & BIT_V(uint16_t, FF_FLAG_DF)) != 0; 409 packet->mf = (flags_foff & BIT_V(uint16_t, FF_FLAG_MF)) != 0; 447 448 packet->df = 1; 449 packet->mf = (offsmf & BIT_V(uint16_t, OF_FLAG_M)) != 0; 410 450 packet->offs = foff * FRAG_OFFS_UNIT; 411 412 /* XXX IP options */413 size_t data_offs = sizeof(uint32_t) *414 BIT_RANGE_EXTRACT(uint8_t, VI_IHL_h, VI_IHL_l, hdr->ver_ihl);415 #endif416 417 packet->ident = 0;418 packet->df = 0;419 packet->mf = 0;420 packet->offs = 0;421 451 422 452 packet->size = payload_len; … … 427 457 } 428 458 429 memcpy(packet->data, (uint8_t *) data + sizeof(ip6_header_t), packet->size);459 memcpy(packet->data, (uint8_t *) data + data_offs, packet->size); 430 460 431 461 return EOK; 432 462 } 433 463 464 /** Encode NDP packet 465 * 466 * @param ndp NDP packet structure to be serialized 467 * @param dgram IPv6 datagram structure to be filled 468 * 469 * @return EOK on success 470 * 471 */ 434 472 int ndp_pdu_encode(ndp_packet_t *ndp, inet_dgram_t *dgram) 435 473 { … … 464 502 addr48(ndp->sender_hw_addr, message->mac); 465 503 466 icmpv6_p seudo_headerphdr;504 icmpv6_phdr_t phdr; 467 505 468 506 host2addr128_t_be(ndp->sender_proto_addr, phdr.src_addr); … … 474 512 uint16_t cs_phdr = 475 513 inet_checksum_calc(INET_CHECKSUM_INIT, &phdr, 476 sizeof(icmpv6_p seudo_header));514 sizeof(icmpv6_phdr_t)); 477 515 478 516 uint16_t cs_all = inet_checksum_calc(cs_phdr, dgram->data, … … 484 522 } 485 523 524 /** Decode NDP packet 525 * 526 * @param dgram Incoming IPv6 datagram encapsulating NDP packet 527 * @param ndp NDP packet structure to be filled 528 * 529 * @return EOK on success 530 * @return EINVAL if the Datagram is invalid 531 * 532 */ 486 533 int ndp_pdu_decode(inet_dgram_t *dgram, ndp_packet_t *ndp) 487 534 {
Note:
See TracChangeset
for help on using the changeset viewer.