From 164eb67be3e2dfd16fb533c73b6126f10b4a75ae Mon Sep 17 00:00:00 2001 From: Tarrade Nicolas Date: Fri, 9 Jun 2017 16:59:19 +0200 Subject: [PATCH 1/5] dhcp: create new brick dhcp (not finished) Signed-off-by: Tarrade Nicolas --- include/packetgraph/dhcp.h | 36 ++++++ src/dhcp.c | 195 ++++++++++++++++++++++++++++++++ src/iprange.c | 220 +++++++++++++++++++++++++++++++++++++ 3 files changed, 451 insertions(+) create mode 100644 include/packetgraph/dhcp.h create mode 100644 src/dhcp.c create mode 100644 src/iprange.c diff --git a/include/packetgraph/dhcp.h b/include/packetgraph/dhcp.h new file mode 100644 index 000000000..9c819fb8d --- /dev/null +++ b/include/packetgraph/dhcp.h @@ -0,0 +1,36 @@ +/* Copyright 2017 Outscale SAS + * + * This file is part of Butterfly. + * + * Butterfly is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as published + * by the Free Software Foundation. + * + * Butterfly is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Butterfly. If not, see . + */ + +#ifndef _PG_DHCP_H +#define _PG_DHCP_H + +#include +#include + + +/** + * Create a new dhcp brick. + * dhcp brick allow ip adress to mac adresses + * @name: name of the brick + * @cidr: range of ip adresses + * @errp: set in case of an error + * @return: a pointer to a brick structure on success, NULL on error + **/ + +struct pg_brick *pg_dhcp_new(const char *name, const char *ipcidr, + enum pg_side outside, struct pg_error **errp); + diff --git a/src/dhcp.c b/src/dhcp.c new file mode 100644 index 000000000..be35944c9 --- /dev/null +++ b/src/dhcp.c @@ -0,0 +1,195 @@ +/* Copyright 2017 Outscale SAS + * + * This file is part of Butterfly. + * + * Butterfly is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as published + * by the Free Software Foundation. + * + * Butterfly is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Butterfly. If not, see . + */ + +#include "brick-int.h" +#include "utlis/network.h" +#include "iprange.c" + +struct pg_dhcp_state { + struct pg_brick brick; + struct ether_addr *mac; + struct in_addr_t addr_net; + struct in_addr_t addr_broad; + enum pg_side outside; +} + +struct pg_dhcp_config { + enum pg_side outside; + struct network_addr *cidr; +}; + +static struct pg_brick_config *dhcp_config_new(const char *name, + enum pg_side outside, + const char *cidr) +{ + struct pg_brick_config *config; + struct pg_dhcp_config *dhcp_config; + + dhcp_config = g_new0(struct pg_dhcp_config, 1); + dhcp_config->outside = outside; + network_addr_t ip_cidr; + int ret = str_to_netaddr(cidr, &ipcidr); + if (ret < 0) + return -1; + dhcp_config->cidr = ip_cidr; + config = g_new0(struct pg_brick_config, 1); + config->brick_config = (void *) dhcp_config; + return pg_brick_config_init(config, name, 1, 1, PG_MONOPOLE); +} + +static int dhcp_poll(struct pg_brick *brick, uint16_t *pkts_cnt + struct pg_error **error) +{ + struct pg_dhcp_state *state; + struct rte_mempool *mp = pg_get_mempool(); + struct rte_mbuf **pkts; + struct pg_brick_side *s; + uint64_t pkts_mask; + int ret; + uint16_t i; + + + state = pg_brick_get_state(brick, struct pg_dhcp_state); + + pkts = g_new0(struct, state->packets_nb); + + +} + +static int dhcp_burst(struct pg_brick *brick, enum pg_side from, + uint16_t edge_index, struct rte_mbuf **pkts, + uint64_t pkts_mask, struct pg_error **errp) +{ + struct pg_dhcp_state *state; + struct pg_brick_side *s = &brick->sides[pg_flip_side(from)]; + struct ether_addr mac_pkts = pg_util_get_ether_src_addr(pkst); + int i; + + while(dhcp_state.mac[i] != NULL) + i++; + if (is_request(*pkts)) + dhcp_state.mac[i] = mac_pkts; + return pg_brick_burst(s->edge.link, from, + s->edge.pair_index, pkts, pkts_mask, errp); +} + +static int dhcp_init(struct pg_brick *brick, + struct pg_brick_config *config, + struct pg_error **errp) +{ + struct pg_dhcp_state *state = pg_brick_get_state(brick, + struct pg_dhcp_state); + struct pg_dhcp_config *dhcp_config; + + state = pg_brick_get_state(brick, struct pg_dhcp_state); + + dhcp_config = (struct pg_dhcp_config *) config->brick_config; + state->outside = dhcp_config->outside; + state->mac = g_malloc0(pg_calcul_range_ip(state->cidr) * + sizeof(struct ether_addr)); + state->addr_net = network(dhcp_config->cidr.addr, + config->cidr.pfx); + state->addr_broad = broadcast(dhcp_config->cidr, + config->cidr.pfx); + g_assert(!state->should_be_zero); + + /* initialize fast path */ + brick->burst = dhcp_burst; + + return 0; +} + +int pg_calcul_range_ip(network_addr_t ipcidr) { + return 1 << (32 - (ipcidr.pfx -1)) - 1; +} + +bool is_discover(struct rte_mbuf **pkts) { + bool result = true; + eth_ip_l4 pkt_dest; + pkt_dest->ethernet = pg_util_get_ether_dest_addr(*pkts); + pkt_dest->ipv4 = pg_utils_get_l3(*pkts); + pkt_dest->v4udp = pg_utils_get_l4(*pkts); + + eth_ip_l4 pkt_src; + pkt_src->ethernet = pg_util_get_ether_src_addr(*pkts); + pkt_src->ipv4 = pg_utils_get_l3(*pkts) + 1; + pkt_src->v4udp = pg_utils_get_l4(*pkts) + 1; + + if (pkt_src->ipv4 != "0.0.0.0") + result = false; + if (pkt_src->v4udp != 68) + result = false; + if (pkt_dest->ethernet != "FF:FF:FF:FF:FF:FF") + result = false; + if (pkt_dest->ipv4 != "255.255.255.255") + result = false; + if (pkt_dest->v4udp != 67) + result == false; + return result; +} + +bool is_request(struct rte_mbuf **pkts) { + bool result = true; + eth_ip_l4 pkt_dest; + pkt_dest->ethernet = pg_util_get_ether_dest_addr(*pkts); + pkt_dest->ipv4 = pg_utils_get_l3(*pkts); + pkt_dest->v4udp = pg_utils_get_l4(*pkts); + + eth_ip_l4 pkt_src; + pkt_src->ethernet = pg_util_get_ether_src_addr(*pkts); + pkt_src->ipv4 = pg_utils_get_l3(*pkts) + 1; + pkt_src->v4udp = pg_utils_get_l4(*pkts) + 1; + + if (pkt_src->ipv4 != "0.0.0.0") + result = false; + if (pkt_src->v4udp != 68) + result = false; + if (pkt_dest->ethernet != "FF:FF:FF:FF:FF:FF") + result = false; + if (pkt_dest->ipv4 != "255.255.255.255") + result = false; + if (pkt_dest->v4udp != 67) + result == false; + if (!pg_utils_get_request_ip(*pkts)) + result == false; + return result; +} + +struct pg_brick *pg_dhcp_new(const char *name, const char *ipcidr, + enum pg_side outside, struct pg_error **errp) +{ + struct pg_brick_config *config; + struct pg_brick *ret; + + config = dhcp_config_new(name, ipcidr, outside); + ret = pg_brick_new("dhcp", config, errp); + + pg_brick_config_free(config); + + return ret; +} + +static struct pg_brick_ops dhcp_ops = { + .name = "dhcp", + .state_size = sizeof(struct pg_dhcp_state), + + .init = dhcp_init, + + .unlink = pg_brick_generic_unlink, +}; + +pg_brick_register(dhcp, &dhcp_ops); diff --git a/src/iprange.c b/src/iprange.c new file mode 100644 index 000000000..786a203d2 --- /dev/null +++ b/src/iprange.c @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2003 Gabriel L. Somlo + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * To compile: + * on Linux: + * gcc -o iprange iprange.c -O2 -Wall + * on Solaris 8, Studio 8 CC: + * cc -xO5 -xarch=v8plusa -xdepend iprange.c -o iprange -lnsl -lresolv + * + * CHANGELOG: + * 2004-10-16 Paul Townsend (alpha alpha beta at purdue dot edu) + * - more general input/output formatting + * + */ + +#include +#include +#include +#include +#include +#include +#include + + +static int Jflg = 0; /* = 1 if "-J" specified */ +static char *PROG; + + +/*---------------------------------------------------------------------*/ +/* network address type: one field for the net address, one for prefix */ +/*---------------------------------------------------------------------*/ +typedef struct network_addr { + in_addr_t addr; + int pfx; +} network_addr_t; + + +/*------------------------------------------------------------------*/ +/* Set a bit to a given value (0 or 1); MSB is bit 1, LSB is bit 32 */ +/*------------------------------------------------------------------*/ +in_addr_t set_bit( in_addr_t addr, int bitno, int val ) { + + if ( val ) + return( addr | (1 << (32 - bitno)) ); + else + return( addr & ~(1 << (32 - bitno)) ); + +} /* set_bit() */ + + +/*--------------------------------------*/ +/* Compute netmask address given prefix */ +/*--------------------------------------*/ +in_addr_t netmask( int prefix ) { + + if ( prefix == 0 ) + return( ~((in_addr_t) -1) ); + else + return( ~((1 << (32 - prefix)) - 1) ); + +} /* netmask() */ + + +/*----------------------------------------------------*/ +/* Compute broadcast address given address and prefix */ +/*----------------------------------------------------*/ +in_addr_t broadcast( in_addr_t addr, int prefix ) { + + return( addr | ~netmask(prefix) ); + +} /* broadcast() */ + + +/*--------------------------------------------------*/ +/* Compute network address given address and prefix */ +/*--------------------------------------------------*/ +in_addr_t network( in_addr_t addr, int prefix ) { + + return( addr & netmask(prefix) ); + +} /* network() */ + + +/*------------------------------------------------*/ +/* Print out a 32-bit address in A.B.C.D/M format */ +/*------------------------------------------------*/ +void print_addr( in_addr_t addr, int prefix ) { + + struct in_addr in; + + in.s_addr = htonl( addr ); + if ( prefix < 32 ) + printf( "%s/%d\n", inet_ntoa(in), prefix ); + else + printf( "%s\n", inet_ntoa(in)); + +} /* print_addr() */ + + +/*------------------------------------------------------------*/ +/* Recursively compute network addresses to cover range lo-hi */ +/*------------------------------------------------------------*/ +/* Note: Worst case scenario is when lo=0.0.0.1 and hi=255.255.255.254 + * * We then have 62 CIDR bloks to cover this interval, and 125 + * * calls to split_range(); + * * The maximum possible recursion depth is 32. + * */ +int split_range( in_addr_t addr, int prefix, in_addr_t lo, in_addr_t hi ) { + + in_addr_t bc, lower_half, upper_half; + + if ( (prefix < 0) || (prefix > 32) ) { + fprintf( stderr, "%s: Invalid mask size %d!\n", PROG, prefix ); + return -1; + } + + bc = broadcast(addr, prefix); + + if ( (lo < addr) || (hi > bc) ) { + fprintf( stderr, "%s: Out of range limits: %x, %x for " + "network %x/%d, broadcast: %x!\n", + PROG, lo, hi, addr, prefix, bc ); + return -1; + } + + if ( (lo == addr) && (hi == bc) ) { + print_addr( addr, prefix ); + return; + } + + prefix++; + lower_half = addr; + upper_half = set_bit( addr, prefix, 1 ); + + if ( hi < upper_half ) { + split_range( lower_half, prefix, lo, hi ); + } else if ( lo >= upper_half ) { + split_range( upper_half, prefix, lo, hi ); + } else { + split_range( lower_half, prefix, lo, broadcast(lower_half, prefix) ); + split_range( upper_half, prefix, upper_half, hi ); + } + +} /* split_range() */ + + +/*-----------------------------------------------------------*/ +/* Convert an A.B.C.D address into a 32-bit host-order value */ +/*-----------------------------------------------------------*/ +in_addr_t a_to_hl( char *ipstr ) { + + struct in_addr in; + if ( !inet_aton(ipstr, &in) ) { + fprintf( stderr, "%s: Invalid address %s!\n", PROG, ipstr ); + exit( 1 ); + } + + return( ntohl(in.s_addr) ); + +} /* a_to_hl() */ + + +/*-----------------------------------------------------------------*/ +/* convert a network address char string into a host-order network */ +/* address and an integer prefix value */ +/*-----------------------------------------------------------------*/ +int str_to_netaddr( char *ipstr, network_addr_t *netaddr) { + + long int prefix = 32; + char *prefixstr; + + if ( (prefixstr = strchr(ipstr, '/')) ) { + *prefixstr = '\0'; + prefixstr++; + prefix = strtol( prefixstr, (char **) NULL, 10 ); + if ( errno || (*prefixstr == '\0') || (prefix < 0) || (prefix > 32) ) { + fprintf( stderr, "%s: Invalid prefix /%s...!\n", PROG, prefixstr ); + return -1; + } + } + + *netaddr.pfx = (int) prefix; + *netaddr.addr = network( a_to_hl(ipstr), prefix ); + + return 0; + +} /* str_to_netaddr() */ + +/*------------------------------------------------------*/ +/* Print out an address range in a.b.c.d-A.B.C.D format */ +/*------------------------------------------------------*/ +void print_addr_range( in_addr_t lo, in_addr_t hi ) { + + struct in_addr in; + + if ( lo != hi ) { + in.s_addr = htonl( lo ); + printf( "%s-", inet_ntoa(in) ); + } + + in.s_addr = htonl( hi ); + printf( "%s\n", inet_ntoa(in) ); + +} /* print_addr_range() */ + +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ + From 245b64a34b191714aeed6e74c1f1ab7cf84e5436 Mon Sep 17 00:00:00 2001 From: Tarrade Nicolas Date: Fri, 4 Aug 2017 11:10:23 +0200 Subject: [PATCH 2/5] Makefile: add dhcp Signed-off-by: Tarrade Nicolas --- Makefile.am | 20 ++- configure_clang | 2 +- include/packetgraph/dhcp.h | 32 +++- include/packetgraph/packetgraph.h | 2 + src/dhcp.c | 262 +++++++++++++++++++++--------- src/iprange.c | 80 ++------- src/packets.c | 7 + 7 files changed, 253 insertions(+), 152 deletions(-) diff --git a/Makefile.am b/Makefile.am index 7f323cb92..aff07ecf7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -37,7 +37,9 @@ libpacketgraph_la_SOURCES = \ src/switch.c\ src/pmtud.c\ src/thread.c\ - src/ip-fragment.c + src/ip-fragment.c\ + src/iprange.c\ + src/dhcp.c pkginclude_HEADERS = \ include/packetgraph/common.h\ @@ -63,7 +65,8 @@ pkginclude_HEADERS = \ include/packetgraph/queue.h\ include/packetgraph/pmtud.h\ include/packetgraph/ip-fragment.h\ - include/packetgraph/errors.h + include/packetgraph/errors.h\ + include/packetgraph/dhcp.h libpacketgraph_la_LIBADD = $(RTE_SDK_LIBS) $(GLIB_LIBS) # FIXME '^pg_[^_]' does not take all symbols needed (i.e. __pg_error_*) @@ -76,7 +79,7 @@ include npfmakefile.am dist_doc_DATA = README.md -check_PROGRAMS = tests-antispoof tests-core tests-diode tests-rxtx tests-firewall tests-integration tests-nic tests-print tests-queue tests-switch tests-vhost tests-vtep tests-pmtud tests-tap tests-ip-fragment tests-thread +check_PROGRAMS = tests-antispoof tests-core tests-diode tests-rxtx tests-firewall tests-integration tests-nic tests-print tests-queue tests-switch tests-vhost tests-vtep tests-pmtud tests-tap tests-ip-fragment tests-thread tests-dhcp noinst_LTLIBRARIES += libpacketgraph-dev.la libpacketgraph_dev_la_SOURCES = $(libpacketgraph_la_SOURCES) @@ -195,6 +198,12 @@ tests_thread_CFLAGS = $(libpacketgraph_dev_la_CFLAGS) tests_thread_LDFLAGS = libpacketgraph-dev.la EXTRA_tests_thread_DEPENDENCIES = libpacketgraph-dev.la +tests_dhcp_SOURCES = \ + tests/dhcp/tests.c +tests_dhcp_CFLAGS = $(libpacketgraph_dev_la_CFLAGS) +tests_dhcp_LDFLAGS = libpacketgraph-dev.la +EXTRA_tests_thread_DEPENDENCIES = libpacketgraph-dev.la + TESTS = \ tests/antispoof/test.sh\ tests/core/test.sh\ @@ -211,7 +220,8 @@ TESTS = \ tests/tap/test.sh\ tests/thread/test.sh\ tests/integration/test.sh\ - tests/vhost/test.sh + tests/vhost/test.sh\ + tests/dhcp/test.sh noinst_PROGRAMS = @@ -408,4 +418,4 @@ doc: doxygen.conf $(srcdir)/doc/deploy_documentation.sh # libtoolize recommanded this -ACLOCAL_AMFLAGS = -I m4 +ACLOCAL_AMFLAGS = -I diff --git a/configure_clang b/configure_clang index bd8438867..0b502935f 100755 --- a/configure_clang +++ b/configure_clang @@ -4,4 +4,4 @@ export AR="llvm-ar" export NM="llvm-nm" export RANLIB="llvm-ranlib" root=$(cd "$(dirname $0)" && pwd) -$root/configure ${@:1} +$root/configure CFLAGS="-O0 -g" ${@:1} diff --git a/include/packetgraph/dhcp.h b/include/packetgraph/dhcp.h index 9c819fb8d..05f024971 100644 --- a/include/packetgraph/dhcp.h +++ b/include/packetgraph/dhcp.h @@ -20,7 +20,7 @@ #include #include - +#include /** * Create a new dhcp brick. @@ -31,6 +31,32 @@ * @return: a pointer to a brick structure on success, NULL on error **/ -struct pg_brick *pg_dhcp_new(const char *name, const char *ipcidr, - enum pg_side outside, struct pg_error **errp); +struct pg_brick *pg_dhcp_new(const char *name, const char *cidr, + struct pg_error **errp); + + +/** + * Calculate the number of potential adresses + * @ipcidr : ip adress with cidr to calculate the range + */ +int pg_calcul_range_ip(network_addr_t ipcidr); + +/** + * Check if a packet is a dhcp discover packet + * @pkts : the packet to check + */ +bool is_discover(struct rte_mbuf *pkts); + +/** + * Check if a packet is a dhcp discover packet + * @pkts : the packet to check + */ +bool is_request(struct rte_mbuf *pkts); + +/** + * Print all the mac adresses register + * @dhcp : brick dhcp + */ +void pg_print_allocate_macs(struct pg_brick *dhcp); +#endif /* _PG_DHCP_H */ diff --git a/include/packetgraph/packetgraph.h b/include/packetgraph/packetgraph.h index cd1837192..772d30748 100644 --- a/include/packetgraph/packetgraph.h +++ b/include/packetgraph/packetgraph.h @@ -42,5 +42,7 @@ #include #include #include +#include +#include #endif /* _PG_PACKETGRAPH_H */ diff --git a/src/dhcp.c b/src/dhcp.c index be35944c9..da5ff2cc4 100644 --- a/src/dhcp.c +++ b/src/dhcp.c @@ -15,59 +15,94 @@ * along with Butterfly. If not, see . */ +#include +#include +#include +#include +#include + +#include +#include "utils/bitmask.h" +#include "utils/mempool.h" +#include "packets.h" #include "brick-int.h" -#include "utlis/network.h" -#include "iprange.c" +#include "utils/network.h" +#include "src/npf/npf/dpdk/npf_dpdk.h" + +#define DHCP_SIDE_TO_NPF(side) \ + ((side) == PG_WEST_SIDE ? PFIL_OUT : PFIL_IN) + +bool eth_compare(uint8_t eth1[6], uint8_t eth2[6]); + +struct dhcp_messages_payload { + uint8_t op; + uint8_t htype; + uint8_t hlen; + uint8_t hops; + uint32_t xid; + uint16_t secs; + uint16_t flags; + struct ether_addr ciaddr; + struct ether_addr yiaddr; + struct ether_addr siaddr; + struct ether_addr giaddr; + struct ether_addr mac_client; + char * server_name; + char * file; + uint8_t dhcp_m_type; + struct ether_addr client_id; + uint8_t *options; +}; struct pg_dhcp_state { struct pg_brick brick; - struct ether_addr *mac; - struct in_addr_t addr_net; - struct in_addr_t addr_broad; - enum pg_side outside; -} + struct ether_addr **mac; + in_addr_t addr_net; + in_addr_t addr_broad; + int *check_ip; +}; struct pg_dhcp_config { - enum pg_side outside; - struct network_addr *cidr; + struct network_addr cidr; }; static struct pg_brick_config *dhcp_config_new(const char *name, - enum pg_side outside, const char *cidr) { + char cidrip[17]; + strcpy(cidrip, cidr); struct pg_brick_config *config; struct pg_dhcp_config *dhcp_config; - dhcp_config = g_new0(struct pg_dhcp_config, 1); - dhcp_config->outside = outside; network_addr_t ip_cidr; - int ret = str_to_netaddr(cidr, &ipcidr); - if (ret < 0) - return -1; + int ret = str_to_netaddr(cidrip, &ip_cidr); + if(ret == -1) + printf("error registering\n"); + print_addr(ip_cidr.addr, ip_cidr.pfx); dhcp_config->cidr = ip_cidr; + print_addr(dhcp_config->cidr.addr, dhcp_config->cidr.pfx); config = g_new0(struct pg_brick_config, 1); config->brick_config = (void *) dhcp_config; return pg_brick_config_init(config, name, 1, 1, PG_MONOPOLE); } -static int dhcp_poll(struct pg_brick *brick, uint16_t *pkts_cnt +static int dhcp_poll(struct pg_brick *brick, uint16_t *pkts_cnt, struct pg_error **error) { - struct pg_dhcp_state *state; - struct rte_mempool *mp = pg_get_mempool(); - struct rte_mbuf **pkts; - struct pg_brick_side *s; - uint64_t pkts_mask; - int ret; - uint16_t i; + //struct pg_dhcp_state *state; + //struct rte_mempool *mp = pg_get_mempool(); + //struct rte_mbuf **pkts; + //struct pg_brick_side *s; + //uint64_t pkts_mask; + //int ret; + //uint16_t i; - state = pg_brick_get_state(brick, struct pg_dhcp_state); + //state = pg_brick_get_state(brick, struct pg_dhcp_state); - pkts = g_new0(struct, state->packets_nb); + //pkts = g_new0(struct, state->packets_nb); - + return 0; } static int dhcp_burst(struct pg_brick *brick, enum pg_side from, @@ -76,15 +111,46 @@ static int dhcp_burst(struct pg_brick *brick, enum pg_side from, { struct pg_dhcp_state *state; struct pg_brick_side *s = &brick->sides[pg_flip_side(from)]; - struct ether_addr mac_pkts = pg_util_get_ether_src_addr(pkst); - int i; + struct ether_addr *mac_pkts; + uint64_t it_mask; + uint64_t bit; + struct rte_mbuf *tmp; + uint16_t ether_type; + uint16_t pkts_cnt = 1; + uint16_t i; + int j; - while(dhcp_state.mac[i] != NULL) - i++; - if (is_request(*pkts)) - dhcp_state.mac[i] = mac_pkts; + state = pg_brick_get_state(brick, struct pg_dhcp_state); + + it_mask = pkts_mask; + for (; it_mask;) { + j = 0; + pg_low_bit_iterate_full(it_mask, bit, i); + tmp = pkts[i]; + struct ether_hdr *ethernet = (struct ether_hdr *) + rte_pktmbuf_mtod(tmp, char *); + ether_type = pg_utils_get_ether_type(tmp); + /* DHCP only manage IPv4 adressing + * Let non-ip packets (like ARP) pass. + */ + if (unlikely(ether_type != PG_BE_ETHER_TYPE_IPv4)) { + continue; + } + if (RTE_ETH_IS_IPV4_HDR(tmp->packet_type)) { + if (((tmp->packet_type) & RTE_PTYPE_L4_UDP)) { + if (is_request(tmp)) { + while(state->check_ip[j] == 0) + j++; + mac_pkts = ðernet->s_addr; + state->mac[j] = mac_pkts; + dhcp_poll(brick, &pkts_cnt, errp); + } + } + } + } return pg_brick_burst(s->edge.link, from, s->edge.pair_index, pkts, pkts_mask, errp); + } static int dhcp_init(struct pg_brick *brick, @@ -98,15 +164,18 @@ static int dhcp_init(struct pg_brick *brick, state = pg_brick_get_state(brick, struct pg_dhcp_state); dhcp_config = (struct pg_dhcp_config *) config->brick_config; - state->outside = dhcp_config->outside; - state->mac = g_malloc0(pg_calcul_range_ip(state->cidr) * + state->mac = g_malloc0(pg_calcul_range_ip(dhcp_config->cidr) * sizeof(struct ether_addr)); state->addr_net = network(dhcp_config->cidr.addr, - config->cidr.pfx); - state->addr_broad = broadcast(dhcp_config->cidr, - config->cidr.pfx); - g_assert(!state->should_be_zero); + dhcp_config->cidr.pfx); + state->addr_broad = broadcast(dhcp_config->cidr.addr, + dhcp_config->cidr.pfx); + state->check_ip = g_malloc0(pg_calcul_range_ip(dhcp_config->cidr) * + sizeof(bool)); + for (int i = 0 ; i < pg_calcul_range_ip(dhcp_config->cidr); i++) { + state->check_ip[i] = 0; + } /* initialize fast path */ brick->burst = dhcp_burst; @@ -114,68 +183,113 @@ static int dhcp_init(struct pg_brick *brick, } int pg_calcul_range_ip(network_addr_t ipcidr) { - return 1 << (32 - (ipcidr.pfx -1)) - 1; + return 1 << ((32 - (ipcidr.pfx - 1)) - 1); } -bool is_discover(struct rte_mbuf **pkts) { +bool is_discover(struct rte_mbuf *pkts) { bool result = true; - eth_ip_l4 pkt_dest; - pkt_dest->ethernet = pg_util_get_ether_dest_addr(*pkts); - pkt_dest->ipv4 = pg_utils_get_l3(*pkts); - pkt_dest->v4udp = pg_utils_get_l4(*pkts); + /*struct eth_ip_l4 pkt_dest; + pkt_dest.ethernet = (rte_pktmbuf_mtod(pkts, struct ether_addr *)); + pkt_dest.ipv4 = pg_utils_get_l3(pkts); + pkt_dest.v4udp = pg_utils_get_l4(pkts); - eth_ip_l4 pkt_src; - pkt_src->ethernet = pg_util_get_ether_src_addr(*pkts); - pkt_src->ipv4 = pg_utils_get_l3(*pkts) + 1; - pkt_src->v4udp = pg_utils_get_l4(*pkts) + 1; + struct eth_ip_l4 pkt_src; + pkt_src.ethernet = (rte_pktmbuf_mtod(pkts, struct ether_addr *) + 1); + pkt_src.ipv4 = pg_utils_get_l3(pkts) + 1; + pkt_src.v4udp = pg_utils_get_l4(pkts) + 1; - if (pkt_src->ipv4 != "0.0.0.0") + if (pkt_src.ipv4 != "0.0.0.0") result = false; - if (pkt_src->v4udp != 68) + if (pkt_src.v4udp != 68) result = false; - if (pkt_dest->ethernet != "FF:FF:FF:FF:FF:FF") + if (pkt_dest.ethernet != "FF:FF:FF:FF:FF:FF") result = false; - if (pkt_dest->ipv4 != "255.255.255.255") + if (pkt_dest.ipv4 != "255.255.255.255") result = false; - if (pkt_dest->v4udp != 67) - result == false; + if (pkt_dest.v4udp != 67) + result == false;*/ return result; } -bool is_request(struct rte_mbuf **pkts) { +bool eth_compare(uint8_t eth1[6], uint8_t eth2[6]) { bool result = true; - eth_ip_l4 pkt_dest; - pkt_dest->ethernet = pg_util_get_ether_dest_addr(*pkts); - pkt_dest->ipv4 = pg_utils_get_l3(*pkts); - pkt_dest->v4udp = pg_utils_get_l4(*pkts); + for(int i = 0; i < 6 ; i++) { + if (eth1[i] != eth2[i]) + result = false; + } + return result; +} - eth_ip_l4 pkt_src; - pkt_src->ethernet = pg_util_get_ether_src_addr(*pkts); - pkt_src->ipv4 = pg_utils_get_l3(*pkts) + 1; - pkt_src->v4udp = pg_utils_get_l4(*pkts) + 1; +bool is_request(struct rte_mbuf *pkts) { - if (pkt_src->ipv4 != "0.0.0.0") + bool result = true; + uint8_t eth_dest[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + uint8_t eth_src[6] = {0x00, 0x18, 0xb9, 0x56, 0x2e, 0x73}; + uint32_t ip_dest; + inet_pton(AF_INET, "255.255.255.255", &ip_dest); + uint32_t ip_src; + inet_pton(AF_INET, "0.0.0.0", &ip_src); + uint16_t udp_dest = 67; + uint16_t udp_src = 68; + uint8_t dhcp_mes_type = 3; + + struct ether_hdr *ethernet = (struct ether_hdr *) rte_pktmbuf_mtod(pkts, char *); + struct ipv4_hdr *ip = (struct ipv4_hdr *) pg_utils_get_l3(pkts); + struct udp_hdr *udp = (struct udp_hdr *) pg_utils_get_l4(pkts); + struct dhcp_messages_payload *dhcp_hdr = (struct dhcp_messages_payload *) + rte_pktmbuf_mtod(pkts, char *) + + pkts->l2_len + pkts->l3_len + pkts->l4_len; + + if (eth_compare(ethernet->d_addr.addr_bytes, eth_dest) == false) result = false; - if (pkt_src->v4udp != 68) + + if (eth_compare(ethernet->s_addr.addr_bytes, eth_src) == false) result = false; - if (pkt_dest->ethernet != "FF:FF:FF:FF:FF:FF") + + if (ip->dst_addr != ip_dest) result = false; - if (pkt_dest->ipv4 != "255.255.255.255") + + printf("ip dest : %u \n", ip->dst_addr); + printf("ip dest2 : %u \n", ip_dest); + printf("%d\n", result); + + if (ip->src_addr != ip_src) result = false; - if (pkt_dest->v4udp != 67) - result == false; - if (!pg_utils_get_request_ip(*pkts)) - result == false; + + printf("ip src : %u \n", ip->src_addr); + printf("ip src : %u \n", ip_src); + printf("%d\n", result); + + if (rte_be_to_cpu_16(udp->dst_port) != udp_dest) + result = false; + + printf("udp dest : %u \n", udp->dst_port); + printf("udp dest2 : %u \n", udp_dest); + printf("%d\n", result); + + if (rte_be_to_cpu_16(udp->src_port) != udp_src) + result = false; + + printf("udp src : %u \n", udp->src_port); + printf("udp src2 : %u \n", udp_src); + printf("%d\n", result); + + if (dhcp_hdr->dhcp_m_type != dhcp_mes_type) + result = false; + printf("dhcp_messages type : %u \n", dhcp_hdr->dhcp_m_type); + printf("dhcp_messages type2 : %u \n", dhcp_mes_type); + + printf("%d\n", result); return result; } -struct pg_brick *pg_dhcp_new(const char *name, const char *ipcidr, - enum pg_side outside, struct pg_error **errp) +struct pg_brick *pg_dhcp_new(const char *name, const char *cidr, + struct pg_error **errp) { struct pg_brick_config *config; struct pg_brick *ret; - config = dhcp_config_new(name, ipcidr, outside); + config = dhcp_config_new(name, cidr); ret = pg_brick_new("dhcp", config, errp); pg_brick_config_free(config); diff --git a/src/iprange.c b/src/iprange.c index 786a203d2..07a31a237 100644 --- a/src/iprange.c +++ b/src/iprange.c @@ -32,21 +32,10 @@ #include #include #include +#include - -static int Jflg = 0; /* = 1 if "-J" specified */ static char *PROG; - -/*---------------------------------------------------------------------*/ -/* network address type: one field for the net address, one for prefix */ -/*---------------------------------------------------------------------*/ -typedef struct network_addr { - in_addr_t addr; - int pfx; -} network_addr_t; - - /*------------------------------------------------------------------*/ /* Set a bit to a given value (0 or 1); MSB is bit 1, LSB is bit 32 */ /*------------------------------------------------------------------*/ @@ -108,59 +97,10 @@ void print_addr( in_addr_t addr, int prefix ) { } /* print_addr() */ - -/*------------------------------------------------------------*/ -/* Recursively compute network addresses to cover range lo-hi */ -/*------------------------------------------------------------*/ -/* Note: Worst case scenario is when lo=0.0.0.1 and hi=255.255.255.254 - * * We then have 62 CIDR bloks to cover this interval, and 125 - * * calls to split_range(); - * * The maximum possible recursion depth is 32. - * */ -int split_range( in_addr_t addr, int prefix, in_addr_t lo, in_addr_t hi ) { - - in_addr_t bc, lower_half, upper_half; - - if ( (prefix < 0) || (prefix > 32) ) { - fprintf( stderr, "%s: Invalid mask size %d!\n", PROG, prefix ); - return -1; - } - - bc = broadcast(addr, prefix); - - if ( (lo < addr) || (hi > bc) ) { - fprintf( stderr, "%s: Out of range limits: %x, %x for " - "network %x/%d, broadcast: %x!\n", - PROG, lo, hi, addr, prefix, bc ); - return -1; - } - - if ( (lo == addr) && (hi == bc) ) { - print_addr( addr, prefix ); - return; - } - - prefix++; - lower_half = addr; - upper_half = set_bit( addr, prefix, 1 ); - - if ( hi < upper_half ) { - split_range( lower_half, prefix, lo, hi ); - } else if ( lo >= upper_half ) { - split_range( upper_half, prefix, lo, hi ); - } else { - split_range( lower_half, prefix, lo, broadcast(lower_half, prefix) ); - split_range( upper_half, prefix, upper_half, hi ); - } - -} /* split_range() */ - - /*-----------------------------------------------------------*/ /* Convert an A.B.C.D address into a 32-bit host-order value */ /*-----------------------------------------------------------*/ -in_addr_t a_to_hl( char *ipstr ) { - +in_addr_t a_to_hl(const char *ipstr ) { struct in_addr in; if ( !inet_aton(ipstr, &in) ) { fprintf( stderr, "%s: Invalid address %s!\n", PROG, ipstr ); @@ -176,24 +116,26 @@ in_addr_t a_to_hl( char *ipstr ) { /* convert a network address char string into a host-order network */ /* address and an integer prefix value */ /*-----------------------------------------------------------------*/ -int str_to_netaddr( char *ipstr, network_addr_t *netaddr) { - +int str_to_netaddr(const char *ipstr, network_addr_t *netaddr) { long int prefix = 32; char *prefixstr; - + if ( (prefixstr = strchr(ipstr, '/')) ) { *prefixstr = '\0'; prefixstr++; prefix = strtol( prefixstr, (char **) NULL, 10 ); - if ( errno || (*prefixstr == '\0') || (prefix < 0) || (prefix > 32) ) { + printf("prefix %i\n", (int) prefix); + if ((*prefixstr == '\0') || (prefix < 0) || (prefix > 32)) { fprintf( stderr, "%s: Invalid prefix /%s...!\n", PROG, prefixstr ); return -1; } } + else { + printf("no prefix"); + } - *netaddr.pfx = (int) prefix; - *netaddr.addr = network( a_to_hl(ipstr), prefix ); - + netaddr->pfx = (int) prefix; + netaddr->addr = network( a_to_hl(ipstr), prefix ); return 0; } /* str_to_netaddr() */ diff --git a/src/packets.c b/src/packets.c index 637d3ce21..e41051d7e 100644 --- a/src/packets.c +++ b/src/packets.c @@ -134,7 +134,9 @@ struct rte_mbuf **pg_packets_prepend_str(struct rte_mbuf **pkts, ip_hdr.hdr_checksum = 0; \ ip_hdr.next_proto_id = proto; \ ip_hdr.src_addr = src_ip; \ + printf(" src_ip %u \n", ip_hdr.src_addr); \ ip_hdr.dst_addr = dst_ip; \ + printf(" dst_ip %u \n", ip_hdr.dst_addr); \ ip_hdr.fragment_offset = \ rte_cpu_to_be_16(IPV4_HDR_DF_FLAG); \ ip_hdr.hdr_checksum = rte_ipv4_cksum(&ip_hdr); \ @@ -142,6 +144,7 @@ struct rte_mbuf **pg_packets_prepend_str(struct rte_mbuf **pkts, if (!tmp) \ return NULL; \ rte_memcpy(tmp, &ip_hdr, sizeof(ip_hdr)); \ + pkts[j]->packet_type += 16; \ pkts[j]->l3_len = sizeof(struct ipv4_hdr); \ } \ @@ -208,12 +211,15 @@ struct rte_mbuf **pg_packets_append_ipv6(struct rte_mbuf **pkts, if (!pkts[j]) \ continue; \ udp_hdr.src_port = rte_cpu_to_be_16(src_port); \ + printf(" udp src %u \n", rte_be_to_cpu_16(udp_hdr.src_port)); \ udp_hdr.dst_port = rte_cpu_to_be_16(dst_port); \ + printf(" udp dest %u \n", rte_be_to_cpu_16(udp_hdr.dst_port)); \ udp_hdr.dgram_len = rte_cpu_to_be_16(datagram_len); \ udp_hdr.dgram_cksum = 0; \ tmp = rte_pktmbuf_##ops(pkts[j], sizeof(udp_hdr)); \ if (!tmp) \ return NULL; \ + pkts[j]->packet_type += 512; \ memcpy(tmp, &udp_hdr, sizeof(udp_hdr)); \ } \ @@ -286,6 +292,7 @@ struct rte_mbuf **pg_packets_prepend_vxlan(struct rte_mbuf **pkts, if (!tmp) \ return NULL; \ rte_memcpy(tmp, ð_hdr, sizeof(eth_hdr)); \ + pkts[j]->packet_type += 1; \ pkts[j]->l2_len = sizeof(struct ether_hdr); \ } \ From cb46a2c40fa749d9601d90fdbf0f2705305c2398 Mon Sep 17 00:00:00 2001 From: Tarrade Nicolas Date: Mon, 7 Aug 2017 16:58:12 +0200 Subject: [PATCH 3/5] tests: add dhcp tests Signed-off-by: Tarrade Nicolas --- configure_clang | 3 --- src/dhcp.c | 29 +++++------------------------ src/iprange.c | 1 - src/packets.c | 5 +---- 4 files changed, 6 insertions(+), 32 deletions(-) diff --git a/configure_clang b/configure_clang index 0b502935f..bd35e987e 100755 --- a/configure_clang +++ b/configure_clang @@ -1,7 +1,4 @@ #!/bin/bash export CC="clang" -export AR="llvm-ar" -export NM="llvm-nm" -export RANLIB="llvm-ranlib" root=$(cd "$(dirname $0)" && pwd) $root/configure CFLAGS="-O0 -g" ${@:1} diff --git a/src/dhcp.c b/src/dhcp.c index da5ff2cc4..5877a4080 100644 --- a/src/dhcp.c +++ b/src/dhcp.c @@ -139,10 +139,10 @@ static int dhcp_burst(struct pg_brick *brick, enum pg_side from, if (RTE_ETH_IS_IPV4_HDR(tmp->packet_type)) { if (((tmp->packet_type) & RTE_PTYPE_L4_UDP)) { if (is_request(tmp)) { - while(state->check_ip[j] == 0) + while(state->check_ip[j] != 0) j++; - mac_pkts = ðernet->s_addr; - state->mac[j] = mac_pkts; + mac_pkts = ðernet->s_addr; + state->mac[j] = mac_pkts; dhcp_poll(brick, &pkts_cnt, errp); } } @@ -232,13 +232,13 @@ bool is_request(struct rte_mbuf *pkts) { uint16_t udp_dest = 67; uint16_t udp_src = 68; uint8_t dhcp_mes_type = 3; + uint32_t hdrs_len = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) + sizeof(struct udp_hdr); struct ether_hdr *ethernet = (struct ether_hdr *) rte_pktmbuf_mtod(pkts, char *); struct ipv4_hdr *ip = (struct ipv4_hdr *) pg_utils_get_l3(pkts); struct udp_hdr *udp = (struct udp_hdr *) pg_utils_get_l4(pkts); struct dhcp_messages_payload *dhcp_hdr = (struct dhcp_messages_payload *) - rte_pktmbuf_mtod(pkts, char *) - + pkts->l2_len + pkts->l3_len + pkts->l4_len; + rte_pktmbuf_mtod_offset(pkts, char *, hdrs_len); if (eth_compare(ethernet->d_addr.addr_bytes, eth_dest) == false) result = false; @@ -249,37 +249,18 @@ bool is_request(struct rte_mbuf *pkts) { if (ip->dst_addr != ip_dest) result = false; - printf("ip dest : %u \n", ip->dst_addr); - printf("ip dest2 : %u \n", ip_dest); - printf("%d\n", result); - if (ip->src_addr != ip_src) result = false; - printf("ip src : %u \n", ip->src_addr); - printf("ip src : %u \n", ip_src); - printf("%d\n", result); - if (rte_be_to_cpu_16(udp->dst_port) != udp_dest) result = false; - printf("udp dest : %u \n", udp->dst_port); - printf("udp dest2 : %u \n", udp_dest); - printf("%d\n", result); - if (rte_be_to_cpu_16(udp->src_port) != udp_src) result = false; - printf("udp src : %u \n", udp->src_port); - printf("udp src2 : %u \n", udp_src); - printf("%d\n", result); - if (dhcp_hdr->dhcp_m_type != dhcp_mes_type) result = false; - printf("dhcp_messages type : %u \n", dhcp_hdr->dhcp_m_type); - printf("dhcp_messages type2 : %u \n", dhcp_mes_type); - printf("%d\n", result); return result; } diff --git a/src/iprange.c b/src/iprange.c index 07a31a237..b9b4cec71 100644 --- a/src/iprange.c +++ b/src/iprange.c @@ -124,7 +124,6 @@ int str_to_netaddr(const char *ipstr, network_addr_t *netaddr) { *prefixstr = '\0'; prefixstr++; prefix = strtol( prefixstr, (char **) NULL, 10 ); - printf("prefix %i\n", (int) prefix); if ((*prefixstr == '\0') || (prefix < 0) || (prefix > 32)) { fprintf( stderr, "%s: Invalid prefix /%s...!\n", PROG, prefixstr ); return -1; diff --git a/src/packets.c b/src/packets.c index e41051d7e..9a45f500c 100644 --- a/src/packets.c +++ b/src/packets.c @@ -134,9 +134,7 @@ struct rte_mbuf **pg_packets_prepend_str(struct rte_mbuf **pkts, ip_hdr.hdr_checksum = 0; \ ip_hdr.next_proto_id = proto; \ ip_hdr.src_addr = src_ip; \ - printf(" src_ip %u \n", ip_hdr.src_addr); \ ip_hdr.dst_addr = dst_ip; \ - printf(" dst_ip %u \n", ip_hdr.dst_addr); \ ip_hdr.fragment_offset = \ rte_cpu_to_be_16(IPV4_HDR_DF_FLAG); \ ip_hdr.hdr_checksum = rte_ipv4_cksum(&ip_hdr); \ @@ -211,14 +209,13 @@ struct rte_mbuf **pg_packets_append_ipv6(struct rte_mbuf **pkts, if (!pkts[j]) \ continue; \ udp_hdr.src_port = rte_cpu_to_be_16(src_port); \ - printf(" udp src %u \n", rte_be_to_cpu_16(udp_hdr.src_port)); \ udp_hdr.dst_port = rte_cpu_to_be_16(dst_port); \ - printf(" udp dest %u \n", rte_be_to_cpu_16(udp_hdr.dst_port)); \ udp_hdr.dgram_len = rte_cpu_to_be_16(datagram_len); \ udp_hdr.dgram_cksum = 0; \ tmp = rte_pktmbuf_##ops(pkts[j], sizeof(udp_hdr)); \ if (!tmp) \ return NULL; \ + pkts[j]->l4_len = sizeof(struct udp_hdr); \ pkts[j]->packet_type += 512; \ memcpy(tmp, &udp_hdr, sizeof(udp_hdr)); \ } \ From b3e706eb52dbfc4d2c2d16ed57734db9a69e3488 Mon Sep 17 00:00:00 2001 From: Tarrade Nicolas Date: Fri, 11 Aug 2017 16:52:10 +0200 Subject: [PATCH 4/5] dhcp : upgrade Signed-off-by: Tarrade Nicolas --- include/packetgraph/dhcp.h | 23 +++- src/dhcp.c | 243 ++++++++++++++++++++++--------------- 2 files changed, 166 insertions(+), 100 deletions(-) diff --git a/include/packetgraph/dhcp.h b/include/packetgraph/dhcp.h index 05f024971..4b508bb81 100644 --- a/include/packetgraph/dhcp.h +++ b/include/packetgraph/dhcp.h @@ -32,9 +32,9 @@ **/ struct pg_brick *pg_dhcp_new(const char *name, const char *cidr, + struct ether_addr mac_dhcp, struct pg_error **errp); - /** * Calculate the number of potential adresses * @ipcidr : ip adress with cidr to calculate the range @@ -54,9 +54,24 @@ bool is_discover(struct rte_mbuf *pkts); bool is_request(struct rte_mbuf *pkts); /** - * Print all the mac adresses register - * @dhcp : brick dhcp + * Create dhcp packet to burst + * @msg_type : dhcp message type : 1 : Discover + * 2 : Offer + * 3 : Request + * 4 : Decline + * 5 : Acknowledgment + * 6 : Negative Acknowledgment + * 7 : Realease + * 8 : Informationnal + * @mac : Mac adresse of the brick + * @ip_offer : ip to give to the brick + * @bail : number of seconds for bail of the ip adresse to the brick + * @ip_router : ip of the default gateaway + * @mask : subnet mask used by the client */ -void pg_print_allocate_macs(struct pg_brick *dhcp); +struct rte_mbuf **pg_dhcp_packet_create(struct pg_brick *brick, + uint8_t msg_type, struct ether_addr mac, + uint32_t ip_offer, int bail, + uint32_t ip_router, uint32_t mask); #endif /* _PG_DHCP_H */ diff --git a/src/dhcp.c b/src/dhcp.c index 5877a4080..bd009ec7f 100644 --- a/src/dhcp.c +++ b/src/dhcp.c @@ -20,6 +20,7 @@ #include #include #include +#include "utils/mac.h" #include #include "utils/bitmask.h" @@ -42,32 +43,42 @@ struct dhcp_messages_payload { uint32_t xid; uint16_t secs; uint16_t flags; - struct ether_addr ciaddr; - struct ether_addr yiaddr; - struct ether_addr siaddr; - struct ether_addr giaddr; + uint32_t ciaddr; + uint32_t yiaddr; + uint32_t siaddr; + uint32_t giaddr; struct ether_addr mac_client; char * server_name; char * file; uint8_t dhcp_m_type; struct ether_addr client_id; + uint32_t subnet_mask; + uint32_t request_ip; + uint32_t server_identifier; + uint32_t router_ip; + int lease_time; uint8_t *options; + GList *request_parameters; }; struct pg_dhcp_state { struct pg_brick brick; struct ether_addr **mac; + struct ether_addr mac_dhcp; in_addr_t addr_net; in_addr_t addr_broad; int *check_ip; + int prefix; }; struct pg_dhcp_config { struct network_addr cidr; + struct ether_addr mac_dhcp; }; static struct pg_brick_config *dhcp_config_new(const char *name, - const char *cidr) + const char *cidr, + struct ether_addr mac_dhcp) { char cidrip[17]; strcpy(cidrip, cidr); @@ -78,33 +89,13 @@ static struct pg_brick_config *dhcp_config_new(const char *name, int ret = str_to_netaddr(cidrip, &ip_cidr); if(ret == -1) printf("error registering\n"); - print_addr(ip_cidr.addr, ip_cidr.pfx); dhcp_config->cidr = ip_cidr; - print_addr(dhcp_config->cidr.addr, dhcp_config->cidr.pfx); + dhcp_config->mac_dhcp = mac_dhcp; config = g_new0(struct pg_brick_config, 1); config->brick_config = (void *) dhcp_config; return pg_brick_config_init(config, name, 1, 1, PG_MONOPOLE); } -static int dhcp_poll(struct pg_brick *brick, uint16_t *pkts_cnt, - struct pg_error **error) -{ - //struct pg_dhcp_state *state; - //struct rte_mempool *mp = pg_get_mempool(); - //struct rte_mbuf **pkts; - //struct pg_brick_side *s; - //uint64_t pkts_mask; - //int ret; - //uint16_t i; - - - //state = pg_brick_get_state(brick, struct pg_dhcp_state); - - //pkts = g_new0(struct, state->packets_nb); - - return 0; -} - static int dhcp_burst(struct pg_brick *brick, enum pg_side from, uint16_t edge_index, struct rte_mbuf **pkts, uint64_t pkts_mask, struct pg_error **errp) @@ -113,12 +104,15 @@ static int dhcp_burst(struct pg_brick *brick, enum pg_side from, struct pg_brick_side *s = &brick->sides[pg_flip_side(from)]; struct ether_addr *mac_pkts; uint64_t it_mask; + struct rte_mbuf **pkt_offer; uint64_t bit; struct rte_mbuf *tmp; uint16_t ether_type; - uint16_t pkts_cnt = 1; uint16_t i; int j; + uint32_t hdrs_len = sizeof(struct ether_hdr) + + sizeof(struct ipv4_hdr) + + sizeof(struct udp_hdr); state = pg_brick_get_state(brick, struct pg_dhcp_state); @@ -127,8 +121,11 @@ static int dhcp_burst(struct pg_brick *brick, enum pg_side from, j = 0; pg_low_bit_iterate_full(it_mask, bit, i); tmp = pkts[i]; - struct ether_hdr *ethernet = (struct ether_hdr *) + struct ether_hdr *eth = (struct ether_hdr *) rte_pktmbuf_mtod(tmp, char *); + struct dhcp_messages_payload *dhcp_hdr = + (struct dhcp_messages_payload *) + rte_pktmbuf_mtod_offset(tmp, char *, hdrs_len); ether_type = pg_utils_get_ether_type(tmp); /* DHCP only manage IPv4 adressing * Let non-ip packets (like ARP) pass. @@ -138,12 +135,37 @@ static int dhcp_burst(struct pg_brick *brick, enum pg_side from, } if (RTE_ETH_IS_IPV4_HDR(tmp->packet_type)) { if (((tmp->packet_type) & RTE_PTYPE_L4_UDP)) { - if (is_request(tmp)) { + if (is_discover(tmp)) { while(state->check_ip[j] != 0) j++; - mac_pkts = ðernet->s_addr; - state->mac[j] = mac_pkts; - dhcp_poll(brick, &pkts_cnt, errp); + in_addr_t ip_offer = + state->addr_net + j; + pkt_offer = + pg_dhcp_packet_create(brick, 2, + eth->s_addr, ip_offer, 3600, + state->addr_net, + netmask(state->prefix)); + return pg_brick_burst(s->edge.link, + from, s->edge.pair_index, pkt_offer, + pkts_mask, errp); + } + if (is_request(tmp)) { + uint32_t index = dhcp_hdr->request_ip - + state->addr_net; + if (!state->check_ip[index]) + { + pkt_offer = + pg_dhcp_packet_create(brick, 5, + eth->s_addr, + dhcp_hdr->request_ip, 3600, + state->addr_net, + netmask(state->prefix)); + mac_pkts = ð->s_addr; + state->mac[j] = mac_pkts; + return pg_brick_burst(s->edge.link, + from, s->edge.pair_index, pkt_offer, + pkts_mask, errp); + } } } } @@ -166,12 +188,14 @@ static int dhcp_init(struct pg_brick *brick, dhcp_config = (struct pg_dhcp_config *) config->brick_config; state->mac = g_malloc0(pg_calcul_range_ip(dhcp_config->cidr) * sizeof(struct ether_addr)); + state->mac_dhcp = dhcp_config->mac_dhcp; state->addr_net = network(dhcp_config->cidr.addr, dhcp_config->cidr.pfx); state->addr_broad = broadcast(dhcp_config->cidr.addr, dhcp_config->cidr.pfx); state->check_ip = g_malloc0(pg_calcul_range_ip(dhcp_config->cidr) * sizeof(bool)); + state->prefix = dhcp_config->cidr.pfx; for (int i = 0 ; i < pg_calcul_range_ip(dhcp_config->cidr); i++) { state->check_ip[i] = 0; @@ -186,29 +210,54 @@ int pg_calcul_range_ip(network_addr_t ipcidr) { return 1 << ((32 - (ipcidr.pfx - 1)) - 1); } +#define PG_PACKETS_TEST_DHCP(pkts, msg_type) \ + bool result = true; \ + uint8_t eth_dest[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};\ + uint8_t eth_src[6] = {0x00, 0x18, 0xb9, 0x56, 0x2e, 0x73}; \ + uint32_t ip_dest; \ + inet_pton(AF_INET, "255.255.255.255", &ip_dest); \ + uint32_t ip_src; \ + inet_pton(AF_INET, "0.0.0.0", &ip_src); \ + uint16_t udp_dest = 67; \ + uint16_t udp_src = 68; \ + uint8_t dhcp_mes_type = msg_type; \ + uint32_t hdrs_len = sizeof(struct ether_hdr) + \ + sizeof(struct ipv4_hdr) + \ + sizeof(struct udp_hdr); \ + struct ether_hdr *ethernet = (struct ether_hdr *) \ + rte_pktmbuf_mtod(pkts, char *);\ + struct ipv4_hdr *ip = (struct ipv4_hdr *) \ + pg_utils_get_l3(pkts); \ + struct udp_hdr *udp = (struct udp_hdr *) \ + pg_utils_get_l4(pkts); \ + struct dhcp_messages_payload *dhcp_hdr = \ + (struct dhcp_messages_payload *) \ + rte_pktmbuf_mtod_offset(pkts, char *, hdrs_len); \ + \ + if (eth_compare(ethernet->d_addr.addr_bytes, eth_dest) == false) \ + result = false; \ + if (eth_compare(ethernet->s_addr.addr_bytes, eth_src) == false) \ + result = false; \ + if (ip->dst_addr != ip_dest) \ + result = false; \ + if (ip->src_addr != ip_src) \ + result = false; \ + if (rte_be_to_cpu_16(udp->dst_port) != udp_dest) \ + result = false; \ + if (rte_be_to_cpu_16(udp->src_port) != udp_src) \ + result = false; \ + if (dhcp_hdr->dhcp_m_type != dhcp_mes_type) \ + result = false; \ + \ + return result; \ + + bool is_discover(struct rte_mbuf *pkts) { - bool result = true; - /*struct eth_ip_l4 pkt_dest; - pkt_dest.ethernet = (rte_pktmbuf_mtod(pkts, struct ether_addr *)); - pkt_dest.ipv4 = pg_utils_get_l3(pkts); - pkt_dest.v4udp = pg_utils_get_l4(pkts); - - struct eth_ip_l4 pkt_src; - pkt_src.ethernet = (rte_pktmbuf_mtod(pkts, struct ether_addr *) + 1); - pkt_src.ipv4 = pg_utils_get_l3(pkts) + 1; - pkt_src.v4udp = pg_utils_get_l4(pkts) + 1; - - if (pkt_src.ipv4 != "0.0.0.0") - result = false; - if (pkt_src.v4udp != 68) - result = false; - if (pkt_dest.ethernet != "FF:FF:FF:FF:FF:FF") - result = false; - if (pkt_dest.ipv4 != "255.255.255.255") - result = false; - if (pkt_dest.v4udp != 67) - result == false;*/ - return result; + PG_PACKETS_TEST_DHCP(pkts, 1); +} + +bool is_request(struct rte_mbuf *pkts) { + PG_PACKETS_TEST_DHCP(pkts, 3); } bool eth_compare(uint8_t eth1[6], uint8_t eth2[6]) { @@ -220,57 +269,59 @@ bool eth_compare(uint8_t eth1[6], uint8_t eth2[6]) { return result; } -bool is_request(struct rte_mbuf *pkts) { - - bool result = true; - uint8_t eth_dest[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - uint8_t eth_src[6] = {0x00, 0x18, 0xb9, 0x56, 0x2e, 0x73}; - uint32_t ip_dest; - inet_pton(AF_INET, "255.255.255.255", &ip_dest); - uint32_t ip_src; - inet_pton(AF_INET, "0.0.0.0", &ip_src); - uint16_t udp_dest = 67; - uint16_t udp_src = 68; - uint8_t dhcp_mes_type = 3; - uint32_t hdrs_len = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) + sizeof(struct udp_hdr); - - struct ether_hdr *ethernet = (struct ether_hdr *) rte_pktmbuf_mtod(pkts, char *); - struct ipv4_hdr *ip = (struct ipv4_hdr *) pg_utils_get_l3(pkts); - struct udp_hdr *udp = (struct udp_hdr *) pg_utils_get_l4(pkts); - struct dhcp_messages_payload *dhcp_hdr = (struct dhcp_messages_payload *) - rte_pktmbuf_mtod_offset(pkts, char *, hdrs_len); - - if (eth_compare(ethernet->d_addr.addr_bytes, eth_dest) == false) - result = false; - - if (eth_compare(ethernet->s_addr.addr_bytes, eth_src) == false) - result = false; - - if (ip->dst_addr != ip_dest) - result = false; - - if (ip->src_addr != ip_src) - result = false; - - if (rte_be_to_cpu_16(udp->dst_port) != udp_dest) - result = false; - - if (rte_be_to_cpu_16(udp->src_port) != udp_src) - result = false; +struct rte_mbuf **pg_dhcp_packet_create(struct pg_brick *brick, + uint8_t msg_type, struct ether_addr mac, + uint32_t ip_offer, int bail, + uint32_t ip_router, uint32_t mask) +{ + struct rte_mbuf **pkts; + struct ether_addr eth_dst; + struct ether_addr eth_src; + struct dhcp_messages_payload dhcp_hdr; + char *tmp; + struct pg_dhcp_state *state; - if (dhcp_hdr->dhcp_m_type != dhcp_mes_type) - result = false; + state = pg_brick_get_state(brick, struct pg_dhcp_state); + + pg_scan_ether_addr(ð_dst, "FF:FF:FF:FF:FF:FF"); + eth_src = state->mac_dhcp; + + pkts = pg_packets_append_ether(pg_packets_create(pg_mask_firsts(1)), + pg_mask_firsts(1), ð_src, ð_dst, + ETHER_TYPE_IPv4); + pg_packets_append_ipv4(pkts, pg_mask_firsts(1), state->addr_net, + 0xFFFFFFFF, sizeof(struct ipv4_hdr), 17); + pg_packets_append_udp(pkts, pg_mask_firsts(1), 68, 67, + sizeof(struct udp_hdr)); + + PG_FOREACH_BIT(pg_mask_firsts(1), j) { + if (!pkts[j]) + continue; + dhcp_hdr.mac_client = mac; + dhcp_hdr.dhcp_m_type = msg_type; + dhcp_hdr.subnet_mask = mask; + dhcp_hdr.yiaddr = ip_offer; + dhcp_hdr.router_ip = ip_router; + dhcp_hdr.lease_time = bail; + dhcp_hdr.server_identifier = state->addr_net; + tmp = rte_pktmbuf_append(pkts[j], + sizeof(struct dhcp_messages_payload)); + if (!tmp) + printf("error buffer\n"); + memcpy(tmp, &dhcp_hdr, sizeof(struct dhcp_messages_payload)); + } - return result; + return pkts; } struct pg_brick *pg_dhcp_new(const char *name, const char *cidr, - struct pg_error **errp) + struct ether_addr mac_dhcp, + struct pg_error **errp) { struct pg_brick_config *config; struct pg_brick *ret; - config = dhcp_config_new(name, cidr); + config = dhcp_config_new(name, cidr, mac_dhcp); ret = pg_brick_new("dhcp", config, errp); pg_brick_config_free(config); From 1652b53448cb3ac781dfa80676b00c5080cfc275 Mon Sep 17 00:00:00 2001 From: Tarrade Nicolas Date: Mon, 23 Oct 2017 16:27:05 +0200 Subject: [PATCH 5/5] dhcp : brick and tests (DON'T Merge) Signed-off-by: Tarrade Nicolas --- include/packetgraph/iprange.h | 82 +++++++++ src/dhcp.c | 7 +- tests/dhcp/test.sh | 2 + tests/dhcp/tests.c | 303 ++++++++++++++++++++++++++++++++++ 4 files changed, 391 insertions(+), 3 deletions(-) create mode 100644 include/packetgraph/iprange.h create mode 100644 tests/dhcp/test.sh create mode 100644 tests/dhcp/tests.c diff --git a/include/packetgraph/iprange.h b/include/packetgraph/iprange.h new file mode 100644 index 000000000..26c5552d6 --- /dev/null +++ b/include/packetgraph/iprange.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2003 Gabriel L. Somlo + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * To compile: + * on Linux: + * gcc -o iprange iprange.c -O2 -Wall + * on Solaris 8, Studio 8 CC: + * cc -xO5 -xarch=v8plusa -xdepend iprange.c -o iprange -lnsl -lresolv + * + * CHANGELOG : + * 2004-10-16 Paul Townsend (alpha alpha beta at purdue dot edu) + * more general input/output formatting + */ + +#include +#include +#include +#include +#include +#include +#include + +/*---------------------------------------------------------------------*/ +/* network address type: one field for the net address, one for prefix */ +/*---------------------------------------------------------------------*/ +typedef struct network_addr { + in_addr_t addr; + int pfx; +} network_addr_t; + +/*------------------------------------------------------------------*/ +/* Set a bit to a given value (0 or 1); MSB is bit 1, LSB is bit 32 */ +/*------------------------------------------------------------------*/ +in_addr_t set_bit(in_addr_t addr, int bitno, int val); + +/*----------------------------------------------------*/ +/* Compute broadcast address given address and prefix */ +/*----------------------------------------------------*/ +in_addr_t broadcast(in_addr_t addr, int prefix); + +/*--------------------------------------*/ +/* Compute netmask address given prefix */ +/*--------------------------------------*/ +in_addr_t netmask(int prefix); + +/*------------------------------------------------*/ +/* Print out a 32-bit address in A.B.C.D/M format */ +/*------------------------------------------------*/ +void print_addr(in_addr_t addr, int prefix); + +/*-----------------------------------------------------------*/ +/* Convert an A.B.C.D address into a 32-bit host-order value */ +/*-----------------------------------------------------------*/ +in_addr_t a_to_hl(const char *ipstr); + +/*--------------------------------------------------*/ +/* Compute network address given address and prefix */ +/*--------------------------------------------------*/ +in_addr_t network(in_addr_t addr, int prefix); + +/*-----------------------------------------------------------------*/ +/* convert a network address char string into a host-order network */ +/* address and an integer prefix value */ +/*-----------------------------------------------------------------*/ +int str_to_netaddr(const char *ipstr, network_addr_t *netaddr); + +/*------------------------------------------------------*/ +/* Print out an address range in a.b.c.d-A.B.C.D format */ +/*------------------------------------------------------*/ +void print_addr_range(in_addr_t lo, in_addr_t hi); diff --git a/src/dhcp.c b/src/dhcp.c index bd009ec7f..9a1f896f0 100644 --- a/src/dhcp.c +++ b/src/dhcp.c @@ -118,7 +118,7 @@ static int dhcp_burst(struct pg_brick *brick, enum pg_side from, it_mask = pkts_mask; for (; it_mask;) { - j = 0; + j = 1; pg_low_bit_iterate_full(it_mask, bit, i); tmp = pkts[i]; struct ether_hdr *eth = (struct ether_hdr *) @@ -138,14 +138,14 @@ static int dhcp_burst(struct pg_brick *brick, enum pg_side from, if (is_discover(tmp)) { while(state->check_ip[j] != 0) j++; - in_addr_t ip_offer = + uint32_t ip_offer = state->addr_net + j; pkt_offer = pg_dhcp_packet_create(brick, 2, eth->s_addr, ip_offer, 3600, state->addr_net, netmask(state->prefix)); - return pg_brick_burst(s->edge.link, + return pg_brick_burst(s->edge.link, from, s->edge.pair_index, pkt_offer, pkts_mask, errp); } @@ -154,6 +154,7 @@ static int dhcp_burst(struct pg_brick *brick, enum pg_side from, state->addr_net; if (!state->check_ip[index]) { + printf("check \n"); pkt_offer = pg_dhcp_packet_create(brick, 5, eth->s_addr, diff --git a/tests/dhcp/test.sh b/tests/dhcp/test.sh new file mode 100644 index 000000000..5c15edaca --- /dev/null +++ b/tests/dhcp/test.sh @@ -0,0 +1,2 @@ +#!/bin/sh +sudo ./tests-dhcp -c1 -n1 --socket-mem 64 --no-shconf diff --git a/tests/dhcp/tests.c b/tests/dhcp/tests.c new file mode 100644 index 000000000..3dae20f20 --- /dev/null +++ b/tests/dhcp/tests.c @@ -0,0 +1,303 @@ + /* Copyright 2017 + * + * This file is part of Packetgraph. + * + * Packetgraph is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as published + * by the Free Software Foundation. + * + * Packetgraph is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Packetgraph. If not, see . + */ + +#include +#include + +#define __FAVOR_BSD +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include "utils/tests.h" +#include +#include +#include "brick-int.h" +#include "collect.h" +#include "fail.h" +#include "packetsgen.h" +#include "packets.h" +#include "utils/mempool.h" +#include "utils/qemu.h" +#include "utils/mac.h" +#include "utils/bitmask.h" + +extern char * ether_ntoa(struct ether_addr *e); +static uint16_t ssh_port_id = 65000; + +struct dhcp_messages_payload { + uint8_t op; + uint8_t htype; + uint8_t hlen; + uint8_t hops; + uint32_t xid; + uint16_t secs; + uint16_t flags; + uint32_t ciaddr; + uint32_t yiaddr; + uint32_t siaddr; + uint32_t giaddr; + struct ether_addr mac_client; + char * server_name; + char * file; + uint8_t dhcp_m_type; + struct ether_addr client_id; + uint32_t subnet_mask; + uint32_t request_ip; + uint32_t server_identifier; + uint32_t router_ip; + int lease_time; + uint8_t *options; + GList *request_parameters; +}; + +struct pg_dhcp_state { + struct pg_brick brick; + struct ether_addr **mac; + in_addr_t addr_net; + in_addr_t addr_broad; + int *check_ip; + int prefix; +}; + +static void test_dhcp_discover(void) +{ + struct pg_brick *dhcp; + struct pg_brick *collect; + struct ether_addr eth_dst; + struct ether_addr eth_src; + struct ether_addr eth_dhcp; + struct rte_mbuf **pkts; + struct rte_mbuf **sended_pkts; + struct dhcp_messages_payload dhcp_hdr; + char *tmp; + uint64_t nb_packets = pg_mask_firsts(1); + uint8_t dhcp_mes_type = 2; + struct pg_error *error = NULL; + + pg_scan_ether_addr(ð_dst, "FF:FF:FF:FF:FF:FF"); + pg_scan_ether_addr(ð_src, "00:18:b9:56:2e:73"); + pg_scan_ether_addr(ð_dhcp, "44:82:c9:2b:a2:37"); + pkts = pg_packets_append_ether(pg_packets_create(nb_packets), + nb_packets, ð_src, ð_dst, + ETHER_TYPE_IPv4); + pg_packets_append_ipv4(pkts, nb_packets, 0x00000000, 0xFFFFFFFF, + sizeof(struct ipv4_hdr), 17); + + pg_packets_append_udp(pkts, nb_packets, 68, 67, sizeof(struct udp_hdr)); + + PG_FOREACH_BIT(nb_packets, j) { + if (!pkts[j]) + continue; + dhcp_hdr.mac_client = eth_src; + dhcp_hdr.dhcp_m_type = 1; + dhcp_hdr.client_id = eth_src; + tmp = rte_pktmbuf_append(pkts[j], sizeof(struct dhcp_messages_payload)); + if (!tmp) + printf("error buffer\n"); + memcpy(tmp, &dhcp_hdr, sizeof(struct dhcp_messages_payload)); + } + + collect = pg_collect_new("collect", &error); + g_assert(!error); + + dhcp = pg_dhcp_new("dhcp", "192.54.30.200/24", eth_dhcp, &error); + g_assert(!error); + + pg_brick_link(dhcp, collect, &error); + g_assert(!error); + + pg_brick_burst_to_east(dhcp, 0, pkts, nb_packets, &error); + g_assert(!error); + + sended_pkts = pg_brick_west_burst_get(collect, &nb_packets, &error); + g_assert(!error); + + PG_FOREACH_BIT(nb_packets, j) { + if (!pkts[j]) + continue; + uint32_t hdrs_len = sizeof(struct ether_hdr) + + sizeof(struct ipv4_hdr) + + sizeof(struct udp_hdr); + struct dhcp_messages_payload *dhcp_hdr_sended = + (struct dhcp_messages_payload *) + rte_pktmbuf_mtod_offset(sended_pkts[j], char *, hdrs_len); + g_assert(dhcp_hdr_sended->dhcp_m_type == dhcp_mes_type); + } + + pg_brick_destroy(collect); + pg_brick_destroy(dhcp); + pg_packets_free(pkts, pg_mask_firsts(1)); + g_free(pkts); +} + +static void test_dhcp_packets_registering(void) +{ + struct pg_brick *dhcp; + struct pg_brick *packets_gen; + struct rte_mbuf **pkts; + struct pg_error *error = NULL; + struct ether_addr eth_dst; + struct ether_addr eth_src; + struct ether_addr eth_dhcp; + struct dhcp_messages_payload dhcp_hdr; + char *tmp; + uint16_t nb_packets = 1; + + pg_scan_ether_addr(ð_dst, "FF:FF:FF:FF:FF:FF"); + pg_scan_ether_addr(ð_src, "00:18:b9:56:2e:73"); + pg_scan_ether_addr(ð_dhcp, "44:82:c9:2b:a2:37"); + pkts = pg_packets_append_ether(pg_packets_create(pg_mask_firsts(1)), + pg_mask_firsts(1), ð_src, ð_dst, + ETHER_TYPE_IPv4); + pg_packets_append_ipv4(pkts, pg_mask_firsts(1), 0x00000000, 0xFFFFFFFF, + sizeof(struct ipv4_hdr), 17); + + pg_packets_append_udp(pkts, pg_mask_firsts(1), 68, 67, sizeof(struct udp_hdr)); + + PG_FOREACH_BIT(pg_mask_firsts(1), j) { + if (!pkts[j]) + continue; + dhcp_hdr.mac_client = eth_src; + dhcp_hdr.dhcp_m_type = 3; + dhcp_hdr.client_id = eth_src; + dhcp_hdr.request_ip = 0xC0361E01; + tmp = rte_pktmbuf_append(pkts[j], sizeof(struct dhcp_messages_payload)); + if (!tmp) + printf("error buffer\n"); + memcpy(tmp, &dhcp_hdr, sizeof(struct dhcp_messages_payload)); + } + + packets_gen = pg_packetsgen_new("packetsgen", 1, 1, PG_EAST_SIDE, pkts, + 1, &error); + g_assert(!error); + + dhcp = pg_dhcp_new("dhcp", "192.54.30.200/24", eth_dhcp, &error); + g_assert(!error); + + pg_brick_link(packets_gen, dhcp, &error); + g_assert(!error); + + pg_brick_poll(packets_gen, &nb_packets, &error); + g_assert(!error); + + struct pg_dhcp_state *state = pg_brick_get_state(dhcp, + struct pg_dhcp_state); + int size = sizeof(state->mac) / sizeof(struct ether_addr); + for(int i = 1; i <= size ; i++) { + printf("%i \n", i); + if (state->mac[i]) { + printf("%s\n", ether_ntoa(state->mac[i])); + } + else { + printf("No Mac assigned\n"); + } + } + + pg_brick_destroy(packets_gen); + pg_brick_destroy(dhcp); + pg_packets_free(pkts, pg_mask_firsts(1)); + g_free(pkts); + +} +/* +static void test_adressing_vm(void) +{ + struct pg_brick *dhcp, *vhost, *print, *collect; + const char *socket_path; + struct ether_addr mac_vm; + struct ether_addr mac_dhcp; + pg_scan_ether_addr(&mac_vm, "42:18:b9:56:2e:73"); + pg_scan_ether_addr(&mac_dhcp, "55:27:c9:ea:9d:36"); + struct pg_error *error = NULL; + int ret, qemu_pid; + + ret = pg_vhost_start("/tmp", &error); + g_assert(ret == 0); + g_assert(!error); + + vhost = pg_vhost_new("vhost", PG_VHOST_USER_DEQUEUE_ZERO_COPY, + &error); + g_assert(!error); + g_assert(vhost); + + dhcp = pg_dhcp_new("dhcp", "192.54.30.200/24", mac_dhcp, &error); + g_assert(!error); + g_assert(dhcp); + + collect = pg_collect_new("collect", &error); + g_assert(!error); + g_assert(collect); + + print = pg_print_new("My print", NULL, PG_PRINT_FLAG_MAX, NULL, + &error); + g_assert(!error); + g_assert(print); + + pg_brick_link(collect, vhost, &error); + g_assert(!error); + + socket_path = pg_vhost_socket_path(vhost, &error); + g_assert(!error); + g_assert(socket_path); + + qemu_pid = pg_util_spawn_qemu(socket_path, NULL, mac_vm, NULL, + glob_vm_path, glob_vm_key_path, + glob_hugepages_path, &error); + + g_assert(!error); + g_assert(qemu_pid); + +# define SSH(c) \ + g_assert(pg_util_ssh("localhost", ssh_port_id, \ + glob_vm_key_path, c) == 0) + SSH("dhclient ens4"); +# undef SSH + + pg_util_stop_qemu(qemu_pid, qemu_exit_signal); + +} +*/ +static void test_dhcp(void) +{ + pg_test_add_func("/dhcp/discover\n", + test_dhcp_discover); + pg_test_add_func("/dhcp/packets_registering\n", + test_dhcp_packets_registering); +} + +int main(int argc, char **argv) +{ + /* tests in the same order as the header function declarations */ + g_test_init(&argc, &argv, NULL); + + /* initialize packetgraph */ + g_assert(pg_start(argc, argv) >= 0); + + test_dhcp(); + int r = g_test_run(); + + pg_stop(); + return r; +}