Skip to content

Commit

Permalink
dhcp : upgrade
Browse files Browse the repository at this point in the history
Signed-off-by: Tarrade Nicolas <[email protected]>
  • Loading branch information
outscale-nts committed Oct 23, 2017
1 parent cb46a2c commit b3e706e
Show file tree
Hide file tree
Showing 2 changed files with 166 additions and 100 deletions.
23 changes: 19 additions & 4 deletions include/packetgraph/dhcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 */
243 changes: 147 additions & 96 deletions src/dhcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <rte_ether.h>
#include <pcap/pcap.h>
#include <endian.h>
#include "utils/mac.h"

#include <packetgraph/packetgraph.h>
#include "utils/bitmask.h"
Expand All @@ -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);
Expand All @@ -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)
Expand All @@ -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);

Expand All @@ -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.
Expand All @@ -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 = &ethernet->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 = &eth->s_addr;
state->mac[j] = mac_pkts;
return pg_brick_burst(s->edge.link,
from, s->edge.pair_index, pkt_offer,
pkts_mask, errp);
}
}
}
}
Expand All @@ -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;
Expand All @@ -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]) {
Expand All @@ -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(&eth_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), &eth_src, &eth_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);
Expand Down

0 comments on commit b3e706e

Please sign in to comment.