xref: /dflybsd-src/stand/lib/bootp.c (revision 479ab7f0492f2a51b48e8537e4f1dc686fc6014b)
1*479ab7f0SSascha Wildner /*	$NetBSD: bootp.c,v 1.14 1998/02/16 11:10:54 drochner Exp $	*/
2*479ab7f0SSascha Wildner 
3*479ab7f0SSascha Wildner /*
4*479ab7f0SSascha Wildner  * Copyright (c) 1992 Regents of the University of California.
5*479ab7f0SSascha Wildner  * All rights reserved.
6*479ab7f0SSascha Wildner  *
7*479ab7f0SSascha Wildner  * This software was developed by the Computer Systems Engineering group
8*479ab7f0SSascha Wildner  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9*479ab7f0SSascha Wildner  * contributed to Berkeley.
10*479ab7f0SSascha Wildner  *
11*479ab7f0SSascha Wildner  * Redistribution and use in source and binary forms, with or without
12*479ab7f0SSascha Wildner  * modification, are permitted provided that the following conditions
13*479ab7f0SSascha Wildner  * are met:
14*479ab7f0SSascha Wildner  * 1. Redistributions of source code must retain the above copyright
15*479ab7f0SSascha Wildner  *    notice, this list of conditions and the following disclaimer.
16*479ab7f0SSascha Wildner  * 2. Redistributions in binary form must reproduce the above copyright
17*479ab7f0SSascha Wildner  *    notice, this list of conditions and the following disclaimer in the
18*479ab7f0SSascha Wildner  *    documentation and/or other materials provided with the distribution.
19*479ab7f0SSascha Wildner  * 3. Neither the name of the University nor the names of its contributors
20*479ab7f0SSascha Wildner  *    may be used to endorse or promote products derived from this software
21*479ab7f0SSascha Wildner  *    without specific prior written permission.
22*479ab7f0SSascha Wildner  *
23*479ab7f0SSascha Wildner  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24*479ab7f0SSascha Wildner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25*479ab7f0SSascha Wildner  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26*479ab7f0SSascha Wildner  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27*479ab7f0SSascha Wildner  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28*479ab7f0SSascha Wildner  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29*479ab7f0SSascha Wildner  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30*479ab7f0SSascha Wildner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31*479ab7f0SSascha Wildner  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32*479ab7f0SSascha Wildner  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33*479ab7f0SSascha Wildner  * SUCH DAMAGE.
34*479ab7f0SSascha Wildner  *
35*479ab7f0SSascha Wildner  * @(#) Header: bootp.c,v 1.4 93/09/11 03:13:51 leres Exp  (LBL)
36*479ab7f0SSascha Wildner  * $FreeBSD: src/lib/libstand/bootp.c,v 1.1.1.1.6.2 2000/09/20 18:37:25 ps Exp $
37*479ab7f0SSascha Wildner  * $DragonFly: src/lib/libstand/bootp.c,v 1.5 2005/12/11 02:27:26 swildner Exp $
38*479ab7f0SSascha Wildner  */
39*479ab7f0SSascha Wildner 
40*479ab7f0SSascha Wildner #include <sys/param.h>
41*479ab7f0SSascha Wildner #include <netinet/in.h>
42*479ab7f0SSascha Wildner #include <netinet/in_systm.h>
43*479ab7f0SSascha Wildner 
44*479ab7f0SSascha Wildner #include <string.h>
45*479ab7f0SSascha Wildner 
46*479ab7f0SSascha Wildner #define BOOTP_DEBUGxx
47*479ab7f0SSascha Wildner #define SUPPORT_DHCP
48*479ab7f0SSascha Wildner 
49*479ab7f0SSascha Wildner #include "stand.h"
50*479ab7f0SSascha Wildner #include "net.h"
51*479ab7f0SSascha Wildner #include "netif.h"
52*479ab7f0SSascha Wildner #include "bootp.h"
53*479ab7f0SSascha Wildner 
54*479ab7f0SSascha Wildner 
55*479ab7f0SSascha Wildner struct in_addr servip;
56*479ab7f0SSascha Wildner 
57*479ab7f0SSascha Wildner static n_long	nmask, smask;
58*479ab7f0SSascha Wildner 
59*479ab7f0SSascha Wildner static time_t	bot;
60*479ab7f0SSascha Wildner 
61*479ab7f0SSascha Wildner static	char vm_rfc1048[4] = VM_RFC1048;
62*479ab7f0SSascha Wildner #ifdef BOOTP_VEND_CMU
63*479ab7f0SSascha Wildner static	char vm_cmu[4] = VM_CMU;
64*479ab7f0SSascha Wildner #endif
65*479ab7f0SSascha Wildner 
66*479ab7f0SSascha Wildner /* Local forwards */
67*479ab7f0SSascha Wildner static	ssize_t bootpsend(struct iodesc *, void *, size_t);
68*479ab7f0SSascha Wildner static	ssize_t bootprecv(struct iodesc *, void *, size_t, time_t);
69*479ab7f0SSascha Wildner static	int vend_rfc1048(u_char *, u_int);
70*479ab7f0SSascha Wildner #ifdef BOOTP_VEND_CMU
71*479ab7f0SSascha Wildner static	void vend_cmu(u_char *);
72*479ab7f0SSascha Wildner #endif
73*479ab7f0SSascha Wildner 
74*479ab7f0SSascha Wildner #ifdef SUPPORT_DHCP
75*479ab7f0SSascha Wildner static char expected_dhcpmsgtype = -1, dhcp_ok;
76*479ab7f0SSascha Wildner struct in_addr dhcp_serverip;
77*479ab7f0SSascha Wildner #endif
78*479ab7f0SSascha Wildner 
79*479ab7f0SSascha Wildner /* Fetch required bootp infomation */
80*479ab7f0SSascha Wildner void
bootp(int sock,int flag)81*479ab7f0SSascha Wildner bootp(int sock, int flag)
82*479ab7f0SSascha Wildner {
83*479ab7f0SSascha Wildner 	struct iodesc *d;
84*479ab7f0SSascha Wildner 	struct bootp *bp;
85*479ab7f0SSascha Wildner 	struct {
86*479ab7f0SSascha Wildner 		u_char header[HEADER_SIZE];
87*479ab7f0SSascha Wildner 		struct bootp wbootp;
88*479ab7f0SSascha Wildner 	} wbuf;
89*479ab7f0SSascha Wildner 	struct {
90*479ab7f0SSascha Wildner 		u_char header[HEADER_SIZE];
91*479ab7f0SSascha Wildner 		struct bootp rbootp;
92*479ab7f0SSascha Wildner 	} rbuf;
93*479ab7f0SSascha Wildner 
94*479ab7f0SSascha Wildner #ifdef BOOTP_DEBUG
95*479ab7f0SSascha Wildner  	if (debug)
96*479ab7f0SSascha Wildner 		printf("bootp: socket=%d\n", sock);
97*479ab7f0SSascha Wildner #endif
98*479ab7f0SSascha Wildner 	if (!bot)
99*479ab7f0SSascha Wildner 		bot = getsecs();
100*479ab7f0SSascha Wildner 
101*479ab7f0SSascha Wildner 	if (!(d = socktodesc(sock))) {
102*479ab7f0SSascha Wildner 		printf("bootp: bad socket. %d\n", sock);
103*479ab7f0SSascha Wildner 		return;
104*479ab7f0SSascha Wildner 	}
105*479ab7f0SSascha Wildner #ifdef BOOTP_DEBUG
106*479ab7f0SSascha Wildner  	if (debug)
107*479ab7f0SSascha Wildner 		printf("bootp: d=%lx\n", (long)d);
108*479ab7f0SSascha Wildner #endif
109*479ab7f0SSascha Wildner 
110*479ab7f0SSascha Wildner 	bp = &wbuf.wbootp;
111*479ab7f0SSascha Wildner 	bzero(bp, sizeof(*bp));
112*479ab7f0SSascha Wildner 
113*479ab7f0SSascha Wildner 	bp->bp_op = BOOTREQUEST;
114*479ab7f0SSascha Wildner 	bp->bp_htype = 1;		/* 10Mb Ethernet (48 bits) */
115*479ab7f0SSascha Wildner 	bp->bp_hlen = 6;
116*479ab7f0SSascha Wildner 	bp->bp_xid = htonl(d->xid);
117*479ab7f0SSascha Wildner 	MACPY(d->myea, bp->bp_chaddr);
118*479ab7f0SSascha Wildner 	strncpy(bp->bp_file, bootfile, sizeof(bp->bp_file));
119*479ab7f0SSascha Wildner 	bcopy(vm_rfc1048, bp->bp_vend, sizeof(vm_rfc1048));
120*479ab7f0SSascha Wildner #ifdef SUPPORT_DHCP
121*479ab7f0SSascha Wildner 	bp->bp_vend[4] = TAG_DHCP_MSGTYPE;
122*479ab7f0SSascha Wildner 	bp->bp_vend[5] = 1;
123*479ab7f0SSascha Wildner 	bp->bp_vend[6] = DHCPDISCOVER;
124*479ab7f0SSascha Wildner 
125*479ab7f0SSascha Wildner 	/*
126*479ab7f0SSascha Wildner 	 * If we are booting from PXE, we want to send the string
127*479ab7f0SSascha Wildner 	 * 'PXEClient' to the DHCP server so you have the option of
128*479ab7f0SSascha Wildner 	 * only responding to PXE aware dhcp requests.
129*479ab7f0SSascha Wildner 	 */
130*479ab7f0SSascha Wildner 	if (flag & BOOTP_PXE) {
131*479ab7f0SSascha Wildner 		bp->bp_vend[7] = TAG_CLASSID;
132*479ab7f0SSascha Wildner 		bp->bp_vend[8] = 9;
133*479ab7f0SSascha Wildner 		bcopy("PXEClient", &bp->bp_vend[9], 9);
134*479ab7f0SSascha Wildner 		bp->bp_vend[18] = TAG_END;
135*479ab7f0SSascha Wildner 	} else
136*479ab7f0SSascha Wildner 		bp->bp_vend[7] = TAG_END;
137*479ab7f0SSascha Wildner #else
138*479ab7f0SSascha Wildner 	bp->bp_vend[4] = TAG_END;
139*479ab7f0SSascha Wildner #endif
140*479ab7f0SSascha Wildner 
141*479ab7f0SSascha Wildner 	d->myip.s_addr = INADDR_ANY;
142*479ab7f0SSascha Wildner 	d->myport = htons(IPPORT_BOOTPC);
143*479ab7f0SSascha Wildner 	d->destip.s_addr = INADDR_BROADCAST;
144*479ab7f0SSascha Wildner 	d->destport = htons(IPPORT_BOOTPS);
145*479ab7f0SSascha Wildner 
146*479ab7f0SSascha Wildner #ifdef SUPPORT_DHCP
147*479ab7f0SSascha Wildner 	expected_dhcpmsgtype = DHCPOFFER;
148*479ab7f0SSascha Wildner 	dhcp_ok = 0;
149*479ab7f0SSascha Wildner #endif
150*479ab7f0SSascha Wildner 
151*479ab7f0SSascha Wildner 	if(sendrecv(d,
152*479ab7f0SSascha Wildner 		    bootpsend, bp, sizeof(*bp),
153*479ab7f0SSascha Wildner 		    bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp))
154*479ab7f0SSascha Wildner 	   == -1) {
155*479ab7f0SSascha Wildner 	    printf("bootp: no reply\n");
156*479ab7f0SSascha Wildner 	    return;
157*479ab7f0SSascha Wildner 	}
158*479ab7f0SSascha Wildner 
159*479ab7f0SSascha Wildner #ifdef SUPPORT_DHCP
160*479ab7f0SSascha Wildner 	if(dhcp_ok) {
161*479ab7f0SSascha Wildner 		u_int32_t leasetime;
162*479ab7f0SSascha Wildner 		bp->bp_vend[6] = DHCPREQUEST;
163*479ab7f0SSascha Wildner 		bp->bp_vend[7] = TAG_REQ_ADDR;
164*479ab7f0SSascha Wildner 		bp->bp_vend[8] = 4;
165*479ab7f0SSascha Wildner 		bcopy(&rbuf.rbootp.bp_yiaddr, &bp->bp_vend[9], 4);
166*479ab7f0SSascha Wildner 		bp->bp_vend[13] = TAG_SERVERID;
167*479ab7f0SSascha Wildner 		bp->bp_vend[14] = 4;
168*479ab7f0SSascha Wildner 		bcopy(&dhcp_serverip.s_addr, &bp->bp_vend[15], 4);
169*479ab7f0SSascha Wildner 		bp->bp_vend[19] = TAG_LEASETIME;
170*479ab7f0SSascha Wildner 		bp->bp_vend[20] = 4;
171*479ab7f0SSascha Wildner 		leasetime = htonl(300);
172*479ab7f0SSascha Wildner 		bcopy(&leasetime, &bp->bp_vend[21], 4);
173*479ab7f0SSascha Wildner 		if (flag & BOOTP_PXE) {
174*479ab7f0SSascha Wildner 			bp->bp_vend[25] = TAG_CLASSID;
175*479ab7f0SSascha Wildner 			bp->bp_vend[26] = 9;
176*479ab7f0SSascha Wildner 			bcopy("PXEClient", &bp->bp_vend[27], 9);
177*479ab7f0SSascha Wildner 			bp->bp_vend[36] = TAG_END;
178*479ab7f0SSascha Wildner 		} else
179*479ab7f0SSascha Wildner 			bp->bp_vend[25] = TAG_END;
180*479ab7f0SSascha Wildner 
181*479ab7f0SSascha Wildner 		expected_dhcpmsgtype = DHCPACK;
182*479ab7f0SSascha Wildner 
183*479ab7f0SSascha Wildner 		if(sendrecv(d,
184*479ab7f0SSascha Wildner 			    bootpsend, bp, sizeof(*bp),
185*479ab7f0SSascha Wildner 			    bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp))
186*479ab7f0SSascha Wildner 		   == -1) {
187*479ab7f0SSascha Wildner 			printf("DHCPREQUEST failed\n");
188*479ab7f0SSascha Wildner 			return;
189*479ab7f0SSascha Wildner 		}
190*479ab7f0SSascha Wildner 	}
191*479ab7f0SSascha Wildner #endif
192*479ab7f0SSascha Wildner 
193*479ab7f0SSascha Wildner 	myip = d->myip = rbuf.rbootp.bp_yiaddr;
194*479ab7f0SSascha Wildner 	servip = rbuf.rbootp.bp_siaddr;
195*479ab7f0SSascha Wildner 	if(rootip.s_addr == INADDR_ANY) rootip = servip;
196*479ab7f0SSascha Wildner 	bcopy(rbuf.rbootp.bp_file, bootfile, sizeof(bootfile));
197*479ab7f0SSascha Wildner 	bootfile[sizeof(bootfile) - 1] = '\0';
198*479ab7f0SSascha Wildner 
199*479ab7f0SSascha Wildner 	if (IN_CLASSA(ntohl(myip.s_addr)))
200*479ab7f0SSascha Wildner 		nmask = htonl(IN_CLASSA_NET);
201*479ab7f0SSascha Wildner 	else if (IN_CLASSB(ntohl(myip.s_addr)))
202*479ab7f0SSascha Wildner 		nmask = htonl(IN_CLASSB_NET);
203*479ab7f0SSascha Wildner 	else
204*479ab7f0SSascha Wildner 		nmask = htonl(IN_CLASSC_NET);
205*479ab7f0SSascha Wildner #ifdef BOOTP_DEBUG
206*479ab7f0SSascha Wildner 	if (debug)
207*479ab7f0SSascha Wildner 		printf("'native netmask' is %s\n", intoa(nmask));
208*479ab7f0SSascha Wildner #endif
209*479ab7f0SSascha Wildner 
210*479ab7f0SSascha Wildner 	/* Check subnet mask against net mask; toss if bogus */
211*479ab7f0SSascha Wildner 	if ((nmask & smask) != nmask) {
212*479ab7f0SSascha Wildner #ifdef BOOTP_DEBUG
213*479ab7f0SSascha Wildner 		if (debug)
214*479ab7f0SSascha Wildner 			printf("subnet mask (%s) bad\n", intoa(smask));
215*479ab7f0SSascha Wildner #endif
216*479ab7f0SSascha Wildner 		smask = 0;
217*479ab7f0SSascha Wildner 	}
218*479ab7f0SSascha Wildner 
219*479ab7f0SSascha Wildner 	/* Get subnet (or natural net) mask */
220*479ab7f0SSascha Wildner 	netmask = nmask;
221*479ab7f0SSascha Wildner 	if (smask)
222*479ab7f0SSascha Wildner 		netmask = smask;
223*479ab7f0SSascha Wildner #ifdef BOOTP_DEBUG
224*479ab7f0SSascha Wildner 	if (debug)
225*479ab7f0SSascha Wildner 		printf("mask: %s\n", intoa(netmask));
226*479ab7f0SSascha Wildner #endif
227*479ab7f0SSascha Wildner 
228*479ab7f0SSascha Wildner 	/* We need a gateway if root is on a different net */
229*479ab7f0SSascha Wildner 	if (!SAMENET(myip, rootip, netmask)) {
230*479ab7f0SSascha Wildner #ifdef BOOTP_DEBUG
231*479ab7f0SSascha Wildner 		if (debug)
232*479ab7f0SSascha Wildner 			printf("need gateway for root ip\n");
233*479ab7f0SSascha Wildner #endif
234*479ab7f0SSascha Wildner 	}
235*479ab7f0SSascha Wildner 
236*479ab7f0SSascha Wildner 	/* Toss gateway if on a different net */
237*479ab7f0SSascha Wildner 	if (!SAMENET(myip, gateip, netmask)) {
238*479ab7f0SSascha Wildner #ifdef BOOTP_DEBUG
239*479ab7f0SSascha Wildner 		if (debug)
240*479ab7f0SSascha Wildner 			printf("gateway ip (%s) bad\n", inet_ntoa(gateip));
241*479ab7f0SSascha Wildner #endif
242*479ab7f0SSascha Wildner 		gateip.s_addr = 0;
243*479ab7f0SSascha Wildner 	}
244*479ab7f0SSascha Wildner 
245*479ab7f0SSascha Wildner 	/* Bump xid so next request will be unique. */
246*479ab7f0SSascha Wildner 	++d->xid;
247*479ab7f0SSascha Wildner }
248*479ab7f0SSascha Wildner 
249*479ab7f0SSascha Wildner /* Transmit a bootp request */
250*479ab7f0SSascha Wildner static ssize_t
bootpsend(struct iodesc * d,void * pkt,size_t len)251*479ab7f0SSascha Wildner bootpsend(struct iodesc *d, void *pkt, size_t len)
252*479ab7f0SSascha Wildner {
253*479ab7f0SSascha Wildner 	struct bootp *bp;
254*479ab7f0SSascha Wildner 
255*479ab7f0SSascha Wildner #ifdef BOOTP_DEBUG
256*479ab7f0SSascha Wildner 	if (debug)
257*479ab7f0SSascha Wildner 		printf("bootpsend: d=%lx called.\n", (long)d);
258*479ab7f0SSascha Wildner #endif
259*479ab7f0SSascha Wildner 
260*479ab7f0SSascha Wildner 	bp = pkt;
261*479ab7f0SSascha Wildner 	bp->bp_secs = htons((u_short)(getsecs() - bot));
262*479ab7f0SSascha Wildner 
263*479ab7f0SSascha Wildner #ifdef BOOTP_DEBUG
264*479ab7f0SSascha Wildner 	if (debug)
265*479ab7f0SSascha Wildner 		printf("bootpsend: calling sendudp\n");
266*479ab7f0SSascha Wildner #endif
267*479ab7f0SSascha Wildner 
268*479ab7f0SSascha Wildner 	return (sendudp(d, pkt, len));
269*479ab7f0SSascha Wildner }
270*479ab7f0SSascha Wildner 
271*479ab7f0SSascha Wildner static ssize_t
bootprecv(struct iodesc * d,void * pkt,size_t len,time_t tleft)272*479ab7f0SSascha Wildner bootprecv(struct iodesc *d, void *pkt, size_t len, time_t tleft)
273*479ab7f0SSascha Wildner {
274*479ab7f0SSascha Wildner 	ssize_t n;
275*479ab7f0SSascha Wildner 	struct bootp *bp;
276*479ab7f0SSascha Wildner 
277*479ab7f0SSascha Wildner #ifdef BOOTP_DEBUGx
278*479ab7f0SSascha Wildner 	if (debug)
279*479ab7f0SSascha Wildner 		printf("bootp_recvoffer: called\n");
280*479ab7f0SSascha Wildner #endif
281*479ab7f0SSascha Wildner 
282*479ab7f0SSascha Wildner 	n = readudp(d, pkt, len, tleft);
283*479ab7f0SSascha Wildner 	if (n == -1 || n < sizeof(struct bootp) - BOOTP_VENDSIZE)
284*479ab7f0SSascha Wildner 		goto bad;
285*479ab7f0SSascha Wildner 
286*479ab7f0SSascha Wildner 	bp = (struct bootp *)pkt;
287*479ab7f0SSascha Wildner 
288*479ab7f0SSascha Wildner #ifdef BOOTP_DEBUG
289*479ab7f0SSascha Wildner 	if (debug)
290*479ab7f0SSascha Wildner 		printf("bootprecv: checked.  bp = 0x%lx, n = %d\n",
291*479ab7f0SSascha Wildner 		    (long)bp, (int)n);
292*479ab7f0SSascha Wildner #endif
293*479ab7f0SSascha Wildner 	if (bp->bp_xid != htonl(d->xid)) {
294*479ab7f0SSascha Wildner #ifdef BOOTP_DEBUG
295*479ab7f0SSascha Wildner 		if (debug) {
296*479ab7f0SSascha Wildner 			printf("bootprecv: expected xid 0x%lx, got 0x%x\n",
297*479ab7f0SSascha Wildner 			    d->xid, ntohl(bp->bp_xid));
298*479ab7f0SSascha Wildner 		}
299*479ab7f0SSascha Wildner #endif
300*479ab7f0SSascha Wildner 		goto bad;
301*479ab7f0SSascha Wildner 	}
302*479ab7f0SSascha Wildner 
303*479ab7f0SSascha Wildner #ifdef BOOTP_DEBUG
304*479ab7f0SSascha Wildner 	if (debug)
305*479ab7f0SSascha Wildner 		printf("bootprecv: got one!\n");
306*479ab7f0SSascha Wildner #endif
307*479ab7f0SSascha Wildner 
308*479ab7f0SSascha Wildner 	/* Suck out vendor info */
309*479ab7f0SSascha Wildner 	if (bcmp(vm_rfc1048, bp->bp_vend, sizeof(vm_rfc1048)) == 0) {
310*479ab7f0SSascha Wildner 		if(vend_rfc1048(bp->bp_vend, sizeof(bp->bp_vend)) != 0)
311*479ab7f0SSascha Wildner 		    goto bad;
312*479ab7f0SSascha Wildner 	}
313*479ab7f0SSascha Wildner #ifdef BOOTP_VEND_CMU
314*479ab7f0SSascha Wildner 	else if (bcmp(vm_cmu, bp->bp_vend, sizeof(vm_cmu)) == 0)
315*479ab7f0SSascha Wildner 		vend_cmu(bp->bp_vend);
316*479ab7f0SSascha Wildner #endif
317*479ab7f0SSascha Wildner 	else
318*479ab7f0SSascha Wildner 		printf("bootprecv: unknown vendor 0x%lx\n", (long)bp->bp_vend);
319*479ab7f0SSascha Wildner 
320*479ab7f0SSascha Wildner 	return(n);
321*479ab7f0SSascha Wildner bad:
322*479ab7f0SSascha Wildner 	errno = 0;
323*479ab7f0SSascha Wildner 	return (-1);
324*479ab7f0SSascha Wildner }
325*479ab7f0SSascha Wildner 
326*479ab7f0SSascha Wildner static int
vend_rfc1048(u_char * cp,u_int len)327*479ab7f0SSascha Wildner vend_rfc1048(u_char *cp, u_int len)
328*479ab7f0SSascha Wildner {
329*479ab7f0SSascha Wildner 	u_char *ep;
330*479ab7f0SSascha Wildner 	int size;
331*479ab7f0SSascha Wildner 	u_char tag;
332*479ab7f0SSascha Wildner 
333*479ab7f0SSascha Wildner #ifdef BOOTP_DEBUG
334*479ab7f0SSascha Wildner 	if (debug)
335*479ab7f0SSascha Wildner 		printf("vend_rfc1048 bootp info. len=%d\n", len);
336*479ab7f0SSascha Wildner #endif
337*479ab7f0SSascha Wildner 	ep = cp + len;
338*479ab7f0SSascha Wildner 
339*479ab7f0SSascha Wildner 	/* Step over magic cookie */
340*479ab7f0SSascha Wildner 	cp += sizeof(int);
341*479ab7f0SSascha Wildner 
342*479ab7f0SSascha Wildner 	while (cp < ep) {
343*479ab7f0SSascha Wildner 		tag = *cp++;
344*479ab7f0SSascha Wildner 		size = *cp++;
345*479ab7f0SSascha Wildner 		if (tag == TAG_END)
346*479ab7f0SSascha Wildner 			break;
347*479ab7f0SSascha Wildner 
348*479ab7f0SSascha Wildner 		if (tag == TAG_SUBNET_MASK) {
349*479ab7f0SSascha Wildner 			bcopy(cp, &smask, sizeof(smask));
350*479ab7f0SSascha Wildner 		}
351*479ab7f0SSascha Wildner 		if (tag == TAG_GATEWAY) {
352*479ab7f0SSascha Wildner 			bcopy(cp, &gateip.s_addr, sizeof(gateip.s_addr));
353*479ab7f0SSascha Wildner 		}
354*479ab7f0SSascha Wildner 		if (tag == TAG_SWAPSERVER) {
355*479ab7f0SSascha Wildner 			/* let it override bp_siaddr */
356*479ab7f0SSascha Wildner 			bcopy(cp, &rootip.s_addr, sizeof(swapip.s_addr));
357*479ab7f0SSascha Wildner 		}
358*479ab7f0SSascha Wildner 		if (tag == TAG_ROOTPATH) {
359*479ab7f0SSascha Wildner 			strncpy(rootpath, (char *)cp, sizeof(rootpath));
360*479ab7f0SSascha Wildner 			rootpath[size] = '\0';
361*479ab7f0SSascha Wildner 		}
362*479ab7f0SSascha Wildner 		if (tag == TAG_HOSTNAME) {
363*479ab7f0SSascha Wildner 			strncpy(hostname, (char *)cp, sizeof(hostname));
364*479ab7f0SSascha Wildner 			hostname[size] = '\0';
365*479ab7f0SSascha Wildner 		}
366*479ab7f0SSascha Wildner #ifdef SUPPORT_DHCP
367*479ab7f0SSascha Wildner 		if (tag == TAG_DHCP_MSGTYPE) {
368*479ab7f0SSascha Wildner 			if(*cp != expected_dhcpmsgtype)
369*479ab7f0SSascha Wildner 			    return(-1);
370*479ab7f0SSascha Wildner 			dhcp_ok = 1;
371*479ab7f0SSascha Wildner 		}
372*479ab7f0SSascha Wildner 		if (tag == TAG_SERVERID) {
373*479ab7f0SSascha Wildner 			bcopy(cp, &dhcp_serverip.s_addr,
374*479ab7f0SSascha Wildner 			      sizeof(dhcp_serverip.s_addr));
375*479ab7f0SSascha Wildner 		}
376*479ab7f0SSascha Wildner #endif
377*479ab7f0SSascha Wildner 		cp += size;
378*479ab7f0SSascha Wildner 	}
379*479ab7f0SSascha Wildner 	return(0);
380*479ab7f0SSascha Wildner }
381*479ab7f0SSascha Wildner 
382*479ab7f0SSascha Wildner #ifdef BOOTP_VEND_CMU
383*479ab7f0SSascha Wildner static void
vend_cmu(u_char * cp)384*479ab7f0SSascha Wildner vend_cmu(u_char *cp)
385*479ab7f0SSascha Wildner {
386*479ab7f0SSascha Wildner 	struct cmu_vend *vp;
387*479ab7f0SSascha Wildner 
388*479ab7f0SSascha Wildner #ifdef BOOTP_DEBUG
389*479ab7f0SSascha Wildner 	if (debug)
390*479ab7f0SSascha Wildner 		printf("vend_cmu bootp info.\n");
391*479ab7f0SSascha Wildner #endif
392*479ab7f0SSascha Wildner 	vp = (struct cmu_vend *)cp;
393*479ab7f0SSascha Wildner 
394*479ab7f0SSascha Wildner 	if (vp->v_smask.s_addr != 0) {
395*479ab7f0SSascha Wildner 		smask = vp->v_smask.s_addr;
396*479ab7f0SSascha Wildner 	}
397*479ab7f0SSascha Wildner 	if (vp->v_dgate.s_addr != 0) {
398*479ab7f0SSascha Wildner 		gateip = vp->v_dgate;
399*479ab7f0SSascha Wildner 	}
400*479ab7f0SSascha Wildner }
401*479ab7f0SSascha Wildner #endif
402