|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)inet.c 1.1 86/02/03 Copyr 1984 Sun Micro";
3: #endif
4:
5: /*
6: * Copyright (c) 1985 by Sun Microsystems, Inc.
7: */
8:
9: /*
10: * Standalone IP send and receive - specific to Ethernet
11: * Includes ARP and Reverse ARP
12: */
13: #include "saio.h"
14: #include "../h/socket.h"
15: #include "../net/if.h"
16: #include "../netinet/in.h"
17: #include "../netinet/if_ether.h"
18: #include "../netinet/in_systm.h"
19: #include "../netinet/ip.h"
20: #include "sainet.h"
21: #include "../mon/sunromvec.h"
22: #include "../mon/idprom.h"
23:
24: #define millitime() (*romp->v_nmiclock)
25:
26: struct ether_addr etherbroadcastaddr = {
27: 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
28: };
29:
30: struct arp_packet {
31: struct ether_header arp_eh;
32: struct ether_arp arp_ea;
33: #define used_size (sizeof (struct ether_header)+sizeof(struct ether_arp))
34: char filler[ETHERMIN - sizeof(struct ether_arp)];
35: };
36:
37: #define WAITCNT 2 /* 4 seconds before bitching about arp/revarp */
38:
39: /*
40: * Fetch our Ethernet address from the ID prom
41: */
42: myetheraddr(ea)
43: struct ether_addr *ea;
44: {
45: struct idprom id;
46:
47: if (idprom(IDFORM_1, &id) != IDFORM_1) {
48: printf("ERROR: missing or invalid ID prom\n");
49: return;
50: }
51: *ea = *(struct ether_addr *)id.id_ether;
52: }
53:
54: /*
55: * Initialize IP state
56: * Find out our Ethernet address and call Reverse ARP
57: * to find out our Internet address
58: * Set the ARP cache to the broadcast host
59: */
60: inet_init(sip, sain, tmpbuf)
61: register struct saioreq *sip;
62: register struct sainet *sain;
63: char *tmpbuf;
64: {
65: myetheraddr(&sain->sain_myether);
66: sain->sain_hisaddr.s_addr = 0;
67: sain->sain_hisether = etherbroadcastaddr;
68: revarp(sip, sain, tmpbuf);
69: }
70:
71:
72: /*
73: * Output an IP packet
74: * Cause ARP to be invoked if necessary
75: */
76: ip_output(sip, buf, len, sain, tmpbuf)
77: register struct saioreq *sip;
78: caddr_t buf, tmpbuf;
79: short len;
80: register struct sainet *sain;
81: {
82: register struct ether_header *eh;
83: register struct ip *ip;
84:
85: eh = (struct ether_header *)buf;
86: ip = (struct ip *)(buf + sizeof(struct ether_header));
87: if (ip->ip_dst.s_addr != sain->sain_hisaddr.s_addr) {
88: sain->sain_hisaddr.s_addr = ip->ip_dst.s_addr;
89: arp(sip, sain, tmpbuf);
90: }
91: eh->ether_type = ETHERPUP_IPTYPE;
92: eh->ether_shost = sain->sain_myether;
93: eh->ether_dhost = sain->sain_hisether;
94: /* checksum the packet */
95: ip->ip_sum = 0;
96: ip->ip_sum = ipcksum((caddr_t)ip, sizeof (struct ip));
97: if (len < ETHERMIN+sizeof(struct ether_header))
98: len = ETHERMIN+sizeof(struct ether_header);
99: return (*sip->si_sif->sif_xmit)(sip->si_devdata, buf, len);
100: }
101:
102: /*
103: * Check incoming packets for IP packets
104: * addressed to us. Also, respond to ARP packets
105: * that wish to know about us.
106: * Returns a length for any IP packet addressed to us, 0 otherwise.
107: */
108: ip_input(sip, buf, sain)
109: register struct saioreq *sip;
110: caddr_t buf;
111: register struct sainet *sain;
112: {
113: register short len;
114: register struct ether_header *eh;
115: register struct ip *ip;
116: register struct ether_arp *ea;
117:
118: len = (*sip->si_sif->sif_poll)(sip->si_devdata, buf);
119: eh = (struct ether_header *)buf;
120: if (eh->ether_type == ETHERPUP_IPTYPE &&
121: len >= sizeof(struct ether_header)+sizeof(struct ip)) {
122: ip = (struct ip *)(buf + sizeof(struct ether_header));
123: #ifdef NOREVARP
124: if ((sain->sain_hisaddr.s_addr & 0xFF000000) == 0 &&
125: bcmp((caddr_t)ðerbroadcastaddr,
126: (caddr_t)&eh->ether_dhost, 6) != 0 &&
127: (in_broadaddr(sain->sain_hisaddr) ||
128: in_lnaof(ip->ip_src) == in_lnaof(sain->sain_hisaddr))) {
129: sain->sain_myaddr = ip->ip_dst;
130: sain->sain_hisaddr = ip->ip_src;
131: sain->sain_hisether = eh->ether_shost;
132: }
133: #endif
134: if (ip->ip_dst.s_addr != sain->sain_myaddr.s_addr)
135: return (0);
136: return (len);
137: }
138: if (eh->ether_type == ETHERPUP_ARPTYPE &&
139: len >= sizeof(struct ether_header)+sizeof(struct ether_arp)) {
140: ea = (struct ether_arp *)(buf + sizeof(struct ether_header));
141: if (ea->arp_pro != ETHERPUP_IPTYPE)
142: return (0);
143: if (arp_spa(ea).s_addr == sain->sain_hisaddr.s_addr)
144: sain->sain_hisether = arp_sha(ea);
145: if (ea->arp_op == ARPOP_REQUEST &&
146: arp_tpa(ea).s_addr == sain->sain_myaddr.s_addr) {
147: ea->arp_op = ARPOP_REPLY;
148: eh->ether_dhost = arp_sha(ea);
149: eh->ether_shost = sain->sain_myether;
150: arp_tha(ea) = arp_sha(ea);
151: arp_tpa(ea) = arp_spa(ea);
152: arp_sha(ea) = sain->sain_myether;
153: arp_spa(ea) = sain->sain_myaddr;
154: (*sip->si_sif->sif_xmit)(sip->si_devdata, buf,
155: sizeof(struct arp_packet));
156: }
157: return (0);
158: }
159: return (0);
160: }
161:
162: /*
163: * arp
164: * Broadcasts to determine Ethernet address given IP address
165: * See RFC 826
166: */
167: arp(sip, sain, tmpbuf)
168: register struct saioreq *sip;
169: register struct sainet *sain;
170: char *tmpbuf;
171: {
172: struct arp_packet out;
173:
174: if (in_broadaddr(sain->sain_hisaddr)
175: #ifdef NOREVARP
176: || (sain->sain_hisaddr.s_addr & 0xFF000000) == 0
177: #endif
178: ) {
179: sain->sain_hisether = etherbroadcastaddr;
180: return;
181: }
182: out.arp_eh.ether_type = ETHERPUP_ARPTYPE;
183: out.arp_ea.arp_op = ARPOP_REQUEST;
184: arp_tha(&out.arp_ea) = etherbroadcastaddr; /* what we want */
185: arp_tpa(&out.arp_ea).s_addr = sain->sain_hisaddr.s_addr;
186: comarp(sip, sain, &out, tmpbuf);
187: }
188:
189: /*
190: * Reverse ARP client side
191: * Determine our Internet address given our Ethernet address
192: * See RFC 903
193: */
194: revarp(sip, sain, tmpbuf)
195: register struct saioreq *sip;
196: register struct sainet *sain;
197: char *tmpbuf;
198: {
199: struct arp_packet out;
200:
201: #ifdef NOREVARP
202: sain->sain_myaddr.s_addr = 0;
203: bcopy((caddr_t)&sain->sain_myether.ether_addr_octet[3],
204: (caddr_t)(&sain->sain_myaddr)+1, 3);
205: #else
206: out.arp_eh.ether_type = ETHERPUP_REVARPTYPE;
207: out.arp_ea.arp_op = REVARP_REQUEST;
208: arp_tha(&out.arp_ea) = sain->sain_myether;
209: arp_tpa(&out.arp_ea).s_addr = 0;/* what we want to find out */
210: comarp(sip, sain, &out, tmpbuf);
211: #endif
212: }
213:
214: /*
215: * Common ARP code
216: * Broadcast the packet and wait for the right response.
217: * Fills in *sain with the results
218: */
219: comarp(sip, sain, out, tmpbuf)
220: register struct saioreq *sip;
221: register struct sainet *sain;
222: register struct arp_packet *out;
223: char *tmpbuf;
224: {
225: register struct arp_packet *in = (struct arp_packet *)tmpbuf;
226: register int e, count, time, feedback,len, delay = 2;
227: char *ind = "-\|/";
228:
229: out->arp_eh.ether_dhost = etherbroadcastaddr;
230: out->arp_eh.ether_shost = sain->sain_myether;
231: out->arp_ea.arp_hrd = ARPHRD_ETHER;
232: out->arp_ea.arp_pro = ETHERPUP_IPTYPE;
233: out->arp_ea.arp_hln = sizeof(struct ether_addr);
234: out->arp_ea.arp_pln = sizeof(struct in_addr);
235: arp_sha(&out->arp_ea) = sain->sain_myether;
236: arp_spa(&out->arp_ea).s_addr = sain->sain_myaddr.s_addr;
237: feedback = 0;
238:
239: for (count=0; ; count++) {
240: if (count == WAITCNT) {
241: if (out->arp_ea.arp_op == ARPOP_REQUEST) {
242: printf("\nRequesting Ethernet address for ");
243: inet_print(arp_tpa(&out->arp_ea));
244: } else {
245: printf("\nRequesting Internet address for ");
246: ether_print(&arp_tha(&out->arp_ea));
247: }
248: }
249: e = (*sip->si_sif->sif_xmit)(sip->si_devdata, (caddr_t)out,
250: sizeof *out);
251: if (e)
252: printf("X\b");
253: else
254: printf("%c\b", ind[feedback++ % 4]); /* Show activity */
255:
256: time = millitime() + (delay * 1000); /* broadcast delay */
257: while (millitime() <= time) {
258: len = (*sip->si_sif->sif_poll)(sip->si_devdata, tmpbuf);
259: if (len < used_size)
260: continue;
261: if (in->arp_ea.arp_pro != ETHERPUP_IPTYPE)
262: continue;
263: if (out->arp_ea.arp_op == ARPOP_REQUEST) {
264: if (in->arp_eh.ether_type != ETHERPUP_ARPTYPE)
265: continue;
266: if (in->arp_ea.arp_op != ARPOP_REPLY)
267: continue;
268: if (arp_spa(&in->arp_ea).s_addr !=
269: arp_tpa(&out->arp_ea).s_addr)
270: continue;
271: if (count >= WAITCNT) {
272: printf("Found at ");
273: ether_print(&arp_sha(&in->arp_ea));
274: }
275: sain->sain_hisether = arp_sha(&in->arp_ea);
276: return;
277: } else { /* Reverse ARP */
278: if (in->arp_eh.ether_type !=ETHERPUP_REVARPTYPE)
279: continue;
280: if (in->arp_ea.arp_op != REVARP_REPLY)
281: continue;
282: if (bcmp((caddr_t)&arp_tha(&in->arp_ea),
283: (caddr_t)&arp_tha(&out->arp_ea),
284: sizeof (struct ether_addr)) != 0)
285: continue;
286:
287: if (count >= WAITCNT) {
288: printf("Internet address is ");
289: inet_print(arp_tpa(&in->arp_ea));
290: }
291: sain->sain_myaddr = arp_tpa(&in->arp_ea);
292: /* short circuit first ARP */
293: sain->sain_hisaddr = arp_spa(&in->arp_ea);
294: sain->sain_hisether = arp_sha(&in->arp_ea);
295: return;
296: }
297: }
298:
299: delay = delay * 2; /* Double the request delay */
300: if (delay > 64) /* maximum delay is 64 seconds */
301: delay = 64;
302:
303: (*sip->si_sif->sif_reset)(sip->si_devdata);
304: }
305: /* NOTREACHED */
306: }
307:
308: /*
309: * Return the host portion of an internet address.
310: */
311: in_lnaof(in)
312: struct in_addr in;
313: {
314: register u_long i = ntohl(in.s_addr);
315:
316: if (IN_CLASSA(i))
317: return ((i)&IN_CLASSA_HOST);
318: else if (IN_CLASSB(i))
319: return ((i)&IN_CLASSB_HOST);
320: else
321: return ((i)&IN_CLASSC_HOST);
322: }
323:
324: /*
325: * Test for broadcast IP address
326: */
327: in_broadaddr(in)
328: struct in_addr in;
329: {
330: register u_long i = ntohl(in.s_addr);
331:
332: if (IN_CLASSA(i)) {
333: i &= IN_CLASSA_HOST;
334: return (i == 0 || i == 0xFFFFFF);
335: } else if (IN_CLASSB(i)) {
336: i &= IN_CLASSB_HOST;
337: return (i == 0 || i == 0xFFFF);
338: } else if (IN_CLASSC(i)) {
339: i &= IN_CLASSC_HOST;
340: return (i == 0 || i == 0xFF);
341: }
342: /* NOTREACHED */
343: }
344:
345: /*
346: * Compute one's complement checksum
347: * for IP packet headers
348: */
349: ipcksum(cp, count)
350: caddr_t cp;
351: register unsigned short count;
352: {
353: register unsigned short *sp = (unsigned short *)cp;
354: register unsigned long sum = 0;
355: register unsigned long oneword = 0x00010000;
356:
357: count >>= 1;
358: while (count--) {
359: sum += *sp++;
360: if (sum >= oneword) { /* Wrap carries into low bit */
361: sum -= oneword;
362: sum++;
363: }
364: }
365: return (~sum);
366: }
367:
368: inet_print(s)
369: struct in_addr s;
370: {
371: printf("%d.%d.%d.%d\n",
372: s.S_un.S_un_b.s_b1, s.S_un.S_un_b.s_b2,
373: s.S_un.S_un_b.s_b3, s.S_un.S_un_b.s_b4);
374: }
375:
376: ether_print(ea)
377: struct ether_addr *ea;
378: {
379: register u_char *p = &ea->ether_addr_octet[0];
380:
381: printf("%x:%x:%x:%x:%x:%x\n", p[0], p[1], p[2], p[3], p[4], p[5]);
382: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.