Giter Site home page Giter Site logo

picotcp's Introduction

picoTCP


Welcome to the one and only picoTCP repository.

picoTCP is a small-footprint, modular TCP/IP stack designed for embedded systems and the Internet of Things. It's actively being developed by Altran Intelligent Systems.

This code is released under the terms of GNU GPL v2 and GNU GPL v3. Some rights reserved. Other licenses may apply at the sole discretion of the copyright holders.

Learn how to use picoTCP in your project by going through the Getting Started guide on our GitHub wiki.

For more information send us an email or contact us on Twitter, Facebook or Reddit.

Wondering about picoTCP's code quality? Check our TiCS score


Continuous integration

Functional tests: Jenkins autotest - Unit tests : Jenkins unit tests - RFC compliance : Jenkins RFC Compliance - TICS quality : Jenkins TICS Coverity Scan Build status: Coverity Scan Build Status


It runs on (pretty much) everything

By keeping interfaces simple, the porting effort to new platforms and OSses are very low. To give you an indication: porting to a new platform can be done in 3 days or less, a new OS in a single day and if you really go crazy, you can do an initial port in a single evening. Different platforms, mean different compilers, that’s why we continuously compile our stack with a bunch of them. The following list shows some of the currently supported platforms, device drivers and compilers.

PicoTCP has been used with

Platforms picoTCP runs on: ARM Cortex-M series (ST Micro STM, NXP LPC, TI Stellaris, Freescale K64F), ARM ARM9-series (ST Micro STR9), Texas Instruments (MSP430), Microchip (PIC24, PIC32), Atmel (AVR 8bit), Linux (User space (TUN/TAP), Kernel space), Windows (User space (TAP))

Network devices picoTCP has worked with: BCM43362 (IEEE 802.11), MRF24WG (IEEE 802.11), LPC Ethernet ENET/EMAC (IEEE 802.3), Stellaris Ethernet (IEEE 802.3), STM32 Ethernet (IEEE 802.3), Wiznet W5100 (IEEE 802.3), USB CDC-ECM (CDC1.2), PPP, Virtual drivers ( TUN/TAP, VDE, Libpcap)

(RT)OSes picoTCP has been integrated into: No OS / Bare metal, FreeRTOS, mbed-RTOS, Frosted, linux / POSIX, MS DOS, MS Windows

Libraries picoTCP has been integrated with: wolfSSL, mbedTLS, Mongoose RESTful library, MicroPython

Compilers picoTCP compiles under: GCC, Clang, TCC, ARM-RCVT, IAR, XC-16, XC-32, MSP-GCC, AVR-GCC

Unfortunately we can't release all the code, a.o. because some parts depend on code or binaries that aren't GPL compatible, some parts were developed under a commercial contract, and some consist of very rough proof-of-concept code. If you want to know more about the availability under the commercial license, or the possibility of using our expert services for porting or driver development, feel free to contact us at [email protected].

Your favorite not in the list? Check out the wiki for information and examples on how to port picoTCP to a new platform!


Highly configurable and modular design

Features are developed as modules in picoTCP, allowing you to pick the features you want in your application. This results in the smallest possible stack that remains compliant with the internet standards. The schematic below provides an overview of all implemented protocols.

modular


Simple example

Preparations

This example uses Ubuntu 14.04. It works on other linux distibutions as well, though you may need to change some package names. See setting up the environment for some more info.

sudo apt-get install git check vde2 libvdeplug2-dev libpcap0.8-dev openvpn wireshark
git clone https://github.com/tass-belgium/picotcp
cd picotcp
make TAP=1
cd ..

The code

Then make a new directory, e.g. example, and create a file with the following content : //: # (The code below is pulled through our CI - please leave the code extractor comments intact!) //: # (code extractor start)

#include <time.h>
#include <pico_stack.h>
#include <pico_ipv4.h>
#include <pico_icmp4.h>
#include <pico_dev_tap.h>

#define NUM_PING 10

static int finished = 0;

/* gets called when the ping receives a reply, or encounters a problem */
void cb_ping(struct pico_icmp4_stats *s)
{
    char host[30];
    pico_ipv4_to_string(host, s->dst.addr);
    if (s->err == 0) {
        /* if all is well, print some pretty info */
        printf("%lu bytes from %s: icmp_req=%lu ttl=%lu time=%lu ms\n", s->size,
                host, s->seq, s->ttl, (long unsigned int)s->time);
        if (s->seq >= NUM_PING)
            finished = 1;
    } else {
        /* if something went wrong, print it and signal we want to stop */
        printf("PING %lu to %s: Error %d\n", s->seq, host, s->err);
        finished = 1;
    }
}


int main(void){
    int id;
    struct pico_ip4 ipaddr, netmask;
    struct pico_device* dev;

    /* initialise the stack. Super important if you don't want ugly stuff like
     * segfaults and such! */
    pico_stack_init();

    /* create the tap device */
    dev = pico_tap_create("tap0");
    if (!dev)
        return -1;

    /* assign the IP address to the tap interface */
    pico_string_to_ipv4("192.168.5.4", &ipaddr.addr);
    pico_string_to_ipv4("255.255.255.0", &netmask.addr);
    pico_ipv4_link_add(dev, ipaddr, netmask);

    printf("starting ping\n");
    id = pico_icmp4_ping("192.168.5.5", NUM_PING, 1000, 10000, 64, cb_ping);

    if (id == -1)
        return -1;

    /* keep running stack ticks to have picoTCP do its network magic. Note that
     * you can do other stuff here as well, or sleep a little. This will impact
     * your network performance, but everything should keep working (provided
     * you don't go overboard with the delays). */
    while (finished != 1)
    {
        usleep(1000);
        pico_stack_tick();
    }

    printf("finished !\n");
    return 0;
}

Building and running

Now we can compile this and link it, by running

gcc -c -o main.o -I../picotcp/build/include main.c
gcc -o main.elf main.o ../picotcp/build/lib/libpicotcp.a

Next we'll create a persistent tap device - a virtual network port. You don't need to repeat this each time, the device will exist until you reboot, or until you go sudo tunctl -d tap0

sudo tunctl -u <username>
sudo ifconfig tap0 192.168.5.5

Now, you should be able to run ./main.elf, and see output like

Protocol ethernet registered (layer: 2).
Protocol ipv4 registered (layer: 3).
Protocol ipv6 registered (layer: 3).
Protocol icmp4 registered (layer: 4).
Protocol icmp6 registered (layer: 4).
Protocol igmp registered (layer: 4).
Protocol udp registered (layer: 4).
Protocol tcp registered (layer: 4).
Device tap0 created.
Assigned ipv4 192.168.5.4 to device tap0
starting ping
64 bytes from 192.168.5.5: icmp_req=1 ttl=64 time=5 ms
64 bytes from 192.168.5.5: icmp_req=2 ttl=64 time=0 ms
64 bytes from 192.168.5.5: icmp_req=3 ttl=64 time=0 ms
64 bytes from 192.168.5.5: icmp_req=4 ttl=64 time=0 ms
64 bytes from 192.168.5.5: icmp_req=5 ttl=64 time=0 ms
64 bytes from 192.168.5.5: icmp_req=6 ttl=64 time=0 ms
64 bytes from 192.168.5.5: icmp_req=7 ttl=64 time=0 ms
64 bytes from 192.168.5.5: icmp_req=8 ttl=64 time=0 ms
64 bytes from 192.168.5.5: icmp_req=9 ttl=64 time=0 ms
64 bytes from 192.168.5.5: icmp_req=10 ttl=64 time=0 ms
finished !

While the application is running, you can also run

ping 192.168.5.4

to send pings in the other direction.

Investigating what happened

Run wireshark, and sniff the tap0 interface. Then run the ./main.elf again, and see what happens. You should see an ARP request from picoTCP to Linux, and a reply. After that you should see the ping requests and replies going back and forth.

Note, sometimes you may see lots of other stuff, IPv6 router sollicitations, various broadcasts, mDNS, DNS-SD, etc - this is your when your Linux notices the new network interface is up, and starts all sorts of discoveries. With the persistent TAP device, this usually only happens the first time you start the application. Start a new wireshark capture, and start the application again, it should be much cleaner now.

Now you could make some changes to the main.c file, and experiment a bit! Keep some statistics of your pings (max, min, avg time). Open a UDP socket, send some stuff to a netcat instance on your linux. Or build a rudimentary port scanner, see what ports are open on your machine.

This is just a very quick overview, more info can be found in our wiki.


Contributors

Contributors are very welcome. Report a bug, suggest a way to improve our documentation, or write some new code.

Note however that, before accepting your code, we would ask you to sign our Contributors License Agreement. Your code remains under your copyright, and will always be available under GPLv2 and GPLv3. However, this CLA enables us to use picoTCP (including code from external contributors like you) under other licenses, including our commercial license. By doing commercial projects, we can keep investing in the quality and features of picoTCP.

picotcp's People

Contributors

adxlarbi avatar alexandervp avatar bogdanlu avatar brechtdevlieger avatar brunochevalier avatar danielinux avatar dekumans avatar douwedb avatar frederikvs avatar gmacario avatar jelledevleeschouwer avatar jibi avatar jonasvanpelt avatar jorisverhaegen avatar jvzp avatar laurensmiers avatar ludolinux avatar matthiasvp avatar maximevince avatar mhagmajer avatar milanplatisa avatar mkrrr avatar phalox avatar q-thomas avatar sergegadeyne avatar simonmaes avatar swendrickx avatar tassdevon avatar tassinfo avatar toonst avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

picotcp's Issues

TCP queue limit does not take into account headers overhead

When filling up the TCP queues (based on rbtrees), the size of the headers is not taken into account, leading to a miscalculation of the memory currently used.

In particular, when using very small segments (e.g. no-nagle and frequent writes with a few bytes), the overhead can be 10x the payload of the queue, quickly consuming the memory available even if the socket size is correctly set. The socket space limit is never reached so the TCP memory pressure feedbacks are ineffective.

Suggested possible solutions:

  • Keep an additional counter in TCP queue that estimates the real amount of memory used for TCP transmission in either direction, something that relies on the frame->buffer_size rather than the payload size, and use this value to decide whether to accept a new incoming segment or to enqueue in pico_socket_sendto. The old counter (the current queue size based on the payloads) must be kept in order to allow underlying TCP metrics to work correctly.
  • Add a limit based on the number of packets (ZMidi workaround) - and let the user set a packet-based additional limit. The limit would sit in the pico_socket.h just after the byte-based limit.

The first solution would be preferred if possible because it requires less configuration on the user/integrator side.

@maximevince please add your comments below and feel free to reassign to @andreixc who is currently working on the module in case you don't have time to introduce a fix.

Sending a fragmented packet to a UDP socket is messing up receiving.

enabled ip fragmentation
created a udp socket that reads data from network
if you send a small packet (non fragmented) everything is fine.
if the packet is fragmented the socket goes nuts and the call to receiveFrom returns 1024 always (we are asking 1024 from it).

This the link to test (both mbed app and py/scapy script)
https://docs.google.com/a/tass.be/file/d/0B1BRitC1U1OeRWhuUFZiSWlxMEU/edit?usp=sharing
https://docs.google.com/a/tass.be/file/d/0B1BRitC1U1OeZkdWLWdJQTJSbXc/edit?usp=sharing

TCP doesn't wait for the other side to finish sending.

When running the robustness test, the following behavior was observed:

we send out FIN,ACK once
the other side hasn't finished sending out its data so it retransmits some frames
we reply with ICMP port unreachable.

Shouldn't we wait for the other side to send FIN,ACK and then delete the socket?
And until we get back the FIN,ACK back maybe we should resend it.
After this point, the next connection passes the 3whs then the board hangs.
I saved a log file.

TCP: connection state not closed after passive close when still data in receive buffer

Test setup:
client (linux) -> server (picotcp)

  1. Establish connection with a picotcp socket
  2. Send a data segment (that will be acknowledged by picotcp) but don't let the application that uses picotcp receive the data (picotcp keeps it in a buffer)
  3. close the connection with the linux client (linux sends FIN first)

After this testsequence the connection is still in the established state. This is not the case when picotcp has empty buffers.
The state is checked from within the socket callback function (mbed code: wakeup() from stack_endpoint.cpp)

Tick timer has a wrap-around every 49.71 days

This is issue 724 in internal redmine

System tick counter is 32 bit in size, and counts every ms..

2^32
/ 1000 --> ms
/ 3600 --> hours
/ 24 --> days

= 49.71 days.

I propose to increase the counter to an unsigned long long everywhere... That timer should never ever overflow.

After 3WHS no data was being sent out.

At the beginning this bug seemed to be directly connected with the mbed porting.
This is untrue.

After checking the queues I could observe that a frame that was supposed to go out
was getting stuck in the output queue.
This is the reason why when we were closing the socket nothing was being sent out (output queue still had frames).

The root cause is in pico_sockets_loop.
if (s != NULL)
break;
s is never NULL so this instruction breaks all the time.

The correct check here is the following:
if(index && index->keyValue)
break;

Route table can contain IP links that are no longer valid

SCENARIO:

  • route table contains two routes both using the same IP link
  • dhcp lease time expires and we go back to INIT state trying to get a new IP
  • we delete the IP link which inside calls a route delete (only once)

RESULT:

  • route table contains 1 route with a IP link no longer valid -> very dangerous as the memory allocated for the IP link has been freed

EXPECTED RESULT:

  • when deleting a IP link, all routes using that link should be deleted also

SOLUTION PROPOSED:

  • in IPv4 module, create a function pico_ipv4_route_del_iplink that will be called only by pico_ipv4_link_del. This function will search the Routes tree for any route using the IP link to be deleted, and will remove that route from the tree
  • update pico_ipv4_route_del to make it clear what parameters are actually needed: gateway and link params are not actually needed as the key to search in the Routes tree is netmask/ip address/metric in the order of importance

DNS client is leaking memory like a drain

Testing on the mbed board (using Pico_Robustness_Test).
The board hangs in like a minute or so.
Using the memory wrapper I could see that the stack is using ~17 Kb of ram.
Adding a counter to the trees I could observe that the UDPTable has ~20 connections left (hanging) in the tree.

Investigating...

TCP ZeroWindow is making the connection stall.

Discovered on mbed, when a Zero Window message comes, the application believes an error was received and closes the connection, which remains in an undefined state.

Maybe the application should be noticed it should try again later(via pico_err).

DHCP: PicoTCP keeps discovering when going back to 'init' state

When T1 (renewal-time) expires the client sends a DHCP Request (for renewal) to the leasing server. When the servers answers this request with a NAK, the DHCP client goes to the 'init' state. (see RFC2131 DHCP p34).

At this point the PicoTCP stack just sends DHCP Discover messages regardless DHCP Offer messages from the server.

Wireshark MBED: https://dl.dropboxusercontent.com/u/49342572/dhcp_mbed
As a comparison: Wireshark Linux stack: https://dl.dropboxusercontent.com/u/49342572/dhcp_linux_stack

TCP Zombie socket is not dropped

Letting an mbed test to run I could observe that there are cases when socket connections start to accumulate into memory.

The case when this happens is this one:
The mbed site sends out FIN,ACK
We reply with FIN,ACK
the socket remains in PICO_SOCKET_STATE_TCP_LAST_ACK and
the final ACK never comes and the deletion of the socket is never triggered.

Maybe when going to PICO_SOCKET_STATE_TCP_LAST_ACK we start a timer to make sure we drop the socket.

DHCP: client takes wrong IP

When a DHCP server offers the client an IP in the BOOTP yiaddr-field, the client sends a DHCP request with the offered IP in the yiaddr field.
When the server then ACK's, but he places a different IP in the yiaddr field now, the picotcp client assigns himself the IP that was originally offered.
(The ubuntu stack assigns himself the second one)

Commit 9315c3 breaks Pico-to-pico TCP connection

commit 9315c3e
Author: Andrei Carp <andrei@andrei-Vostro-3560.(none)>
Date: Tue Jul 16 08:50:50 2013 +0300

Philippe's patch that fixes #753. It doesn't fix #745, the connection still stalls.

The above introduces a regression in pico-to-pico TCP connection (the connection in autotest.sh stalls).

SYN flood produces HardFault

A SYN flood with only a changing source port (same ip's same destination port) produces a HardFault after 40 to 50 SYN packets.

HOWTO reproduce:

sudo ./run.sh --test denialofserviceattack testcases/hardware/tcp_connect_bench_dut.txt

TCP: RST|ACK after split-handshake attack?

Host A is a client not listening on any port. Host B is a malicious server listening on port 80.
A --- SYN ---> B
A <--- SYN --- B
A --- ???? ---> B
If host A is a picotcp instance, it will react with a RST|ACK segment.
If host A is a linux stack, it will react with SYN|ACK.
This is known as the split-handshake attack.
Is there an intentional reason why picotcp responds differently, or is this a bug?

Flooding TCP socket with small packets causes inactivity until the socket is dropped.

With the current implementation, if we open a tcp socket to a certain port and flood it with 1 byte packets, after ~50 packets the stack will report a zero window and the board will be unresponsive for a few minutes until the socket is dropped( the board doesn't enter hard fault, but it will not respond to any ping, arping etc).

After the memory is freed the stack is responsive again.
This is caused because we are not taking into consideration the overhead on this frames.

I don't think it correct that we report zero window after 50 packets (50 bytes used from a 4K buffer).

https://docs.google.com/a/tass.be/file/d/0B1BRitC1U1OeSHhzSlNzeGFvYUk/edit?usp=sharing

TCP retransmission timer causes illegal memory acces.

While working on the mbed board I could observe that from time to time the board is freezing.
The last function calls to the stack are :
tcp_retrans_timeout->tcp_add_retransmission_timer and the offending memory pointer is passed to pico_tree_first_node which will rise a Hard Fault.

Large fragmented packet sent to a TCP socket causes bad behavior

If you send a fragmented packet larger than the buffer size of the socket,
the packet remains blocked somewhere on ip layer or causes hard fault.

If the fragmented packet total size is lower than the socket buffer everything is fine.

Test and main can be found here.
https://docs.google.com/a/tass.be/file/d/0B1BRitC1U1OedHZKc1I5Zndxck0/edit?usp=sharing
https://docs.google.com/a/tass.be/file/d/0B1BRitC1U1Oedk5PUVFGNXVNLUk/edit?usp=sharing

DHCP client is leaking memory.

This was discovered on the mbed platform.
If you connect the board to a network where there is no DHCP server
for each xid generated and tried for 5 times 100 bytes of ram is lost.
Even if the server responds later on the previous memory is lost.

Each time Ethernet::connect is called it will call pico_dhcp_initiate_negotiation which will create a new cookie, but when it fails there is no way to cleanup the used memory.

Basically if you repeat the call to pico_dhcp_initiate_negotiation memory is leaked.

Mbed: NULL pointer accessed after SYN, SYNACK, RST

This is a bug within the mbed stack_endpoint.cpp.
When a valid RST TCP segment is received instaid of an ACK after an initial SYN, SYNACK, a hardfault occures due to NULL pointer access. When RST is received, the wakeup function (in stack_endpoint.cpp) gets an ev equal to PICO_SOCK_EV_ERR and pico_err is equal to PICO_ERR_ECONNRESET, thus the socket will be closed and ep->s will be accessed. But before that on line 66, ep is overwritten with ep_accepted (ep_accepted seems not NULL in the debugger, therefore the if statement on line 64 is executed). Because no socket was accepted before, ep (overwritten by ep_accepted) has a non valid socket field.
One line 82, pico_socket_close() will access the socket that is a NULL pointer.

Code snippet:

60 static void wakeup(uint16_t ev, struct pico_socket *s)
61 {
62   struct stack_endpoint *ep = (struct stack_endpoint *)s->priv;
63   if (!ep) {
64     if (ep_accepting != NULL) {
65         ptsock_dbg("Delivering %02x to accepting socket...\n", ev);
66         ep = ep_accepting;
67     } else {
68         ptsock_dbg("WAKEUP: socket not found! ev=%04x\n", ev);
69         return;
70     }
71   }
72   //if (((ep->revents & PICO_SOCK_EV_RD) == 0) && (ev & PICO_SOCK_EV_RD))
73   //  printf("Activating RD\n");
74   ep->revents |= ev;
75 
76   if(ev & PICO_SOCK_EV_ERR)
77   {
78     if(pico_err == PICO_ERR_ECONNRESET)
79     {
80       ptsock_dbg("Connection reset by peer...\n");
81       ep->state = SOCK_RESET_BY_PEER;
82       pico_socket_close(ep->s);
83       ep->s->priv = NULL;
84     }
85   }

Memory content of ep after line 66 has been executed:

screenshot from 2013-08-09 14 10 56

Autotest is failing with segmentation fault in the icmp/ping module

Internal redmine issue #672

The offending test is the one starting at line 52 in the script (DHCP test)

DHCP TEST
./test/autotest.sh: line 52: 10741 Segmentation fault ./build/test/picoapp.elf --barevde pic0:/tmp/pic0.ctl: -a dhcpclient:pic0

Core was generated by `./build/test/picoapp.elf --barevde pic0 /tmp/pic0.ctl  -a dhcpclient pic0'.

Program terminated with signal 11, Segmentation fault.
#0  0x08054d58 in cookie_compare (ka=0x9a63a20, kb=0x9a60020) at modules/pico_icmp4.c:175
175      if (a->id < b->id)
(gdb) p a
$1 = (struct pico_icmp4_ping_cookie *) 0x9a63a20
(gdb) p b
$2 = (struct pico_icmp4_ping_cookie *) 0x9a60020
(gdb) p a->id
$3 = 37312
(gdb) p b->id
Cannot access memory at address 0x9a60026
(gdb) up
#1  0x08067ea1 in pico_tree_findKey (tree=0x80704b4, key=0x9a60020) at stack/pico_tree.c:179
179          result = tree->compare(found->keyValue, key);
(gdb) p key
$4 = (void *) 0x9a60020
(gdb) l
174    
175      while(IS_NOT_LEAF(found))
176      {
177          int result;
178    
179          result = tree->compare(found->keyValue, key);
180          if(result == 0)
181             return found->keyValue;
182          else if(result < 0)
183           found = found->rightChild;
(gdb) up
#2  0x08054f7e in next_ping (now=4235431418, arg=0x9a60020) at modules/pico_icmp4.c:238
238        if(pico_tree_findKey(&Pings,cookie)){
(gdb) l
233    
234    static void next_ping(unsigned long now, void *arg)
235    {
236      struct pico_icmp4_ping_cookie *newcookie, *cookie = (struct pico_icmp4_ping_cookie *)arg;
237    
238        if(pico_tree_findKey(&Pings,cookie)){
239        if (cookie->seq < cookie->count) {
240          newcookie = pico_zalloc(sizeof(struct pico_icmp4_ping_cookie));
241          if (!newcookie)
242            return;
(gdb) p cookie
$5 = (struct pico_icmp4_ping_cookie *) 0x9a60020
(gdb) up
#3  0x08067483 in pico_check_timers () at stack/pico_stack.c:479
479        t->timer(pico_tick, t->arg);
(gdb) quit

Sending packets to a non-existing host (neither linux or picotcp) makes the stack respond with ICMP

PicoTCP has the following IP : 192.168.1.81
Linux has the following IP : 192.168.1.2

Linux sends a SYN towards 192.168.1.100 with a broadcast MAC.
PicoTCP gets the packet, starts sending ARPs on the network asking who has
192.168.1.100?
After it doesn't get an answer it replies to 192.168.1.2 with ICMP host unreachable.

At a first glance, this looks non-severe, but if I flood the network with these kind of packets PicoTCP will finish the memory and in the end kill the rtos.

To reproduce this init picoTCP either on linux or mbed and use the script to send packets:
https://docs.google.com/a/tass.be/file/d/0B1BRitC1U1OeeHhLNklVa2xGS1E/edit?usp=sharing

When Nagle is enabled, sending fails after 5120 bytes, due to a memory leak

If you run the test from task #719

This is the output:

Starting the receiving part...
Received : 1048576 bytes
Expected : 1048576 bytes
Receiving has passed...

Starting the sending part...
Send error
Sent : 5120 bytes
Expected : 1048576 bytes
Sending part of the test has failed. Exiting connection.
Socket closed!
Test was finished...

RB Tree, Leaf colour was being changed.

While I was digging through the stack I observed that the LEAF color was being changed to red which is not allowed!

The fix I suggest is in pico_tree.c :
fix_insert_collisions changed the while to this :
while(node->parent->color == RED && IS_NOT_LEAF(GRANPA(node)) )

TCP connection stalls under heavy packet loss

This is issue 745 on internal redmine.

See test test/python/tcpbench-delay.py

If loss is decreased, the test succeeds. If 5% as with the current script, the connection lingers indefinitely.

Find the cause and fix.

TCP: picotcp sends ICMP unreachable instaid of TCP RST

When you send a TCP segment to a closed port of picotcp (SYN, SYN|ACK, ACK, PSH|ACK,... except for RST), it responds with ICMP unreachable.
RFC793:
"If the connection does not exist (CLOSED) then a reset is sent in response to any incoming segment except another reset. In particular, SYNs addressed to a non-existent connection are rejected by this means. "
The linux stack will respond with a RST segment when you send a segment to a non listening port.

The definition of ICMP port unreachable:
"Port Unreachable - generated if the designated transport protocol (e.g., UDP) is unable to demultiplex the datagram in the transport layer of the final destination but has no protocol mechanism to inform the sender"

Is the ICMP unreachable a way for picotcp to protect the TCP layer from overload on a SYN attack? What should be the correct response for pico?

Mbed: DHCP: EthernetInterface.connect() returns -1 when first try fails. What now?

Discover, Offer, Request, but the server does not respond with ACK or NAK. The following should happen:
RFC 2131 p17:
"The client retransmits the DHCPREQUEST according to the retransmission algorithm. A client might retransmit the DHCPREQUEST message four times, for a total delay of 60 seconds, before restarting the initialization procedure. If the client receives neither a DHCPACK or a DHCPNAK message after employing the retransmission algorithm, the client reverts to INIT state and restarts the initialization process.
The client SHOULD notify the user that the initialization process has failed and is restarting."
This notification of failure is done by the connect() method (EthernetInterface class) by returning -1. The DHCP client however, restarts the negotiation procedure in the background. How can the user program know (from the mbed BSD interface) that the second negotiation will succeed or not?

tcp_send_rst is trying to access net pointer from a closed socket

In some cases after previous connection was closed and still a retransmission comes
from the mbed website the board would hang. This is caused by an illegal memory access since Keil reported that the Fault registers were set.

The offending instruction is in tcp_send_rst,
f = t->sock.net->alloc(t->sock.net, PICO_SIZE_TCPHDR + opt_len);
because t->sock.net was NULL, I'm working to figure out exactly what is happening.
I know that it has something to do with the socket being removed from tree and the socket was in PICO_SOCKET_STATE_TCP_LAST_ACK.

The reason why this happens is still not clear, keep checking this.

DNS client is leaking connections

For each retransmission of the dns query a socket remains in the tree,
without ever being closed.

Each time pico_dns_client_send is called it opens a new socket but it doesn't check
if the previous socket was closed.

In pico_dns_client_retransmission we could close the socket before calling pico_dns_client_send(key);

TCP needs a better garbage collector.

TCP layer needs a component that is able to close and remove from the socket tree the sockets that haven't had activity in some time or sockets which for some reason closing or opening remained stuck in some state.

While working with the mbed platform I could observe that during time tcp sockets in the following states
0x070F (PICO_SOCKET_STATE_TCP_LAST_ACK)
0x090F (PICO_SOCKET_STATE_TCP_FIN_WAIT2)
0x0004 (PICO_SOCKET_STATE_BOUND)

As an idea we could use a timer to check all sockets and a timestamp to see the last time that socket had activity and/or we should make the states when establishing/closing a connection to timeout and lead to dropping of sockets.

TCP: PicoTCP does not respond to duplicate SYN

remote client -> PicoTCP server

When a PicoTCP server is within the connection established state, it does not react to another SYN from the same socket (same port and ip). This can be the case when the remote client has crashed, reboots and tries to reconnect to the PicoTCP server. Normally the client will choose another source port, but this is not guaranteed.
The server should react with a simple ACK instaid. The remote client will discover that the ack number is wrong (number from original connection) and will send a RST to the server. The connection on the server should be closed now.
See RFC793 p34 half open connection discovery

Flooding UDP socket with small packets causes HardFault

If you flood a udp socket with packets(in this case I used small packets-1 byte payload), but the socket doesn't read anything, the board will enter hard fault.

The script I used
import sys, socket
import random, string
import select
from time import sleep

SERVER_ADDRESS = "192.168.1.81"
SERVER_PORT = 6677
PACKET = 'a'

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect((SERVER_ADDRESS,SERVER_PORT))

s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, True)

cnt = 0
while(True):
print "Sending packet %d" % cnt
s.sendall(PACKET)
sleep(0.001)
cnt+=1

The mbed application opens a socket, binds it to 6677 and then calls thread::wait forever, so the stack can tick.

DHCP client doesn't repeat queries

If there is no DHCP server to answer the first 3 queries (first call to pico_dhcp_initiate_negotiation) , there will be no other request for a new IP, even if pico_dhcp_initiate_negotiation is called again. So if the dhcp doesn't get an answer at its first question it will never ask again.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.