This source file includes following definitions.
- bootp
- bootpsend
- bootprecv
- vend_cmu
- vend_rfc1048
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 #include <sys/types.h>
44 #include <sys/socket.h>
45 #include <netinet/in.h>
46 #include <netinet/in_systm.h>
47
48 #include "stand.h"
49 #include "net.h"
50 #include "netif.h"
51 #include "bootp.h"
52
53 static n_long nmask, smask;
54
55 static time_t bot;
56
57 static char vm_rfc1048[4] = VM_RFC1048;
58 static char vm_cmu[4] = VM_CMU;
59
60
61 static ssize_t bootpsend(struct iodesc *, void *, size_t);
62 static ssize_t bootprecv(struct iodesc *, void *, size_t, time_t);
63 static void vend_cmu(u_char *);
64 static void vend_rfc1048(u_char *, u_int);
65
66
67 void
68 bootp(int sock)
69 {
70 struct iodesc *d;
71 struct bootp *bp;
72 struct {
73 u_char header[HEADER_SIZE];
74 struct bootp wbootp;
75 } wbuf;
76 struct {
77 u_char header[HEADER_SIZE];
78 struct bootp rbootp;
79 } rbuf;
80
81 #ifdef BOOTP_DEBUG
82 if (debug)
83 printf("bootp: socket=%d\n", sock);
84 #endif
85 if (!bot)
86 bot = getsecs();
87
88 if (!(d = socktodesc(sock))) {
89 printf("bootp: bad socket. %d\n", sock);
90 return;
91 }
92 #ifdef BOOTP_DEBUG
93 if (debug)
94 printf("bootp: d=%x\n", (u_int)d);
95 #endif
96
97 bp = &wbuf.wbootp;
98 bzero(bp, sizeof(*bp));
99
100 bp->bp_op = BOOTREQUEST;
101 bp->bp_htype = HTYPE_ETHERNET;
102 bp->bp_hlen = 6;
103 bp->bp_xid = htonl(d->xid);
104 MACPY(d->myea, bp->bp_chaddr);
105 bzero(bp->bp_file, sizeof(bp->bp_file));
106 bcopy(vm_rfc1048, bp->bp_vend, sizeof(vm_rfc1048));
107
108 d->myip = myip;
109 d->myport = htons(IPPORT_BOOTPC);
110 d->destip.s_addr = INADDR_BROADCAST;
111 d->destport = htons(IPPORT_BOOTPS);
112
113 (void)sendrecv(d,
114 bootpsend, bp, sizeof(*bp),
115 bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp));
116
117
118 ++d->xid;
119 }
120
121
122 static ssize_t
123 bootpsend(struct iodesc *d, void *pkt, size_t len)
124 {
125 struct bootp *bp;
126
127 #ifdef BOOTP_DEBUG
128 if (debug)
129 printf("bootpsend: d=%x called.\n", (u_int)d);
130 #endif
131
132 bp = pkt;
133 bp->bp_secs = htons((u_short)(getsecs() - bot));
134
135 #ifdef BOOTP_DEBUG
136 if (debug)
137 printf("bootpsend: calling sendudp\n");
138 #endif
139
140 return (sendudp(d, pkt, len));
141 }
142
143
144 static ssize_t
145 bootprecv(struct iodesc *d, void *pkt, size_t len, time_t tleft)
146 {
147 ssize_t n;
148 struct bootp *bp;
149
150 #ifdef BOOTP_DEBUG
151 if (debug)
152 printf("bootprecv: called\n");
153 #endif
154
155 n = readudp(d, pkt, len, tleft);
156 if (n < 0 || (size_t)n < sizeof(struct bootp))
157 goto bad;
158
159 bp = (struct bootp *)pkt;
160
161 #ifdef BOOTP_DEBUG
162 if (debug)
163 printf("bootprecv: checked. bp = 0x%x, n = %d\n",
164 (unsigned)bp, n);
165 #endif
166 if (bp->bp_xid != htonl(d->xid)) {
167 #ifdef BOOTP_DEBUG
168 if (debug) {
169 printf("bootprecv: expected xid 0x%lx, got 0x%lx\n",
170 d->xid, ntohl(bp->bp_xid));
171 }
172 #endif
173 goto bad;
174 }
175
176 #ifdef BOOTP_DEBUG
177 if (debug)
178 printf("bootprecv: got one!\n");
179 #endif
180
181
182 myip = d->myip = bp->bp_yiaddr;
183 #ifdef BOOTP_DEBUG
184 if (debug)
185 printf("our ip address is %s\n", inet_ntoa(d->myip));
186 #endif
187 if (IN_CLASSA(d->myip.s_addr))
188 nmask = IN_CLASSA_NET;
189 else if (IN_CLASSB(d->myip.s_addr))
190 nmask = IN_CLASSB_NET;
191 else
192 nmask = IN_CLASSC_NET;
193 #ifdef BOOTP_DEBUG
194 if (debug)
195 printf("'native netmask' is %s\n", intoa(nmask));
196 #endif
197
198
199 if (bp->bp_siaddr.s_addr != 0)
200 rootip = bp->bp_siaddr;
201 if (bp->bp_file[0] != '\0') {
202 strncpy(bootfile, (char *)bp->bp_file, sizeof(bootfile));
203 bootfile[sizeof(bootfile) - 1] = '\0';
204 }
205
206
207 if (bcmp(vm_cmu, bp->bp_vend, sizeof(vm_cmu)) == 0)
208 vend_cmu(bp->bp_vend);
209 else if (bcmp(vm_rfc1048, bp->bp_vend, sizeof(vm_rfc1048)) == 0)
210 vend_rfc1048(bp->bp_vend, sizeof(bp->bp_vend));
211 else
212 printf("bootprecv: unknown vendor 0x%lx\n", (long)bp->bp_vend);
213
214
215 if ((nmask & smask) != nmask) {
216 #ifdef BOOTP_DEBUG
217 if (debug)
218 printf("subnet mask (%s) bad\n", intoa(smask));
219 #endif
220 smask = 0;
221 }
222
223
224 netmask = nmask;
225 if (smask)
226 netmask = smask;
227 #ifdef BOOTP_DEBUG
228 if (debug)
229 printf("mask: %s\n", intoa(netmask));
230 #endif
231
232
233 if (!SAMENET(d->myip, rootip, netmask)) {
234 #ifdef BOOTP_DEBUG
235 if (debug)
236 printf("need gateway for root ip\n");
237 #endif
238 }
239
240 if (!SAMENET(d->myip, swapip, netmask)) {
241 #ifdef BOOTP_DEBUG
242 if (debug)
243 printf("need gateway for swap ip\n");
244 #endif
245 }
246
247
248 if (!SAMENET(d->myip, gateip, netmask)) {
249 #ifdef BOOTP_DEBUG
250 if (debug)
251 printf("gateway ip (%s) bad\n", inet_ntoa(gateip));
252 #endif
253 gateip.s_addr = 0;
254 }
255
256 return (n);
257
258 bad:
259 errno = 0;
260 return (-1);
261 }
262
263 static void
264 vend_cmu(u_char *cp)
265 {
266 struct cmu_vend *vp;
267
268 #ifdef BOOTP_DEBUG
269 if (debug)
270 printf("vend_cmu bootp info.\n");
271 #endif
272 vp = (struct cmu_vend *)cp;
273
274 if (vp->v_smask.s_addr != 0)
275 smask = vp->v_smask.s_addr;
276 if (vp->v_dgate.s_addr != 0)
277 gateip = vp->v_dgate;
278 }
279
280 static void
281 vend_rfc1048(u_char *cp, u_int len)
282 {
283 u_char *ep;
284 int size;
285 u_char tag;
286
287 #ifdef BOOTP_DEBUG
288 if (debug)
289 printf("vend_rfc1048 bootp info. len=%d\n", len);
290 #endif
291 ep = cp + len;
292
293
294 cp += sizeof(int);
295
296 while (cp < ep) {
297 tag = *cp++;
298 size = *cp++;
299 if (tag == TAG_END)
300 break;
301
302 if (tag == TAG_SUBNET_MASK)
303 bcopy(cp, &smask, sizeof(smask));
304 if (tag == TAG_GATEWAY)
305 bcopy(cp, &gateip.s_addr, sizeof(gateip.s_addr));
306 if (tag == TAG_SWAPSERVER)
307 bcopy(cp, &swapip.s_addr, sizeof(swapip.s_addr));
308 if (tag == TAG_DOMAIN_SERVER)
309 bcopy(cp, &nameip.s_addr, sizeof(nameip.s_addr));
310 if (tag == TAG_ROOTPATH) {
311 strncpy(rootpath, (char *)cp, sizeof(rootpath));
312 rootpath[size] = '\0';
313 }
314 if (tag == TAG_HOSTNAME) {
315 strncpy(hostname, (char *)cp, sizeof(hostname));
316 hostname[size] = '\0';
317 }
318 if (tag == TAG_DOMAINNAME) {
319 strncpy(domainname, (char *)cp, sizeof(domainname));
320 domainname[size] = '\0';
321 }
322 cp += size;
323 }
324 }