|
|
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.