1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * 26 * DECLINE/RELEASE configuration functionality for the DHCP client. 27 */ 28 29 #pragma ident "%Z%%M% %I% %E% SMI" 30 31 #include <sys/types.h> 32 #include <string.h> 33 #include <netinet/in.h> 34 #include <sys/socket.h> 35 #include <net/if.h> 36 #include <netinet/dhcp.h> 37 #include <dhcpmsg.h> 38 #include <dhcp_hostconf.h> 39 #include <unistd.h> 40 41 #include "packet.h" 42 #include "interface.h" 43 #include "states.h" 44 45 /* 46 * send_decline(): sends a DECLINE message (broadcasted) 47 * 48 * input: struct ifslist *: the interface to send the DECLINE on 49 * char *: an optional text explanation to send with the message 50 * struct in_addr *: the IP address being declined 51 * output: void 52 */ 53 54 void 55 send_decline(struct ifslist *ifsp, char *msg, struct in_addr *declined_ip) 56 { 57 dhcp_pkt_t *dpkt; 58 59 dpkt = init_pkt(ifsp, DECLINE); 60 add_pkt_opt32(dpkt, CD_SERVER_ID, ifsp->if_server.s_addr); 61 62 if (msg != NULL) 63 add_pkt_opt(dpkt, CD_MESSAGE, msg, strlen(msg) + 1); 64 65 add_pkt_opt32(dpkt, CD_REQUESTED_IP_ADDR, declined_ip->s_addr); 66 add_pkt_opt(dpkt, CD_END, NULL, 0); 67 68 (void) send_pkt(ifsp, dpkt, htonl(INADDR_BROADCAST), NULL); 69 } 70 71 /* 72 * dhcp_release(): sends a RELEASE message to a DHCP server and removes 73 * the interface from DHCP control 74 * 75 * input: struct ifslist *: the interface to send the RELEASE on and remove 76 * const char *: an optional text explanation to send with the message 77 * output: int: 1 on success, 0 on failure 78 */ 79 80 int 81 dhcp_release(struct ifslist *ifsp, const char *msg) 82 { 83 int retval = 0; 84 int error = DHCP_IPC_E_INT; 85 dhcp_pkt_t *dpkt; 86 87 if (ifsp->if_dflags & DHCP_IF_BOOTP) 88 goto out; 89 90 if (ifsp->if_state != BOUND && ifsp->if_state != RENEWING && 91 ifsp->if_state != REBINDING) 92 goto out; 93 94 dhcpmsg(MSG_INFO, "releasing interface %s", ifsp->if_name); 95 96 dpkt = init_pkt(ifsp, RELEASE); 97 dpkt->pkt->ciaddr.s_addr = ifsp->if_addr.s_addr; 98 99 if (msg != NULL) 100 add_pkt_opt(dpkt, CD_MESSAGE, msg, strlen(msg) + 1); 101 102 add_pkt_opt32(dpkt, CD_SERVER_ID, ifsp->if_server.s_addr); 103 add_pkt_opt(dpkt, CD_END, NULL, 0); 104 105 (void) send_pkt(ifsp, dpkt, ifsp->if_server.s_addr, NULL); 106 107 /* 108 * XXX this totally sucks, but since udp is best-effort, 109 * without this delay, there's a good chance that the packet 110 * that we just enqueued for sending will get pitched 111 * when we canonize the interface below. 112 */ 113 114 (void) usleep(500); 115 (void) canonize_ifs(ifsp); 116 117 remove_ifs(ifsp); 118 error = DHCP_IPC_SUCCESS; 119 retval = 1; 120 out: 121 ipc_action_finish(ifsp, error); 122 async_finish(ifsp); 123 return (retval); 124 } 125 126 /* 127 * dhcp_drop(): drops the interface from DHCP control 128 * 129 * input: struct ifslist *: the interface to drop 130 * const char *: unused 131 * output: int: always 1 132 */ 133 134 /* ARGSUSED */ 135 int 136 dhcp_drop(struct ifslist *ifsp, const char *msg) 137 { 138 PKT_LIST *plp[2]; 139 140 dhcpmsg(MSG_INFO, "dropping interface %s", ifsp->if_name); 141 142 if (ifsp->if_state == BOUND || ifsp->if_state == RENEWING || 143 ifsp->if_state == REBINDING) { 144 145 if ((ifsp->if_dflags & DHCP_IF_BOOTP) == 0) { 146 plp[0] = ifsp->if_ack; 147 plp[1] = ifsp->if_orig_ack; 148 if (write_hostconf(ifsp->if_name, plp, 2, 149 monosec_to_time(ifsp->if_curstart_monosec)) == -1) 150 dhcpmsg(MSG_ERR, "cannot write %s (reboot will " 151 "not use cached configuration)", 152 ifname_to_hostconf(ifsp->if_name)); 153 } 154 (void) canonize_ifs(ifsp); 155 } 156 remove_ifs(ifsp); 157 ipc_action_finish(ifsp, DHCP_IPC_SUCCESS); 158 async_finish(ifsp); 159 return (1); 160 } 161