diff options
author | taesubkim <taesub.kim@samsung.com> | 2016-04-26 15:47:01 +0900 |
---|---|---|
committer | taesubkim <taesub.kim@samsung.com> | 2016-04-26 16:14:46 +0900 |
commit | 22633ced6225d294ce8483efbf2b39ea0c0c1b65 (patch) | |
tree | 8c5f2312feec413068a18e57a80321b31b4f7b74 /gdhcp | |
parent | bcae74da8fa2958b3fec9153fc33e41f0e0317bf (diff) | |
download | connman-22633ced6225d294ce8483efbf2b39ea0c0c1b65.tar.gz connman-22633ced6225d294ce8483efbf2b39ea0c0c1b65.tar.bz2 connman-22633ced6225d294ce8483efbf2b39ea0c0c1b65.zip |
Imported Upstream version 1.29upstream/1.29
Change-Id: I2958446c35966d9ed72df0120b80561be7d89f54
Signed-off-by: Taesub Kim <taesub.kim@samsung.com>
Diffstat (limited to 'gdhcp')
-rw-r--r-- | gdhcp/client.c | 33 | ||||
-rw-r--r-- | gdhcp/common.c | 61 | ||||
-rw-r--r-- | gdhcp/common.h | 8 | ||||
-rw-r--r-- | gdhcp/gdhcp.h | 10 | ||||
-rw-r--r-- | gdhcp/ipv4ll.c | 23 | ||||
-rw-r--r-- | gdhcp/ipv4ll.h | 2 | ||||
-rw-r--r-- | gdhcp/server.c | 20 |
7 files changed, 120 insertions, 37 deletions
diff --git a/gdhcp/client.c b/gdhcp/client.c index 66c3a90d..5a4a89c8 100644 --- a/gdhcp/client.c +++ b/gdhcp/client.c @@ -514,11 +514,13 @@ static int send_release(GDHCPClient *dhcp_client, uint32_t server, uint32_t ciaddr) { struct dhcp_packet packet; + uint64_t rand; debug(dhcp_client, "sending DHCP release request"); init_packet(dhcp_client, &packet, DHCPRELEASE); - packet.xid = rand(); + dhcp_get_random(&rand); + packet.xid = rand; packet.ciaddr = htonl(ciaddr); dhcp_add_option_uint32(&packet, DHCP_SERVER_ID, server); @@ -540,7 +542,7 @@ static gboolean send_probe_packet(gpointer dhcp_data) /* if requested_ip is not valid, pick a new address*/ if (dhcp_client->requested_ip == 0) { debug(dhcp_client, "pick a new random address"); - dhcp_client->requested_ip = ipv4ll_random_ip(0); + dhcp_client->requested_ip = ipv4ll_random_ip(); } debug(dhcp_client, "sending IPV4LL probe request"); @@ -1361,7 +1363,6 @@ static int dhcp_recv_l2_packet(struct dhcp_packet *dhcp_pkt, int fd, static void ipv4ll_start(GDHCPClient *dhcp_client) { guint timeout; - int seed; remove_timeouts(dhcp_client); @@ -1369,9 +1370,7 @@ static void ipv4ll_start(GDHCPClient *dhcp_client) dhcp_client->retry_times = 0; dhcp_client->requested_ip = 0; - /*try to start with a based mac address ip*/ - seed = (dhcp_client->mac_address[4] << 8 | dhcp_client->mac_address[4]); - dhcp_client->requested_ip = ipv4ll_random_ip(seed); + dhcp_client->requested_ip = ipv4ll_random_ip(); /*first wait a random delay to avoid storm of arp request on boot*/ timeout = ipv4ll_random_delay_ms(PROBE_WAIT); @@ -1670,6 +1669,7 @@ static gboolean start_expire(gpointer user_data) static gboolean continue_rebound(gpointer user_data) { GDHCPClient *dhcp_client = user_data; + uint64_t rand; switch_listening_mode(dhcp_client, L2); send_request(dhcp_client); @@ -1680,9 +1680,10 @@ static gboolean continue_rebound(gpointer user_data) /*recalculate remaining rebind time*/ dhcp_client->T2 >>= 1; if (dhcp_client->T2 > 60) { + dhcp_get_random(&rand); dhcp_client->t2_timeout = g_timeout_add_full(G_PRIORITY_HIGH, - dhcp_client->T2 * 1000 + (rand() % 2000) - 1000, + dhcp_client->T2 * 1000 + (rand % 2000) - 1000, continue_rebound, dhcp_client, NULL); @@ -1714,6 +1715,7 @@ static gboolean start_rebound(gpointer user_data) static gboolean continue_renew (gpointer user_data) { GDHCPClient *dhcp_client = user_data; + uint64_t rand; switch_listening_mode(dhcp_client, L3); send_request(dhcp_client); @@ -1724,8 +1726,9 @@ static gboolean continue_renew (gpointer user_data) dhcp_client->T1 >>= 1; if (dhcp_client->T1 > 60) { + dhcp_get_random(&rand); dhcp_client->t1_timeout = g_timeout_add_full(G_PRIORITY_HIGH, - dhcp_client->T1 * 1000 + (rand() % 2000) - 1000, + dhcp_client->T1 * 1000 + (rand % 2000) - 1000, continue_renew, dhcp_client, NULL); @@ -2461,7 +2464,7 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition, rapid_commit = dhcpv6_get_option(packet6, pkt_len, G_DHCPV6_RAPID_COMMIT, &option_len, &count); - if (!rapid_commit || option_len == 0 || + if (!rapid_commit || option_len != 0 || count != 1) /* RFC 3315, 17.1.4 */ return TRUE; @@ -2707,6 +2710,7 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const char *last_address) { int re; uint32_t addr; + uint64_t rand; if (dhcp_client->type == G_DHCP_IPV6) { if (dhcp_client->information_req_cb) { @@ -2815,7 +2819,8 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const char *last_address) if (re != 0) return re; - dhcp_client->xid = rand(); + dhcp_get_random(&rand); + dhcp_client->xid = rand; dhcp_client->start = time(NULL); } @@ -2984,6 +2989,14 @@ int g_dhcp_client_get_index(GDHCPClient *dhcp_client) return dhcp_client->ifindex; } +char *g_dhcp_client_get_server_address(GDHCPClient *dhcp_client) +{ + if (!dhcp_client) + return NULL; + + return get_ip(dhcp_client->server_ip); +} + char *g_dhcp_client_get_address(GDHCPClient *dhcp_client) { return g_strdup(dhcp_client->assigned_ip); diff --git a/gdhcp/common.c b/gdhcp/common.c index 45278a88..f3d4677e 100644 --- a/gdhcp/common.c +++ b/gdhcp/common.c @@ -35,6 +35,7 @@ #include <netpacket/packet.h> #include <net/ethernet.h> #include <arpa/inet.h> +#include <fcntl.h> #include "gdhcp.h" #include "common.h" @@ -58,6 +59,42 @@ static const DHCPOption client_options[] = { { OPTION_UNKNOWN, 0x00 }, }; +#define URANDOM "/dev/urandom" +static int random_fd = -1; + +int dhcp_get_random(uint64_t *val) +{ + int r; + + if (random_fd < 0) { + random_fd = open(URANDOM, O_RDONLY); + if (random_fd < 0) { + r = -errno; + *val = random(); + + return r; + } + } + + if (read(random_fd, val, sizeof(uint64_t)) < 0) { + r = -errno; + *val = random(); + + return r; + } + + return 0; +} + +void dhcp_cleanup_random(void) +{ + if (random_fd < 0) + return; + + close(random_fd); + random_fd = -1; +} + GDHCPOptionType dhcp_get_code_type(uint8_t code) { int i; @@ -356,12 +393,14 @@ void dhcp_init_header(struct dhcp_packet *packet, char type) void dhcpv6_init_header(struct dhcpv6_packet *packet, uint8_t type) { int id; + uint64_t rand; memset(packet, 0, sizeof(*packet)); packet->message = type; - id = random(); + dhcp_get_random(&rand); + id = rand; packet->transaction_id[0] = (id >> 16) & 0xff; packet->transaction_id[1] = (id >> 8) & 0xff; @@ -434,19 +473,14 @@ uint16_t dhcp_checksum(void *addr, int count) static const struct in6_addr in6addr_all_dhcp_relay_agents_and_servers_mc = IN6ADDR_ALL_DHCP_RELAY_AGENTS_AND_SERVERS_MC_INIT; -/* from netinet/in.h */ -struct in6_pktinfo { - struct in6_addr ipi6_addr; /* src/dst IPv6 address */ - unsigned int ipi6_ifindex; /* send/recv interface index */ -}; - int dhcpv6_send_packet(int index, struct dhcpv6_packet *dhcp_pkt, int len) { struct msghdr m; struct iovec v; struct in6_pktinfo *pktinfo; struct cmsghdr *cmsg; - int fd, ret; + int fd, ret, opt = 1; + struct sockaddr_in6 src; struct sockaddr_in6 dst; void *control_buf; size_t control_buf_len; @@ -455,6 +489,17 @@ int dhcpv6_send_packet(int index, struct dhcpv6_packet *dhcp_pkt, int len) if (fd < 0) return -errno; + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); + + memset(&src, 0, sizeof(src)); + src.sin6_family = AF_INET6; + src.sin6_port = htons(DHCPV6_CLIENT_PORT); + + if (bind(fd, (struct sockaddr *) &src, sizeof(src)) <0) { + close(fd); + return -errno; + } + memset(&dst, 0, sizeof(dst)); dst.sin6_family = AF_INET6; dst.sin6_port = htons(DHCPV6_SERVER_PORT); diff --git a/gdhcp/common.h b/gdhcp/common.h index c6927992..75abc183 100644 --- a/gdhcp/common.h +++ b/gdhcp/common.h @@ -170,6 +170,14 @@ static const uint8_t dhcp_option_lengths[] = { [OPTION_U32] = 4, }; +/* already defined within netinet/in.h if using GNU compiler */ +#ifndef __USE_GNU +struct in6_pktinfo { + struct in6_addr ipi6_addr; /* src/dst IPv6 address */ + unsigned int ipi6_ifindex; /* send/recv interface index */ +}; +#endif + uint8_t *dhcp_get_option(struct dhcp_packet *packet, int code); uint8_t *dhcpv6_get_option(struct dhcpv6_packet *packet, uint16_t pkt_len, int code, uint16_t *option_len, int *option_count); diff --git a/gdhcp/gdhcp.h b/gdhcp/gdhcp.h index f3e47bf6..0ed7fa54 100644 --- a/gdhcp/gdhcp.h +++ b/gdhcp/gdhcp.h @@ -150,6 +150,7 @@ GDHCPClientError g_dhcp_client_set_send(GDHCPClient *client, unsigned char option_code, const char *option_value); +char *g_dhcp_client_get_server_address(GDHCPClient *client); char *g_dhcp_client_get_address(GDHCPClient *client); char *g_dhcp_client_get_netmask(GDHCPClient *client); GList *g_dhcp_client_get_option(GDHCPClient *client, @@ -201,6 +202,9 @@ typedef enum { typedef void (*GDHCPSaveLeaseFunc) (unsigned char *mac, unsigned int nip, unsigned int expire); + +typedef void (*GDHCPLeaseAddedCb) (unsigned char *mac, uint32_t ip); + struct _GDHCPServer; typedef struct _GDHCPServer GDHCPServer; @@ -223,6 +227,12 @@ void g_dhcp_server_set_lease_time(GDHCPServer *dhcp_server, unsigned int lease_time); void g_dhcp_server_set_save_lease(GDHCPServer *dhcp_server, GDHCPSaveLeaseFunc func, gpointer user_data); +void g_dhcp_server_set_lease_added_cb(GDHCPServer *dhcp_server, + GDHCPLeaseAddedCb cb); + +int dhcp_get_random(uint64_t *val); +void dhcp_cleanup_random(void); + #ifdef __cplusplus } #endif diff --git a/gdhcp/ipv4ll.c b/gdhcp/ipv4ll.c index 9bf52b0a..c43971f0 100644 --- a/gdhcp/ipv4ll.c +++ b/gdhcp/ipv4ll.c @@ -34,23 +34,19 @@ #include <glib.h> #include "ipv4ll.h" +#include "common.h" /** * Return a random link local IP (in host byte order) */ -uint32_t ipv4ll_random_ip(int seed) +uint32_t ipv4ll_random_ip(void) { unsigned tmp; + uint64_t rand; - if (seed) - srand(seed); - else { - struct timeval tv; - gettimeofday(&tv, NULL); - srand(tv.tv_usec); - } do { - tmp = rand(); + dhcp_get_random(&rand); + tmp = rand; tmp = tmp & IN_CLASSB_HOST; } while (tmp > (IN_CLASSB_HOST - 0x0200)); return ((LINKLOCAL_ADDR + 0x0100) + tmp); @@ -61,13 +57,10 @@ uint32_t ipv4ll_random_ip(int seed) */ guint ipv4ll_random_delay_ms(guint secs) { - struct timeval tv; - guint tmp; + uint64_t rand; - gettimeofday(&tv, NULL); - srand(tv.tv_usec); - tmp = rand(); - return tmp % (secs * 1000); + dhcp_get_random(&rand); + return rand % (secs * 1000); } int ipv4ll_send_arp_packet(uint8_t* source_eth, uint32_t source_ip, diff --git a/gdhcp/ipv4ll.h b/gdhcp/ipv4ll.h index aaac33ed..bee8138a 100644 --- a/gdhcp/ipv4ll.h +++ b/gdhcp/ipv4ll.h @@ -43,7 +43,7 @@ extern "C" { #define RATE_LIMIT_INTERVAL 60 #define DEFEND_INTERVAL 10 -uint32_t ipv4ll_random_ip(int seed); +uint32_t ipv4ll_random_ip(void); guint ipv4ll_random_delay_ms(guint secs); int ipv4ll_send_arp_packet(uint8_t* source_eth, uint32_t source_ip, uint32_t target_ip, int ifindex); diff --git a/gdhcp/server.c b/gdhcp/server.c index aa40488c..8574c24c 100644 --- a/gdhcp/server.c +++ b/gdhcp/server.c @@ -56,7 +56,7 @@ struct _GDHCPServer { char *interface; uint32_t start_ip; uint32_t end_ip; - uint32_t server_nip; + uint32_t server_nip; /* our address in network byte order */ uint32_t lease_seconds; int listener_sockfd; guint listener_watch; @@ -65,6 +65,7 @@ struct _GDHCPServer { GHashTable *nip_lease_hash; GHashTable *option_hash; /* Options send to client */ GDHCPSaveLeaseFunc save_lease_func; + GDHCPLeaseAddedCb lease_added_cb; GDHCPDebugFunc debug_func; gpointer debug_data; }; @@ -213,6 +214,9 @@ static struct dhcp_lease *add_lease(GDHCPServer *dhcp_server, uint32_t expire, g_hash_table_insert(dhcp_server->nip_lease_hash, GINT_TO_POINTER((int) lease->lease_nip), lease); + if (dhcp_server->lease_added_cb) + dhcp_server->lease_added_cb(lease->lease_mac, yiaddr); + return lease; } @@ -450,7 +454,7 @@ static void init_packet(GDHCPServer *dhcp_server, struct dhcp_packet *packet, packet->gateway_nip = client_packet->gateway_nip; packet->ciaddr = client_packet->ciaddr; dhcp_add_option_uint32(packet, DHCP_SERVER_ID, - dhcp_server->server_nip); + ntohl(dhcp_server->server_nip)); } static void add_option(gpointer key, gpointer value, gpointer user_data) @@ -664,7 +668,8 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition, server_id_option = dhcp_get_option(&packet, DHCP_SERVER_ID); if (server_id_option) { - uint32_t server_nid = get_be32(server_id_option); + uint32_t server_nid = + get_unaligned((const uint32_t *) server_id_option); if (server_nid != dhcp_server->server_nip) return TRUE; @@ -814,6 +819,15 @@ void g_dhcp_server_set_save_lease(GDHCPServer *dhcp_server, dhcp_server->save_lease_func = func; } +void g_dhcp_server_set_lease_added_cb(GDHCPServer *dhcp_server, + GDHCPLeaseAddedCb cb) +{ + if (!dhcp_server) + return; + + dhcp_server->lease_added_cb = cb; +} + GDHCPServer *g_dhcp_server_ref(GDHCPServer *dhcp_server) { if (!dhcp_server) |