From 4aca87515a5083ae0e31ce3177189fd43b6d05ac Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sat, 3 Jan 2015 13:58:15 +0100 Subject: patch to Vanilla Tomato 1.28 --- .../router/busybox/networking/udhcp/serverpacket.c | 223 +++++++++++---------- 1 file changed, 115 insertions(+), 108 deletions(-) (limited to 'release/src/router/busybox/networking/udhcp/serverpacket.c') diff --git a/release/src/router/busybox/networking/udhcp/serverpacket.c b/release/src/router/busybox/networking/udhcp/serverpacket.c index 09682444..8b0f1856 100644 --- a/release/src/router/busybox/networking/udhcp/serverpacket.c +++ b/release/src/router/busybox/networking/udhcp/serverpacket.c @@ -1,6 +1,7 @@ +/* vi: set sw=4 ts=4: */ /* serverpacket.c * - * Constuct and send DHCP server packets + * Construct and send DHCP server packets * * Russ Dill July 2001 * @@ -19,22 +20,18 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include -#include -#include -#include -#include - +#include "common.h" +#include "dhcpc.h" #include "dhcpd.h" #include "options.h" -#include "common.h" + /* send a packet to giaddr using the kernel ip stack */ static int send_packet_to_relay(struct dhcpMessage *payload) { - DEBUG(LOG_INFO, "Forwarding packet to relay"); + DEBUG("Forwarding packet to relay"); - return kernel_packet(payload, server_config.server, SERVER_PORT, + return udhcp_send_kernel_packet(payload, server_config.server, SERVER_PORT, payload->giaddr, SERVER_PORT); } @@ -42,46 +39,45 @@ static int send_packet_to_relay(struct dhcpMessage *payload) /* send a packet to a specific arp address and ip address by creating our own ip packet */ static int send_packet_to_client(struct dhcpMessage *payload, int force_broadcast) { - unsigned char *chaddr; - u_int32_t ciaddr; - + const uint8_t *chaddr; + uint32_t ciaddr; + if (force_broadcast) { - DEBUG(LOG_INFO, "broadcasting packet to client (NAK)"); + DEBUG("broadcasting packet to client (NAK)"); ciaddr = INADDR_BROADCAST; chaddr = MAC_BCAST_ADDR; } else if (payload->ciaddr) { - DEBUG(LOG_INFO, "unicasting packet to client ciaddr"); + DEBUG("unicasting packet to client ciaddr"); ciaddr = payload->ciaddr; chaddr = payload->chaddr; - } else if (ntohs(payload->flags) & BROADCAST_FLAG) { - DEBUG(LOG_INFO, "broadcasting packet to client (requested)"); + } else if (payload->flags & htons(BROADCAST_FLAG)) { + DEBUG("broadcasting packet to client (requested)"); ciaddr = INADDR_BROADCAST; chaddr = MAC_BCAST_ADDR; } else { - DEBUG(LOG_INFO, "unicasting packet to client yiaddr"); + DEBUG("unicasting packet to client yiaddr"); ciaddr = payload->yiaddr; chaddr = payload->chaddr; } - return raw_packet(payload, server_config.server, SERVER_PORT, - ciaddr, CLIENT_PORT, chaddr, server_config.ifindex); + return udhcp_send_raw_packet(payload, + /*src*/ server_config.server, SERVER_PORT, + /*dst*/ ciaddr, CLIENT_PORT, chaddr, + server_config.ifindex); } /* send a dhcp packet, if force broadcast is set, the packet will be broadcast to the client */ static int send_packet(struct dhcpMessage *payload, int force_broadcast) { - int ret; - if (payload->giaddr) - ret = send_packet_to_relay(payload); - else ret = send_packet_to_client(payload, force_broadcast); - return ret; + return send_packet_to_relay(payload); + return send_packet_to_client(payload, force_broadcast); } static void init_packet(struct dhcpMessage *packet, struct dhcpMessage *oldpacket, char type) { - init_header(packet, type); + udhcp_init_header(packet, type); packet->xid = oldpacket->xid; memcpy(packet->chaddr, oldpacket->chaddr, 16); packet->flags = oldpacket->flags; @@ -96,78 +92,82 @@ static void add_bootp_options(struct dhcpMessage *packet) { packet->siaddr = server_config.siaddr; if (server_config.sname) - strncpy(packet->sname, server_config.sname, sizeof(packet->sname) - 1); + strncpy((char*)packet->sname, server_config.sname, sizeof(packet->sname) - 1); if (server_config.boot_file) - strncpy(packet->file, server_config.boot_file, sizeof(packet->file) - 1); + strncpy((char*)packet->file, server_config.boot_file, sizeof(packet->file) - 1); } - + /* send a DHCP OFFER to a DHCP DISCOVER */ -int sendOffer(struct dhcpMessage *oldpacket) +int FAST_FUNC send_offer(struct dhcpMessage *oldpacket) { struct dhcpMessage packet; - struct dhcpOfferedAddr *lease = NULL; - u_int32_t req_align, lease_time_align = server_config.lease; - unsigned char *req, *lease_time; + uint32_t req_align; + uint32_t lease_time_aligned = server_config.lease; + uint32_t static_lease_ip; + uint8_t *req, *lease_time, *p_host_name; struct option_set *curr; struct in_addr addr; init_packet(&packet, oldpacket, DHCPOFFER); - + + static_lease_ip = getIpByMac(server_config.static_leases, oldpacket->chaddr); + /* ADDME: if static, short circuit */ - /* the client is in our lease/offered table */ - if ((lease = find_lease_by_chaddr(oldpacket->chaddr))) { - if (!lease_expired(lease)) - lease_time_align = lease->expires - time(0); - packet.yiaddr = lease->yiaddr; - - /* Or the client has a requested ip */ - } else if ((req = get_option(oldpacket, DHCP_REQUESTED_IP)) && - - /* Don't look here (ugly hackish thing to do) */ - memcpy(&req_align, req, 4) && - - /* and the ip is in the lease range */ - ntohl(req_align) >= ntohl(server_config.start) && - ntohl(req_align) <= ntohl(server_config.end) && - - /* and its not already taken/offered */ /* ADDME: check that its not a static lease */ - ((!(lease = find_lease_by_yiaddr(req_align)) || - - /* or its taken, but expired */ /* ADDME: or maybe in here */ - lease_expired(lease)))) { - packet.yiaddr = req_align; /* FIXME: oh my, is there a host using this IP? */ - - /* otherwise, find a free IP */ /*ADDME: is it a static lease? */ + if (!static_lease_ip) { + struct dhcpOfferedAddr *lease; + + lease = find_lease_by_chaddr(oldpacket->chaddr); + /* the client is in our lease/offered table */ + if (lease) { + signed_leasetime_t tmp = lease->expires - time(NULL); + if (tmp >= 0) + lease_time_aligned = tmp; + packet.yiaddr = lease->yiaddr; + /* Or the client has requested an ip */ + } else if ((req = get_option(oldpacket, DHCP_REQUESTED_IP)) != NULL + /* Don't look here (ugly hackish thing to do) */ + && (move_from_unaligned32(req_align, req), 1) + /* and the ip is in the lease range */ + && ntohl(req_align) >= server_config.start_ip + && ntohl(req_align) <= server_config.end_ip + /* and is not already taken/offered */ + && (!(lease = find_lease_by_yiaddr(req_align)) + /* or its taken, but expired */ + || lease_expired(lease)) + ) { + packet.yiaddr = req_align; + /* otherwise, find a free IP */ + } else { + packet.yiaddr = find_free_or_expired_address(); + } + + if (!packet.yiaddr) { + bb_error_msg("no IP addresses to give - OFFER abandoned"); + return -1; + } + p_host_name = get_option(oldpacket, DHCP_HOST_NAME); + if (!add_lease(packet.chaddr, packet.yiaddr, server_config.offer_time, p_host_name)) { + bb_error_msg("lease pool is full - OFFER abandoned"); + return -1; + } + lease_time = get_option(oldpacket, DHCP_LEASE_TIME); + if (lease_time) { + move_from_unaligned32(lease_time_aligned, lease_time); + lease_time_aligned = ntohl(lease_time_aligned); + if (lease_time_aligned > server_config.lease) + lease_time_aligned = server_config.lease; + } + + /* Make sure we aren't just using the lease time from the previous offer */ + if (lease_time_aligned < server_config.min_lease) + lease_time_aligned = server_config.min_lease; } else { - packet.yiaddr = find_address(0); - - /* try for an expired lease */ - if (!packet.yiaddr) packet.yiaddr = find_address(1); - } - - if(!packet.yiaddr) { - LOG(LOG_WARNING, "no IP addresses to give -- OFFER abandoned"); - return -1; - } - - if (!add_lease(packet.chaddr, packet.yiaddr, server_config.offer_time)) { - LOG(LOG_WARNING, "lease pool is full -- OFFER abandoned"); - return -1; - } - - if ((lease_time = get_option(oldpacket, DHCP_LEASE_TIME))) { - memcpy(&lease_time_align, lease_time, 4); - lease_time_align = ntohl(lease_time_align); - if (lease_time_align > server_config.lease) - lease_time_align = server_config.lease; + /* It is a static lease... use it */ + packet.yiaddr = static_lease_ip; } - /* Make sure we aren't just using the lease time from the previous offer */ - if (lease_time_align < server_config.min_lease) - lease_time_align = server_config.lease; - /* ADDME: end of short circuit */ - add_simple_option(packet.options, DHCP_LEASE_TIME, htonl(lease_time_align)); + add_simple_option(packet.options, DHCP_LEASE_TIME, htonl(lease_time_aligned)); curr = server_config.options; while (curr) { @@ -177,46 +177,48 @@ int sendOffer(struct dhcpMessage *oldpacket) } add_bootp_options(&packet); - + addr.s_addr = packet.yiaddr; - LOG(LOG_INFO, "sending OFFER of %s", inet_ntoa(addr)); + bb_info_msg("Sending OFFER of %s", inet_ntoa(addr)); return send_packet(&packet, 0); } -int sendNAK(struct dhcpMessage *oldpacket) +int FAST_FUNC send_NAK(struct dhcpMessage *oldpacket) { struct dhcpMessage packet; init_packet(&packet, oldpacket, DHCPNAK); - - DEBUG(LOG_INFO, "sending NAK"); + + DEBUG("Sending NAK"); return send_packet(&packet, 1); } -int sendACK(struct dhcpMessage *oldpacket, u_int32_t yiaddr) +int FAST_FUNC send_ACK(struct dhcpMessage *oldpacket, uint32_t yiaddr) { struct dhcpMessage packet; struct option_set *curr; - unsigned char *lease_time; - u_int32_t lease_time_align = server_config.lease; + uint8_t *lease_time; + uint32_t lease_time_aligned = server_config.lease; struct in_addr addr; + uint8_t *p_host_name; init_packet(&packet, oldpacket, DHCPACK); packet.yiaddr = yiaddr; - - if ((lease_time = get_option(oldpacket, DHCP_LEASE_TIME))) { - memcpy(&lease_time_align, lease_time, 4); - lease_time_align = ntohl(lease_time_align); - if (lease_time_align > server_config.lease) - lease_time_align = server_config.lease; - else if (lease_time_align < server_config.min_lease) - lease_time_align = server_config.lease; + + lease_time = get_option(oldpacket, DHCP_LEASE_TIME); + if (lease_time) { + move_from_unaligned32(lease_time_aligned, lease_time); + lease_time_aligned = ntohl(lease_time_aligned); + if (lease_time_aligned > server_config.lease) + lease_time_aligned = server_config.lease; + else if (lease_time_aligned < server_config.min_lease) + lease_time_aligned = server_config.min_lease; } - - add_simple_option(packet.options, DHCP_LEASE_TIME, htonl(lease_time_align)); - + + add_simple_option(packet.options, DHCP_LEASE_TIME, htonl(lease_time_aligned)); + curr = server_config.options; while (curr) { if (curr->data[OPT_CODE] != DHCP_LEASE_TIME) @@ -227,24 +229,29 @@ int sendACK(struct dhcpMessage *oldpacket, u_int32_t yiaddr) add_bootp_options(&packet); addr.s_addr = packet.yiaddr; - LOG(LOG_INFO, "sending ACK to %s", inet_ntoa(addr)); + bb_info_msg("Sending ACK to %s", inet_ntoa(addr)); - if (send_packet(&packet, 0) < 0) + if (send_packet(&packet, 0) < 0) return -1; - add_lease(packet.chaddr, packet.yiaddr, lease_time_align); + p_host_name = get_option(oldpacket, DHCP_HOST_NAME); + add_lease(packet.chaddr, packet.yiaddr, lease_time_aligned, p_host_name); + if (ENABLE_FEATURE_UDHCPD_WRITE_LEASES_EARLY) { + /* rewrite the file with leases at every new acceptance */ + write_leases(); + } return 0; } -int send_inform(struct dhcpMessage *oldpacket) +int FAST_FUNC send_inform(struct dhcpMessage *oldpacket) { struct dhcpMessage packet; struct option_set *curr; init_packet(&packet, oldpacket, DHCPACK); - + curr = server_config.options; while (curr) { if (curr->data[OPT_CODE] != DHCP_LEASE_TIME) -- cgit v1.2.3-54-g00ecf