Changeset 330df83 in mainline for uspace/srv/net/inetsrv/pdu.c


Ignore:
Timestamp:
2013-07-19T20:42:57Z (12 years ago)
Author:
Manuele Conti <conti.ma@…>
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.
Message:

Merge with mainline changes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/net/inetsrv/pdu.c

    r8a8a08d1 r330df83  
    4949#include "pdu.h"
    5050
    51 static FIBRIL_MUTEX_INITIALIZE(ip_ident_lock);
    52 static uint16_t ip_ident = 0;
    53 
    5451/** One's complement addition.
    5552 *
     
    107104 */
    108105int 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)
    110107{
    111108        /* Upper bound for fragment offset field */
     
    117114       
    118115        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);
    122120        assert(offs % FRAG_OFFS_UNIT == 0);
    123121        assert(offs / FRAG_OFFS_UNIT < fragoff_limit);
     
    125123        /* Value for the fragment offset field */
    126124        uint16_t foff = offs / FRAG_OFFS_UNIT;
    127        
    128         if (hdr_size >= mtu)
    129                 return EINVAL;
    130125       
    131126        /* Amount of space in the PDU available for payload */
     
    152147                return ENOMEM;
    153148       
    154         /* Allocate identifier */
    155         fibril_mutex_lock(&ip_ident_lock);
    156         uint16_t ident = ++ip_ident;
    157         fibril_mutex_unlock(&ip_ident_lock);
    158        
    159149        /* Encode header fields */
    160150        ip_header_t *hdr = (ip_header_t *) data;
     
    164154        hdr->tos = packet->tos;
    165155        hdr->tot_len = host2uint16_t_be(size);
    166         hdr->id = host2uint16_t_be(ident);
     156        hdr->id = host2uint16_t_be(packet->ident);
    167157        hdr->flags_foff = host2uint16_t_be(flags_foff);
    168158        hdr->ttl = packet->ttl;
     
    178168       
    179169        /* 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);
    181171       
    182172        *rdata = data;
     
    202192 * @param rdata  Place to store pointer to allocated data buffer
    203193 * @param rsize  Place to store size of allocated data buffer
    204  * @param roffs Place to store offset of remaning data
     194 * @param roffs  Place to store offset of remaning data
    205195 *
    206196 */
     
    208198    size_t offs, size_t mtu, void **rdata, size_t *rsize, size_t *roffs)
    209199{
     200        /* IPv6 mandates a minimal MTU of 1280 bytes */
     201        if (mtu < 1280)
     202                return ELIMIT;
     203       
    210204        /* 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);
    212206       
    213207        /* Verify that total size of datagram is within reasonable bounds */
     
    215209                return ELIMIT;
    216210       
    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);
    221229        assert(offs % FRAG_OFFS_UNIT == 0);
    222230        assert(offs / FRAG_OFFS_UNIT < fragoff_limit);
    223231       
    224 #if 0
    225         // FIXME TODO fragmentation
    226        
    227232        /* Value for the fragment offset field */
    228233        uint16_t foff = offs / FRAG_OFFS_UNIT;
    229 #endif
    230        
    231         if (hdr_size >= mtu)
    232                 return EINVAL;
    233234       
    234235        /* Amount of space in the PDU available for payload */
     
    245246        size_t rem_offs = offs + xfer_size;
    246247       
    247 #if 0
    248         // FIXME TODO fragmentation
    249        
    250248        /* 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);
    256252       
    257253        void *data = calloc(size, 1);
     
    259255                return ENOMEM;
    260256       
    261 #if 0
    262         // FIXME TODO fragmentation
    263        
    264         /* Allocate identifier */
    265         fibril_mutex_lock(&ip_ident_lock);
    266         uint16_t ident = ++ip_ident;
    267         fibril_mutex_unlock(&ip_ident_lock);
    268 #endif
    269        
    270257        /* Encode header fields */
    271258        ip6_header_t *hdr6 = (ip6_header_t *) data;
     
    273260        hdr6->ver_tc = (6 << (VI_VERSION_l));
    274261        memset(hdr6->tc_fl, 0, 3);
    275         hdr6->payload_len = host2uint16_t_be(packet->size);
    276         hdr6->next = packet->proto;
    277262        hdr6->hop_limit = packet->ttl;
    278263       
     
    280265        host2addr128_t_be(dest, hdr6->dest_addr);
    281266       
     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       
    282289        /* 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);
    284291       
    285292        *rdata = data;
     
    290297}
    291298
     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 */
    292310int inet_pdu_decode(void *data, size_t size, inet_packet_t *packet)
    293311{
     
    353371}
    354372
     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 */
    355384int inet_pdu_decode6(void *data, size_t size, inet_packet_t *packet)
    356385{
     
    373402        size_t payload_len = uint16_t_be2host(hdr6->payload_len);
    374403        if (payload_len + sizeof(ip6_header_t) > size) {
    375                 log_msg(LOG_DEFAULT, LVL_DEBUG, "Total Length = %zu > PDU size = %zu",
     404                log_msg(LOG_DEFAULT, LVL_DEBUG, "Payload Length = %zu > PDU size = %zu",
    376405                    payload_len + sizeof(ip6_header_t), size);
    377406                return EINVAL;
    378407        }
    379408       
    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        }
    390433       
    391434        addr128_t src;
     
    399442       
    400443        packet->tos = 0;
    401         packet->proto = hdr6->next;
     444        packet->proto = next;
    402445        packet->ttl = hdr6->hop_limit;
    403        
    404 #if 0
    405         // FIXME TODO fragmentation
    406        
    407446        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;
    410450        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 #endif
    416        
    417         packet->ident = 0;
    418         packet->df = 0;
    419         packet->mf = 0;
    420         packet->offs = 0;
    421451       
    422452        packet->size = payload_len;
     
    427457        }
    428458       
    429         memcpy(packet->data, (uint8_t *) data + sizeof(ip6_header_t), packet->size);
     459        memcpy(packet->data, (uint8_t *) data + data_offs, packet->size);
    430460       
    431461        return EOK;
    432462}
    433463
     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 */
    434472int ndp_pdu_encode(ndp_packet_t *ndp, inet_dgram_t *dgram)
    435473{
     
    464502        addr48(ndp->sender_hw_addr, message->mac);
    465503       
    466         icmpv6_pseudo_header phdr;
     504        icmpv6_phdr_t phdr;
    467505       
    468506        host2addr128_t_be(ndp->sender_proto_addr, phdr.src_addr);
     
    474512        uint16_t cs_phdr =
    475513            inet_checksum_calc(INET_CHECKSUM_INIT, &phdr,
    476             sizeof(icmpv6_pseudo_header));
     514            sizeof(icmpv6_phdr_t));
    477515       
    478516        uint16_t cs_all = inet_checksum_calc(cs_phdr, dgram->data,
     
    484522}
    485523
     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 */
    486533int ndp_pdu_decode(inet_dgram_t *dgram, ndp_packet_t *ndp)
    487534{
Note: See TracChangeset for help on using the changeset viewer.