static void send_ACK(GDHCPServer *dhcp_server, 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 = htonl(dest); lease_time_sec = dhcp_server->lease_seconds; dhcp_add_option_uint32(&packet, DHCP_LEASE_TIME, lease_time_sec); add_server_options(dhcp_server, &packet); addr.s_addr = htonl(dest); debug(dhcp_server, "Sending ACK to %s", inet_ntoa(addr)); send_packet_to_client(dhcp_server, &packet); add_lease(dhcp_server, 0, packet.chaddr, packet.yiaddr); if (dhcp_server->event_fn) dhcp_server->event_fn(ether_ntoa((void*)packet.chaddr), inet_ntoa(addr), dhcp_server->fn_data); }
static void init_packet(GDHCPServer *dhcp_server, struct dhcp_packet *packet, struct dhcp_packet *client_packet, char type) { /* Sets op, htype, hlen, cookie fields * and adds DHCP_MESSAGE_TYPE option */ dhcp_init_header(packet, type); packet->xid = client_packet->xid; memcpy(packet->chaddr, client_packet->chaddr, sizeof(client_packet->chaddr)); packet->flags = client_packet->flags; packet->gateway_nip = client_packet->gateway_nip; packet->ciaddr = client_packet->ciaddr; dhcp_add_option_uint32(packet, DHCP_SERVER_ID, dhcp_server->server_nip); }
static void send_offer(GDHCPServer *dhcp_server, struct dhcp_packet *client_packet, struct dhcp_lease *lease, uint32_t requested_nip) { struct dhcp_packet packet; struct in_addr addr; init_packet(dhcp_server, &packet, client_packet, DHCPOFFER); if (lease) packet.yiaddr = htonl(lease->lease_nip); else if (check_requested_nip(dhcp_server, requested_nip)) packet.yiaddr = htonl(requested_nip); else packet.yiaddr = htonl(find_free_or_expired_nip( dhcp_server, client_packet->chaddr)); debug(dhcp_server, "find yiaddr %u", packet.yiaddr); if (!packet.yiaddr) { debug(dhcp_server, "Err: Can not found lease and send offer"); return; } lease = add_lease(dhcp_server, OFFER_TIME, packet.chaddr, packet.yiaddr); if (!lease) { debug(dhcp_server, "Err: No free IP addresses. OFFER abandoned"); return; } dhcp_add_option_uint32(&packet, DHCP_LEASE_TIME, dhcp_server->lease_seconds); add_server_options(dhcp_server, &packet); addr.s_addr = packet.yiaddr; debug(dhcp_server, "Sending OFFER of %s", inet_ntoa(addr)); send_packet_to_client(dhcp_server, &packet); }
static void add_option(gpointer key, gpointer value, gpointer user_data) { const char *option_value = value; uint8_t option_code = GPOINTER_TO_INT(key); struct in_addr nip; struct dhcp_packet *packet = user_data; if (!option_value) return; switch (option_code) { case G_DHCP_SUBNET: case G_DHCP_ROUTER: case G_DHCP_DNS_SERVER: if (inet_aton(option_value, &nip) == 0) return; dhcp_add_option_uint32(packet, (uint8_t) option_code, ntohl(nip.s_addr)); break; default: return; } }