10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 53431Scarlsonj * Common Development and Distribution License (the "License"). 63431Scarlsonj * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 223431Scarlsonj * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 233431Scarlsonj * Use is subject to license terms. 240Sstevel@tonic-gate * 250Sstevel@tonic-gate * INFORM_SENT state of the client state machine. 260Sstevel@tonic-gate */ 270Sstevel@tonic-gate 280Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 290Sstevel@tonic-gate 300Sstevel@tonic-gate #include <sys/types.h> 310Sstevel@tonic-gate #include <time.h> 320Sstevel@tonic-gate #include <sys/socket.h> 330Sstevel@tonic-gate #include <netinet/in.h> 340Sstevel@tonic-gate #include <netinet/udp.h> 350Sstevel@tonic-gate #include <netinet/ip_var.h> 360Sstevel@tonic-gate #include <netinet/udp_var.h> 370Sstevel@tonic-gate #include <dhcpmsg.h> 380Sstevel@tonic-gate 393431Scarlsonj #include "agent.h" 403431Scarlsonj #include "states.h" 413431Scarlsonj #include "interface.h" 420Sstevel@tonic-gate #include "packet.h" 433431Scarlsonj 443431Scarlsonj static boolean_t stop_informing(dhcp_smach_t *, unsigned int); 450Sstevel@tonic-gate 460Sstevel@tonic-gate /* 470Sstevel@tonic-gate * dhcp_inform(): sends an INFORM packet and sets up reception for an ACK 480Sstevel@tonic-gate * 493431Scarlsonj * input: dhcp_smach_t *: the state machine to use 500Sstevel@tonic-gate * output: void 510Sstevel@tonic-gate * note: the INFORM cannot be sent successfully if the interface 523431Scarlsonj * does not have an IP address (this is mostly an issue for IPv4). 53*4106Scarlsonj * We switch into INFORM_SENT state before sending the packet so 54*4106Scarlsonj * that the packet-sending subsystem uses regular sockets and sets 55*4106Scarlsonj * the source address. (See set_smach_state.) 560Sstevel@tonic-gate */ 570Sstevel@tonic-gate 580Sstevel@tonic-gate void 593431Scarlsonj dhcp_inform(dhcp_smach_t *dsmp) 600Sstevel@tonic-gate { 610Sstevel@tonic-gate dhcp_pkt_t *dpkt; 620Sstevel@tonic-gate 63*4106Scarlsonj if (!set_smach_state(dsmp, INFORM_SENT)) 643431Scarlsonj goto failed; 653431Scarlsonj 663431Scarlsonj if (dsmp->dsm_isv6) { 673431Scarlsonj dpkt = init_pkt(dsmp, DHCPV6_MSG_INFO_REQ); 680Sstevel@tonic-gate 693431Scarlsonj /* Add required Option Request option */ 703431Scarlsonj (void) add_pkt_prl(dpkt, dsmp); 713431Scarlsonj dsmp->dsm_server = ipv6_all_dhcp_relay_and_servers; 723431Scarlsonj (void) send_pkt_v6(dsmp, dpkt, dsmp->dsm_server, 733431Scarlsonj stop_informing, DHCPV6_INF_TIMEOUT, DHCPV6_INF_MAX_RT); 743431Scarlsonj } else { 753431Scarlsonj ipaddr_t server; 760Sstevel@tonic-gate 773431Scarlsonj /* 783431Scarlsonj * Assemble a DHCPREQUEST packet, without the Server ID option. 793431Scarlsonj * Fill in ciaddr, since we know this. dsm_server will be set 803431Scarlsonj * to the server's IP address, which will be the broadcast 813431Scarlsonj * address if we don't know it. The max DHCP message size 823431Scarlsonj * option is set to the interface max, minus the size of the 833431Scarlsonj * UDP and IP headers. 843431Scarlsonj */ 853431Scarlsonj 863431Scarlsonj dpkt = init_pkt(dsmp, INFORM); 873431Scarlsonj IN6_V4MAPPED_TO_INADDR(&dsmp->dsm_lif->lif_v6addr, 883431Scarlsonj &dpkt->pkt->ciaddr); 890Sstevel@tonic-gate 903431Scarlsonj (void) add_pkt_opt16(dpkt, CD_MAX_DHCP_SIZE, 913431Scarlsonj htons(dsmp->dsm_lif->lif_pif->pif_max - 923431Scarlsonj sizeof (struct udpiphdr))); 933448Sdh155122 if (class_id_len != 0) { 943448Sdh155122 (void) add_pkt_opt(dpkt, CD_CLASS_ID, class_id, 953448Sdh155122 class_id_len); 963448Sdh155122 } 973431Scarlsonj (void) add_pkt_prl(dpkt, dsmp); 983431Scarlsonj (void) add_pkt_opt(dpkt, CD_END, NULL, 0); 990Sstevel@tonic-gate 1003431Scarlsonj IN6_V4MAPPED_TO_IPADDR(&dsmp->dsm_server, server); 1013431Scarlsonj if (!send_pkt(dsmp, dpkt, server, NULL)) { 1023431Scarlsonj dhcpmsg(MSG_ERROR, "dhcp_inform: send_pkt failed"); 1033431Scarlsonj goto failed; 1043431Scarlsonj } 1050Sstevel@tonic-gate } 1060Sstevel@tonic-gate 1073431Scarlsonj return; 1080Sstevel@tonic-gate 1093431Scarlsonj failed: 1103431Scarlsonj dsmp->dsm_dflags |= DHCP_IF_FAILED; 1113431Scarlsonj ipc_action_finish(dsmp, DHCP_IPC_E_INT); 112*4106Scarlsonj (void) set_smach_state(dsmp, INIT); 1133431Scarlsonj } 1140Sstevel@tonic-gate 1153431Scarlsonj /* 1163431Scarlsonj * stop_informing(): decides when to stop retransmitting Information-Requests 1173431Scarlsonj * 1183431Scarlsonj * input: dhcp_smach_t *: the state machine Info-Reqs are being sent from 1193431Scarlsonj * unsigned int: the number of requests sent so far 1203431Scarlsonj * output: boolean_t: B_TRUE if retransmissions should stop 1213431Scarlsonj */ 1220Sstevel@tonic-gate 1233431Scarlsonj /* ARGSUSED */ 1243431Scarlsonj static boolean_t 1253431Scarlsonj stop_informing(dhcp_smach_t *dsmp, unsigned int n_requests) 1263431Scarlsonj { 1273431Scarlsonj return (B_FALSE); 1280Sstevel@tonic-gate } 129