Ignore:
File:
1 edited

Legend:

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

    ra1a101d r1d24ad3  
    4444#include <mem.h>
    4545#include <stdlib.h>
    46 
     46#include <net/socket_codes.h>
    4747#include "inetsrv.h"
    4848#include "inet_std.h"
     
    106106    void **rdata, size_t *rsize, size_t *roffs)
    107107{
    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 
     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       
    122119        /* Upper bound for fragment offset field */
    123         fragoff_limit = 1 << (FF_FRAGOFF_h - FF_FRAGOFF_l);
    124 
     120        size_t fragoff_limit = 1 << (FF_FRAGOFF_h - FF_FRAGOFF_l);
     121       
    125122        /* Verify that total size of datagram is within reasonable bounds */
    126123        if (offs + packet->size > FRAG_OFFS_UNIT * fragoff_limit)
    127124                return ELIMIT;
    128 
    129         hdr_size = sizeof(ip_header_t);
    130         data_offs = ROUND_UP(hdr_size, 4);
    131 
     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       
    132141        assert(offs % FRAG_OFFS_UNIT == 0);
    133142        assert(offs / FRAG_OFFS_UNIT < fragoff_limit);
    134 
     143       
    135144        /* Value for the fragment offset field */
    136         foff = offs / FRAG_OFFS_UNIT;
    137 
     145        uint16_t foff = offs / FRAG_OFFS_UNIT;
     146       
    138147        if (hdr_size >= mtu)
    139148                return EINVAL;
    140 
     149       
    141150        /* Amount of space in the PDU available for payload */
    142         spc_avail = mtu - hdr_size;
     151        size_t spc_avail = mtu - hdr_size;
    143152        spc_avail -= (spc_avail % FRAG_OFFS_UNIT);
    144 
     153       
    145154        /* Amount of data (payload) to transfer */
    146         xfer_size = min(packet->size - offs, spc_avail);
    147 
     155        size_t xfer_size = min(packet->size - offs, spc_avail);
     156       
    148157        /* Total PDU size */
    149         size = hdr_size + xfer_size;
    150 
     158        size_t size = hdr_size + xfer_size;
     159       
    151160        /* Offset of remaining payload */
    152         rem_offs = offs + xfer_size;
    153 
     161        size_t rem_offs = offs + xfer_size;
     162       
    154163        /* Flags */
    155         flags_foff =
     164        uint16_t flags_foff =
    156165            (packet->df ? BIT_V(uint16_t, FF_FLAG_DF) : 0) +
    157166            (rem_offs < packet->size ? BIT_V(uint16_t, FF_FLAG_MF) : 0) +
    158167            (foff << FF_FRAGOFF_l);
    159 
    160         data = calloc(size, 1);
     168       
     169        void *data = calloc(size, 1);
    161170        if (data == NULL)
    162171                return ENOMEM;
    163 
     172       
    164173        /* Allocate identifier */
    165174        fibril_mutex_lock(&ip_ident_lock);
    166         ident = ++ip_ident;
     175        uint16_t ident = ++ip_ident;
    167176        fibril_mutex_unlock(&ip_ident_lock);
    168 
     177       
    169178        /* Encode header fields */
    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 
     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       
    186223        /* Copy payload */
    187         memcpy((uint8_t *)data + data_offs, packet->data + offs, xfer_size);
    188 
     224        memcpy((uint8_t *) data + data_offs, packet->data + offs, xfer_size);
     225       
    189226        *rdata = data;
    190227        *rsize = size;
    191228        *roffs = rem_offs;
    192 
     229       
    193230        return EOK;
    194231}
     
    196233int inet_pdu_decode(void *data, size_t size, inet_packet_t *packet)
    197234{
    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 
    206235        log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_pdu_decode()");
    207 
     236       
    208237        if (size < sizeof(ip_header_t)) {
    209238                log_msg(LOG_DEFAULT, LVL_DEBUG, "PDU too short (%zu)", size);
    210239                return EINVAL;
    211240        }
    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);
     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);
    217246        if (version != 4) {
    218247                log_msg(LOG_DEFAULT, LVL_DEBUG, "Version (%d) != 4", version);
    219248                return EINVAL;
    220249        }
    221 
    222         tot_len = uint16_t_be2host(hdr->tot_len);
     250       
     251        size_t tot_len = uint16_t_be2host(hdr->tot_len);
    223252        if (tot_len < sizeof(ip_header_t)) {
    224253                log_msg(LOG_DEFAULT, LVL_DEBUG, "Total Length too small (%zu)", tot_len);
    225254                return EINVAL;
    226255        }
    227 
     256       
    228257        if (tot_len > size) {
    229258                log_msg(LOG_DEFAULT, LVL_DEBUG, "Total Length = %zu > PDU size = %zu",
     
    231260                return EINVAL;
    232261        }
    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,
     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,
    237266            flags_foff);
    238267        /* XXX Checksum */
    239 
    240         packet->src.ipv4 = uint32_t_be2host(hdr->src_addr);
    241         packet->dest.ipv4 = uint32_t_be2host(hdr->dest_addr);
     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);
    242271        packet->tos = hdr->tos;
    243272        packet->proto = hdr->proto;
    244273        packet->ttl = hdr->ttl;
    245274        packet->ident = ident;
    246 
     275       
    247276        packet->df = (flags_foff & BIT_V(uint16_t, FF_FLAG_DF)) != 0;
    248277        packet->mf = (flags_foff & BIT_V(uint16_t, FF_FLAG_MF)) != 0;
    249278        packet->offs = foff * FRAG_OFFS_UNIT;
    250 
     279       
    251280        /* XXX IP options */
    252         data_offs = sizeof(uint32_t) * BIT_RANGE_EXTRACT(uint8_t, VI_IHL_h,
    253             VI_IHL_l, hdr->ver_ihl);
    254 
     281        size_t data_offs = sizeof(uint32_t) *
     282            BIT_RANGE_EXTRACT(uint8_t, VI_IHL_h, VI_IHL_l, hdr->ver_ihl);
     283       
    255284        packet->size = tot_len - data_offs;
    256285        packet->data = calloc(packet->size, 1);
     
    259288                return ENOMEM;
    260289        }
    261 
    262         memcpy(packet->data, (uint8_t *)data + data_offs, packet->size);
    263 
     290       
     291        memcpy(packet->data, (uint8_t *) data + data_offs, packet->size);
     292       
    264293        return EOK;
    265294}
    266295
     296int inet_pdu_decode6(void *data, size_t size, inet_packet_t *packet)
     297{
     298        // FIXME TODO
     299        return ENOTSUP;
     300}
     301
    267302/** @}
    268303 */
Note: See TracChangeset for help on using the changeset viewer.