Convert to network byte order just before sending the packet.
/* Explicitly saying that we want RFC-compliant packets helps
* some buggy DHCP servers to NOT send bigger packets */
- dhcp_add_simple_option(&packet, DHCP_MAX_SIZE, htons(576));
+ dhcp_add_simple_option(&packet, DHCP_MAX_SIZE, 576);
add_request_options(dhcp_client, &packet);
init_packet(dhcp_client , &packet, DHCPREQUEST);
packet.xid = dhcp_client->xid;
- packet.ciaddr = dhcp_client->requested_ip;
+ packet.ciaddr = htonl(dhcp_client->requested_ip);
add_request_options(dhcp_client, &packet);
init_packet(dhcp_client , &packet, DHCPREQUEST);
packet.xid = dhcp_client->xid;
- packet.ciaddr = dhcp_client->requested_ip;
+ packet.ciaddr = htonl(dhcp_client->requested_ip);
add_request_options(dhcp_client, &packet);
init_packet(dhcp_client, &packet, DHCPRELEASE);
packet.xid = rand();
- packet.ciaddr = ciaddr;
+ packet.ciaddr = htonl(ciaddr);
dhcp_add_simple_option(&packet, DHCP_SERVER_ID, server);
arp.arp_op != htons(ARPOP_REQUEST))
return -EINVAL;
- ip_requested = ntohl(dhcp_client->requested_ip);
+ ip_requested = htonl(dhcp_client->requested_ip);
source_conflict = !memcmp(arp.arp_spa, &ip_requested,
sizeof(ip_requested));
static uint32_t get_lease(struct dhcp_packet *packet)
{
- uint8_t *option_u8;
+ uint8_t *option;
uint32_t lease_seconds;
- option_u8 = dhcp_get_option(packet, DHCP_LEASE_TIME);
- if (option_u8 == NULL)
+ option = dhcp_get_option(packet, DHCP_LEASE_TIME);
+ if (option == NULL)
return 3600;
- lease_seconds = dhcp_get_unaligned((uint32_t *) option_u8);
- lease_seconds = ntohl(lease_seconds);
+ lease_seconds = get_be32(option);
/* paranoia: must not be prone to overflows */
lease_seconds &= 0x0fffffff;
if (lease_seconds < 10)
dest += sprint_nip(dest, "", option);
break;
case OPTION_U16: {
- uint16_t val_u16 = dhcp_get_unaligned(
- (uint16_t *) option);
- dest += sprintf(dest, "%u", ntohs(val_u16));
+ uint16_t val_u16 = get_be16(option);
+ dest += sprintf(dest, "%u", val_u16);
break;
}
case OPTION_U32: {
- uint32_t val_u32 = dhcp_get_unaligned(
- (uint32_t *) option);
- dest += sprintf(dest, type == OPTION_U32 ? "%lu" :
- "%ld", (unsigned long) ntohl(val_u32));
+ uint32_t val_u32 = get_be32(option);
+ dest += sprintf(dest, "%u", val_u32);
break;
}
case OPTION_STRING:
GDHCPClient *dhcp_client = user_data;
struct dhcp_packet packet;
struct dhcpv6_packet *packet6 = NULL;
- uint8_t *message_type = NULL, *client_id = NULL, *option_u8,
+ uint8_t *message_type = NULL, *client_id = NULL, *option,
*server_id = NULL;
uint16_t option_len = 0, status = 0;
gpointer pkt;
return TRUE;
}
- option_u8 = dhcpv6_get_option(packet6, pkt_len,
+ option = dhcpv6_get_option(packet6, pkt_len,
G_DHCPV6_STATUS_CODE, &option_len, NULL);
- if (option_u8 != 0 && option_len > 0) {
- status = option_u8[0]<<8 | option_u8[1];
+ if (option != 0 && option_len > 0) {
+ status = option[0]<<8 | option[1];
if (status != 0) {
debug(dhcp_client, "error code %d", status);
if (option_len > 2) {
gchar *txt = g_strndup(
- (gchar *)&option_u8[2],
+ (gchar *)&option[2],
option_len - 2);
debug(dhcp_client, "error text: %s",
txt);
dhcp_client->timeout = 0;
dhcp_client->retry_times = 0;
- option_u8 = dhcp_get_option(&packet, DHCP_SERVER_ID);
- dhcp_client->server_ip =
- dhcp_get_unaligned((uint32_t *) option_u8);
- dhcp_client->requested_ip = packet.yiaddr;
+ option = dhcp_get_option(&packet, DHCP_SERVER_ID);
+ dhcp_client->server_ip = get_be32(option);
+ dhcp_client->requested_ip = ntohl(packet.yiaddr);
dhcp_client->state = REQUESTING;
len = dhcp_option_lengths[type & OPTION_TYPE_MASK];
option[OPT_LEN] = len;
-#if __BYTE_ORDER == __BIG_ENDIAN
- data <<= 8 * (4 - len);
-#endif
+ switch (len) {
+ case 1:
+ option[OPT_DATA] = data;
+ break;
+ case 2:
+ put_be16(data, option + OPT_DATA);
+ break;
+ case 4:
+ put_be32(data, option + OPT_DATA);
+ break;
+ default:
+ printf("Invalid option len %d for code 0x%x\n", len, code);
+ return;
+ }
- dhcp_put_unaligned(data, (uint32_t *)(option + OPT_DATA));
dhcp_add_binary_option(packet, option);
return;
memset(&client, 0, sizeof(client));
client.sin_family = AF_INET;
client.sin_port = htons(source_port);
- client.sin_addr.s_addr = source_ip;
+ client.sin_addr.s_addr = htonl(source_ip);
if (bind(fd, (struct sockaddr *) &client, sizeof(client)) < 0) {
close(fd);
return -errno;
#include <glib.h>
+#include "unaligned.h"
#include "gdhcp.h"
-#define dhcp_get_unaligned(ptr) \
-({ \
- struct __attribute__((packed)) { \
- typeof(*(ptr)) __v; \
- } *__p = (void *) (ptr); \
- __p->__v; \
-})
-
-#define dhcp_put_unaligned(val, ptr) \
-do { \
- struct __attribute__((packed)) { \
- typeof(*(ptr)) __v; \
- } *__p = (void *) (ptr); \
- __p->__v = (val); \
-} while (0)
-
#define CLIENT_PORT 68
#define SERVER_PORT 67
#include "ipv4ll.h"
/**
- * Return a random link local IP
+ * Return a random link local IP (in host byte order)
*/
uint32_t ipv4ll_random_ip(int seed)
{
tmp = rand();
tmp = tmp & IN_CLASSB_HOST;
} while (tmp > (IN_CLASSB_HOST - 0x0200));
- return ((LINKLOCAL_ADDR + 0x0100) + tmp);
+ return ntohl(((LINKLOCAL_ADDR + 0x0100) + tmp));
}
/**
lease_mac = find_lease_by_mac(dhcp_server, mac);
lease_nip = g_hash_table_lookup(dhcp_server->nip_lease_hash,
- GINT_TO_POINTER((int) yiaddr));
+ GINT_TO_POINTER((int) ntohl(yiaddr)));
debug(dhcp_server, "lease_mac %p lease_nip %p", lease_mac, lease_nip);
if (lease_nip != NULL) {
g_list_remove(dhcp_server->lease_list,
lease_nip);
g_hash_table_remove(dhcp_server->nip_lease_hash,
- GINT_TO_POINTER((int) yiaddr));
+ GINT_TO_POINTER((int) ntohl(yiaddr)));
if (lease_mac == NULL)
*lease = lease_nip;
memset(lease, 0, sizeof(*lease));
memcpy(lease->lease_mac, chaddr, ETH_ALEN);
- lease->lease_nip = yiaddr;
+ lease->lease_nip = ntohl(yiaddr);
if (expire == 0)
lease->expire = time(NULL) + dhcp_server->lease_seconds;
if ((ip_addr & 0xff) == 0xff)
continue;
- lease = find_lease_by_nip(dhcp_server,
- (uint32_t) htonl(ip_addr));
+ lease = find_lease_by_nip(dhcp_server, ip_addr);
if (lease != NULL)
continue;
if (arp_check(htonl(ip_addr), safe_mac) == TRUE)
- return htonl(ip_addr);
+ return ip_addr;
}
/* The last lease is the oldest one */
return;
dhcp_add_simple_option(packet, (uint8_t) option_code,
- nip.s_addr);
+ ntohl(nip.s_addr));
break;
default:
return;
if (requested_nip == 0)
return FALSE;
- if (ntohl(requested_nip) < dhcp_server->start_ip)
+ if (requested_nip < dhcp_server->start_ip)
return FALSE;
- if (ntohl(requested_nip) > dhcp_server->end_ip)
+ if (requested_nip > dhcp_server->end_ip)
return FALSE;
lease = find_lease_by_nip(dhcp_server, requested_nip);
init_packet(dhcp_server, &packet, client_packet, DHCPOFFER);
if (lease)
- packet.yiaddr = lease->lease_nip;
+ packet.yiaddr = htonl(lease->lease_nip);
else if (check_requested_nip(dhcp_server, requested_nip) == TRUE)
- packet.yiaddr = requested_nip;
+ packet.yiaddr = htonl(requested_nip);
else
- packet.yiaddr = find_free_or_expired_nip(
- dhcp_server, client_packet->chaddr);
+ packet.yiaddr = htonl(find_free_or_expired_nip(
+ dhcp_server, client_packet->chaddr));
debug(dhcp_server, "find yiaddr %u", packet.yiaddr);
}
dhcp_add_simple_option(&packet, DHCP_LEASE_TIME,
- htonl(dhcp_server->lease_seconds));
+ dhcp_server->lease_seconds);
add_server_options(dhcp_server, &packet);
addr.s_addr = packet.yiaddr;
}
static void send_ACK(GDHCPServer *dhcp_server,
- struct dhcp_packet *client_packet, uint32_t yiaddr)
+ struct dhcp_packet *client_packet, uint32_t dest)
{
struct dhcp_packet packet;
uint32_t lease_time_sec;
struct in_addr addr;
init_packet(dhcp_server, &packet, client_packet, DHCPACK);
- packet.yiaddr = yiaddr;
+ packet.yiaddr = htonl(dest);
lease_time_sec = dhcp_server->lease_seconds;
- dhcp_add_simple_option(&packet, DHCP_LEASE_TIME, htonl(lease_time_sec));
+ dhcp_add_simple_option(&packet, DHCP_LEASE_TIME, lease_time_sec);
add_server_options(dhcp_server, &packet);
- addr.s_addr = yiaddr;
+ addr.s_addr = htonl(dest);
debug(dhcp_server, "Sending ACK to %s", inet_ntoa(addr));
server_id_option = dhcp_get_option(&packet, DHCP_SERVER_ID);
if (server_id_option) {
- uint32_t server_nid = dhcp_get_unaligned(
- (uint32_t *) server_id_option);
+ uint32_t server_nid = get_be32(server_id_option);
if (server_nid != dhcp_server->server_nip)
return TRUE;
request_ip_option = dhcp_get_option(&packet, DHCP_REQUESTED_IP);
if (request_ip_option)
- requested_nip = dhcp_get_unaligned(
- (uint32_t *) request_ip_option);
+ requested_nip = get_be32(request_ip_option);
lease = find_lease_by_mac(dhcp_server, packet.chaddr);