Changeset 1cc8b42 in mainline for uspace/srv/inet/pdu.c


Ignore:
Timestamp:
2012-02-27T20:34:58Z (12 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
f9d3dd4
Parents:
56792a2
Message:

Correct IP checksum and identification.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/inet/pdu.c

    r56792a2 r1cc8b42  
    3939#include <byteorder.h>
    4040#include <errno.h>
     41#include <fibril_synch.h>
    4142#include <io/log.h>
    4243#include <mem.h>
     
    4647#include "inet_std.h"
    4748#include "pdu.h"
     49
     50static FIBRIL_MUTEX_INITIALIZE(ip_ident_lock);
     51static uint16_t ip_ident = 0;
     52
     53#define INET_CHECKSUM_INIT 0xffff
     54
     55/** One's complement addition.
     56 *
     57 * Result is a + b + carry.
     58 */
     59static uint16_t inet_ocadd16(uint16_t a, uint16_t b)
     60{
     61        uint32_t s;
     62
     63        s = (uint32_t)a + (uint32_t)b;
     64        return (s & 0xffff) + (s >> 16);
     65}
     66
     67static uint16_t inet_checksum_calc(uint16_t ivalue, void *data, size_t size)
     68{
     69        uint16_t sum;
     70        uint16_t w;
     71        size_t words, i;
     72        uint8_t *bdata;
     73
     74        sum = ~ivalue;
     75        words = size / 2;
     76        bdata = (uint8_t *)data;
     77
     78        for (i = 0; i < words; i++) {
     79                w = ((uint16_t)bdata[2*i] << 8) | bdata[2*i + 1];
     80                sum = inet_ocadd16(sum, w);
     81        }
     82
     83        if (size % 2 != 0) {
     84                w = ((uint16_t)bdata[2*words] << 8);
     85                sum = inet_ocadd16(sum, w);
     86        }
     87
     88        return ~sum;
     89}
    4890
    4991/** Encode Internet PDU.
     
    5698        size_t hdr_size;
    5799        size_t data_offs;
     100        uint16_t chksum;
     101        uint16_t ident;
     102
     103        fibril_mutex_lock(&ip_ident_lock);
     104        ident = ++ip_ident;
     105        fibril_mutex_unlock(&ip_ident_lock);
    58106
    59107        hdr_size = sizeof(ip_header_t);
     
    69117        hdr->tos = packet->tos;
    70118        hdr->tot_len = host2uint16_t_be(size);
    71         hdr->id = host2uint16_t_be(42);
     119        hdr->id = host2uint16_t_be(ident);
    72120        hdr->flags_foff = host2uint16_t_be(packet->df ?
    73121            BIT_V(uint16_t, FF_FLAG_DF) : 0);
     
    78126        hdr->dest_addr = host2uint32_t_be(packet->dest.ipv4);
    79127
     128        chksum = inet_checksum_calc(INET_CHECKSUM_INIT, (void *)hdr, hdr_size);
     129        hdr->chksum = host2uint16_t_be(chksum);
     130
    80131        memcpy((uint8_t *)data + data_offs, packet->data, packet->size);
    81132
Note: See TracChangeset for help on using the changeset viewer.