select.c revision 948f2876ce2a3010558f4f6937e16086ebcd36f2
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * CDDL HEADER START
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * The contents of this file are subject to the terms of the
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Common Development and Distribution License (the "License").
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * You may not use this file except in compliance with the License.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * or http://www.opensolaris.org/os/licensing.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * See the License for the specific language governing permissions
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * and limitations under the License.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * When distributing Covered Code, include this CDDL HEADER in each
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * If applicable, add the following below this CDDL HEADER, with the
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * fields enclosed by brackets "[]" replaced with your own identifying
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * information: Portions Copyright [yyyy] [name of copyright owner]
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * CDDL HEADER END
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Use is subject to license terms.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * SELECTING state of the client state machine.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#pragma ident "%Z%%M% %I% %E% SMI"
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <sys/types.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <stdio.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <stdlib.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <strings.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <time.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <limits.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <netinet/in.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <net/route.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <net/if.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <netinet/dhcp.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <netinet/udp.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <netinet/ip_var.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include <netinet/udp_var.h>
724365f7556fc4201fdb11766ebc6bd918523130sethg#include <dhcpmsg.h>
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include "states.h"
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include "agent.h"
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include "util.h"
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include "interface.h"
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#include "packet.h"
724365f7556fc4201fdb11766ebc6bd918523130sethg#include "defaults.h"
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindistatic stop_func_t stop_selecting;
724365f7556fc4201fdb11766ebc6bd918523130sethg
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * dhcp_start(): starts DHCP on a state machine
724365f7556fc4201fdb11766ebc6bd918523130sethg *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * input: iu_tq_t *: unused
724365f7556fc4201fdb11766ebc6bd918523130sethg * void *: the state machine on which to start DHCP
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * output: void
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
724365f7556fc4201fdb11766ebc6bd918523130sethg/* ARGSUSED */
724365f7556fc4201fdb11766ebc6bd918523130sethgstatic void
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindidhcp_start(iu_tq_t *tqp, void *arg)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dhcp_smach_t *dsmp = arg;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
724365f7556fc4201fdb11766ebc6bd918523130sethg dsmp->dsm_start_timer = -1;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) set_smach_state(dsmp, INIT);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (verify_smach(dsmp)) {
724365f7556fc4201fdb11766ebc6bd918523130sethg dhcpmsg(MSG_VERBOSE, "starting DHCP on %s", dsmp->dsm_name);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dhcp_selecting(dsmp);
724365f7556fc4201fdb11766ebc6bd918523130sethg }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
724365f7556fc4201fdb11766ebc6bd918523130sethg/*
724365f7556fc4201fdb11766ebc6bd918523130sethg * set_start_timer(): sets a random timer to start a DHCP state machine
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * input: dhcp_smach_t *: the state machine on which to start DHCP
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * output: boolean_t: B_TRUE if a timer is now running
724365f7556fc4201fdb11766ebc6bd918523130sethg */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindiboolean_t
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindiset_start_timer(dhcp_smach_t *dsmp)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
724365f7556fc4201fdb11766ebc6bd918523130sethg if (dsmp->dsm_start_timer != -1)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (B_TRUE);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dsmp->dsm_start_timer = iu_schedule_timer_ms(tq,
724365f7556fc4201fdb11766ebc6bd918523130sethg lrand48() % DHCP_SELECT_WAIT, dhcp_start, dsmp);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (dsmp->dsm_start_timer == -1)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (B_FALSE);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi hold_smach(dsmp);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return (B_TRUE);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * dhcp_selecting(): sends a DISCOVER and sets up reception of OFFERs for
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * IPv4, or sends a Solicit and sets up reception of
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Advertisements for DHCPv6.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * input: dhcp_smach_t *: the state machine on which to send the DISCOVER
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * output: void
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindivoid
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindidhcp_selecting(dhcp_smach_t *dsmp)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dhcp_pkt_t *dpkt;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi const char *reqhost;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi char hostfile[PATH_MAX + 1];
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * We first set up to collect OFFER/Advertise packets as they arrive.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * We then send out DISCOVER/Solicit probes. Then we wait a
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * user-tunable number of seconds before seeing if OFFERs/
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Advertisements have come in response to our DISCOVER/Solicit. If
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * none have come in, we continue to wait, sending out our DISCOVER/
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Solicit probes with exponential backoff. If no OFFER/Advertisement
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * is ever received, we will wait forever (note that since we're
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * event-driven though, we're still able to service other state
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * machines).
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi *
724365f7556fc4201fdb11766ebc6bd918523130sethg * Note that we do an reset_smach() here because we may be landing in
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * dhcp_selecting() as a result of restarting DHCP, so the state
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * machine may not be fresh.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
724365f7556fc4201fdb11766ebc6bd918523130sethg reset_smach(dsmp);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (!set_smach_state(dsmp, SELECTING)) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dhcpmsg(MSG_ERROR,
724365f7556fc4201fdb11766ebc6bd918523130sethg "dhcp_selecting: cannot switch to SELECTING state; "
724365f7556fc4201fdb11766ebc6bd918523130sethg "reverting to INIT on %s", dsmp->dsm_name);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi goto failed;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
724365f7556fc4201fdb11766ebc6bd918523130sethg }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dsmp->dsm_offer_timer = iu_schedule_timer(tq,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dsmp->dsm_offer_wait, dhcp_requesting, dsmp);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (dsmp->dsm_offer_timer == -1) {
724365f7556fc4201fdb11766ebc6bd918523130sethg dhcpmsg(MSG_ERROR, "dhcp_selecting: cannot schedule to read "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "%s packets", dsmp->dsm_isv6 ? "Advertise" : "OFFER");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi goto failed;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
724365f7556fc4201fdb11766ebc6bd918523130sethg
724365f7556fc4201fdb11766ebc6bd918523130sethg hold_smach(dsmp);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Assemble and send the DHCPDISCOVER or Solicit message.
724365f7556fc4201fdb11766ebc6bd918523130sethg *
724365f7556fc4201fdb11766ebc6bd918523130sethg * If this fails, we'll wait for the select timer to go off
724365f7556fc4201fdb11766ebc6bd918523130sethg * before trying again.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (dsmp->dsm_isv6) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dhcpv6_ia_na_t d6in;
724365f7556fc4201fdb11766ebc6bd918523130sethg
724365f7556fc4201fdb11766ebc6bd918523130sethg if ((dpkt = init_pkt(dsmp, DHCPV6_MSG_SOLICIT)) == NULL) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dhcpmsg(MSG_ERROR, "dhcp_selecting: unable to set up "
724365f7556fc4201fdb11766ebc6bd918523130sethg "Solicit packet");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /* Add an IA_NA option for our controlling LIF */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi d6in.d6in_iaid = htonl(dsmp->dsm_lif->lif_iaid);
724365f7556fc4201fdb11766ebc6bd918523130sethg d6in.d6in_t1 = htonl(0);
724365f7556fc4201fdb11766ebc6bd918523130sethg d6in.d6in_t2 = htonl(0);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) add_pkt_opt(dpkt, DHCPV6_OPT_IA_NA,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (dhcpv6_option_t *)&d6in + 1,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi sizeof (d6in) - sizeof (dhcpv6_option_t));
724365f7556fc4201fdb11766ebc6bd918523130sethg
724365f7556fc4201fdb11766ebc6bd918523130sethg /* Option Request option for desired information */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) add_pkt_prl(dpkt, dsmp);
724365f7556fc4201fdb11766ebc6bd918523130sethg
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /* Enable Rapid-Commit */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) add_pkt_opt(dpkt, DHCPV6_OPT_RAPID_COMMIT, NULL, 0);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /* xxx add Reconfigure Accept */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) send_pkt_v6(dsmp, dpkt, ipv6_all_dhcp_relay_and_servers,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi stop_selecting, DHCPV6_SOL_TIMEOUT, DHCPV6_SOL_MAX_RT);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi } else {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if ((dpkt = init_pkt(dsmp, DISCOVER)) == NULL) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dhcpmsg(MSG_ERROR, "dhcp_selecting: unable to set up "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "DISCOVER packet");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * The max DHCP message size option is set to the interface
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * MTU, minus the size of the UDP and IP headers.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) add_pkt_opt16(dpkt, CD_MAX_DHCP_SIZE,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi htons(dsmp->dsm_lif->lif_max - sizeof (struct udpiphdr)));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) add_pkt_opt32(dpkt, CD_LEASE_TIME, htonl(DHCP_PERM));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (class_id_len != 0) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) add_pkt_opt(dpkt, CD_CLASS_ID, class_id,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi class_id_len);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) add_pkt_prl(dpkt, dsmp);
724365f7556fc4201fdb11766ebc6bd918523130sethg
724365f7556fc4201fdb11766ebc6bd918523130sethg if (df_get_bool(dsmp->dsm_name, dsmp->dsm_isv6,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi DF_REQUEST_HOSTNAME)) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dhcpmsg(MSG_DEBUG,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "dhcp_selecting: DF_REQUEST_HOSTNAME");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) snprintf(hostfile, sizeof (hostfile),
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "/etc/hostname.%s", dsmp->dsm_name);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if ((reqhost = iffile_to_hostname(hostfile)) != NULL) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dhcpmsg(MSG_DEBUG, "dhcp_selecting: host %s",
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi reqhost);
724365f7556fc4201fdb11766ebc6bd918523130sethg dsmp->dsm_reqhost = strdup(reqhost);
724365f7556fc4201fdb11766ebc6bd918523130sethg if (dsmp->dsm_reqhost != NULL)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) add_pkt_opt(dpkt, CD_HOSTNAME,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dsmp->dsm_reqhost,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi strlen(dsmp->dsm_reqhost));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi else
724365f7556fc4201fdb11766ebc6bd918523130sethg dhcpmsg(MSG_WARNING,
724365f7556fc4201fdb11766ebc6bd918523130sethg "dhcp_selecting: cannot allocate "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "memory for host name option");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
724365f7556fc4201fdb11766ebc6bd918523130sethg (void) add_pkt_opt(dpkt, CD_END, NULL, 0);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (void) send_pkt(dsmp, dpkt, htonl(INADDR_BROADCAST),
724365f7556fc4201fdb11766ebc6bd918523130sethg stop_selecting);
724365f7556fc4201fdb11766ebc6bd918523130sethg }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindifailed:
724365f7556fc4201fdb11766ebc6bd918523130sethg (void) set_smach_state(dsmp, INIT);
724365f7556fc4201fdb11766ebc6bd918523130sethg dsmp->dsm_dflags |= DHCP_IF_FAILED;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi ipc_action_finish(dsmp, DHCP_IPC_E_MEMORY);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi}
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*
724365f7556fc4201fdb11766ebc6bd918523130sethg * dhcp_collect_dlpi(): collects incoming OFFERs, ACKs, and NAKs via DLPI.
724365f7556fc4201fdb11766ebc6bd918523130sethg *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * input: iu_eh_t *: unused
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * int: unused
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * short: unused
724365f7556fc4201fdb11766ebc6bd918523130sethg * iu_event_id_t: the id of this event callback with the handler
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * void *: the physical interface that received the message
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * output: void
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/* ARGSUSED */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindivoid
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindidhcp_collect_dlpi(iu_eh_t *eh, int fd, short events, iu_event_id_t id,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi void *arg)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi{
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dhcp_pif_t *pif = arg;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi PKT_LIST *plp;
724365f7556fc4201fdb11766ebc6bd918523130sethg uchar_t recv_type;
724365f7556fc4201fdb11766ebc6bd918523130sethg const char *pname;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dhcp_smach_t *dsmp;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi uint_t xid;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if ((plp = recv_pkt(fd, pif->pif_max, B_FALSE, B_TRUE, pif)) == NULL)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi recv_type = pkt_recv_type(plp);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi pname = pkt_type_to_string(recv_type, B_FALSE);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * DHCP_PUNTYPED messages are BOOTP server responses.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (!pkt_v4_match(recv_type,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi DHCP_PACK | DHCP_PNAK | DHCP_POFFER | DHCP_PUNTYPED)) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dhcpmsg(MSG_VERBOSE, "dhcp_collect_dlpi: ignored %s packet "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "received via DLPI on %s", pname, pif->pif_name);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi free_pkt_entry(plp);
724365f7556fc4201fdb11766ebc6bd918523130sethg return;
724365f7556fc4201fdb11766ebc6bd918523130sethg }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Loop through the state machines that match on XID to find one that's
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * interested in this offer. If there are none, then discard.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi xid = pkt_get_xid(plp->pkt, B_FALSE);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi for (dsmp = lookup_smach_by_xid(xid, NULL, B_FALSE); dsmp != NULL;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dsmp = lookup_smach_by_xid(xid, dsmp, B_FALSE)) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
724365f7556fc4201fdb11766ebc6bd918523130sethg /*
724365f7556fc4201fdb11766ebc6bd918523130sethg * Find state machine on correct interface.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (dsmp->dsm_lif->lif_pif == pif)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi break;
724365f7556fc4201fdb11766ebc6bd918523130sethg }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (dsmp == NULL) {
724365f7556fc4201fdb11766ebc6bd918523130sethg dhcpmsg(MSG_VERBOSE, "dhcp_collect_dlpi: no matching state "
724365f7556fc4201fdb11766ebc6bd918523130sethg "machine for %s packet XID %#x received via DLPI on %s",
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi pname, xid, pif->pif_name);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi free_pkt_entry(plp);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return;
724365f7556fc4201fdb11766ebc6bd918523130sethg }
724365f7556fc4201fdb11766ebc6bd918523130sethg
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /*
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Ignore state machines that aren't looking for DLPI messages.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (!dsmp->dsm_using_dlpi) {
724365f7556fc4201fdb11766ebc6bd918523130sethg dhcpmsg(MSG_VERBOSE, "dhcp_collect_dlpi: ignore state "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "machine for %s packet XID %#x received via DLPI on %s",
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi pname, xid, pif->pif_name);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi free_pkt_entry(plp);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (pkt_v4_match(recv_type, DHCP_PACK)) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (!dhcp_bound(dsmp, plp)) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi dhcpmsg(MSG_WARNING, "dhcp_collect_dlpi: dhcp_bound "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "failed for %s", dsmp->dsm_name);
724365f7556fc4201fdb11766ebc6bd918523130sethg dhcp_restart(dsmp);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi }
dhcpmsg(MSG_VERBOSE, "dhcp_collect_dlpi: %s on %s",
pname, dsmp->dsm_name);
} else if (pkt_v4_match(recv_type, DHCP_PNAK)) {
free_pkt_entry(plp);
dhcp_restart(dsmp);
} else {
pkt_smach_enqueue(dsmp, plp);
}
}
/*
* stop_selecting(): decides when to stop retransmitting DISCOVERs -- only when
* abandoning the state machine. For DHCPv6, this timer may
* go off before the offer wait timer. If so, then this is a
* good time to check for valid Advertisements, so cancel the
* timer and go check.
*
* input: dhcp_smach_t *: the state machine DISCOVERs are being sent on
* unsigned int: the number of DISCOVERs sent so far
* output: boolean_t: B_TRUE if retransmissions should stop
*/
/* ARGSUSED1 */
static boolean_t
stop_selecting(dhcp_smach_t *dsmp, unsigned int n_discovers)
{
/*
* If we're using v4 and the underlying LIF we're trying to configure
* has been touched by the user, then bail out.
*/
if (!dsmp->dsm_isv6 && !verify_lif(dsmp->dsm_lif)) {
finished_smach(dsmp, DHCP_IPC_E_UNKIF);
return (B_TRUE);
}
if (dsmp->dsm_recv_pkt_list != NULL) {
dhcp_requesting(NULL, dsmp);
if (dsmp->dsm_state != SELECTING)
return (B_TRUE);
}
return (B_FALSE);
}