Revision: 528
          http://vde.svn.sourceforge.net/vde/?rev=528&view=rev
Author:   danielel
Date:     2011-12-30 10:33:54 +0000 (Fri, 30 Dec 2011)
Log Message:
-----------
Added DHCP client
Added arp command to show arp tables

Modified Paths:
--------------
    branches/vde-router/vde-2/src/vde_router/Makefile.am
    branches/vde-router/vde-2/src/vde_router/vde_router.c
    branches/vde-router/vde-2/src/vde_router/vde_router.h
    branches/vde-router/vde-2/src/vde_router/vder_datalink.c
    branches/vde-router/vde-2/src/vde_router/vder_packet.c
    branches/vde-router/vde-2/src/vde_router/vder_packet.h
    branches/vde-router/vde-2/src/vde_router/vder_queue.c
    branches/vde-router/vde-2/src/vde_router/vder_udp.c
    branches/vde-router/vde-2/src/vde_router/vder_udp.h

Added Paths:
-----------
    branches/vde-router/vde-2/src/vde_router/vder_dhcp.c
    branches/vde-router/vde-2/src/vde_router/vder_dhcp.h

Removed Paths:
-------------
    branches/vde-router/vde-2/src/vde_router/vder_dhcpd.c
    branches/vde-router/vde-2/src/vde_router/vder_dhcpd.h

Modified: branches/vde-router/vde-2/src/vde_router/Makefile.am
===================================================================
--- branches/vde-router/vde-2/src/vde_router/Makefile.am        2011-12-27 
14:45:35 UTC (rev 527)
+++ branches/vde-router/vde-2/src/vde_router/Makefile.am        2011-12-30 
10:33:54 UTC (rev 528)
@@ -13,6 +13,6 @@
 bin_PROGRAMS = vde_router
 vde_router_SOURCES = rbtree.h  vde_headers.h  vder_arp.h  vder_datalink.h  
vder_icmp.h \
     vde_router.h  vder_packet.h        vder_queue.h rbtree.c  vder_arp.c  
vder_datalink.c \
-    vder_icmp.c  vde_router.c  vder_packet.c  vder_queue.c vder_udp.c 
vder_dhcpd.c
+    vder_icmp.c  vde_router.c  vder_packet.c  vder_queue.c vder_udp.c 
vder_dhcp.c
 
 vde_router_LDADD = $(top_builddir)/src/common/libvdecommon.la 
$(top_builddir)/src/lib/libvdeplug.la -lpthread

Modified: branches/vde-router/vde-2/src/vde_router/vde_router.c
===================================================================
--- branches/vde-router/vde-2/src/vde_router/vde_router.c       2011-12-27 
14:45:35 UTC (rev 527)
+++ branches/vde-router/vde-2/src/vde_router/vde_router.c       2011-12-30 
10:33:54 UTC (rev 528)
@@ -11,7 +11,7 @@
 #include "vde_router.h"
 #include "vder_queue.h"
 #include "vder_packet.h"
-#include "vder_dhcpd.h"
+#include "vder_dhcp.h"
 #include <stdlib.h>
 #include <unistd.h>
 #include <stdio.h>
@@ -64,6 +64,7 @@
                printoutc(fd, "ifconfig     show/change interface addresses 
configuration");
                printoutc(fd, "dhcpd        start/stop dhcp server on a 
specific interface");
                printoutc(fd, "route        show/change routing table");
+               printoutc(fd, "arp                      show neighbors ip/mac 
associations");
                printoutc(fd, "queue        show/change outgoing frames 
queues");
                printoutc(fd, "ipfilter     show/change ip filtering 
configuration");
                printoutc(fd, "stats        print interface statistics");
@@ -87,17 +88,21 @@
        } else if (match_input("ifconfig",arg)) {
                printoutc(fd, "Syntax:");
                printoutc(fd, "\tifconfig [<devname> [<action> <address> 
<netmask>]]");
+               printoutc(fd, "--or--");
+               printoutc(fd, "\tifconfig <devname> add dhcp");
                printoutc(fd, "Show/store IP address configuration. If no 
<devname> is provided, the default action");
                printoutc(fd, "will be to display the current configuration for 
all the existing ethernet devices.");
                printoutc(fd, "<action> can be \"add\" or \"del\". If \"add\" 
is specified, all other arguments are mandatory.");
                printoutc(fd, "If \"del\" is specified, only <address> will be 
used to search for an existing entry.");
                printoutc(fd, "Each virtual ethernet can be associated to more 
than one IP addresses. A static route for");
                printoutc(fd, "the resulting neighborhood will be added.");
+               printoutc(fd, "Dhcp option allows to ask for a dynamic IP 
address.");
                printoutc(fd, "");
                printoutc(fd, "Examples:");
                printoutc(fd, "ifconfig");
                printoutc(fd, "ifconfig eth0");
                printoutc(fd, "ifconfig eth1 add 10.0.0.1 255.0.0.0");
+               printoutc(fd, "ifconfig eth1 add dhcp");
                printoutc(fd, "ifconfig eth1 del 10.0.0.1");
                return 0;
        } else if (match_input("dhcpd",arg)) {
@@ -199,6 +204,10 @@
                printoutc(fd, "ipfilter add src eth1 tos 2 to 172.16.0.0 
255.255.0.0 prio 7");
                printoutc(fd, "ipfilter del src eth1 tos 2 to 172.16.0.0 
255.255.0.0");
                return 0;
+       } else if (match_input("arp",arg)) {
+               printoutc(fd, "Syntax:");
+               printoutc(fd, "\tarp");
+               return 0;
        } else if (match_input("stats",arg)) {
                printoutc(fd, "Syntax:");
                printoutc(fd, "\tstats");
@@ -247,7 +256,10 @@
                        char *txt_address, *txt_netmask;
                        txt_address = strdup(vder_ntoa(addr->address));
                        txt_netmask= strdup(vder_ntoa(addr->netmask));
-                       printoutc(fd, "\taddress: %s netmask: %s", txt_address, 
txt_netmask);
+                       if (addr->address == (uint32_t)(-1))
+                               printoutc(fd, "\tAcquiring one IP address via 
DHCP...");
+                       else
+                               printoutc(fd, "\taddress: %s netmask: %s", 
txt_address, txt_netmask);
                        free(txt_address);
                        free(txt_netmask);
                        addr = addr->next;
@@ -358,16 +370,21 @@
                        not_understood(fd, "");
                        return EINVAL;
                }
-               if (!inet_aton(arg, &temp_address) || 
!is_unicast(temp_address.s_addr)) {
+               if (match_input("dhcp", arg)) {
+                       temp_address.s_addr = (uint32_t)(-1);
+                       pthread_create(&selected->dhcpclient, 0, 
dhcp_client_loop, selected); 
+               }
+               else if (!inet_aton(arg, &temp_address) || 
!is_unicast(temp_address.s_addr)) {
                        printoutc(fd, "Invalid address \"%s\"", arg);
                        return EINVAL;
                }
                arg = strtok_r(NULL, " ", &nextargs);
-               if (!arg && (action == ACTION_ADD)) {
+               if (!arg && (action == ACTION_ADD) && (temp_address.s_addr != 
(uint32_t)(-1))) {
                        printoutc(fd, "Error: parameter 'netmask' required.");
                        return EINVAL;
                }
-               if ((action == ACTION_ADD) && (!inet_aton(arg, &temp_netmask) 
|| !is_netmask(temp_netmask.s_addr))) {
+               if ((action == ACTION_ADD) && (temp_address.s_addr != 
(uint32_t)(-1)) &&
+                       (!inet_aton(arg, &temp_netmask) || 
!is_netmask(temp_netmask.s_addr))) {
                        printoutc(fd, "Invalid netmask \"%s\"", arg);
                        return EINVAL;
                }
@@ -974,7 +991,7 @@
                return EINVAL;
        iface = Router.iflist;
        while(iface) {
-               printoutc(fd, "eth%d frame sent:%d, frame received:%d",
+               printoutc(fd, "eth%d frames sent:%d, frames received:%d",
                        iface->interface_id, iface->stats.sent, 
iface->stats.recvd);
                printoutc(fd, "");
                iface = iface->next;
@@ -982,6 +999,42 @@
        return 0;
 }
 
+static int arp(int fd, char *args)
+{
+       struct vder_iface *iface;
+       struct rb_node *node;
+       if (strlen(args) > 0)
+               return EINVAL;
+       iface = Router.iflist;
+       while(iface) {
+               node = iface->arp_table.rb_node;
+               while (node) {
+                       struct vder_arp_entry *ae = rb_entry(node, struct 
vder_arp_entry, rb_node);
+                       char *txt_address = strdup(vder_ntoa(ae->ipaddr));
+                       printoutc(fd, "%s %02x:%02x:%02x:%02x:%02x:%02x 
(eth%d)", txt_address,
+                               ae->macaddr[0], ae->macaddr[1], ae->macaddr[2], 
ae->macaddr[3], ae->macaddr[4], ae->macaddr[5],
+                               iface->interface_id);
+                       free(txt_address);
+                       node = node->rb_left;
+               }
+               node = iface->arp_table.rb_node;
+               if (node)
+                       node = node->rb_right;
+               while (node) {
+                       struct vder_arp_entry *ae = rb_entry(node, struct 
vder_arp_entry, rb_node);
+                       char *txt_address = strdup(vder_ntoa(ae->ipaddr));
+                       printoutc(fd, "%s %02x:%02x:%02x:%02x:%02x:%02x 
(eth%d)", txt_address,
+                               ae->macaddr[0], ae->macaddr[1], ae->macaddr[2], 
ae->macaddr[3], ae->macaddr[4], ae->macaddr[5],
+                               iface->interface_id);
+                       free(txt_address);
+                       node = node->rb_right;
+               }
+               iface = iface->next;
+       }
+       return 0;
+}
+
+
 #define DEFAULT_LEASE_TIME htonl(0xa8c0)
 static int dhcpd(int fd,char *s)
 {
@@ -1070,6 +1123,7 @@
 } commandlist [] = {
        {"help", help, WITHFILE},
        {"ifconfig", ifconfig, WITHFILE},
+       {"arp", arp, WITHFILE},
        {"route", route, WITHFILE},
        {"connect", doconnect, 0},
        {"stats", stats, WITHFILE},

Modified: branches/vde-router/vde-2/src/vde_router/vde_router.h
===================================================================
--- branches/vde-router/vde-2/src/vde_router/vde_router.h       2011-12-27 
14:45:35 UTC (rev 527)
+++ branches/vde-router/vde-2/src/vde_router/vde_router.h       2011-12-30 
10:33:54 UTC (rev 528)
@@ -164,6 +164,7 @@
        pthread_t receiver;
        pthread_t queue_manager;
        pthread_t dhcpd;
+       pthread_t dhcpclient;
        int dhcpd_started;
        struct {
                uint32_t sent;

Modified: branches/vde-router/vde-2/src/vde_router/vder_datalink.c
===================================================================
--- branches/vde-router/vde-2/src/vde_router/vder_datalink.c    2011-12-27 
14:45:35 UTC (rev 527)
+++ branches/vde-router/vde-2/src/vde_router/vder_datalink.c    2011-12-30 
10:33:54 UTC (rev 528)
@@ -372,7 +372,8 @@
        pthread_mutex_unlock(&Router.global_config_lock);
 
        /* Add static route towards neightbors */
-       vder_route_add(address->address, address->netmask, 0U, 1, iface);
+       if (addr != (uint32_t) (-1))
+               vder_route_add(address->address, address->netmask, 0U, 1, 
iface);
 
        return 0;
 }
@@ -469,7 +470,7 @@
        while (iface) {
                struct vder_ip4address *cur = iface->address_list;
                while(cur) {
-                       if (cur->address == addr) {
+                       if ((cur->address == addr)|| (cur->address == 
(uint32_t)(-1))) {
                                return 1;
                        }
                        cur = cur->next;

Copied: branches/vde-router/vde-2/src/vde_router/vder_dhcp.c (from rev 527, 
branches/vde-router/vde-2/src/vde_router/vder_dhcpd.c)
===================================================================
--- branches/vde-router/vde-2/src/vde_router/vder_dhcp.c                        
        (rev 0)
+++ branches/vde-router/vde-2/src/vde_router/vder_dhcp.c        2011-12-30 
10:33:54 UTC (rev 528)
@@ -0,0 +1,468 @@
+#include "vder_udp.h"
+#include "vder_arp.h"
+#include "vder_dhcp.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+static struct vder_dhcp_negotiation *Negotiation_list;
+static struct vder_udp_socket *udpsock;
+static struct vder_dhcpd_settings Settings;
+
+static struct vder_dhcp_negotiation *
+get_negotiation_by_xid(uint32_t xid)
+{
+       struct vder_dhcp_negotiation *cur = Negotiation_list;
+       while (cur) {
+               if (cur->xid == xid)
+                       return cur;
+               cur = cur->next;
+       }
+       return NULL;
+}
+
+static uint8_t dhcp_get_next_option(uint8_t *begin, uint8_t *data, int *len, 
uint8_t **nextopt)
+{
+       uint8_t *p;
+       uint8_t type;
+       uint8_t opt_len;
+
+       if (!begin)
+               p = *nextopt;
+       else
+               p = begin;
+
+       type = *p;
+       *nextopt = ++p;
+       if ((type == DHCPOPT_END) || (type == DHCPOPT_PAD)) {
+               memset(data, 0, *len);
+               len = 0;
+               return type;
+       }
+       opt_len = *p;
+       p++;
+       if (*len > opt_len)
+               *len = opt_len;
+       memcpy(data, p, *len);
+       *nextopt = p + opt_len;
+       return type;
+}
+
+static int is_options_valid(uint8_t *opt_buffer, int len)
+{
+       uint8_t *p = opt_buffer;
+       while (len > 0) {
+               if (*p == DHCPOPT_END)
+                       return 1;
+               else if (*p == DHCPOPT_PAD) {
+                       p++;
+                       len--;
+               } else {
+                       uint8_t opt_len;
+                       p++;
+                       len--;
+                       opt_len = *p;
+                       p += opt_len + 1;
+                       len -= opt_len;
+               }
+       }
+       return 0;
+}
+
+#define DHCP_DATAGRAM_SIZE 308
+#define OPENDNS (htonl(0xd043dede))
+
+static void dhcpd_make_reply(struct vder_dhcp_negotiation *dn, uint8_t 
reply_type)
+{
+
+       uint8_t buf_out[DHCP_DATAGRAM_SIZE] = {0};
+       struct dhcphdr *dh_out = (struct dhcphdr *) buf_out;
+       uint32_t server_address = vder_get_right_localip(Settings.iface, 
Settings.pool_next);
+       uint32_t netmask = vder_get_netmask(Settings.iface, server_address);
+       uint32_t bcast = vder_get_broadcast(server_address, netmask);
+       uint32_t dns_server = OPENDNS;
+
+       int sent = 0;
+
+
+       memcpy(dh_out->hwaddr, dn->hwaddr, HLEN_ETHER);
+       dh_out->op = DHCP_OP_REPLY;
+       dh_out->htype = HTYPE_ETHER;
+       dh_out->hlen = HLEN_ETHER;
+       dh_out->xid = dn->xid;
+       dh_out->yiaddr = dn->arp->ipaddr;
+       dh_out->siaddr = server_address;
+       dh_out->dhcp_magic = DHCPD_MAGIC_COOKIE;
+
+       /* Option: msg type, len 1 */
+       dh_out->options[0] = DHCPOPT_MSGTYPE;
+       dh_out->options[1] = 1;
+       dh_out->options[2] = reply_type;
+
+       /* Option: server id, len 4 */
+       dh_out->options[3] = DHCPOPT_SERVERID;
+       dh_out->options[4] = 4;
+       memcpy(dh_out->options + 5, &server_address, 4);
+
+       /* Option: Lease time, len 4 */
+       dh_out->options[9] = DHCPOPT_LEASETIME;
+       dh_out->options[10] = 4;
+       memcpy(dh_out->options + 11, &Settings.lease_time, 4);
+
+       /* Option: Netmask, len 4 */
+       dh_out->options[15] = DHCPOPT_NETMASK;
+       dh_out->options[16] = 4;
+       memcpy(dh_out->options + 17, &netmask, 4);
+
+       /* Option: Router, len 4 */
+       dh_out->options[21] = DHCPOPT_ROUTER;
+       dh_out->options[22] = 4;
+       memcpy(dh_out->options + 23, &server_address, 4);
+
+       /* Option: Broadcast, len 4 */
+       dh_out->options[27] = DHCPOPT_BCAST;
+       dh_out->options[28] = 4;
+       memcpy(dh_out->options + 29, &bcast, 4);
+
+       /* Option: DNS, len 4 */
+       dh_out->options[33] = DHCPOPT_DNS;
+       dh_out->options[34] = 4;
+       memcpy(dh_out->options + 35, &dns_server, 4);
+
+       dh_out->options[40] = DHCPOPT_END;
+
+       sent = vder_udpsocket_sendto(udpsock, buf_out, DHCP_DATAGRAM_SIZE, 
dh_out->yiaddr, DHCP_CLIENT_PORT);
+       if (sent < 0) {
+               perror("udp sendto");
+       }
+}
+
+#define dhcpd_make_offer(x) dhcpd_make_reply(x, DHCP_MSG_OFFER)
+#define dhcpd_make_ack(x) dhcpd_make_reply(x, DHCP_MSG_ACK)
+
+#define ip_inrange(x) ((ntohl(x) >= ntohl(Settings.pool_start)) && (ntohl(x) 
<= ntohl(Settings.pool_end)))
+
+static void dhcp_recv(uint8_t *buffer, int len)
+{
+       struct dhcphdr *dhdr = (struct dhcphdr *) buffer;
+       struct vder_dhcp_negotiation *dn = get_negotiation_by_xid(dhdr->xid);
+       uint8_t *nextopt, opt_data[20], opt_type;
+       int opt_len = 20;
+
+
+       if (!is_options_valid(dhdr->options, len - sizeof(struct dhcphdr)))
+               return;
+
+
+
+       if (!dn) {
+               dn = malloc(sizeof(struct vder_dhcp_negotiation));
+               memset(dn, 0, sizeof(struct vder_dhcp_negotiation));
+               dn->xid = dhdr->xid;
+               dn->state = DHCPSTATE_DISCOVER;
+               memcpy(dn->hwaddr, dhdr->hwaddr, HLEN_ETHER);
+               dn->next = Negotiation_list;
+               Negotiation_list = dn;
+               dn->arp = vder_arp_get_record_by_macaddr(Settings.iface, 
dn->hwaddr);
+               if (!dn->arp) {
+                       dn->arp = malloc(sizeof(struct vder_arp_entry));
+                       if (!dn->arp)
+                               return;
+                       memcpy(dn->arp->macaddr, dn->hwaddr, HLEN_ETHER);
+                       dn->arp->ipaddr = Settings.pool_next;
+                       Settings.pool_next = htonl(ntohl(Settings.pool_next) + 
1);
+                       vder_add_arp_entry(Settings.iface, dn->arp);
+               }
+       }
+
+       if (!ip_inrange(dn->arp->ipaddr))
+               return;
+
+
+       opt_type = dhcp_get_next_option(dhdr->options, opt_data, &opt_len, 
&nextopt);
+       while (opt_type != DHCPOPT_END) {
+               /* parse interesting options here */
+               if (opt_type == DHCPOPT_MSGTYPE) {
+
+                       /* server simple state machine */
+                       uint8_t msg_type = opt_data[0];
+                       if (msg_type == DHCP_MSG_DISCOVER) {
+                               dhcpd_make_offer(dn);
+                               dn->state = DHCPSTATE_OFFER;
+                               return;
+                       } else if (msg_type == DHCP_MSG_REQUEST) {
+                               dhcpd_make_ack(dn);
+                               return;
+                       }
+               }
+               opt_len = 20;
+               opt_type = dhcp_get_next_option(NULL, opt_data, &opt_len, 
&nextopt);
+       }
+}
+
+
+void *dhcp_server_loop(void *ptr_settings)
+{
+       uint32_t from_ip;
+       uint16_t from_port;
+
+       unsigned char buffer[2000];
+       int len;
+
+       memcpy(&Settings, ptr_settings, sizeof(struct vder_dhcpd_settings));
+       Settings.pool_next = Settings.pool_start;
+       free(ptr_settings);
+
+
+       if(!Settings.iface)
+               return NULL;
+       if (!udpsock)
+               udpsock = vder_udpsocket_open(DHCPD_PORT);
+       if (!udpsock)
+               return NULL;
+
+
+       while(1) {
+               len = vder_udpsocket_recvfrom(udpsock, buffer, 2000, &from_ip, 
&from_port, -1);
+               if (len < 0) {
+                       perror("udp recv");
+                       return NULL;
+               }
+               if ((from_ip == 0) && (from_port == DHCP_CLIENT_PORT)) {
+                       dhcp_recv(buffer, len);
+               }
+       }
+}
+
+
+
+struct dhcp_client_cookie
+{
+       uint32_t xid;
+       uint32_t address;
+       uint32_t netmask;
+       uint32_t gateway;
+       uint32_t server_id;
+       uint32_t lease_time;
+       struct vder_udp_socket *socket;
+       struct vder_iface *iface;
+       struct timeval start_time;
+       int attempt;
+       enum dhcp_negotiation_state state;
+};
+
+static int dhclient_recv_offer(struct dhcp_client_cookie *cli, uint8_t *data, 
int len)
+{
+       struct dhcphdr *dhdr = (struct dhcphdr *) data;
+       uint8_t *nextopt, opt_data[20], opt_type;
+       int opt_len = 20;
+       uint8_t msg_type = 0xFF;
+
+
+       if (dhdr->xid != cli->xid) {
+               printf("bad xid\n");
+               return 0;
+       }
+
+       if (!is_options_valid(dhdr->options, len - sizeof(struct dhcphdr))) {
+               printf("bad options\n");
+               return 0;
+       }
+
+       cli->address = dhdr->yiaddr;
+
+       opt_type = dhcp_get_next_option(dhdr->options, opt_data, &opt_len, 
&nextopt);
+       while (opt_type != DHCPOPT_END) {
+               if (opt_type == DHCPOPT_MSGTYPE)
+                       msg_type = opt_data[0];
+               if ((opt_type == DHCPOPT_LEASETIME) && (opt_len == 4))
+                       memcpy(&cli->lease_time, opt_data, 4);
+               if ((opt_type == DHCPOPT_ROUTER) && (opt_len == 4))
+                       memcpy(&cli->gateway, opt_data, 4);
+               if ((opt_type == DHCPOPT_NETMASK) && (opt_len == 4))
+                       memcpy(&cli->netmask, opt_data, 4);
+               if ((opt_type == DHCPOPT_SERVERID) && (opt_len == 4))
+                       memcpy(&cli->server_id, opt_data, 4);
+
+               opt_len = 20;
+               opt_type = dhcp_get_next_option(NULL, opt_data, &opt_len, 
&nextopt);
+       }
+       if ((msg_type != DHCP_MSG_OFFER) || !cli->lease_time || !cli->netmask 
|| !cli->server_id )
+               return 0;
+       return 1;
+}
+
+static int dhclient_recv_ack(struct dhcp_client_cookie *cli, uint8_t *data, 
int len)
+{
+       struct dhcphdr *dhdr = (struct dhcphdr *) data;
+       uint8_t *nextopt, opt_data[20], opt_type;
+       int opt_len = 20;
+       uint8_t msg_type = 0xFF;
+
+       if (dhdr->xid != cli->xid)
+               return 0;
+
+       if (!is_options_valid(dhdr->options, len - sizeof(struct dhcphdr)))
+               return 0;
+
+
+       opt_type = dhcp_get_next_option(dhdr->options, opt_data, &opt_len, 
&nextopt);
+       while (opt_type != DHCPOPT_END) {
+               if (opt_type == DHCPOPT_MSGTYPE)
+                       msg_type = opt_data[0];
+
+               opt_len = 20;
+               opt_type = dhcp_get_next_option(NULL, opt_data, &opt_len, 
&nextopt);
+       }
+       if (msg_type != DHCP_MSG_ACK)
+               return 0;
+       return 1;
+}
+
+
+static void dhclient_send(struct dhcp_client_cookie *cli, uint8_t msg_type)
+{
+
+       uint8_t buf_out[DHCP_DATAGRAM_SIZE] = {0};
+       struct dhcphdr *dh_out = (struct dhcphdr *) buf_out;
+       int sent = 0;
+       struct timeval now;
+       int i = 0;
+       gettimeofday(&now, NULL);
+
+       memcpy(dh_out->hwaddr, cli->iface->macaddr, HLEN_ETHER);
+       dh_out->op = DHCP_OP_REQUEST;
+       dh_out->htype = HTYPE_ETHER;
+       dh_out->hlen = HLEN_ETHER;
+       dh_out->xid = cli->xid;
+       dh_out->secs = (msg_type == DHCP_MSG_REQUEST)?0:htons(now.tv_sec - 
cli->start_time.tv_sec);
+       dh_out->dhcp_magic = DHCPD_MAGIC_COOKIE;
+
+
+       /* Option: msg type, len 1 */
+       dh_out->options[i++] = DHCPOPT_MSGTYPE;
+       dh_out->options[i++] = 1;
+       dh_out->options[i++] = msg_type;
+
+       if (msg_type == DHCP_MSG_REQUEST) {
+               dh_out->options[i++] = DHCPOPT_REQIP;
+               dh_out->options[i++] = 4;
+               dh_out->options[i++] = (ntohl(cli->address) & 0xFF000000) >> 24;
+               dh_out->options[i++] = (ntohl(cli->address) & 0xFF0000) >> 16;
+               dh_out->options[i++] = (ntohl(cli->address) & 0xFF00) >> 8;
+               dh_out->options[i++] = (ntohl(cli->address) & 0xFF);
+               dh_out->options[i++] = DHCPOPT_SERVERID;
+               dh_out->options[i++] = 4;
+               dh_out->options[i++] = (ntohl(cli->server_id) & 0xFF000000) >> 
24;
+               dh_out->options[i++] = (ntohl(cli->server_id) & 0xFF0000) >> 16;
+               dh_out->options[i++] = (ntohl(cli->server_id) & 0xFF00) >> 8;
+               dh_out->options[i++] = (ntohl(cli->server_id) & 0xFF);
+       }
+
+       /* Option: req list, len 4 */
+       dh_out->options[i++] = DHCPOPT_PARMLIST;
+       dh_out->options[i++] = 5;
+       dh_out->options[i++] = DHCPOPT_NETMASK;
+       dh_out->options[i++] = DHCPOPT_BCAST;
+       dh_out->options[i++] = DHCPOPT_TIME;
+       dh_out->options[i++] = DHCPOPT_ROUTER;
+       dh_out->options[i++] = DHCPOPT_HOSTNAME;
+
+       dh_out->options[i] = DHCPOPT_END;
+
+       sent = vder_udpsocket_sendto_broadcast(cli->socket, buf_out, 
DHCP_DATAGRAM_SIZE, cli->iface, (uint32_t)(-1), DHCPD_PORT);
+       if (sent < 0) {
+               perror("udp sendto");
+       }
+}
+
+void dhcp_retry(struct dhcp_client_cookie *client)
+{
+       const int MAX_RETRY = 5;
+       if (++client->attempt > MAX_RETRY) {
+               gettimeofday(&client->start_time, NULL);
+               client->attempt = 0;
+               client->xid ^= client->start_time.tv_usec ^ 
client->start_time.tv_sec;
+       }
+}
+
+void *dhcp_client_loop(void *iface)
+{
+       unsigned char buffer[2000];
+       int len;
+       struct dhcp_client_cookie client;
+       uint16_t from_port;
+       uint32_t from_ip;
+
+       memset(&client, 0, sizeof(client));
+
+       client.iface = (struct vder_iface *) iface;
+       client.state = DHCPSTATE_DISCOVER;
+       client.socket = vder_udpsocket_open(DHCP_CLIENT_PORT);
+       if (!client.socket) {
+               perror("dhcp client socket");
+               return NULL;
+       }
+
+       gettimeofday(&client.start_time, NULL);
+       client.attempt = 0;
+       client.xid = client.start_time.tv_usec ^ client.start_time.tv_sec;
+
+
+       if (!client.socket) {
+               return NULL;
+       }
+
+       while(1) {
+               switch (client.state) {
+                       case DHCPSTATE_DISCOVER:
+                               dhcp_retry(&client);
+                               dhclient_send(&client, DHCP_MSG_DISCOVER);
+                               len = vder_udpsocket_recvfrom(client.socket, 
buffer, 2000, &from_ip, &from_port, 5000);
+                               if (len < 0) {
+                                       perror("udp recv");
+                                       return NULL;
+                               }
+                               if (len > 0) {
+                                       if (dhclient_recv_offer(&client, 
buffer, len)) {
+                                               client.state = 
DHCPSTATE_REQUEST;
+                                       }
+                               }
+                               break;
+                       case DHCPSTATE_REQUEST:
+                               dhclient_send(&client, DHCP_MSG_REQUEST);
+                               len = vder_udpsocket_recvfrom(client.socket, 
buffer, 2000, &from_ip, &from_port, 10000);
+                               if (len < 0) {
+                                       perror("udp recv");
+                                       return NULL;
+                               }
+                               if (len == 0)
+                                       break;
+                               if (dhclient_recv_ack(&client, buffer, len))
+                                       client.state = DHCPSTATE_ACK;
+                               else {
+                                       if (client.address)
+                                               
vder_iface_address_del(client.iface, client.address);
+                                       client.state = DHCPSTATE_DISCOVER;
+                                       client.address = 0;
+                                       client.netmask = 0;
+                                       client.gateway = 0;
+                               }
+                               break;
+                       case DHCPSTATE_ACK:
+                               vder_iface_address_del(client.iface, 
(uint32_t)-1);
+                               vder_iface_address_add(client.iface, 
client.address, client.netmask);
+                               if ((client.gateway != 0) && ((client.gateway & 
client.netmask) == (client.address & client.netmask)))
+                                       vder_route_add(0, 0, client.gateway, 1, 
client.iface);
+                               sleep(client.lease_time);
+                               client.state = DHCPSTATE_REQUEST;
+                               break;
+                       default:
+                               client.address = 0;
+                               client.netmask = 0;
+                               client.gateway = 0;
+                               client.state = DHCPSTATE_DISCOVER;
+               }
+       }
+}

Copied: branches/vde-router/vde-2/src/vde_router/vder_dhcp.h (from rev 527, 
branches/vde-router/vde-2/src/vde_router/vder_dhcpd.h)
===================================================================
--- branches/vde-router/vde-2/src/vde_router/vder_dhcp.h                        
        (rev 0)
+++ branches/vde-router/vde-2/src/vde_router/vder_dhcp.h        2011-12-30 
10:33:54 UTC (rev 528)
@@ -0,0 +1,110 @@
+#ifndef __VDER_DHCPD
+#define __VDER_DHCPD
+
+#include "vder_arp.h"
+
+#define DHCPD_PORT (htons(67))
+#define DHCP_CLIENT_PORT (htons(68))
+
+
+#define DHCP_GATEWAY 0x01
+#define DHCP_DNS 0x02
+
+struct vder_dhcpd_settings
+{
+       struct vder_iface *iface;
+       uint32_t my_ip;
+       uint32_t netmask;
+       uint32_t pool_start;
+       uint32_t pool_next;
+       uint32_t pool_end;
+       unsigned long lease_time;
+       uint8_t flags;
+};
+
+#define DHCP_OP_REQUEST 1
+#define DHCP_OP_REPLY   2
+
+#define HTYPE_ETHER 1
+#define HLEN_ETHER 6
+
+#define FLAG_BROADCAST (htons(0xF000))
+
+#define DHCPD_MAGIC_COOKIE (htonl(0x63825363))
+
+/* DHCP OPTIONS, RFC2132 */
+#define DHCPOPT_PAD                    0x00
+#define DHCPOPT_NETMASK                0x01
+#define DHCPOPT_TIME                   0x02
+#define DHCPOPT_ROUTER                         0x03
+#define DHCPOPT_DNS                            0x06
+#define DHCPOPT_HOSTNAME               0x0c
+#define DHCPOPT_DOMAINNAME             0x0f
+#define DHCPOPT_MTU                    0x1a
+#define DHCPOPT_BCAST                  0x1c
+#define DHCPOPT_NETBIOSNS              0x2c
+#define DHCPOPT_NETBIOSSCOPE   0x2f
+
+#define DHCPOPT_REQIP                  0x32
+#define DHCPOPT_LEASETIME              0x33
+#define DHCPOPT_MSGTYPE                        0x35
+#define DHCPOPT_SERVERID               0x36
+#define DHCPOPT_PARMLIST               0x37
+#define DHCPOPT_RENEWALTIME    0x3a
+#define DHCPOPT_REBINDINGTIME  0x3b
+#define DHCPOPT_DOMAINSEARCH   0x77
+#define DHCPOPT_STATICROUTE            0x79
+#define DHCPOPT_END                    0xFF
+
+/* DHCP MESSAGE TYPE */
+#define DHCP_MSG_DISCOVER              1
+#define DHCP_MSG_OFFER                         2
+#define DHCP_MSG_REQUEST               3
+#define DHCP_MSG_DECLINE               4
+#define DHCP_MSG_ACK                   5
+#define DHCP_MSG_NAK                   6
+#define DHCP_MSG_RELEASE               7
+#define DHCP_MSG_INFORM                        8
+
+
+struct __attribute__((packed)) dhcphdr
+{
+       uint8_t op;
+       uint8_t htype;
+       uint8_t hlen;
+       uint8_t hops; //zero
+       uint32_t xid; //store this in the request
+       uint16_t secs; // ignore
+       uint16_t flags;
+       uint32_t ciaddr; // client address - if asking for renewal
+       uint32_t yiaddr; // your address (client)
+       uint32_t siaddr; // dhcp offered address
+       uint32_t giaddr; // relay agent, bootp.
+       uint8_t hwaddr[6];
+       uint8_t hwaddr_padding[10];
+       char    hostname[64];
+       char    bootp_filename[128]; 
+       uint32_t dhcp_magic;
+       uint8_t options[0];
+};
+
+enum dhcp_negotiation_state {
+       DHCPSTATE_DISCOVER = 0,
+       DHCPSTATE_OFFER,
+       DHCPSTATE_REQUEST,
+       DHCPSTATE_ACK
+};
+
+struct vder_dhcp_negotiation {
+       struct vder_dhcp_negotiation *next;
+       uint32_t xid;
+       uint8_t hwaddr[6];
+       uint32_t assigned_address;
+       enum dhcp_negotiation_state state;
+       struct vder_arp_entry *arp;
+};
+
+void *dhcp_server_loop(void *ptr_iface);
+void *dhcp_client_loop(void *ptr_iface);
+
+#endif

Deleted: branches/vde-router/vde-2/src/vde_router/vder_dhcpd.c
===================================================================
--- branches/vde-router/vde-2/src/vde_router/vder_dhcpd.c       2011-12-27 
14:45:35 UTC (rev 527)
+++ branches/vde-router/vde-2/src/vde_router/vder_dhcpd.c       2011-12-30 
10:33:54 UTC (rev 528)
@@ -1,232 +0,0 @@
-#include "vder_udp.h"
-#include "vder_arp.h"
-#include "vder_dhcpd.h"
-#include <stdio.h>
-
-static struct vder_dhcp_negotiation *Negotiation_list;
-static struct vder_udp_socket *udpsock;
-static struct vder_dhcpd_settings Settings;
-
-static struct vder_dhcp_negotiation *
-get_negotiation_by_xid(uint32_t xid)
-{
-       struct vder_dhcp_negotiation *cur = Negotiation_list;
-       while (cur) {
-               if (cur->xid == xid)
-                       return cur;
-               cur = cur->next;
-       }
-       return NULL;
-}
-
-static uint8_t dhcp_get_next_option(uint8_t *begin, uint8_t *data, int *len, 
uint8_t **nextopt)
-{
-       uint8_t *p;
-       uint8_t type;
-       uint8_t opt_len;
-
-       if (!begin)
-               p = *nextopt;
-       else
-               p = begin;
-
-       type = *p;
-       *nextopt = ++p;
-       if ((type == DHCPOPT_END) || (type == DHCPOPT_PAD)) {
-               memset(data, 0, *len);
-               len = 0;
-               return type;
-       }
-       opt_len = *p;
-       p++;
-       if (*len > opt_len)
-               *len = opt_len;
-       memcpy(data, p, *len);
-       *nextopt = p + opt_len;
-       return type;
-}
-
-static int is_options_valid(uint8_t *opt_buffer, int len)
-{
-       uint8_t *p = opt_buffer;
-       while (len > 0) {
-               if (*p == DHCPOPT_END)
-                       return 1;
-               else if (*p == DHCPOPT_PAD) {
-                       p++;
-                       len--;
-               } else {
-                       uint8_t opt_len;
-                       p++;
-                       len--;
-                       opt_len = *p;
-                       p += opt_len + 1;
-                       len -= opt_len;
-               }
-       }
-       return 0;
-}
-
-#define DHCP_OFFER_SIZE 308
-#define OPENDNS (htonl(0xd043dede))
-
-static void dhcpd_make_reply(struct vder_dhcp_negotiation *dn, uint8_t 
reply_type)
-{
-
-       uint8_t buf_out[DHCP_OFFER_SIZE] = {0};
-       struct dhcphdr *dh_out = (struct dhcphdr *) buf_out;
-       uint32_t server_address = vder_get_right_localip(Settings.iface, 
Settings.pool_next);
-       uint32_t netmask = vder_get_netmask(Settings.iface, server_address);
-       uint32_t bcast = vder_get_broadcast(server_address, netmask);
-       uint32_t dns_server = OPENDNS;
-
-       int sent = 0;
-
-
-       memcpy(dh_out->hwaddr, dn->hwaddr, HLEN_ETHER);
-       dh_out->op = DHCP_OP_REPLY;
-       dh_out->htype = HTYPE_ETHER;
-       dh_out->hlen = HLEN_ETHER;
-       dh_out->xid = dn->xid;
-       dh_out->yiaddr = dn->arp->ipaddr;
-       dh_out->siaddr = server_address;
-       dh_out->dhcp_magic = DHCPD_MAGIC_COOKIE;
-
-       /* Option: msg type, len 1 */
-       dh_out->options[0] = DHCPOPT_MSGTYPE;
-       dh_out->options[1] = 1;
-       dh_out->options[2] = reply_type;
-
-       /* Option: server id, len 4 */
-       dh_out->options[3] = DHCPOPT_SERVERID;
-       dh_out->options[4] = 4;
-       memcpy(dh_out->options + 5, &server_address, 4);
-
-       /* Option: Lease time, len 4 */
-       dh_out->options[9] = DHCPOPT_LEASETIME;
-       dh_out->options[10] = 4;
-       memcpy(dh_out->options + 11, &Settings.lease_time, 4);
-
-       /* Option: Netmask, len 4 */
-       dh_out->options[15] = DHCPOPT_NETMASK;
-       dh_out->options[16] = 4;
-       memcpy(dh_out->options + 17, &netmask, 4);
-
-       /* Option: Router, len 4 */
-       dh_out->options[21] = DHCPOPT_ROUTER;
-       dh_out->options[22] = 4;
-       memcpy(dh_out->options + 23, &server_address, 4);
-
-       /* Option: Broadcast, len 4 */
-       dh_out->options[27] = DHCPOPT_BCAST;
-       dh_out->options[28] = 4;
-       memcpy(dh_out->options + 29, &bcast, 4);
-
-       /* Option: DNS, len 4 */
-       dh_out->options[33] = DHCPOPT_DNS;
-       dh_out->options[34] = 4;
-       memcpy(dh_out->options + 35, &dns_server, 4);
-
-       dh_out->options[40] = DHCPOPT_END;
-
-       sent = vder_udpsocket_sendto(udpsock, buf_out, DHCP_OFFER_SIZE, 
dh_out->yiaddr, DHCP_CLIENT_PORT);
-       if (sent < 0) {
-               perror("udp sendto");
-       }
-}
-
-#define dhcpd_make_offer(x) dhcpd_make_reply(x, DHCP_MSG_OFFER)
-#define dhcpd_make_ack(x) dhcpd_make_reply(x, DHCP_MSG_ACK)
-
-#define ip_inrange(x) ((ntohl(x) >= ntohl(Settings.pool_start)) && (ntohl(x) 
<= ntohl(Settings.pool_end)))
-
-static void dhcp_recv(uint8_t *buffer, int len)
-{
-       struct dhcphdr *dhdr = (struct dhcphdr *) buffer;
-       struct vder_dhcp_negotiation *dn = get_negotiation_by_xid(dhdr->xid);
-       uint8_t *nextopt, opt_data[20], opt_type;
-       int opt_len = 20;
-
-
-       if (!is_options_valid(dhdr->options, len - sizeof(struct dhcphdr)))
-               return;
-
-
-
-       if (!dn) {
-               dn = malloc(sizeof(struct vder_dhcp_negotiation));
-               memset(dn, 0, sizeof(struct vder_dhcp_negotiation));
-               dn->xid = dhdr->xid;
-               dn->state = DHCPSTATE_DISCOVER;
-               memcpy(dn->hwaddr, dhdr->hwaddr, HLEN_ETHER);
-               dn->next = Negotiation_list;
-               Negotiation_list = dn;
-               dn->arp = vder_arp_get_record_by_macaddr(Settings.iface, 
dn->hwaddr);
-               if (!dn->arp) {
-                       dn->arp = malloc(sizeof(struct vder_arp_entry));
-                       if (!dn->arp)
-                               return;
-                       memcpy(dn->arp->macaddr, dn->hwaddr, HLEN_ETHER);
-                       dn->arp->ipaddr = Settings.pool_next;
-                       Settings.pool_next = htonl(ntohl(Settings.pool_next) + 
1);
-                       vder_add_arp_entry(Settings.iface, dn->arp);
-               }
-       }
-
-       if (!ip_inrange(dn->arp->ipaddr))
-               return;
-
-
-       opt_type = dhcp_get_next_option(dhdr->options, opt_data, &opt_len, 
&nextopt);
-       while (opt_type != DHCPOPT_END) {
-               /* parse interesting options here */
-               if (opt_type == DHCPOPT_MSGTYPE) {
-
-                       /* server simple state machine */
-                       uint8_t msg_type = opt_data[0];
-                       if (msg_type == DHCP_MSG_DISCOVER) {
-                               dhcpd_make_offer(dn);
-                               dn->state = DHCPSTATE_OFFER;
-                               return;
-                       } else if (msg_type == DHCP_MSG_REQUEST) {
-                               dhcpd_make_ack(dn);
-                               return;
-                       }
-               }
-               opt_len = 20;
-               opt_type = dhcp_get_next_option(NULL, opt_data, &opt_len, 
&nextopt);
-       }
-}
-
-
-void *dhcp_server_loop(void *ptr_settings)
-{
-       uint32_t from_ip;
-       uint16_t from_port;
-
-       unsigned char buffer[2000];
-       int len;
-
-       memcpy(&Settings, ptr_settings, sizeof(struct vder_dhcpd_settings));
-       Settings.pool_next = Settings.pool_start;
-       free(ptr_settings);
-
-
-       if(!Settings.iface)
-               return NULL;
-       udpsock = vder_udpsocket_open(DHCPD_PORT);
-       if (!udpsock) {
-               return NULL;
-       }
-
-       while(1) {
-               len = vder_udpsocket_recvfrom(udpsock, buffer, 2000, &from_ip, 
&from_port);
-               if (len < 0) {
-                       perror("udp recv");
-                       return NULL;
-               }
-               if ((from_ip == 0) && (from_port == DHCP_CLIENT_PORT)) {
-                       dhcp_recv(buffer, len);
-               }
-       }
-}

Deleted: branches/vde-router/vde-2/src/vde_router/vder_dhcpd.h
===================================================================
--- branches/vde-router/vde-2/src/vde_router/vder_dhcpd.h       2011-12-27 
14:45:35 UTC (rev 527)
+++ branches/vde-router/vde-2/src/vde_router/vder_dhcpd.h       2011-12-30 
10:33:54 UTC (rev 528)
@@ -1,100 +0,0 @@
-#ifndef __VDER_DHCPD
-#define __VDER_DHCPD
-
-#include "vder_arp.h"
-
-#define DHCPD_PORT (htons(67))
-#define DHCP_CLIENT_PORT (htons(68))
-
-
-#define DHCP_GATEWAY 0x01
-#define DHCP_DNS 0x02
-
-struct vder_dhcpd_settings
-{
-       struct vder_iface *iface;
-       uint32_t my_ip;
-       uint32_t netmask;
-       uint32_t pool_start;
-       uint32_t pool_next;
-       uint32_t pool_end;
-       unsigned long lease_time;
-       uint8_t flags;
-};
-
-#define DHCP_OP_REQUEST 1
-#define DHCP_OP_REPLY   2
-
-#define HTYPE_ETHER 1
-#define HLEN_ETHER 6
-
-#define FLAG_BROADCAST (htons(0xF000))
-
-#define DHCPD_MAGIC_COOKIE (htonl(0x63825363))
-
-/* DHCP OPTIONS, RFC2132 */
-#define DHCPOPT_PAD                    0x00
-#define DHCPOPT_NETMASK                0x01
-#define DHCPOPT_ROUTER                         0x03
-#define DHCPOPT_DNS                            0x06
-#define DHCPOPT_BCAST                  0x1c
-#define DHCPOPT_REQIP                  0x32
-#define DHCPOPT_LEASETIME              0x33
-#define DHCPOPT_MSGTYPE                        0x35
-#define DHCPOPT_SERVERID               0x36
-#define DHCPOPT_PARMLIST               0x37
-#define DHCPOPT_RENEWALTIME    0x3a
-#define DHCPOPT_REBINDINGTIME  0x3b
-#define DHCPOPT_END                    0xFF
-
-/* DHCP MESSAGE TYPE */
-#define DHCP_MSG_DISCOVER              1
-#define DHCP_MSG_OFFER                         2
-#define DHCP_MSG_REQUEST               3
-#define DHCP_MSG_DECLINE               4
-#define DHCP_MSG_ACK                   5
-#define DHCP_MSG_NAK                   6
-#define DHCP_MSG_RELEASE               7
-#define DHCP_MSG_INFORM                        8
-
-
-struct __attribute__((packed)) dhcphdr
-{
-       uint8_t op;
-       uint8_t htype;
-       uint8_t hlen;
-       uint8_t hops; //zero
-       uint32_t xid; //store this in the request
-       uint16_t secs; // ignore
-       uint16_t flags;
-       uint32_t ciaddr; // client address - if asking for renewal
-       uint32_t yiaddr; // your address (client)
-       uint32_t siaddr; // dhcp offered address
-       uint32_t giaddr; // relay agent, bootp.
-       uint8_t hwaddr[6];
-       uint8_t hwaddr_padding[10];
-       char    hostname[64];
-       char    bootp_filename[128]; 
-       uint32_t dhcp_magic;
-       uint8_t options[0];
-};
-
-enum dhcp_negotiation_state {
-       DHCPSTATE_DISCOVER = 0,
-       DHCPSTATE_OFFER,
-       DHCPSTATE_REQUEST,
-       DHCPSTATE_ACK
-};
-
-struct vder_dhcp_negotiation {
-       struct vder_dhcp_negotiation *next;
-       uint32_t xid;
-       uint8_t hwaddr[6];
-       uint32_t assigned_address;
-       enum dhcp_negotiation_state state;
-       struct vder_arp_entry *arp;
-};
-
-void *dhcp_server_loop(void *ptr_iface);
-
-#endif

Modified: branches/vde-router/vde-2/src/vde_router/vder_packet.c
===================================================================
--- branches/vde-router/vde-2/src/vde_router/vder_packet.c      2011-12-27 
14:45:35 UTC (rev 527)
+++ branches/vde-router/vde-2/src/vde_router/vder_packet.c      2011-12-30 
10:33:54 UTC (rev 528)
@@ -77,9 +77,9 @@
        int recvd = 0;
        int is_broadcast = vder_ipaddress_is_broadcast(iph->daddr);
 
-
        if (!vder_ipaddress_is_local(iph->daddr) && !is_broadcast)
                return 0;
+
        switch(iph->protocol) {
                case PROTO_ICMP:
                        vder_icmp_recv(vb);
@@ -125,7 +125,28 @@
        return vder_sendto(ro->iface, vdb, ae->macaddr);
 }
 
+int vder_packet_broadcast(struct vde_buff *vdb, struct vder_iface *iface, 
uint32_t dst_ip, uint8_t protocol)
+{
+       struct iphdr *iph=iphead(vdb);
+       struct vde_ethernet_header *eth = ethhead(vdb);
+       uint8_t bcast_macaddr[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
 
+       eth->buftype = htons(PTYPE_IP);
+
+       memset(iph,0x45,1);
+       iph->tos = 0;
+       iph->frag_off=htons(0x4000); // Don't fragment.
+       iph->tot_len = htons(vdb->len - sizeof(struct vde_ethernet_header));
+       iph->id = 0;
+       iph->protocol = protocol;
+       iph->ttl = DEFAULT_TTL;
+       iph->daddr = dst_ip;
+       //iph->saddr = vder_get_right_localip(iface, iph->daddr);
+       iph->saddr = 0;
+       iph->check = htons(vder_ip_checksum(iph));
+       return vder_sendto(iface, vdb, bcast_macaddr);
+}
+
 void vder_packet_recv(struct vder_iface *vif, int timeout)
 {
        struct pollfd pfd;

Modified: branches/vde-router/vde-2/src/vde_router/vder_packet.h
===================================================================
--- branches/vde-router/vde-2/src/vde_router/vder_packet.h      2011-12-27 
14:45:35 UTC (rev 527)
+++ branches/vde-router/vde-2/src/vde_router/vder_packet.h      2011-12-30 
10:33:54 UTC (rev 528)
@@ -11,6 +11,7 @@
 void vder_packet_recv(struct vder_iface *vif, int timeout);
 uint16_t net_checksum(void *inbuf, int len);
 int vder_packet_send(struct vde_buff *vdb, uint32_t dst_ip, uint8_t protocol);
+int vder_packet_broadcast(struct vde_buff *vdb, struct vder_iface *iface, 
uint32_t dst_ip, uint8_t protocol);
 char *vder_ntoa(uint32_t addr);
 
 #endif

Modified: branches/vde-router/vde-2/src/vde_router/vder_queue.c
===================================================================
--- branches/vde-router/vde-2/src/vde_router/vder_queue.c       2011-12-27 
14:45:35 UTC (rev 527)
+++ branches/vde-router/vde-2/src/vde_router/vder_queue.c       2011-12-30 
10:33:54 UTC (rev 528)
@@ -156,8 +156,6 @@
 }
 
 
-
-
 void qred_setup(struct vder_queue *q, uint32_t min, uint32_t max, double P, 
uint32_t limit)
 {
        pthread_mutex_lock(&q->lock);

Modified: branches/vde-router/vde-2/src/vde_router/vder_udp.c
===================================================================
--- branches/vde-router/vde-2/src/vde_router/vder_udp.c 2011-12-27 14:45:35 UTC 
(rev 527)
+++ branches/vde-router/vde-2/src/vde_router/vder_udp.c 2011-12-30 10:33:54 UTC 
(rev 528)
@@ -1,5 +1,6 @@
 #include "vder_udp.h"
 #include <stdio.h>
+#include <unistd.h>
 
 /* UDP header, rfc 768 */
 
@@ -17,6 +18,7 @@
        int found = 0;
        struct vde_buff *copy = NULL;
        uint16_t port = transport_dport(buf);
+
        while(cur) {
                if (cur->port == port) {
                        if (!found) {
@@ -88,6 +90,7 @@
                errno = EINVAL;
                return -1;
        }
+
        ro = vder_get_route(dst);
        if (!ro) {
                errno = EHOSTUNREACH;
@@ -113,8 +116,39 @@
        return len;
 }
 
+int vder_udpsocket_sendto_broadcast(struct vder_udp_socket *sock, void *data, 
size_t len,
+       struct vder_iface *iface, uint32_t dst, uint16_t dstport)
+{
+       struct vde_buff *b;
+       struct udphdr *uh;
+       uint8_t *datagram;
+       int bufsize;
+       if (len <= 0) {
+               errno = EINVAL;
+               return -1;
+       }
 
-int vder_udpsocket_recvfrom(struct vder_udp_socket *sock, void *data, size_t 
len, uint32_t *from, uint16_t *fromport)
+       bufsize = sizeof(struct vde_buff) + sizeof(struct vde_ethernet_header) 
+ sizeof(struct iphdr) + sizeof(struct udphdr) + len;
+       b = malloc(bufsize);
+       if (!b)
+               return -1;
+       b->len = bufsize - sizeof(struct vde_buff);
+       b->src = NULL;
+       b->priority = PRIO_BESTEFFORT;
+       uh = (struct udphdr *) payload(b);
+       datagram = (uint8_t *)((payload(b) + sizeof(struct udphdr)));
+       memcpy(datagram, data, len);
+
+       uh->sport = sock->port;
+       uh->dport = dstport;
+       uh->len = htons(len);
+       uh->crc = 0;
+       vder_packet_broadcast(b, iface, dst, PROTO_UDP);
+       return len;
+}
+
+
+int vder_udpsocket_recvfrom(struct vder_udp_socket *sock, void *data, size_t 
len, uint32_t *from, uint16_t *fromport, int timeout)
 {
        struct vde_buff *b;
        struct udphdr *uh;
@@ -125,6 +159,17 @@
                return -1;
        }
 
+       while ((timeout > 0) && (sock->inq.n == 0)) {
+               usleep(10000);
+               timeout -= 10;
+               if (timeout < 0)
+                       timeout = 0;
+       }
+
+       if ((timeout == 0) && (sock->inq.n == 0)) {
+               return 0;
+       }
+
        do {
                b = dequeue(&sock->inq);
        } while(!b);

Modified: branches/vde-router/vde-2/src/vde_router/vder_udp.h
===================================================================
--- branches/vde-router/vde-2/src/vde_router/vder_udp.h 2011-12-27 14:45:35 UTC 
(rev 527)
+++ branches/vde-router/vde-2/src/vde_router/vder_udp.h 2011-12-30 10:33:54 UTC 
(rev 528)
@@ -27,6 +27,8 @@
 struct vder_udp_socket *vder_udpsocket_open(uint16_t port);
 void vder_udp_close(struct vder_udp_socket *sock);
 int vder_udpsocket_sendto(struct vder_udp_socket *sock, void *data, size_t 
len, uint32_t dst, uint16_t dstport);
-int vder_udpsocket_recvfrom(struct vder_udp_socket *sock, void *data, size_t 
len, uint32_t *from, uint16_t *fromport);
+int vder_udpsocket_sendto_broadcast(struct vder_udp_socket *sock, void *data, 
size_t len,
+       struct vder_iface *iface, uint32_t dst, uint16_t dstport);
+int vder_udpsocket_recvfrom(struct vder_udp_socket *sock, void *data, size_t 
len, uint32_t *from, uint16_t *fromport, int timeout);
 
 #endif

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
Ridiculously easy VDI. With Citrix VDI-in-a-Box, you don't need a complex
infrastructure or vast IT resources to deliver seamless, secure access to
virtual desktops. With this all-in-one solution, easily deploy virtual 
desktops for less than the cost of PCs and save 60% on VDI infrastructure 
costs. Try it free! http://p.sf.net/sfu/Citrix-VDIinabox
_______________________________________________
vde-users mailing list
vde-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/vde-users

Reply via email to