[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Lost] [Patch] tcpip - udp
Am Dienstag, 26. August 2008 20:51:52 schrieb Antoine Kaufmann:
> Re: [Lost] [Patch] tcpip - udp
> Von:
> Antoine Kaufmann <toni@xxxxxxxxxxxxxxxx>
> An:
> "Lost-Patches" <lost@xxxxxxxxxx>
> Datum:
> Dienstag 20:51:52
> Anhänge:
> tcpip-udp.patch
>
> Es sind nicht genügend Informationen zur Überprüfung der Gültigkeit der
> Signatur vorhanden. Details anzeigen
>
> Am Dienstag, 26. August 2008 13.47:15 schrieb Antoine Kaufmann:
> > + tcpip: udp-Unterstützung
>
> In dieser Version habe ich noch den source_ip-Parameter für udp_send
> rausgeworfen. Die Quell-IP kann udp_send über die Routingtabelle ausfindig
> machen.
>
> Index: trunk/src/modules/tcpip/include/udp.h
> ===================================================================
> --- /dev/null
> +++ trunk/src/modules/tcpip/include/udp.h
> @@ -0,0 +1,191 @@
> +/*
> + * 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;
> +
> + /** Pointer auf die Daten */
> + uint8_t data[];
Wenn mich meine C-Kenntnisse nicht täuschen, kommen da nicht vier Byte
Pointer, sondern direkt die Daten. Der Kommentar führt dann in die Irre.
> +};
> +
> +
> +/**
> + * UDP-Code initialisieren
> + */
> +void init_udp();
> +
> +/**
> + * 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); +
> +/*word tcp_checksum
> + (struct tcp_header* header, struct tcp_pseudo_header* pseudo_header,
> + void* data, dword data_size);
> +void tcp_update_checksum
> + (struct tcp_header* header, struct tcp_pseudo_header* pseudo_header,
> + void* data, dword data_size);
> +
> +void tcp_receive(dword source_ip, void* data, dword data_size);
> +void tcp_send_ack(struct tcp_connection* conn); // TODO Ersetzen*/
Auskommentierter Code.
> +
> +#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,284 @@
> +/*
> + * 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 UPD-Ports auf denen gelauscht wird. */
UDP, nicht UPD.
> +list_t* udp_ports;
> +
> +/**
> + * 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
> + */
> +struct udp_port* udp_listen(uint32_t ip, uint16_t port)
> +{
> + struct udp_port* p = malloc(sizeof(*p));
> +
> + p->ip = ip;
> + p->port = port;
> + p->in_buffer = list_create();
> +
> + list_push(udp_ports, p);
> + return p;
> +}
Ich finde, hier wäre eine Prüfung schick, ob nicht schon jemand anderes auf
diesem Port lauscht.
> +
> +/**
> + * 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() {}
> +
> +/**
> + * 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 einên udp_in_buffer oder NULL wenn kein Paket
Sondêrzeichen im Kommentar.
> + * 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
> + while (!(ib = list_pop(port->in_buffer)) &&
> + (timeout > get_tick_count()))
timeout ist kein Timestamp, sondern die Zeit, die gewartet werden soll. Das
ist meistens deutlich kleiner als 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;
> +
> + puts("udp_receive");
Öhm, nein. Nicht im SVN.
> + // Ein Kaputtes Paket
Sehr kaputt? *g*
> + 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);
Kann man irgendwie noch nicht benutzen in dieser Form, oder? Ein
LostIO-Interface wäre noch ganz nett.