/* NOINLINE: limit stack usage in caller */ static NOINLINE void send_inform(struct dhcp_packet *oldpacket) { struct dhcp_packet packet; /* "If a client has obtained a network address through some other means * (e.g., manual configuration), it may use a DHCPINFORM request message * to obtain other local configuration parameters. Servers receiving a * DHCPINFORM message construct a DHCPACK message with any local * configuration parameters appropriate for the client without: * allocating a new address, checking for an existing binding, filling * in 'yiaddr' or including lease time parameters. The servers SHOULD * unicast the DHCPACK reply to the address given in the 'ciaddr' field * of the DHCPINFORM message. * ... * The server responds to a DHCPINFORM message by sending a DHCPACK * message directly to the address given in the 'ciaddr' field * of the DHCPINFORM message. The server MUST NOT send a lease * expiration time to the client and SHOULD NOT fill in 'yiaddr'." */ //TODO: do a few sanity checks: is ciaddr set? //Better yet: is ciaddr == IP source addr? init_packet(&packet, oldpacket, DHCPACK); add_server_options(&packet); send_packet(&packet, /*force_bcast:*/ 0); }
/* NOINLINE: limit stack usage in caller */ static NOINLINE void send_ACK(struct dhcp_packet *oldpacket, uint32_t yiaddr) { struct dhcp_packet packet; uint32_t lease_time_sec; struct in_addr addr; const char *p_host_name; init_packet(&packet, oldpacket, DHCPACK); packet.yiaddr = yiaddr; lease_time_sec = select_lease_time(oldpacket); udhcp_add_simple_option(&packet, DHCP_LEASE_TIME, htonl(lease_time_sec)); add_server_options(&packet); addr.s_addr = yiaddr; bb_info_msg("Sending ACK to %s", inet_ntoa(addr)); send_packet(&packet, /*force_bcast:*/ 0); p_host_name = (const char*) udhcp_get_option(oldpacket, DHCP_HOST_NAME); add_lease(packet.chaddr, packet.yiaddr, lease_time_sec, p_host_name, p_host_name ? (unsigned char)p_host_name[OPT_LEN - OPT_DATA] : 0 ); if (ENABLE_FEATURE_UDHCPD_WRITE_LEASES_EARLY) { /* rewrite the file with leases at every new acceptance */ write_leases(); } }
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 send_inform(GDHCPServer *dhcp_server, struct dhcp_packet *client_packet) { struct dhcp_packet packet; init_packet(dhcp_server, &packet, client_packet, DHCPACK); add_server_options(dhcp_server, &packet); send_packet_to_client(dhcp_server, &packet); }
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); }
// update everyone on the current netgame options void multi_options_update_netgame() { ubyte data[MAX_PACKET_SIZE],code; int packet_size = 0; Assert(Net_player->flags & NETINFO_FLAG_GAME_HOST); // build the header and add the opcode BUILD_HEADER(OPTIONS_UPDATE); code = MULTI_OPTION_SERVER; ADD_DATA(code); // add the netgame options add_server_options(data, &packet_size, &Netgame.options); // send the packet if(Net_player->flags & NETINFO_FLAG_AM_MASTER){ multi_io_send_to_all_reliable(data, packet_size); } else { multi_io_send_reliable(Net_player, data, packet_size); } }
static void send_ACK(GDHCPServer *dhcp_server, struct dhcp_packet *client_packet, uint32_t yiaddr) { struct dhcp_packet packet; uint32_t lease_time_sec; struct in_addr addr; init_packet(dhcp_server, &packet, client_packet, DHCPACK); packet.yiaddr = yiaddr; lease_time_sec = dhcp_server->lease_seconds; dhcp_add_simple_option(&packet, DHCP_LEASE_TIME, htonl(lease_time_sec)); add_server_options(dhcp_server, &packet); addr.s_addr = yiaddr; 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); }
/* NOINLINE: limit stack usage in caller */ static NOINLINE void send_offer(struct dhcp_packet *oldpacket, uint32_t static_lease_nip, struct dyn_lease *lease, uint8_t *requested_ip_opt, unsigned arpping_ms) { struct dhcp_packet packet; uint32_t lease_time_sec; struct in_addr addr; init_packet(&packet, oldpacket, DHCPOFFER); /* If it is a static lease, use its IP */ packet.yiaddr = static_lease_nip; /* Else: */ if (!static_lease_nip) { /* We have no static lease for client's chaddr */ uint32_t req_nip; const char *p_host_name; if (lease) { /* We have a dynamic lease for client's chaddr. * Reuse its IP (even if lease is expired). * Note that we ignore requested IP in this case. */ packet.yiaddr = lease->lease_nip; } /* Or: if client has requested an IP */ else if (requested_ip_opt != NULL /* (read IP) */ && (move_from_unaligned32(req_nip, requested_ip_opt), 1) /* and the IP is in the lease range */ && ntohl(req_nip) >= server_config.start_ip && ntohl(req_nip) <= server_config.end_ip /* and */ && ( !(lease = find_lease_by_nip(req_nip)) /* is not already taken */ || is_expired_lease(lease) /* or is taken, but expired */ ) ) { packet.yiaddr = req_nip; } else { /* Otherwise, find a free IP */ packet.yiaddr = find_free_or_expired_nip(oldpacket->chaddr, arpping_ms); } if (!packet.yiaddr) { bb_error_msg("no free IP addresses. OFFER abandoned"); return; } /* Reserve the IP for a short time hoping to get DHCPREQUEST soon */ p_host_name = (const char*) udhcp_get_option(oldpacket, DHCP_HOST_NAME); lease = add_lease(packet.chaddr, packet.yiaddr, server_config.offer_time, p_host_name, p_host_name ? (unsigned char)p_host_name[OPT_LEN - OPT_DATA] : 0 ); if (!lease) { bb_error_msg("no free IP addresses. OFFER abandoned"); return; } } lease_time_sec = select_lease_time(oldpacket); udhcp_add_simple_option(&packet, DHCP_LEASE_TIME, htonl(lease_time_sec)); add_server_options(&packet); addr.s_addr = packet.yiaddr; bb_info_msg("Sending OFFER of %s", inet_ntoa(addr)); /* send_packet emits error message itself if it detects failure */ send_packet(&packet, /*force_bcast:*/ 0); }