Ignore:
File:
1 edited

Legend:

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

    r1d24ad3 ra1a101d  
    4444#include <mem.h>
    4545#include <stdlib.h>
    46 #include <net/socket_codes.h>
     46
    4747#include "inetsrv.h"
    4848#include "inet_std.h"
     
    106106    void **rdata, size_t *rsize, size_t *roffs)
    107107{
    108         addr32_t src_v4;
    109         addr128_t src_v6;
    110         uint16_t src_af = inet_addr_get(&packet->src, &src_v4, &src_v6);
    111        
    112         addr32_t dest_v4;
    113         addr128_t dest_v6;
    114         uint16_t dest_af = inet_addr_get(&packet->dest, &dest_v4, &dest_v6);
    115        
    116         if (src_af != dest_af)
    117                 return EINVAL;
    118        
     108        void *data;
     109        size_t size;
     110        ip_header_t *hdr;
     111        size_t hdr_size;
     112        size_t data_offs;
     113        uint16_t chksum;
     114        uint16_t ident;
     115        uint16_t flags_foff;
     116        uint16_t foff;
     117        size_t fragoff_limit;
     118        size_t xfer_size;
     119        size_t spc_avail;
     120        size_t rem_offs;
     121
    119122        /* Upper bound for fragment offset field */
    120         size_t fragoff_limit = 1 << (FF_FRAGOFF_h - FF_FRAGOFF_l);
    121        
     123        fragoff_limit = 1 << (FF_FRAGOFF_h - FF_FRAGOFF_l);
     124
    122125        /* Verify that total size of datagram is within reasonable bounds */
    123126        if (offs + packet->size > FRAG_OFFS_UNIT * fragoff_limit)
    124127                return ELIMIT;
    125        
    126         size_t hdr_size;
    127        
    128         switch (src_af) {
    129         case AF_INET:
    130                 hdr_size = sizeof(ip_header_t);
    131                 break;
    132         case AF_INET6:
    133                 hdr_size = sizeof(ip6_header_t);
    134                 break;
    135         default:
    136                 assert(false);
    137         }
    138        
    139         size_t data_offs = ROUND_UP(hdr_size, 4);
    140        
     128
     129        hdr_size = sizeof(ip_header_t);
     130        data_offs = ROUND_UP(hdr_size, 4);
     131
    141132        assert(offs % FRAG_OFFS_UNIT == 0);
    142133        assert(offs / FRAG_OFFS_UNIT < fragoff_limit);
    143        
     134
    144135        /* Value for the fragment offset field */
    145         uint16_t foff = offs / FRAG_OFFS_UNIT;
    146        
     136        foff = offs / FRAG_OFFS_UNIT;
     137
    147138        if (hdr_size >= mtu)
    148139                return EINVAL;
    149        
     140
    150141        /* Amount of space in the PDU available for payload */
    151         size_t spc_avail = mtu - hdr_size;
     142        spc_avail = mtu - hdr_size;
    152143        spc_avail -= (spc_avail % FRAG_OFFS_UNIT);
    153        
     144
    154145        /* Amount of data (payload) to transfer */
    155         size_t xfer_size = min(packet->size - offs, spc_avail);
    156        
     146        xfer_size = min(packet->size - offs, spc_avail);
     147
    157148        /* Total PDU size */
    158         size_t size = hdr_size + xfer_size;
    159        
     149        size = hdr_size + xfer_size;
     150
    160151        /* Offset of remaining payload */
    161         size_t rem_offs = offs + xfer_size;
    162        
     152        rem_offs = offs + xfer_size;
     153
    163154        /* Flags */
    164         uint16_t flags_foff =
     155        flags_foff =
    165156            (packet->df ? BIT_V(uint16_t, FF_FLAG_DF) : 0) +
    166157            (rem_offs < packet->size ? BIT_V(uint16_t, FF_FLAG_MF) : 0) +
    167158            (foff << FF_FRAGOFF_l);
    168        
    169         void *data = calloc(size, 1);
     159
     160        data = calloc(size, 1);
    170161        if (data == NULL)
    171162                return ENOMEM;
    172        
     163
    173164        /* Allocate identifier */
    174165        fibril_mutex_lock(&ip_ident_lock);
    175         uint16_t ident = ++ip_ident;
     166        ident = ++ip_ident;
    176167        fibril_mutex_unlock(&ip_ident_lock);
    177        
     168
    178169        /* Encode header fields */
    179         ip_header_t *hdr;
    180         ip6_header_t *hdr6;
    181        
    182         switch (src_af) {
    183         case AF_INET:
    184                 hdr = (ip_header_t *) data;
    185                
    186                 hdr->ver_ihl =
    187                     (4 << VI_VERSION_l) | (hdr_size / sizeof(uint32_t));
    188                 hdr->tos = packet->tos;
    189                 hdr->tot_len = host2uint16_t_be(size);
    190                 hdr->id = host2uint16_t_be(ident);
    191                 hdr->flags_foff = host2uint16_t_be(flags_foff);
    192                 hdr->ttl = packet->ttl;
    193                 hdr->proto = packet->proto;
    194                 hdr->chksum = 0;
    195                 hdr->src_addr = host2uint32_t_be(src_v4);
    196                 hdr->dest_addr = host2uint32_t_be(dest_v4);
    197                
    198                 /* Compute checksum */
    199                 uint16_t chksum = inet_checksum_calc(INET_CHECKSUM_INIT,
    200                     (void *) hdr, hdr_size);
    201                 hdr->chksum = host2uint16_t_be(chksum);
    202                
    203                 break;
    204         case AF_INET6:
    205                 // TODO FIXME: fragmentation
    206                
    207                 hdr6 = (ip6_header_t *) data;
    208                
    209                 hdr6->ver_tc = (6 << (VI_VERSION_l));
    210                 memset(hdr6->tc_fl, 0, 3);
    211                 hdr6->payload_len = host2uint16_t_be(packet->size);
    212                 hdr6->next = packet->proto;
    213                 hdr6->hop_limit = packet->ttl;
    214                
    215                 host2addr128_t_be(src_v6, hdr6->src_addr);
    216                 host2addr128_t_be(dest_v6, hdr6->dest_addr);
    217                
    218                 break;
    219         default:
    220                 assert(false);
    221         }
    222        
     170        hdr = (ip_header_t *)data;
     171        hdr->ver_ihl = (4 << VI_VERSION_l) | (hdr_size / sizeof(uint32_t));
     172        hdr->tos = packet->tos;
     173        hdr->tot_len = host2uint16_t_be(size);
     174        hdr->id = host2uint16_t_be(ident);
     175        hdr->flags_foff = host2uint16_t_be(flags_foff);
     176        hdr->ttl = packet->ttl;
     177        hdr->proto = packet->proto;
     178        hdr->chksum = 0;
     179        hdr->src_addr = host2uint32_t_be(packet->src.ipv4);
     180        hdr->dest_addr = host2uint32_t_be(packet->dest.ipv4);
     181
     182        /* Compute checksum */
     183        chksum = inet_checksum_calc(INET_CHECKSUM_INIT, (void *)hdr, hdr_size);
     184        hdr->chksum = host2uint16_t_be(chksum);
     185
    223186        /* Copy payload */
    224         memcpy((uint8_t *) data + data_offs, packet->data + offs, xfer_size);
    225        
     187        memcpy((uint8_t *)data + data_offs, packet->data + offs, xfer_size);
     188
    226189        *rdata = data;
    227190        *rsize = size;
    228191        *roffs = rem_offs;
    229        
     192
    230193        return EOK;
    231194}
     
    233196int inet_pdu_decode(void *data, size_t size, inet_packet_t *packet)
    234197{
     198        ip_header_t *hdr;
     199        size_t tot_len;
     200        size_t data_offs;
     201        uint8_t version;
     202        uint16_t ident;
     203        uint16_t flags_foff;
     204        uint16_t foff;
     205
    235206        log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_pdu_decode()");
    236        
     207
    237208        if (size < sizeof(ip_header_t)) {
    238209                log_msg(LOG_DEFAULT, LVL_DEBUG, "PDU too short (%zu)", size);
    239210                return EINVAL;
    240211        }
    241        
    242         ip_header_t *hdr = (ip_header_t *) data;
    243        
    244         uint8_t version = BIT_RANGE_EXTRACT(uint8_t, VI_VERSION_h,
    245             VI_VERSION_l, hdr->ver_ihl);
     212
     213        hdr = (ip_header_t *)data;
     214
     215        version = BIT_RANGE_EXTRACT(uint8_t, VI_VERSION_h, VI_VERSION_l,
     216            hdr->ver_ihl);
    246217        if (version != 4) {
    247218                log_msg(LOG_DEFAULT, LVL_DEBUG, "Version (%d) != 4", version);
    248219                return EINVAL;
    249220        }
    250        
    251         size_t tot_len = uint16_t_be2host(hdr->tot_len);
     221
     222        tot_len = uint16_t_be2host(hdr->tot_len);
    252223        if (tot_len < sizeof(ip_header_t)) {
    253224                log_msg(LOG_DEFAULT, LVL_DEBUG, "Total Length too small (%zu)", tot_len);
    254225                return EINVAL;
    255226        }
    256        
     227
    257228        if (tot_len > size) {
    258229                log_msg(LOG_DEFAULT, LVL_DEBUG, "Total Length = %zu > PDU size = %zu",
     
    260231                return EINVAL;
    261232        }
    262        
    263         uint16_t ident = uint16_t_be2host(hdr->id);
    264         uint16_t flags_foff = uint16_t_be2host(hdr->flags_foff);
    265         uint16_t foff = BIT_RANGE_EXTRACT(uint16_t, FF_FRAGOFF_h, FF_FRAGOFF_l,
     233
     234        ident = uint16_t_be2host(hdr->id);
     235        flags_foff = uint16_t_be2host(hdr->flags_foff);
     236        foff = BIT_RANGE_EXTRACT(uint16_t, FF_FRAGOFF_h, FF_FRAGOFF_l,
    266237            flags_foff);
    267238        /* XXX Checksum */
    268        
    269         inet_addr_set(uint32_t_be2host(hdr->src_addr), &packet->src);
    270         inet_addr_set(uint32_t_be2host(hdr->dest_addr), &packet->dest);
     239
     240        packet->src.ipv4 = uint32_t_be2host(hdr->src_addr);
     241        packet->dest.ipv4 = uint32_t_be2host(hdr->dest_addr);
    271242        packet->tos = hdr->tos;
    272243        packet->proto = hdr->proto;
    273244        packet->ttl = hdr->ttl;
    274245        packet->ident = ident;
    275        
     246
    276247        packet->df = (flags_foff & BIT_V(uint16_t, FF_FLAG_DF)) != 0;
    277248        packet->mf = (flags_foff & BIT_V(uint16_t, FF_FLAG_MF)) != 0;
    278249        packet->offs = foff * FRAG_OFFS_UNIT;
    279        
     250
    280251        /* XXX IP options */
    281         size_t data_offs = sizeof(uint32_t) *
    282             BIT_RANGE_EXTRACT(uint8_t, VI_IHL_h, VI_IHL_l, hdr->ver_ihl);
    283        
     252        data_offs = sizeof(uint32_t) * BIT_RANGE_EXTRACT(uint8_t, VI_IHL_h,
     253            VI_IHL_l, hdr->ver_ihl);
     254
    284255        packet->size = tot_len - data_offs;
    285256        packet->data = calloc(packet->size, 1);
     
    288259                return ENOMEM;
    289260        }
    290        
    291         memcpy(packet->data, (uint8_t *) data + data_offs, packet->size);
    292        
     261
     262        memcpy(packet->data, (uint8_t *)data + data_offs, packet->size);
     263
    293264        return EOK;
    294265}
    295266
    296 int inet_pdu_decode6(void *data, size_t size, inet_packet_t *packet)
    297 {
    298         // FIXME TODO
    299         return ENOTSUP;
    300 }
    301 
    302267/** @}
    303268 */
Note: See TracChangeset for help on using the changeset viewer.