|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)nd.c 1.1 86/02/03 Copyr 1985 Sun Micro";
3: #endif
4:
5: /*
6: * Copyright (c) 1985 by Sun Microsystems, Inc.
7: */
8:
9: /*
10: * standalone nd.c
11: * Used only in /boot after TFTP boot.
12: * Never in PROM or boot blocks
13: */
14:
15: /* This value is used in header files, it must be at least 1 */
16: #define NND 1
17:
18: #include "saio.h"
19: #include "param.h"
20: #include "../h/socket.h"
21: #include "../net/if.h"
22: #include "../netinet/in.h"
23: #include "../netinet/if_ether.h"
24: #include "../netinet/in_systm.h"
25: #include "../netinet/ip.h"
26: #include "sainet.h"
27: #include "../sun/ndio.h"
28: #include "../mon/sunromvec.h"
29: #include "../mon/idprom.h"
30:
31: #define millitime() (*romp->v_nmiclock)
32:
33: /*
34: * Each network device driver must start off their local variables
35: * structure (pointed to by sip->si_devdata) by a struct nd or a union
36: * of a struct nd and other protocol structures. This reserves the
37: * space needed by the protocol handler(s) without any further ado.
38: * Therefore, the protocol can simply assume that sip->si_devdata
39: * points to its parameters.
40: */
41: #define NDBASE (struct nd *)(sip->si_devdata)
42:
43: /* standalone RAM variables */
44: struct nd {
45: int nd_seq; /* current sequence number */
46: struct ether_header nd_xh; /* xmit header and packet */
47: struct ndpack nd_xp; /* must be contiguous */
48: int nd_block; /* block number of data in "cache" */
49: char nd_data[NDMAXDATA]; /* "cache" of receive data */
50: char nd_buf[1600]; /* temp buf for packets */
51: struct sainet nd_inet; /* INET state */
52: };
53:
54: #define NDHDRSIZE (sizeof(struct ether_header) + sizeof(struct ndpack))
55:
56: /*
57: * Zap this to indicate ND device from which to boot by default
58: */
59: short ndbootdev = 0x40; /* public partition #0 */
60:
61: /*
62: * Initialize network disk operation.
63: * Get server address and partition number from si_unit and si_boff.
64: */
65: etheropen(sip)
66: struct saioreq *sip;
67: {
68: register struct nd *nd = NDBASE;
69: register i;
70: char buf[DEV_BSIZE];
71:
72: bzero((caddr_t)nd, sizeof *nd);
73:
74: /*
75: * Initialize INET state
76: */
77: inet_init(sip, &nd->nd_inet, nd->nd_buf);
78:
79: /*
80: * Set src and dst host addresses
81: * Dst host is argument with our net number plugged in
82: */
83: nd->nd_xp.np_ip.ip_src = nd->nd_inet.sain_myaddr;
84: nd->nd_xp.np_ip.ip_dst.s_addr = sip->si_unit;
85: nd->nd_xp.np_ip.ip_dst.s_addr += nd->nd_xp.np_ip.ip_src.s_addr -
86: in_lnaof(nd->nd_xp.np_ip.ip_src);
87: /* fix for FF broadcast ? */
88:
89: nd->nd_block = -10; /* impossible block number */
90: nd->nd_seq = millitime(); /* initial sequence number */
91: /* set ether, ip and ndpack fixed fields */
92: nd->nd_xp.np_ip.ip_v = IPVERSION;
93: nd->nd_xp.np_ip.ip_hl = sizeof (struct ip) / 4;
94: nd->nd_xp.np_ip.ip_len = sizeof (struct ndpack);
95: nd->nd_xp.np_ip.ip_ttl = NDXTIMER;
96: nd->nd_xp.np_ip.ip_p = IPPROTO_ND;
97: nd->nd_xp.np_op = (NDOPREAD | NDOPWAIT);
98: nd->nd_xp.np_min = (int)sip->si_boff;
99: /*
100: * We XOR here to keep similar semantics of bie(,,40)
101: * to mean private when default is public
102: */
103: nd->nd_xp.np_min ^= ndbootdev;
104: nd->nd_xp.np_bcount = NDMAXDATA;
105:
106: /* try to read block 0 */
107: if (ndread(sip, 0, buf))
108: return (-1);
109: return (0);
110: }
111:
112: /*
113: * Strategy routine. User interface to do reads and writes is thru here.
114: * We currently don't support writes.
115: */
116: int
117: etherstrategy(sip, rw)
118: register struct saioreq *sip;
119: int rw;
120: {
121: int cnt = sip->si_cc;
122: int blk = sip->si_bn;
123: char *ma = sip->si_ma;
124:
125: if (rw == WRITE)
126: return (0);
127: while (cnt > 0) {
128: if (ndread(sip, blk, ma))
129: break;
130: blk++;
131: ma += DEV_BSIZE;
132: cnt -= DEV_BSIZE;
133: }
134: return (sip->si_cc - cnt);
135: }
136:
137: /*
138: * Receive packets from an nd server.
139: * We keep a 1K cache to speed things up
140: */
141: ndread(sip, block, caddr)
142: struct saioreq *sip;
143: int block;
144: caddr_t caddr;
145: {
146: register struct nd *nd = NDBASE;
147: register char *cp;
148: register short ok, i;
149:
150: cp = nd->nd_data;
151: if (block == nd->nd_block)
152: goto copy;
153: if (block == (nd->nd_block+1)) {
154: cp += DEV_BSIZE;
155: goto copy;
156: }
157: /*
158: * Fill in the request block
159: */
160: nd->nd_xp.np_blkno = block;
161: nd->nd_xp.np_seq = ++nd->nd_seq;
162:
163: #define LIMIT 500
164: for (i=0 ; i<LIMIT ; i++) {
165: if (ip_output(sip, (caddr_t)&nd->nd_xh, NDHDRSIZE,
166: &nd->nd_inet, nd->nd_buf)) {
167: printf("X\010");
168: continue;
169: }
170: ok = ndrecv(sip);
171: if (ok >= 0)
172: break;
173: printf("?\b"); /* Indicate there's a problem */
174: }
175: if (i == LIMIT) {
176: printf("nd: no file server, giving up.\n");
177: return (-1);
178: }
179: if (ok == 0)
180: return (-1);
181: nd->nd_block = block;
182: copy:
183: bcopy(cp, caddr, DEV_BSIZE);
184: return (0);
185: }
186:
187: #define NDREPLYTIME (2*1000) /* miilliseconds between retransmits */
188:
189: ndrecv(sip)
190: struct saioreq *sip;
191: {
192: register struct nd *nd = NDBASE;
193: register struct ndpack *np;
194: register struct ether_header *eh;
195: register int time;
196: register short len;
197:
198: time = millitime() + NDREPLYTIME;
199: for (;;) {
200: if (millitime() > time) {
201: (*sip->si_sif->sif_reset)(sip->si_devdata, sip);
202: return (-1);
203: }
204: len = ip_input(sip, nd->nd_buf, &nd->nd_inet);
205: if (len < NDHDRSIZE)
206: continue;
207: eh = (struct ether_header *)nd->nd_buf;
208: np = (struct ndpack *)&eh[1];
209:
210: /*
211: * avoid bug in older servers.
212: * The problem is that pre-Sun Unix 1.1 servers would
213: * respond to ANY directed boot request that they
214: * received, whether or not it was directed to their
215: * Internet address. (They assumed that the boot
216: * proms knew their Ethernet address.) We now broadcast
217: * all boot requests, directed or otherwise, so we have
218: * to filter out replies from ones we don't care about.
219: */
220: if (in_lnaof(nd->nd_xp.np_ip.ip_dst) != 0 &&
221: in_lnaof(nd->nd_xp.np_ip.ip_dst) !=
222: in_lnaof(np->np_ip.ip_src))
223: continue;
224:
225: if (np->np_ip.ip_p == IPPROTO_ND && np->np_seq == nd->nd_seq)
226: break;
227: }
228:
229: if (np->np_op == NDOPERROR) {
230: printf("nd: err %x bn %d\n", np->np_error, np->np_blkno);
231: return (0);
232: }
233: if (np->np_op != (NDOPREAD|NDOPDONE|NDOPWAIT) ||
234: np->np_ccount != NDMAXDATA ||
235: np->np_ip.ip_len != (sizeof(struct ndpack)+NDMAXDATA)) {
236: #ifdef DEBUG
237: printf("ND protocol violation\n");
238: #endif DEBUG
239: return (-1);
240: }
241: /* lock onto server if we are still broadcasting */
242: if (in_broadaddr(nd->nd_xp.np_ip.ip_dst))
243: nd->nd_xp.np_ip.ip_dst = np->np_ip.ip_src;
244: #ifdef NOREVARP
245: if ((nd->nd_xp.np_ip.ip_dst.s_addr & 0xFF000000) == 0)
246: nd->nd_xp.np_ip.ip_dst = np->np_ip.ip_src;
247: #endif
248: if ((nd->nd_seq & 7) == 0)
249: printf((nd->nd_seq & 8) ? "-\b" : "=\b");
250: bcopy(nd->nd_buf + NDHDRSIZE, nd->nd_data, NDMAXDATA);
251: return (1);
252: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.