xref: /onnv-gate/usr/src/cmd/cmd-inet/sbin/dhcpagent/renew.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <sys/types.h>
30*0Sstevel@tonic-gate #include <time.h>
31*0Sstevel@tonic-gate #include <unistd.h>
32*0Sstevel@tonic-gate #include <netinet/in.h>
33*0Sstevel@tonic-gate #include <netinet/dhcp.h>
34*0Sstevel@tonic-gate #include <netinet/udp.h>
35*0Sstevel@tonic-gate #include <netinet/ip_var.h>
36*0Sstevel@tonic-gate #include <netinet/udp_var.h>
37*0Sstevel@tonic-gate #include <libinetutil.h>
38*0Sstevel@tonic-gate #include <dhcpmsg.h>
39*0Sstevel@tonic-gate #include <string.h>
40*0Sstevel@tonic-gate 
41*0Sstevel@tonic-gate #include "packet.h"
42*0Sstevel@tonic-gate #include "agent.h"
43*0Sstevel@tonic-gate #include "script_handler.h"
44*0Sstevel@tonic-gate #include "interface.h"
45*0Sstevel@tonic-gate #include "states.h"
46*0Sstevel@tonic-gate #include "util.h"
47*0Sstevel@tonic-gate 
48*0Sstevel@tonic-gate /*
49*0Sstevel@tonic-gate  * next_extend_time(): returns the next time an EXTEND request should be sent
50*0Sstevel@tonic-gate  *
51*0Sstevel@tonic-gate  *   input: monosec_t: the absolute time when the next state is entered
52*0Sstevel@tonic-gate  *  output: uint32_t: the number of seconds in the future to send the next
53*0Sstevel@tonic-gate  *		      EXTEND request
54*0Sstevel@tonic-gate  */
55*0Sstevel@tonic-gate 
56*0Sstevel@tonic-gate static uint32_t
57*0Sstevel@tonic-gate next_extend_time(monosec_t limit_monosec)
58*0Sstevel@tonic-gate {
59*0Sstevel@tonic-gate 	monosec_t	current_monosec = monosec();
60*0Sstevel@tonic-gate 
61*0Sstevel@tonic-gate 	if (limit_monosec - current_monosec < DHCP_REBIND_MIN)
62*0Sstevel@tonic-gate 		return (0);
63*0Sstevel@tonic-gate 
64*0Sstevel@tonic-gate 	return ((limit_monosec - current_monosec) / 2);
65*0Sstevel@tonic-gate }
66*0Sstevel@tonic-gate 
67*0Sstevel@tonic-gate /*
68*0Sstevel@tonic-gate  * dhcp_renew(): attempts to renew a DHCP lease
69*0Sstevel@tonic-gate  *
70*0Sstevel@tonic-gate  *   input: iu_tq_t *: unused
71*0Sstevel@tonic-gate  *	    void *: the ifslist to renew the lease on
72*0Sstevel@tonic-gate  *  output: void
73*0Sstevel@tonic-gate  */
74*0Sstevel@tonic-gate 
75*0Sstevel@tonic-gate /* ARGSUSED */
76*0Sstevel@tonic-gate void
77*0Sstevel@tonic-gate dhcp_renew(iu_tq_t *tqp, void *arg)
78*0Sstevel@tonic-gate {
79*0Sstevel@tonic-gate 	struct ifslist *ifsp = (struct ifslist *)arg;
80*0Sstevel@tonic-gate 	uint32_t	next;
81*0Sstevel@tonic-gate 
82*0Sstevel@tonic-gate 
83*0Sstevel@tonic-gate 	ifsp->if_timer[DHCP_T1_TIMER] = -1;
84*0Sstevel@tonic-gate 
85*0Sstevel@tonic-gate 	if (check_ifs(ifsp) == 0) {
86*0Sstevel@tonic-gate 		(void) release_ifs(ifsp);
87*0Sstevel@tonic-gate 		return;
88*0Sstevel@tonic-gate 	}
89*0Sstevel@tonic-gate 
90*0Sstevel@tonic-gate 	/*
91*0Sstevel@tonic-gate 	 * sanity check: don't send packets if we're past t2.
92*0Sstevel@tonic-gate 	 */
93*0Sstevel@tonic-gate 
94*0Sstevel@tonic-gate 	if (monosec() > (ifsp->if_curstart_monosec + ifsp->if_t2))
95*0Sstevel@tonic-gate 		return;
96*0Sstevel@tonic-gate 
97*0Sstevel@tonic-gate 	next = next_extend_time(ifsp->if_curstart_monosec + ifsp->if_t2);
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate 	/*
100*0Sstevel@tonic-gate 	 * if there isn't an async event pending, then try to renew.
101*0Sstevel@tonic-gate 	 */
102*0Sstevel@tonic-gate 
103*0Sstevel@tonic-gate 	if (!async_pending(ifsp))
104*0Sstevel@tonic-gate 		if (async_start(ifsp, DHCP_EXTEND, B_FALSE) != 0)
105*0Sstevel@tonic-gate 
106*0Sstevel@tonic-gate 			/*
107*0Sstevel@tonic-gate 			 * try to send extend.  if we don't succeed,
108*0Sstevel@tonic-gate 			 * async_timeout() will clean us up.
109*0Sstevel@tonic-gate 			 */
110*0Sstevel@tonic-gate 
111*0Sstevel@tonic-gate 			(void) dhcp_extending(ifsp);
112*0Sstevel@tonic-gate 
113*0Sstevel@tonic-gate 	/*
114*0Sstevel@tonic-gate 	 * if we're within DHCP_REBIND_MIN seconds of REBINDING, don't
115*0Sstevel@tonic-gate 	 * reschedule ourselves.
116*0Sstevel@tonic-gate 	 */
117*0Sstevel@tonic-gate 
118*0Sstevel@tonic-gate 	if (next == 0)
119*0Sstevel@tonic-gate 		return;
120*0Sstevel@tonic-gate 
121*0Sstevel@tonic-gate 	/*
122*0Sstevel@tonic-gate 	 * no big deal if we can't reschedule; we still have the REBIND
123*0Sstevel@tonic-gate 	 * state to save us.
124*0Sstevel@tonic-gate 	 */
125*0Sstevel@tonic-gate 
126*0Sstevel@tonic-gate 	(void) schedule_ifs_timer(ifsp, DHCP_T1_TIMER, next, dhcp_renew);
127*0Sstevel@tonic-gate }
128*0Sstevel@tonic-gate 
129*0Sstevel@tonic-gate /*
130*0Sstevel@tonic-gate  * dhcp_rebind(): attempts to renew a DHCP lease from the REBINDING state
131*0Sstevel@tonic-gate  *
132*0Sstevel@tonic-gate  *   input: iu_tq_t *: unused
133*0Sstevel@tonic-gate  *	    void *: the ifslist to renew the lease on
134*0Sstevel@tonic-gate  *  output: void
135*0Sstevel@tonic-gate  */
136*0Sstevel@tonic-gate 
137*0Sstevel@tonic-gate /* ARGSUSED */
138*0Sstevel@tonic-gate void
139*0Sstevel@tonic-gate dhcp_rebind(iu_tq_t *tqp, void *arg)
140*0Sstevel@tonic-gate {
141*0Sstevel@tonic-gate 	struct ifslist *ifsp = (struct ifslist *)arg;
142*0Sstevel@tonic-gate 	uint32_t	next;
143*0Sstevel@tonic-gate 
144*0Sstevel@tonic-gate 	ifsp->if_timer[DHCP_T2_TIMER] = -1;
145*0Sstevel@tonic-gate 
146*0Sstevel@tonic-gate 	if (check_ifs(ifsp) == 0) {
147*0Sstevel@tonic-gate 		(void) release_ifs(ifsp);
148*0Sstevel@tonic-gate 		return;
149*0Sstevel@tonic-gate 	}
150*0Sstevel@tonic-gate 
151*0Sstevel@tonic-gate 	/*
152*0Sstevel@tonic-gate 	 * sanity check: don't send packets if we've already expired.
153*0Sstevel@tonic-gate 	 */
154*0Sstevel@tonic-gate 
155*0Sstevel@tonic-gate 	if (monosec() > (ifsp->if_curstart_monosec + ifsp->if_lease))
156*0Sstevel@tonic-gate 		return;
157*0Sstevel@tonic-gate 
158*0Sstevel@tonic-gate 	next = next_extend_time(ifsp->if_curstart_monosec + ifsp->if_lease);
159*0Sstevel@tonic-gate 
160*0Sstevel@tonic-gate 	/*
161*0Sstevel@tonic-gate 	 * if this is our first venture into the REBINDING state, then
162*0Sstevel@tonic-gate 	 * reset the server address.  we know the renew timer has
163*0Sstevel@tonic-gate 	 * already been cancelled (or we wouldn't be here).
164*0Sstevel@tonic-gate 	 */
165*0Sstevel@tonic-gate 
166*0Sstevel@tonic-gate 	if (ifsp->if_state == RENEWING) {
167*0Sstevel@tonic-gate 		ifsp->if_state = REBINDING;
168*0Sstevel@tonic-gate 		ifsp->if_server.s_addr = htonl(INADDR_BROADCAST);
169*0Sstevel@tonic-gate 	}
170*0Sstevel@tonic-gate 
171*0Sstevel@tonic-gate 	/*
172*0Sstevel@tonic-gate 	 * if there isn't an async event pending, then try to rebind.
173*0Sstevel@tonic-gate 	 */
174*0Sstevel@tonic-gate 
175*0Sstevel@tonic-gate 	if (!async_pending(ifsp))
176*0Sstevel@tonic-gate 		if (async_start(ifsp, DHCP_EXTEND, B_FALSE) != 0)
177*0Sstevel@tonic-gate 
178*0Sstevel@tonic-gate 			/*
179*0Sstevel@tonic-gate 			 * try to send extend.  if we don't succeed,
180*0Sstevel@tonic-gate 			 * async_timeout() will clean us up.
181*0Sstevel@tonic-gate 			 */
182*0Sstevel@tonic-gate 
183*0Sstevel@tonic-gate 			(void) dhcp_extending(ifsp);
184*0Sstevel@tonic-gate 
185*0Sstevel@tonic-gate 	/*
186*0Sstevel@tonic-gate 	 * if we're within DHCP_REBIND_MIN seconds of EXPIRE, don't
187*0Sstevel@tonic-gate 	 * reschedule ourselves.
188*0Sstevel@tonic-gate 	 */
189*0Sstevel@tonic-gate 
190*0Sstevel@tonic-gate 	if (next == 0) {
191*0Sstevel@tonic-gate 		dhcpmsg(MSG_WARNING, "dhcp_rebind: lease on %s expires in less "
192*0Sstevel@tonic-gate 		    "than %i seconds!", ifsp->if_name, DHCP_REBIND_MIN);
193*0Sstevel@tonic-gate 		return;
194*0Sstevel@tonic-gate 	}
195*0Sstevel@tonic-gate 
196*0Sstevel@tonic-gate 	if (schedule_ifs_timer(ifsp, DHCP_T2_TIMER, next, dhcp_rebind) == 0)
197*0Sstevel@tonic-gate 
198*0Sstevel@tonic-gate 		/*
199*0Sstevel@tonic-gate 		 * we'll just end up in dhcp_expire(), but it sure sucks.
200*0Sstevel@tonic-gate 		 */
201*0Sstevel@tonic-gate 
202*0Sstevel@tonic-gate 		dhcpmsg(MSG_CRIT, "dhcp_rebind: cannot reschedule another "
203*0Sstevel@tonic-gate 		    "rebind attempt; lease may expire for %s", ifsp->if_name);
204*0Sstevel@tonic-gate }
205*0Sstevel@tonic-gate 
206*0Sstevel@tonic-gate /*
207*0Sstevel@tonic-gate  * dhcp_restart(): callback function to script_start
208*0Sstevel@tonic-gate  *
209*0Sstevel@tonic-gate  *   input: struct ifslist *: the interface to be restarted
210*0Sstevel@tonic-gate  *	    const char *: unused
211*0Sstevel@tonic-gate  *  output: int: always 1
212*0Sstevel@tonic-gate  */
213*0Sstevel@tonic-gate 
214*0Sstevel@tonic-gate /* ARGSUSED */
215*0Sstevel@tonic-gate static int
216*0Sstevel@tonic-gate dhcp_restart(struct ifslist *ifsp, const char *msg)
217*0Sstevel@tonic-gate {
218*0Sstevel@tonic-gate 	dhcpmsg(MSG_INFO, "lease expired on %s -- restarting DHCP",
219*0Sstevel@tonic-gate 	    ifsp->if_name);
220*0Sstevel@tonic-gate 
221*0Sstevel@tonic-gate 	/*
222*0Sstevel@tonic-gate 	 * in the case where the lease is less than DHCP_REBIND_MIN
223*0Sstevel@tonic-gate 	 * seconds, we will never enter dhcp_renew() and thus the packet
224*0Sstevel@tonic-gate 	 * counters will not be reset.  in that case, reset them here.
225*0Sstevel@tonic-gate 	 */
226*0Sstevel@tonic-gate 
227*0Sstevel@tonic-gate 	if (ifsp->if_state == BOUND) {
228*0Sstevel@tonic-gate 		ifsp->if_bad_offers = 0;
229*0Sstevel@tonic-gate 		ifsp->if_sent	    = 0;
230*0Sstevel@tonic-gate 		ifsp->if_received   = 0;
231*0Sstevel@tonic-gate 	}
232*0Sstevel@tonic-gate 
233*0Sstevel@tonic-gate 	(void) canonize_ifs(ifsp);
234*0Sstevel@tonic-gate 
235*0Sstevel@tonic-gate 	/* reset_ifs() in dhcp_selecting() will clean up any leftover state */
236*0Sstevel@tonic-gate 	dhcp_selecting(ifsp);
237*0Sstevel@tonic-gate 	return (1);
238*0Sstevel@tonic-gate }
239*0Sstevel@tonic-gate 
240*0Sstevel@tonic-gate /*
241*0Sstevel@tonic-gate  * dhcp_expire(): expires a lease on a given interface and restarts DHCP
242*0Sstevel@tonic-gate  *
243*0Sstevel@tonic-gate  *   input: iu_tq_t *: unused
244*0Sstevel@tonic-gate  *	    void *: the ifslist to expire the lease on
245*0Sstevel@tonic-gate  *  output: void
246*0Sstevel@tonic-gate  */
247*0Sstevel@tonic-gate 
248*0Sstevel@tonic-gate /* ARGSUSED */
249*0Sstevel@tonic-gate void
250*0Sstevel@tonic-gate dhcp_expire(iu_tq_t *tqp, void *arg)
251*0Sstevel@tonic-gate {
252*0Sstevel@tonic-gate 	struct ifslist	*ifsp = (struct ifslist *)arg;
253*0Sstevel@tonic-gate 
254*0Sstevel@tonic-gate 	ifsp->if_timer[DHCP_LEASE_TIMER] = -1;
255*0Sstevel@tonic-gate 
256*0Sstevel@tonic-gate 	if (check_ifs(ifsp) == 0) {
257*0Sstevel@tonic-gate 		(void) release_ifs(ifsp);
258*0Sstevel@tonic-gate 		return;
259*0Sstevel@tonic-gate 	}
260*0Sstevel@tonic-gate 
261*0Sstevel@tonic-gate 	if (async_pending(ifsp))
262*0Sstevel@tonic-gate 
263*0Sstevel@tonic-gate 		if (async_cancel(ifsp) == 0) {
264*0Sstevel@tonic-gate 
265*0Sstevel@tonic-gate 			dhcpmsg(MSG_WARNING, "dhcp_expire: cannot cancel "
266*0Sstevel@tonic-gate 			    "current asynchronous command against %s",
267*0Sstevel@tonic-gate 			    ifsp->if_name);
268*0Sstevel@tonic-gate 
269*0Sstevel@tonic-gate 			/*
270*0Sstevel@tonic-gate 			 * try to schedule ourselves for callback.
271*0Sstevel@tonic-gate 			 * we're really situation critical here
272*0Sstevel@tonic-gate 			 * there's not much hope for us if this fails.
273*0Sstevel@tonic-gate 			 */
274*0Sstevel@tonic-gate 
275*0Sstevel@tonic-gate 			if (iu_schedule_timer(tq, DHCP_EXPIRE_WAIT, dhcp_expire,
276*0Sstevel@tonic-gate 			    ifsp) != -1) {
277*0Sstevel@tonic-gate 				hold_ifs(ifsp);
278*0Sstevel@tonic-gate 				return;
279*0Sstevel@tonic-gate 			}
280*0Sstevel@tonic-gate 
281*0Sstevel@tonic-gate 			dhcpmsg(MSG_CRIT, "dhcp_expire: cannot reschedule "
282*0Sstevel@tonic-gate 			    "dhcp_expire to get called back, proceeding...");
283*0Sstevel@tonic-gate 		}
284*0Sstevel@tonic-gate 
285*0Sstevel@tonic-gate 	/*
286*0Sstevel@tonic-gate 	 * just march on if this fails; at worst someone will be able
287*0Sstevel@tonic-gate 	 * to async_start() while we're actually busy with our own
288*0Sstevel@tonic-gate 	 * asynchronous transaction.  better than not having a lease.
289*0Sstevel@tonic-gate 	 */
290*0Sstevel@tonic-gate 
291*0Sstevel@tonic-gate 	if (async_start(ifsp, DHCP_START, B_FALSE) == 0)
292*0Sstevel@tonic-gate 		dhcpmsg(MSG_WARNING, "dhcp_expire: cannot start asynchronous "
293*0Sstevel@tonic-gate 		    "transaction on %s, continuing...", ifsp->if_name);
294*0Sstevel@tonic-gate 
295*0Sstevel@tonic-gate 	(void) script_start(ifsp, EVENT_EXPIRE, dhcp_restart, NULL, NULL);
296*0Sstevel@tonic-gate }
297*0Sstevel@tonic-gate 
298*0Sstevel@tonic-gate /*
299*0Sstevel@tonic-gate  * dhcp_extending(): sends a REQUEST to extend a lease on a given interface
300*0Sstevel@tonic-gate  *		     and registers to receive the ACK/NAK server reply
301*0Sstevel@tonic-gate  *
302*0Sstevel@tonic-gate  *   input: struct ifslist *: the interface to send the REQUEST on
303*0Sstevel@tonic-gate  *  output: int: 1 if the extension request was sent, 0 otherwise
304*0Sstevel@tonic-gate  */
305*0Sstevel@tonic-gate 
306*0Sstevel@tonic-gate int
307*0Sstevel@tonic-gate dhcp_extending(struct ifslist *ifsp)
308*0Sstevel@tonic-gate {
309*0Sstevel@tonic-gate 	dhcp_pkt_t		*dpkt;
310*0Sstevel@tonic-gate 
311*0Sstevel@tonic-gate 	if (ifsp->if_state == BOUND) {
312*0Sstevel@tonic-gate 		ifsp->if_neg_monosec	= monosec();
313*0Sstevel@tonic-gate 		ifsp->if_state		= RENEWING;
314*0Sstevel@tonic-gate 		ifsp->if_bad_offers	= 0;
315*0Sstevel@tonic-gate 		ifsp->if_sent		= 0;
316*0Sstevel@tonic-gate 		ifsp->if_received	= 0;
317*0Sstevel@tonic-gate 	}
318*0Sstevel@tonic-gate 
319*0Sstevel@tonic-gate 	dhcpmsg(MSG_DEBUG, "dhcp_extending: registering dhcp_acknak on %s",
320*0Sstevel@tonic-gate 	    ifsp->if_name);
321*0Sstevel@tonic-gate 
322*0Sstevel@tonic-gate 	if (register_acknak(ifsp) == 0) {
323*0Sstevel@tonic-gate 
324*0Sstevel@tonic-gate 		ipc_action_finish(ifsp, DHCP_IPC_E_MEMORY);
325*0Sstevel@tonic-gate 		async_finish(ifsp);
326*0Sstevel@tonic-gate 
327*0Sstevel@tonic-gate 		dhcpmsg(MSG_WARNING, "dhcp_extending: cannot register "
328*0Sstevel@tonic-gate 		    "dhcp_acknak for %s, not sending renew request",
329*0Sstevel@tonic-gate 		    ifsp->if_name);
330*0Sstevel@tonic-gate 
331*0Sstevel@tonic-gate 		return (0);
332*0Sstevel@tonic-gate 	}
333*0Sstevel@tonic-gate 
334*0Sstevel@tonic-gate 	/*
335*0Sstevel@tonic-gate 	 * assemble DHCPREQUEST message.  The max dhcp message size
336*0Sstevel@tonic-gate 	 * option is set to the interface max, minus the size of the udp and
337*0Sstevel@tonic-gate 	 * ip headers.
338*0Sstevel@tonic-gate 	 */
339*0Sstevel@tonic-gate 
340*0Sstevel@tonic-gate 	dpkt = init_pkt(ifsp, REQUEST);
341*0Sstevel@tonic-gate 	dpkt->pkt->ciaddr.s_addr = ifsp->if_addr.s_addr;
342*0Sstevel@tonic-gate 
343*0Sstevel@tonic-gate 	add_pkt_opt16(dpkt, CD_MAX_DHCP_SIZE, htons(ifsp->if_max -
344*0Sstevel@tonic-gate 			sizeof (struct udpiphdr)));
345*0Sstevel@tonic-gate 	add_pkt_opt32(dpkt, CD_LEASE_TIME, htonl(DHCP_PERM));
346*0Sstevel@tonic-gate 
347*0Sstevel@tonic-gate 	add_pkt_opt(dpkt, CD_CLASS_ID, class_id, class_id_len);
348*0Sstevel@tonic-gate 	add_pkt_opt(dpkt, CD_REQUEST_LIST, ifsp->if_prl, ifsp->if_prllen);
349*0Sstevel@tonic-gate 	/*
350*0Sstevel@tonic-gate 	 * if_reqhost was set for this interface in dhcp_selecting()
351*0Sstevel@tonic-gate 	 * if the REQUEST_HOSTNAME option was set and a host name was
352*0Sstevel@tonic-gate 	 * found.
353*0Sstevel@tonic-gate 	 */
354*0Sstevel@tonic-gate 	if (ifsp->if_reqhost != NULL) {
355*0Sstevel@tonic-gate 		add_pkt_opt(dpkt, CD_HOSTNAME, ifsp->if_reqhost,
356*0Sstevel@tonic-gate 		    strlen(ifsp->if_reqhost));
357*0Sstevel@tonic-gate 	}
358*0Sstevel@tonic-gate 	add_pkt_opt(dpkt, CD_END, NULL, 0);
359*0Sstevel@tonic-gate 
360*0Sstevel@tonic-gate 	/*
361*0Sstevel@tonic-gate 	 * if we can't send the packet, leave the event handler registered
362*0Sstevel@tonic-gate 	 * anyway, since we're not expecting to get any other types of
363*0Sstevel@tonic-gate 	 * packets in other than ACKs/NAKs anyway.
364*0Sstevel@tonic-gate 	 */
365*0Sstevel@tonic-gate 
366*0Sstevel@tonic-gate 	return (send_pkt(ifsp, dpkt, ifsp->if_server.s_addr, NULL));
367*0Sstevel@tonic-gate }
368