Revision: 527
http://vde.svn.sourceforge.net/vde/?rev=527&view=rev
Author: danielel
Date: 2011-12-27 14:45:35 +0000 (Tue, 27 Dec 2011)
Log Message:
-----------
Added support for DHCP server
some minor bugfixes
Modified Paths:
--------------
branches/vde-router/vde-2/src/vde_router/Makefile.am
branches/vde-router/vde-2/src/vde_router/vde_headers.h
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_arp.c
branches/vde-router/vde-2/src/vde_router/vder_arp.h
branches/vde-router/vde-2/src/vde_router/vder_datalink.c
branches/vde-router/vde-2/src/vde_router/vder_datalink.h
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_queue.h
Added Paths:
-----------
branches/vde-router/vde-2/src/vde_router/vder_dhcpd.c
branches/vde-router/vde-2/src/vde_router/vder_dhcpd.h
branches/vde-router/vde-2/src/vde_router/vder_udp.c
branches/vde-router/vde-2/src/vde_router/vder_udp.h
Modified: branches/vde-router/vde-2/src/vde_router/Makefile.am
===================================================================
--- branches/vde-router/vde-2/src/vde_router/Makefile.am 2011-12-21
17:28:47 UTC (rev 526)
+++ branches/vde-router/vde-2/src/vde_router/Makefile.am 2011-12-27
14:45:35 UTC (rev 527)
@@ -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_icmp.c vde_router.c vder_packet.c vder_queue.c vder_udp.c
vder_dhcpd.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_headers.h
===================================================================
--- branches/vde-router/vde-2/src/vde_router/vde_headers.h 2011-12-21
17:28:47 UTC (rev 526)
+++ branches/vde-router/vde-2/src/vde_router/vde_headers.h 2011-12-27
14:45:35 UTC (rev 527)
@@ -88,8 +88,9 @@
#define check_destination(vb,mac) ( strncmp((ethhead(vb))->dst, mac) == 0)
#define iphead(vb) ((struct iphdr *)(vb->data + 14))
+#define udp_pseudohead(vb) ((uint8_t *)(vb->data + 14 + sizeof(struct iphdr) -
(2 * sizeof(uint32_t))))
#define footprint(vb) ((uint8_t *)(vb->data + 14))
#define arphead(vb) ((struct vde_arp_header *)(vb->data + 14))
-#define payload(vb) ((struct vde_ethernet_header *)(vb->data + 14 +
sizeof(struct iphdr)))
+#define payload(vb) ((uint8_t *)(vb->data + 14 + sizeof(struct iphdr)))
#endif
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-21
17:28:47 UTC (rev 526)
+++ branches/vde-router/vde-2/src/vde_router/vde_router.c 2011-12-27
14:45:35 UTC (rev 527)
@@ -11,6 +11,7 @@
#include "vde_router.h"
#include "vder_queue.h"
#include "vder_packet.h"
+#include "vder_dhcpd.h"
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
@@ -61,6 +62,7 @@
printoutc(fd, "help print a summary of mgmt commands.
Use \"help <command>\" for details.");
printoutc(fd, "connect create a new interface connect it
to vde socket");
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, "queue show/change outgoing frames
queues");
printoutc(fd, "ipfilter show/change ip filtering
configuration");
@@ -98,6 +100,18 @@
printoutc(fd, "ifconfig eth1 add 10.0.0.1 255.0.0.0");
printoutc(fd, "ifconfig eth1 del 10.0.0.1");
return 0;
+ } else if (match_input("dhcpd",arg)) {
+ printoutc(fd, "Syntax:");
+ printoutc(fd, "\tdhcpd start <devname> <dhcp_pool_start>
<dhcp_pool_end>");
+ printoutc(fd, "--or--");
+ printoutc(fd, "\tdhcpd stop <devname>");
+ printoutc(fd, "Start/stop DHCP server on a specific interface.
Devices/machines connected to the router");
+ printoutc(fd, "will be provided with a dynamic IP address on
request.");
+ printoutc(fd, "");
+ printoutc(fd, "Examples:");
+ printoutc(fd, "dhcpd start eth0 10.0.0.101 10.0.0.120");
+ printoutc(fd, "dhcpd stop eth0");
+ return 0;
} else if (match_input("route",arg)) {
printoutc(fd, "Syntax:");
printoutc(fd, "\troute [<action> <address> <netmask> [gw
<gateway>] [via <interface>] [metric <metric>]]");
@@ -213,14 +227,6 @@
exit(0);
}
-static char *vder_ntoa(uint32_t addr)
-{
- struct in_addr a;
- char *res;
- a.s_addr = addr;
- res = inet_ntoa(a);
- return res;
-}
static int not_understood(int fd, char *s)
{
@@ -625,7 +631,7 @@
return EINVAL;
}
}
- } else if (match_input("from",arg)){
+ } else if (match_input("from",arg)) {
arg = strtok_r(NULL, " ", &nextargs);
if (!arg)
return EINVAL;
@@ -642,7 +648,7 @@
printoutc(fd, "Invalid netmask \"%s\"", arg);
return EINVAL;
}
- } else if (match_input("to",arg)){
+ } else if (match_input("to",arg)) {
arg = strtok_r(NULL, " ", &nextargs);
if (!arg)
return EINVAL;
@@ -659,7 +665,7 @@
printoutc(fd, "Invalid netmask \"%s\"", arg);
return EINVAL;
}
- } else if (match_input("tos",arg)){
+ } else if (match_input("tos",arg)) {
arg = strtok_r(NULL, " ", &nextargs);
if (!arg)
return EINVAL;
@@ -668,7 +674,7 @@
printoutc(fd, "Invalid tos %s", arg);
return EINVAL;
}
- } else if (match_input("sport",arg)){
+ } else if (match_input("sport",arg)) {
arg = strtok_r(NULL, " ", &nextargs);
if (!arg)
return EINVAL;
@@ -677,7 +683,7 @@
return EINVAL;
}
sport = htons(atoi(arg));
- } else if (match_input("dport",arg)){
+ } else if (match_input("dport",arg)) {
arg = strtok_r(NULL, " ", &nextargs);
if (!arg)
return EINVAL;
@@ -686,7 +692,7 @@
return EINVAL;
}
dport = htons(atoi(arg));
- } else if (match_input("prio",arg)){
+ } else if (match_input("prio",arg)) {
if (filter_action != filter_invalid) {
printoutc(fd, "Invalid double action for
filter");
}
@@ -804,6 +810,8 @@
return strtod(arg, NULL);
}
+
+
static int queue(int fd, char *s)
{
struct vder_iface *cur = Router.iflist, *selected = NULL;
@@ -974,6 +982,86 @@
return 0;
}
+#define DEFAULT_LEASE_TIME htonl(0xa8c0)
+static int dhcpd(int fd,char *s)
+{
+ char *nextargs = NULL, *arg;
+ struct vder_dhcpd_settings *dhcpd_settings;
+ struct vder_iface *selected = NULL;
+ struct in_addr temp_pool_start, temp_pool_end;
+ enum command_action_enum action = -1;
+
+ arg = strtok_r(s, " ", &nextargs);
+ if(!arg) {
+ printoutc(fd, "Error: arguments required");
+ return EINVAL;
+ }
+ if ((!arg) || (strlen(arg) < 4) || ((strncmp(arg, "start", 5) != 0) &&
(strncmp(arg, "stop", 4) != 0))) {
+ printoutc(fd, "Invalid action \"%s\".", arg);
+ return EINVAL;
+ }
+ if (strncmp(arg, "start", 5) == 0)
+ action = ACTION_ADD;
+ else
+ action = ACTION_DELETE;
+
+
+ arg = strtok_r(NULL, " ", &nextargs);
+ if (!arg) {
+ not_understood(fd, "");
+ return EINVAL;
+ }
+ if ((strlen(arg) < 4) || (strncmp(arg, "eth", 3)!= 0)) {
+ printoutc(fd, "Invalid interface \"%s\".", arg);
+ return EINVAL;
+ }
+ selected = select_interface(arg);
+ if (!selected)
+ return ENXIO;
+
+ if (action == ACTION_ADD) {
+ arg = strtok_r(NULL, " ", &nextargs);
+ if (!arg) {
+ not_understood(fd, "");
+ return EINVAL;
+ }
+
+ if (!inet_aton(arg, &temp_pool_start) ||
!is_unicast(temp_pool_start.s_addr)) {
+ printoutc(fd, "Invalid pool start address \"%s\"", arg);
+ return EINVAL;
+ }
+
+ arg = strtok_r(NULL, " ", &nextargs);
+ if (!arg) {
+ not_understood(fd, "");
+ return EINVAL;
+ }
+ if (!inet_aton(arg, &temp_pool_end) ||
!is_unicast(temp_pool_end.s_addr)) {
+ printoutc(fd, "Invalid pool end address \"%s\"", arg);
+ return EINVAL;
+ }
+
+ dhcpd_settings = malloc(sizeof(struct vder_dhcpd_settings));
+ if (!dhcpd_settings)
+ return ENOMEM;
+
+ dhcpd_settings->iface = selected;
+ dhcpd_settings->my_ip = vder_get_right_localip(selected,
temp_pool_start.s_addr);
+ dhcpd_settings->netmask = vder_get_netmask(selected,
dhcpd_settings->my_ip);
+ dhcpd_settings->pool_start = temp_pool_start.s_addr;
+ dhcpd_settings->pool_end = temp_pool_end.s_addr;
+ dhcpd_settings->lease_time = DEFAULT_LEASE_TIME;
+ dhcpd_settings->flags = 0;
+ selected->dhcpd_started = 1;
+ pthread_create(&selected->dhcpd, 0, dhcp_server_loop,
dhcpd_settings);
+ } else if (selected->dhcpd_started) {
+ pthread_cancel(selected->dhcpd);
+ selected->dhcpd_started = 0;
+ }
+ return 0;
+}
+
+
#define WITHFILE 0x80
static struct comlist {
char *tag;
@@ -987,6 +1075,7 @@
{"stats", stats, WITHFILE},
{"ipfilter", filter, WITHFILE},
{"queue", queue, WITHFILE},
+ {"dhcpd", dhcpd, 0 },
{"logout",logout, 0},
{"shutdown",doshutdown, 0}
};
@@ -1276,6 +1365,7 @@
npfd++;
}
+
while(1) {
n = poll(pfd, npfd, -1);
if (n>0) {
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-21
17:28:47 UTC (rev 526)
+++ branches/vde-router/vde-2/src/vde_router/vde_router.h 2011-12-27
14:45:35 UTC (rev 527)
@@ -163,6 +163,8 @@
pthread_t sender;
pthread_t receiver;
pthread_t queue_manager;
+ pthread_t dhcpd;
+ int dhcpd_started;
struct {
uint32_t sent;
uint32_t recvd;
Modified: branches/vde-router/vde-2/src/vde_router/vder_arp.c
===================================================================
--- branches/vde-router/vde-2/src/vde_router/vder_arp.c 2011-12-21 17:28:47 UTC
(rev 526)
+++ branches/vde-router/vde-2/src/vde_router/vder_arp.c 2011-12-27 14:45:35 UTC
(rev 527)
@@ -12,7 +12,7 @@
#include <errno.h>
#include "rbtree.h"
-static void add_arp_entry(struct vder_iface *vif, struct vder_arp_entry *p)
+void vder_add_arp_entry(struct vder_iface *vif, struct vder_arp_entry *p)
{
struct rb_node **link, *parent;
uint32_t hostorder_ip = ntohl(p->ipaddr);
@@ -119,9 +119,36 @@
memcpy(ae->macaddr,ah->s_mac,6);
ae->ipaddr = ah->s_addr;
- add_arp_entry(vif, ae);
+ vder_add_arp_entry(vif, ae);
if(ntohs(ah->opcode) == ARP_REQUEST)
vder_arp_reply(vif, vdb);
return 0;
}
+
+struct vder_arp_entry *vder_arp_get_record_by_macaddr(struct vder_iface *vif,
uint8_t *mac)
+{
+ struct rb_node *node;
+ struct vder_arp_entry *found=NULL;
+ node = vif->arp_table.rb_node;
+ while(node) {
+ struct vder_arp_entry *entry = rb_entry(node, struct
vder_arp_entry, rb_node);
+ if (memcmp(entry->macaddr, mac, ETHERNET_ADDRESS_SIZE) == 0) {
+ found = entry;
+ break;
+ }
+ node = node->rb_left;
+ }
+ if (found)
+ return found;
+ node = vif->arp_table.rb_node;
+ while(node) {
+ struct vder_arp_entry *entry = rb_entry(node, struct
vder_arp_entry, rb_node);
+ if (memcmp(entry->macaddr, mac, ETHERNET_ADDRESS_SIZE) == 0) {
+ found = entry;
+ break;
+ }
+ node = node->rb_right;
+ }
+ return found;
+}
Modified: branches/vde-router/vde-2/src/vde_router/vder_arp.h
===================================================================
--- branches/vde-router/vde-2/src/vde_router/vder_arp.h 2011-12-21 17:28:47 UTC
(rev 526)
+++ branches/vde-router/vde-2/src/vde_router/vder_arp.h 2011-12-27 14:45:35 UTC
(rev 527)
@@ -5,10 +5,16 @@
*/
#ifndef __VDER_ARP
#define __VDER_ARP
+void vder_add_arp_entry(struct vder_iface *vif, struct vder_arp_entry *p);
struct vder_arp_entry *vder_get_arp_entry(struct vder_iface *vif, uint32_t
addr);
size_t vder_arp_query(struct vder_iface *oif, uint32_t tgt);
size_t vder_arp_reply(struct vder_iface *oif, struct vde_buff *vdb);
/* Parse an incoming arp packet */;
int vder_parse_arp(struct vder_iface *vif, struct vde_buff *vdb);
+
+
+/* O(N) search by macaddr (required by dhcp server) */
+struct vder_arp_entry *vder_arp_get_record_by_macaddr(struct vder_iface *vif,
uint8_t *mac);
+
#endif
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-21
17:28:47 UTC (rev 526)
+++ branches/vde-router/vde-2/src/vde_router/vder_datalink.c 2011-12-27
14:45:35 UTC (rev 527)
@@ -15,8 +15,8 @@
#include <errno.h>
#include <pthread.h>
#include <semaphore.h>
-#include <stdio.h>
#include <sys/time.h>
+#include <stdio.h>
struct vde_router Router = {};
@@ -46,11 +46,7 @@
vif->macaddr[5] = vif->interface_id;
}
-/* Get TCP/UDP header ports */
-#define transport_sport(vdb) *((uint16_t *)((unsigned char*)(payload(vdb)) +
0))
-#define transport_dport(vdb) *((uint16_t *)((unsigned char*)(payload(vdb)) +
2))
-
/* Queue management */
static void queue_init(struct vder_queue *q)
@@ -60,87 +56,6 @@
qunlimited_setup(q);
}
-static void enqueue(struct vder_queue *q, struct vde_buff *b)
-{
- pthread_mutex_lock(&q->lock);
-
- if (!q->may_enqueue(q, b)) {
- free(b);
- pthread_mutex_unlock(&q->lock);
- return;
- }
-
- b->next = NULL;
- if (!q->head) {
- q->head = b;
- q->tail = b;
- } else {
- q->tail->next = b;
- q->tail = b;
- }
- q->size += b->len;
- q->n++;
- pthread_mutex_unlock(&q->lock);
- if (q->policy != QPOLICY_TOKEN) {
- if (q->type == QTYPE_OUT)
- sem_post(&q->semaphore);
- else
- sem_post(q->prio_semaphore);
- }
-}
-
-static struct vde_buff *prio_dequeue(struct vder_iface *vif)
-{
- struct vder_queue *q;
- int i;
- struct vde_buff *ret = NULL;
- sem_wait(&vif->prio_semaphore);
- for (i = 0; i < PRIO_NUM; i++) {
- q = &(vif->prio_q[i]);
- pthread_mutex_lock(&q->lock);
- if (q->size == 0){
- pthread_mutex_unlock(&q->lock);
- continue;
- }
- if (q->n) {
- ret = q->head;
- q->head = ret->next;
- q->n--;
- q->size -= ret->len;
- if (q->n == 0) {
- q->tail = NULL;
- q->head = NULL;
- }
- pthread_mutex_unlock(&q->lock);
- break;
- }
- pthread_mutex_unlock(&q->lock);
- }
- return ret;
-}
-
-static struct vde_buff *dequeue(struct vder_queue *q)
-{
- struct vde_buff *ret = NULL;
- if (q->type == QTYPE_OUT)
- sem_wait(&q->semaphore);
- else
- return NULL;
- pthread_mutex_lock(&q->lock);
- if (q->n) {
- ret = q->head;
- q->head = ret->next;
- q->n--;
- q->size -= ret->len;
- if (q->n == 0) {
- q->tail = NULL;
- q->head = NULL;
- }
- }
- pthread_mutex_unlock(&q->lock);
- return ret;
-}
-
#define microseconds(tv) (unsigned long long)((tv.tv_sec * 1000000) +
(tv.tv_usec));
static void *vder_timer_loop(void *arg)
@@ -241,6 +156,27 @@
return 0U;
}
+uint32_t vder_get_netmask(struct vder_iface *vif, uint32_t localip)
+{
+ struct vder_ip4address *cur = vif->address_list;
+ while(cur) {
+ if (cur->address == localip)
+ return cur->netmask;
+ cur = cur->next;
+ }
+ return 0U;
+}
+
+uint32_t vder_get_network(uint32_t localip, uint32_t netmask)
+{
+ return (localip & netmask);
+}
+
+uint32_t vder_get_broadcast(uint32_t localip, uint32_t netmask)
+{
+ return (localip | (~netmask));
+}
+
/* insert route, ordered by netmask, metric.
* Default gw will be the last ones.
*/
@@ -543,8 +479,26 @@
return 0;
}
+int vder_ipaddress_is_broadcast(uint32_t addr)
+{
+ struct vder_iface *iface = Router.iflist;
+ if (addr == (uint32_t)(-1))
+ return 1;
+ while (iface) {
+ struct vder_ip4address *cur = iface->address_list;
+ while(cur) {
+ if (((cur->address & cur->netmask) == (addr &
cur->netmask)) && ((cur->netmask | addr) == 0xFFFFFFFF)) {
+ return 1;
+ }
+ cur = cur->next;
+ }
+ iface = iface->next;
+ }
+ return 0;
+}
+
/* IP filter management */
int vder_filter_del(struct vder_iface *src, uint8_t proto,
uint32_t saddr_address, uint32_t saddr_netmask,
Modified: branches/vde-router/vde-2/src/vde_router/vder_datalink.h
===================================================================
--- branches/vde-router/vde-2/src/vde_router/vder_datalink.h 2011-12-21
17:28:47 UTC (rev 526)
+++ branches/vde-router/vde-2/src/vde_router/vder_datalink.h 2011-12-27
14:45:35 UTC (rev 527)
@@ -9,19 +9,26 @@
#include "vde_headers.h"
#include "vde_router.h"
+
/* Global router initialization */
void vderouter_init(void);
/* Route management */
uint32_t vder_get_right_localip(struct vder_iface *vif, uint32_t dst);
+uint32_t vder_get_netmask(struct vder_iface *vif, uint32_t localip);
+uint32_t vder_get_network(uint32_t localip, uint32_t netmask);
+uint32_t vder_get_broadcast(uint32_t localip, uint32_t netmask);
+
int vder_route_add(uint32_t address, uint32_t netmask, uint32_t gateway,
uint16_t metric, struct vder_iface *dst);
int vder_route_del(uint32_t address, uint32_t netmask, int metric);
struct vder_route * vder_get_route(uint32_t address);
int vder_default_route(uint32_t gateway, int metric);
uint32_t vder_get_right_localip(struct vder_iface *vif, uint32_t dst);
int vder_ipaddress_is_local(uint32_t addr);
+int vder_ipaddress_is_broadcast(uint32_t addr);
+
/* Interface management */
struct vder_iface *vder_iface_new(char *sock, uint8_t *macaddr);
@@ -59,4 +66,9 @@
enum filter_action action, uint8_t priority);
int vder_filter(struct vde_buff *buf);
+
+/* Get TCP/UDP header ports */
+#define transport_sport(vdb) *((uint16_t *)((unsigned char*)(payload(vdb)) +
0))
+#define transport_dport(vdb) *((uint16_t *)((unsigned char*)(payload(vdb)) +
2))
+
#endif
Added: branches/vde-router/vde-2/src/vde_router/vder_dhcpd.c
===================================================================
--- branches/vde-router/vde-2/src/vde_router/vder_dhcpd.c
(rev 0)
+++ branches/vde-router/vde-2/src/vde_router/vder_dhcpd.c 2011-12-27
14:45:35 UTC (rev 527)
@@ -0,0 +1,232 @@
+#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);
+ }
+ }
+}
Added: branches/vde-router/vde-2/src/vde_router/vder_dhcpd.h
===================================================================
--- branches/vde-router/vde-2/src/vde_router/vder_dhcpd.h
(rev 0)
+++ branches/vde-router/vde-2/src/vde_router/vder_dhcpd.h 2011-12-27
14:45:35 UTC (rev 527)
@@ -0,0 +1,100 @@
+#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-21
17:28:47 UTC (rev 526)
+++ branches/vde-router/vde-2/src/vde_router/vder_packet.c 2011-12-27
14:45:35 UTC (rev 527)
@@ -6,14 +6,26 @@
#include "vder_datalink.h"
#include "vder_arp.h"
#include "vder_icmp.h"
+#include "vder_udp.h"
#include <sys/poll.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
#define MAX_PACKET_SIZE 2000
+char *vder_ntoa(uint32_t addr)
+{
+ struct in_addr a;
+ char *res;
+ a.s_addr = addr;
+ res = inet_ntoa(a);
+ return res;
+}
+
/*
* Forward the ip packet to next hop. TTL is decreased,
* checksum is set again for coherence, and TTL overdue
@@ -33,7 +45,7 @@
*/
uint16_t net_checksum(void *inbuf, int len)
{
- uint8_t *buf = (uint8_t *) buf;
+ uint8_t *buf = (uint8_t *) inbuf;
uint32_t sum = 0, carry=0;
int i=0;
for(i=0; i<len; i++){
@@ -62,14 +74,25 @@
int vder_ip_input(struct vde_buff *vb)
{
struct iphdr *iph = iphead(vb);
- if (vder_ipaddress_is_local(iph->daddr)) {
- if (iph->protocol == PROTO_ICMP)
+ 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);
- else
- vder_icmp_service_unreachable((uint32_t)iph->saddr,
footprint(vb));
- return 1;
+ recvd=1;
+ break;
+ case PROTO_UDP:
+ if (vder_udp_recv(vb) == 1)
+ recvd=1;
+ break;
}
- return 0;
+ if (!recvd && !is_broadcast)
+ vder_icmp_service_unreachable((uint32_t)iph->saddr,
footprint(vb));
+ return 1;
}
int vder_packet_send(struct vde_buff *vdb, uint32_t dst_ip, uint8_t protocol)
@@ -142,7 +165,7 @@
if (vder_ip_input(packet)) {
/* If the packet is for us, process it here. */
- free(packet);
+ //free(packet);
return;
} else {
struct iphdr *hdr = iphead(packet);
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-21
17:28:47 UTC (rev 526)
+++ branches/vde-router/vde-2/src/vde_router/vder_packet.h 2011-12-27
14:45:35 UTC (rev 527)
@@ -8,8 +8,9 @@
#define DEFAULT_TTL 64
uint16_t vder_ip_checksum(struct iphdr *iph);
-struct vde_buff *vder_packet_recv(struct vder_iface *vif, int timeout);
+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);
+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-21
17:28:47 UTC (rev 526)
+++ branches/vde-router/vde-2/src/vde_router/vder_queue.c 2011-12-27
14:45:35 UTC (rev 527)
@@ -6,6 +6,88 @@
#include "vder_queue.h"
#include "vde_router.h"
#include <stdlib.h>
+
+void enqueue(struct vder_queue *q, struct vde_buff *b)
+{
+ pthread_mutex_lock(&q->lock);
+
+ if (!q->may_enqueue(q, b)) {
+ free(b);
+ pthread_mutex_unlock(&q->lock);
+ return;
+ }
+
+ b->next = NULL;
+ if (!q->head) {
+ q->head = b;
+ q->tail = b;
+ } else {
+ q->tail->next = b;
+ q->tail = b;
+ }
+ q->size += b->len;
+ q->n++;
+ pthread_mutex_unlock(&q->lock);
+ if (q->policy != QPOLICY_TOKEN) {
+ if (q->type != QTYPE_PRIO)
+ sem_post(&q->semaphore);
+ else
+ sem_post(q->prio_semaphore);
+ }
+}
+
+struct vde_buff *prio_dequeue(struct vder_iface *vif)
+{
+ struct vder_queue *q;
+ int i;
+ struct vde_buff *ret = NULL;
+ sem_wait(&vif->prio_semaphore);
+ for (i = 0; i < PRIO_NUM; i++) {
+ q = &(vif->prio_q[i]);
+ pthread_mutex_lock(&q->lock);
+ if (q->size == 0){
+ pthread_mutex_unlock(&q->lock);
+ continue;
+ }
+ if (q->n) {
+ ret = q->head;
+ q->head = ret->next;
+ q->n--;
+ q->size -= ret->len;
+ if (q->n == 0) {
+ q->tail = NULL;
+ q->head = NULL;
+ }
+ pthread_mutex_unlock(&q->lock);
+ break;
+ }
+ pthread_mutex_unlock(&q->lock);
+ }
+ return ret;
+}
+
+struct vde_buff *dequeue(struct vder_queue *q)
+{
+ struct vde_buff *ret = NULL;
+ if (q->type != QTYPE_PRIO)
+ sem_wait(&q->semaphore);
+ else
+ return NULL;
+ pthread_mutex_lock(&q->lock);
+ if (q->n) {
+ ret = q->head;
+ q->head = ret->next;
+ q->n--;
+ q->size -= ret->len;
+ if (q->n == 0) {
+ q->tail = NULL;
+ q->head = NULL;
+ }
+ }
+ pthread_mutex_unlock(&q->lock);
+ return ret;
+}
+
/* Unlimited policy */
int qunlimited_may_enqueue(struct vder_queue *q, struct vde_buff *b)
{
Modified: branches/vde-router/vde-2/src/vde_router/vder_queue.h
===================================================================
--- branches/vde-router/vde-2/src/vde_router/vder_queue.h 2011-12-21
17:28:47 UTC (rev 526)
+++ branches/vde-router/vde-2/src/vde_router/vder_queue.h 2011-12-27
14:45:35 UTC (rev 527)
@@ -8,6 +8,9 @@
#include <stdint.h>
#include "vde_router.h"
#include "vder_datalink.h"
+void enqueue(struct vder_queue *q, struct vde_buff *b);
+struct vde_buff *prio_dequeue(struct vder_iface *vif);
+struct vde_buff *dequeue(struct vder_queue *q);
void qunlimited_setup(struct vder_queue *q);
void qfifo_setup(struct vder_queue *q, uint32_t limit);
Added: branches/vde-router/vde-2/src/vde_router/vder_udp.c
===================================================================
--- branches/vde-router/vde-2/src/vde_router/vder_udp.c
(rev 0)
+++ branches/vde-router/vde-2/src/vde_router/vder_udp.c 2011-12-27 14:45:35 UTC
(rev 527)
@@ -0,0 +1,140 @@
+#include "vder_udp.h"
+#include <stdio.h>
+
+/* UDP header, rfc 768 */
+
+struct __attribute__((packed)) udphdr {
+ uint16_t sport, dport, len, crc;
+};
+
+static struct vder_udp_socket *socket_list = NULL;
+
+
+/* interface toward the router */
+int vder_udp_recv(struct vde_buff *buf)
+{
+ struct vder_udp_socket *cur = socket_list;
+ int found = 0;
+ struct vde_buff *copy = NULL;
+ uint16_t port = transport_dport(buf);
+ while(cur) {
+ if (cur->port == port) {
+ if (!found) {
+ enqueue(&cur->inq, buf);
+ found = 1;
+ } else {
+ copy = malloc(sizeof(struct vde_buff) +
buf->len);
+ if (!copy)
+ break;
+ memcpy(copy, buf, sizeof(struct vde_buff) +
buf->len);
+ enqueue(&cur->inq, copy);
+ }
+ }
+ cur = cur->next;
+ }
+ return found;
+}
+
+struct vder_udp_socket *vder_udpsocket_open(uint16_t port)
+{
+
+ struct vder_udp_socket *vu;
+
+ if (port == 0) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ vu = malloc(sizeof(struct vder_udp_socket));
+ if (!vu)
+ return NULL;
+
+ memset(&vu->inq, 0, sizeof(struct vder_queue));
+ pthread_mutex_init(&vu->inq.lock, NULL);
+ qfifo_setup(&vu->inq, UDPSOCK_BUFFER_SIZE);
+ vu->port = port;
+ vu->next = socket_list;
+ socket_list = vu;
+ return vu;
+}
+
+void vder_udp_close(struct vder_udp_socket *sock)
+{
+ struct vder_udp_socket *prev = NULL, *cur = socket_list;
+ while(cur) {
+ if (cur == sock) {
+ if (!prev) {
+ socket_list = cur->next;
+ } else {
+ prev->next = cur->next;
+ }
+ free(sock);
+ return;
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+}
+
+
+int vder_udpsocket_sendto(struct vder_udp_socket *sock, void *data, size_t
len, uint32_t dst, uint16_t dstport)
+{
+ struct vde_buff *b;
+ struct udphdr *uh;
+ uint8_t *datagram;
+ struct vder_route *ro;
+ int bufsize;
+ if (len <= 0) {
+ errno = EINVAL;
+ return -1;
+ }
+ ro = vder_get_route(dst);
+ if (!ro) {
+ errno = EHOSTUNREACH;
+ return -1;
+ }
+
+ 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_send(b, 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)
+{
+ struct vde_buff *b;
+ struct udphdr *uh;
+ uint8_t *datagram;
+
+ if (len <= 0) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ do {
+ b = dequeue(&sock->inq);
+ } while(!b);
+ uh = (struct udphdr *) payload(b);
+ datagram = (uint8_t *)(payload(b) + sizeof(struct udphdr));
+ if (ntohs(uh->len) < len)
+ len = ntohs(uh->len);
+ memcpy(data, datagram, len);
+ *fromport = uh->sport;
+ return len;
+}
+
+
Added: branches/vde-router/vde-2/src/vde_router/vder_udp.h
===================================================================
--- branches/vde-router/vde-2/src/vde_router/vder_udp.h
(rev 0)
+++ branches/vde-router/vde-2/src/vde_router/vder_udp.h 2011-12-27 14:45:35 UTC
(rev 527)
@@ -0,0 +1,32 @@
+#include "vde_headers.h"
+#include "vde_router.h"
+#include "vder_queue.h"
+#include "vder_datalink.h"
+#include "vder_packet.h"
+#include <stdint.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef __VDER_UDP_H
+#define __VDER_UDP_H
+
+
+struct vder_udp_socket {
+ struct vder_udp_socket *next;
+ uint16_t port;
+ struct vder_queue inq;
+};
+
+#define UDPSOCK_BUFFER_SIZE 1024 * 16
+
+struct vder_udp_socket *get_by_port(uint16_t port);
+
+
+/* interface toward the router */
+int vder_udp_recv(struct vde_buff *buf);
+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);
+
+#endif
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
------------------------------------------------------------------------------
Write once. Port to many.
Get the SDK and tools to simplify cross-platform app development. Create
new or port existing apps to sell to consumers worldwide. Explore the
Intel AppUpSM program developer opportunity. appdeveloper.intel.com/join
http://p.sf.net/sfu/intel-appdev
_______________________________________________
vde-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/vde-users