[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Lost] [Patch] tcpip - udp



On Sun, Aug 31 11:35, Kevin Wolf wrote:
> Kann man irgendwie noch nicht benutzen in dieser Form, oder? Ein 
> LostIO-Interface wäre noch ganz nett.

Dem ist so, aber der dhcp-Patch, der irgendwann folgt, baut darauf auf,
und ein halbes LostIO-Interface habe ich auch schon. Aber das kann ich
mit einem späteren Patch einbauen, oder?

Im Anhang die korrigierte Version.

-- 
Antoine Kaufmann
<toni@xxxxxxxxxxxxxxxx>
Index: trunk/src/modules/tcpip/include/udp.h
===================================================================
--- /dev/null
+++ trunk/src/modules/tcpip/include/udp.h
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2008 The LOST Project. All rights reserved.
+ *
+ * This code is derived from software contributed to the LOST Project
+ * by Antoine Kaufmann
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the LOST Project
+ *     and its contributors.
+ * 4. Neither the name of the LOST Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _UDP_H_
+#define _UDP_H_
+
+#include <stdint.h>
+
+#include "collections.h"
+
+/** Header eines UDP-Pakets */
+struct udp_header {
+    /** Quellport des Pakets. Wird nur benoetigt, wenn der Versender dieses
+     * Pakets eine Antwort erwartet. */
+    uint16_t    source_port;
+
+    /** Ziel-Port */
+    uint16_t    dest_port;
+
+    /** Laenge des Pakets (mit Header, min 8) */
+    uint16_t    length;
+
+    /** Pruefsumme oder 0 wenn diese nicht gepfrueft werden soll. */
+    uint16_t    checksum;
+} __attribute__ ((packed));
+
+
+/* TODO: Gehoert nach ip.h */
+/** IP-Pseudoheader (wird zur Berechnung der TCP- und UDP-Pruefsummen benutzt.*/
+struct udp_pseudo_header {
+    /** Quell-IP des Pakets */
+    uint32_t    source_ip;
+
+    /** Ziel-IP des Pakets */
+    uint32_t    dest_ip;
+
+    /** Protokoll (TCP: 6, UDP: 17) */
+    uint16_t    proto;
+
+    /** Laenge des TCP-/UDP-Pakets */
+    uint16_t    length;
+} __attribute__ ((packed));
+
+
+/** Geoeffneter UDP-Port (listening) */
+struct udp_port {
+    /** Adresse auf der gelauscht wird. Oder 0 fuer alle */
+    uint32_t    ip;
+
+    /** Portnummer */
+    uint16_t    port;
+
+    /** Puffer mit den Paketen die eingegangen sind. */
+    list_t* in_buffer;
+};
+
+
+/** UDP-Paket, wie es im In-Buffer liegt */
+struct udp_packet {
+    /** Quell-IP */
+    uint32_t    source_ip;
+
+    /** Quell-Port */
+    uint16_t    source_port;
+
+    /** Ziel-IP notwendig wenn auf 0.0.0.0 gelauscht wird. */
+    uint32_t    dest_ip;
+
+    /** Laenge der Daten */
+    size_t      data_len;
+
+    /** Die eigentlichen Daten folgen dieser Struktur */
+    uint8_t     data[];
+};
+
+
+/**
+ * UDP-Code initialisieren
+ */
+void init_udp(void);
+
+/**
+ * Auf UDP-Port lauschen.
+ *
+ * @param ip    IP auf der gelauscht werden soll, oder 0 fuer alle
+ * @param port  Port
+ *
+ * @return Pointer auf ein Port-Handle
+ */
+struct udp_port* udp_listen(uint32_t ip, uint16_t port);
+
+/**
+ * Port wieder freigeben
+ *
+ * @param port Pointer auf ein Port-Handle
+ */
+void udp_port_release(struct udp_port* port);
+
+/**
+ * Warten bis ein Paket eintrifft, oder die Zeit abgelaufen ist.
+ *
+ * @param port      Port auf dem gewartet werden soll
+ * @param timeout   Zeit in Millisekunden nach der aufgegeben werden soll oder 0
+ *                  falls garnicht gewartet werden soll.
+ *
+ * @return Pointer auf einên udp_in_buffer oder NULL wenn kein Paket
+ *         eingetroffen ist.
+ */
+struct udp_packet* udp_port_wait(struct udp_port* port, uint64_t timeout);
+
+/**
+ * UDP-Paket senden
+ *
+ * @param dest_ip   IP an die das Paket gesendet werden soll.
+ * @param dest_port Zielport
+ * @param src_port  Quellport
+ * @param data      Paket-Daten
+ * @param length    Laenge der Daten
+ */
+void udp_send(uint32_t dest_ip, uint16_t dest_port, uint16_t src_port,
+    void* data, size_t length);
+
+/**
+ * UDP-Paket direkt senden ohne Routing
+ *
+ * @param device    Karte ueber die das Paket gesendet wird
+ * @param dest_ip   IP an die das Paket gesendet werden soll.
+ * @param dest_port Zielport
+ * @param src_ip    IP von der aus das Paket gesendet werden soll
+ * @param src_port  Quellport
+ * @param data      Paket-Daten
+ * @param len       Laenge der Daten
+ */
+void udp_send_direct(struct device* device, uint32_t dest_ip,
+    uint16_t dest_port, uint32_t src_ip, uint16_t src_port, void* data,
+    size_t len);
+
+
+/**
+ * UDP-Paket empfangen. Wird vom IP-Empfangscode aufgerufen.
+ *
+ * @param source_ip Quell-IP
+ * @param dest_ip   Ziel-IP
+ * @param data      Empfangenes UDP-Paket
+ * @param len       Laenge des Pakets
+ */
+void udp_receive(uint32_t src_ip, uint32_t dest_ip, void* data, size_t len);
+
+#endif
+
Index: trunk/src/modules/tcpip/ip.c
===================================================================
--- trunk.orig/src/modules/tcpip/ip.c
+++ trunk/src/modules/tcpip/ip.c
@@ -45,6 +45,7 @@
 #include "arp.h"
 #include "ethernet.h"
 #include "tcp.h"
+#include "udp.h"
 
 //Hier koennen die Debug-Nachrichten aktiviert werden
 #define DEBUG 0
@@ -276,6 +277,8 @@ void ip_receive(struct device *device, v
 
         case IP_PROTO_UDP:
             DEBUG_MSG("UDP-Paket eingegangen");
+            udp_receive(header->source_ip, header->dest_ip, packet,
+                packet_size);
             break;
 
         default:
Index: trunk/src/modules/tcpip/udp.c
===================================================================
--- /dev/null
+++ trunk/src/modules/tcpip/udp.c
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) 2008 The LOST Project. All rights reserved.
+ *
+ * This code is derived from software contributed to the LOST Project
+ * by Antoine Kaufmann
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the LOST Project
+ *     and its contributors.
+ * 4. Neither the name of the LOST Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <collections.h>
+#include <network.h>
+#include <syscall.h>
+#include <rpc.h>
+
+#include "ip.h"
+#include "udp.h"
+
+/** Liste mit den UDP-Ports auf denen gelauscht wird. */
+list_t* udp_ports;
+
+/** Port suchen, der auf dieser IP und diesem Port lauscht. */
+static struct udp_port* get_port(uint32_t ip, uint16_t port);
+
+
+/**
+ * UDP-Code initialisieren
+ */
+void init_udp()
+{
+    udp_ports = list_create();
+}
+
+/**
+ * Auf UDP-Port lauschen.
+ *
+ * @param ip    IP auf der gelauscht werden soll, oder 0 fuer alle
+ * @param port  Port
+ *
+ * @return Pointer auf ein Port-Handle oder NULL wenn auf dem Port schon
+ *         gelauscht wird.
+ */
+struct udp_port* udp_listen(uint32_t ip, uint16_t port)
+{
+    struct udp_port* p;
+
+    // Sicherstellen, dass auf diesem Port noch nicht gelauscht wird
+    if (get_port(ip, port)) {
+        return NULL;
+    }
+
+    p = malloc(sizeof(*p));
+    p->ip = ip;
+    p->port = port;
+    p->in_buffer = list_create();
+
+    list_push(udp_ports, p);
+    return p;
+}
+
+/**
+ * Port wieder freigeben
+ *
+ * @param port Pointer auf ein Port-Handle
+ */
+void udp_port_release(struct udp_port* port)
+{
+    int i;
+    struct udp_port* list_p;
+    struct udp_packet* ib;
+
+    // Wenn sich der Index zwischen list_get_element_at und list_remove
+    // verschiebt haben wir ein Problem
+    p();
+    for (i = 0; (list_p = list_get_element_at(udp_ports, i)); i++) {
+        if (list_p == port) {
+            list_remove(udp_ports, i);
+
+            for (i = 0; (ib = list_get_element_at(port->in_buffer, i)); i++) {
+                free(ib);
+            }
+
+            list_destroy(port->in_buffer);
+            free(port);
+            break;
+        }
+    }
+    v();
+}
+
+/**
+ * Timer Stub fuer udp_port_wait
+ */
+static void udp_timer_stub(void) {}
+
+/**
+ * Warten bis ein Paket eintrifft, oder die Zeit abgelaufen ist.
+ *
+ * @param port      Port auf dem gewartet werden soll
+ * @param timeout   Zeit in Mikrosekunden nach der aufgegeben werden soll oder 0
+ *                  falls garnicht gewartet werden soll.
+ *
+ * @return Pointer auf einen udp_in_buffer oder NULL wenn kein Paket
+ *         eingetroffen ist.
+ */
+struct udp_packet* udp_port_wait(struct udp_port* port, uint64_t timeout)
+{
+    struct udp_packet* ib;
+
+    if (timeout == 0) {
+        return list_pop(port->in_buffer);
+    } else {
+        // Timer einrichten, damit spaetestens beim Timeout ein RPC kommt
+        timer_register(udp_timer_stub, timeout);
+
+        // Warten bis ein Paket in der Liste ist
+        timeout += get_tick_count();
+        while (!(ib = list_pop(port->in_buffer)) &&
+            (timeout > get_tick_count()))
+        {
+            wait_for_rpc();
+        }
+
+        return ib;
+    }
+}
+
+/**
+ * Port suchen, der auf dieser IP und diesem Port lauscht.
+ *
+ * @param source_ip IP
+ * @paran port      Port
+ *
+ * @return Pointer auf den Port oder NULL wenn keine gefunden wurde
+ */
+static struct udp_port* get_port(uint32_t ip, uint16_t port)
+{
+    struct udp_port* p;
+    int i;
+
+    for (i = 0; (p = list_get_element_at(udp_ports, i)); i++) {
+        if ((p->port == port) && ((p->ip == ip) || !p->ip)) {
+            return p;
+        }
+    }
+
+    return NULL;
+}
+
+/**
+ * UDP-Paket zusammenbauen
+ *
+ * @param buffer    Puffer
+ * @param dest_port Zielport
+ * @param src_port  Quellport
+ * @param data      Paket-Daten
+ * @param len       Laenge der Daten
+ */
+static void udp_fill_packet(void* buffer, uint16_t dest_port, uint16_t src_port,
+    void* data, size_t len)
+{
+    struct udp_header* header = buffer;
+    void* packet_data = buffer + sizeof(struct udp_header);
+
+    // Header des Pakets befuellen
+    header->dest_port   = big_endian_word(dest_port);
+    header->source_port = big_endian_word(src_port);
+    header->length      = big_endian_word(len + sizeof(struct udp_header));
+    header->checksum    = 0; // TODO ;-)
+
+    // Daten ins Paket kopieren
+    memcpy(packet_data, data, len);
+}
+
+/**
+ * UDP-Paket senden
+ *
+ * @param dest_ip   IP an die das Paket gesendet werden soll.
+ * @param dest_port Zielport
+ * @param src_port  Quellport
+ * @param data      Paket-Daten
+ * @param length    Laenge der Daten
+ */
+void udp_send(uint32_t dest_ip, uint16_t dest_port, uint16_t src_port,
+    void* data, size_t length)
+{
+    size_t packet_len = length + sizeof(struct udp_header);
+    uint8_t packet[packet_len];
+    struct routing_entry* route;
+
+    // Quell-IP finden wir in der Route
+    if (!(route = get_routing_entry(dest_ip))) {
+        return;
+    }
+
+    udp_fill_packet(packet, dest_port, route->device->dev.ip, data, length);
+
+    // Raus damit
+    ip_send(dest_ip, IP_PROTO_UDP, packet, packet_len);
+}
+
+/**
+ * UDP-Paket direkt senden ohne Routing
+ *
+ * @param device    Karte ueber die das Paket gesendet wird
+ * @param dest_ip   IP an die das Paket gesendet werden soll.
+ * @param dest_port Zielport
+ * @param src_ip    IP von der aus das Paket gesendet werden soll
+ * @param src_port  Quellport
+ * @param data      Paket-Daten
+ * @param len       Laenge der Daten
+ */
+void udp_send_direct(struct device* device, uint32_t dest_ip,
+    uint16_t dest_port, uint32_t src_ip, uint16_t src_port, void* data,
+    size_t len)
+{
+    size_t packet_len = len + sizeof(struct udp_header);
+    uint8_t packet[packet_len];
+
+    udp_fill_packet(packet, dest_port, src_ip, data, len);
+
+    // Raus damit
+    ip_send_direct(device, dest_ip, IP_PROTO_UDP, packet, packet_len);
+
+}
+
+/**
+ * UDP-Paket empfangen. Wird vom IP-Empfangscode aufgerufen.
+ *
+ * @param source_ip Quell-IP
+ * @param dest_ip   Ziel-IP
+ * @param data      Empfangenes UDP-Paket
+ * @param len       Laenge des Pakets
+ */
+void udp_receive(uint32_t src_ip, uint32_t dest_ip, void* data, size_t len)
+{
+    struct udp_header* header = data;
+    struct udp_port* port;
+    struct udp_packet* ib;
+    size_t data_len;
+
+    // Ein kaputtes Paket
+    if (len < sizeof(struct udp_header)) {
+        return;
+    }
+
+    // Pfruefen ob auf diesem Port gelauscht wird
+    if (!(port = get_port(dest_ip, big_endian_word(header->dest_port)))) {
+        return;
+    }
+
+    // TODO: Pruefen der Pruefsumme falls gesetzt
+
+
+    // in_buffer vorbereiten um in die Liste zu haengen
+    data_len = big_endian_word(header->length) - sizeof(struct udp_header);
+    ib = malloc(sizeof(*ib) + data_len);
+
+    ib->source_ip = big_endian_dword(src_ip);
+    ib->dest_ip = big_endian_dword(dest_ip);
+    ib->source_port = big_endian_word(header->source_port);
+
+    ib->data_len = data_len;
+    memcpy(ib->data, data + sizeof(struct udp_header), data_len);
+
+    list_push(port->in_buffer, ib);
+}
+
Index: trunk/src/modules/tcpip/main.c
===================================================================
--- trunk.orig/src/modules/tcpip/main.c
+++ trunk/src/modules/tcpip/main.c
@@ -45,6 +45,7 @@
 #include "arp.h"
 #include "ip.h"
 #include "tcp.h"
+#include "udp.h"
 #include "lostio_if.h"
 #include "dns.h"
 #include "lostio.h"
@@ -77,6 +78,7 @@ int main(int argc, char* argv[])
     init_arp();
     init_ip();
     init_tcp();
+    init_udp();
     init_lostio_interface();
 
     register_message_handler(RPC_IP_REGISTER_DRIVER, rpc_register_driver);

Attachment: pgp_RqWxt2ChE.pgp
Description: PGP signature