|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
26: /*
27: * Copyright (c) 1982, 1986, 1988, 1993
28: * The Regents of the University of California. All rights reserved.
29: *
30: * Redistribution and use in source and binary forms, with or without
31: * modification, are permitted provided that the following conditions
32: * are met:
33: * 1. Redistributions of source code must retain the above copyright
34: * notice, this list of conditions and the following disclaimer.
35: * 2. Redistributions in binary form must reproduce the above copyright
36: * notice, this list of conditions and the following disclaimer in the
37: * documentation and/or other materials provided with the distribution.
38: * 3. All advertising materials mentioning features or use of this software
39: * must display the following acknowledgement:
40: * This product includes software developed by the University of
41: * California, Berkeley and its contributors.
42: * 4. Neither the name of the University nor the names of its contributors
43: * may be used to endorse or promote products derived from this software
44: * without specific prior written permission.
45: *
46: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56: * SUCH DAMAGE.
57: *
58: * @(#)if_ether.c 8.2 (Berkeley) 9/26/94
59: */
60:
61: /*
62: * Ethernet address resolution protocol.
63: * TODO:
64: * add "inuse/lock" bit (or ref. count) along with valid bit
65: */
66:
67:
68: #include <sys/param.h>
69: #include <sys/systm.h>
70: #include <sys/malloc.h>
71: #include <sys/mbuf.h>
72: #include <sys/socket.h>
73: #include <sys/time.h>
74: #include <sys/kernel.h>
75: #include <sys/errno.h>
76: #include <sys/ioctl.h>
77: #include <sys/syslog.h>
78:
79: #include <net/if.h>
80: #include <net/if_dl.h>
81: #include <net/route.h>
82:
83: #include <netinet/in.h>
84: #include <netinet/in_systm.h>
85: #include <netinet/in_var.h>
86: #include <netinet/ip.h>
87: #include <netinet/if_ether.h>
88:
89: #if INET
90:
91: struct ifqueue arpintrq;
92:
93: struct llinfo_arp llinfo_arp; /* head of the llinfo queue */
94:
95: #define SIN(s) ((struct sockaddr_in *)s)
96: #define SDL(s) ((struct sockaddr_dl *)s)
97: #define SRP(s) ((struct sockaddr_inarp *)s)
98:
99: /*
100: * ARP trailer negotiation. Trailer protocol is not IP specific,
101: * but ARP request/response use IP addresses.
102: */
103: #define ETHERTYPE_IPTRAILERS ETHERTYPE_TRAIL
104:
105: /* timer values */
106: int arpt_prune = (5*60*1); /* walk list every 5 minutes */
107: int arpt_keep = (20*60); /* once resolved, good for 20 more minutes */
108: int arpt_down = 20; /* once declared down, don't send for 20 secs */
109: #define rt_expire rt_rmx.rmx_expire
110:
111: static void arprequest __P((struct arpcom *, u_long *, u_long *, u_char *));
112: static void arptfree __P((struct llinfo_arp *));
113: static void arptimer __P((void *));
114: static struct llinfo_arp *arplookup __P((u_long, int, int));
115: static void in_arpinput __P((struct mbuf *));
116:
117: extern struct ifnet loif;
118: struct llinfo_arp llinfo_arp = {&llinfo_arp, &llinfo_arp};
119: struct ifqueue arpintrq = {0, 0, 0, 50};
120: int arp_inuse, arp_allocated, arp_intimer;
121: int arp_maxtries = 5;
122: int useloopback = 1; /* use loopback interface for local traffic */
123: int arpinit_done = 0;
124:
125: /* revarp state */
126: static struct in_addr myip, srv_ip;
127: static int myip_initialized = 0;
128: static int revarp_in_progress = 0;
129: static struct ifnet *myip_ifp = NULL;
130:
131: /* Should be in spl.h */
132: int splimp(void);
133: int splnet(void);
134: int splx(int);
135:
136: /*
137: * Timeout routine. Age arp_tab entries periodically.
138: */
139: /* ARGSUSED */
140: static void
141: arptimer(arg)
142: void *arg;
143: {
144: int s;
145: register struct llinfo_arp *la = llinfo_arp.la_next;
146:
147: s = splnet();
148: while (la != &llinfo_arp) {
149: register struct rtentry *rt = la->la_rt;
150: la = la->la_next;
151: if (rt->rt_expire && rt->rt_expire <= time.tv_sec)
152: arptfree(la->la_prev); /* timer has expired; clear */
153: }
154: timeout(arptimer, NULL, arpt_prune * hz);
155: splx(s);
156:
157: }
158:
159: /*
160: * Parallel to llc_rtrequest.
161: */
162: void
163: arp_rtrequest(req, rt, sa)
164: int req;
165: register struct rtentry *rt;
166: struct sockaddr *sa;
167: {
168: register struct sockaddr *gate = rt->rt_gateway;
169: register struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo;
170: static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
171:
172: if (!arpinit_done) {
173: arpinit_done = 1;
174: timeout(arptimer, (caddr_t)0, hz);
175: }
176: if (rt->rt_flags & RTF_GATEWAY)
177: return;
178: switch (req) {
179:
180: case RTM_ADD:
181: /*
182: * XXX: If this is a manually added route to interface
183: * such as older version of routed or gated might provide,
184: * restore cloning bit.
185: */
186: if ((rt->rt_flags & RTF_HOST) == 0 &&
187: SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff)
188: rt->rt_flags |= RTF_CLONING;
189: if (rt->rt_flags & RTF_CLONING) {
190: /*
191: * Case 1: This route should come from a route to iface.
192: */
193: rt_setgate(rt, rt_key(rt),
194: (struct sockaddr *)&null_sdl);
195: gate = rt->rt_gateway;
196: SDL(gate)->sdl_type = rt->rt_ifp->if_type;
197: SDL(gate)->sdl_index = rt->rt_ifp->if_index;
198: /*
199: * Give this route an expiration time, even though
200: * it's a "permanent" route, so that routes cloned
201: * from it do not need their expiration time set.
202: */
203: rt->rt_expire = time.tv_sec;
204: break;
205: }
206: /* Announce a new entry if requested. */
207: if (rt->rt_flags & RTF_ANNOUNCE)
208: arprequest((struct arpcom *)rt->rt_ifp,
209: &SIN(rt_key(rt))->sin_addr.s_addr,
210: &SIN(rt_key(rt))->sin_addr.s_addr,
211: (u_char *)LLADDR(SDL(gate)));
212: /*FALLTHROUGH*/
213: case RTM_RESOLVE:
214: if (gate->sa_family != AF_LINK ||
215: gate->sa_len < sizeof(null_sdl)) {
216: log(LOG_DEBUG, "arp_rtrequest: bad gateway value");
217: break;
218: }
219: SDL(gate)->sdl_type = rt->rt_ifp->if_type;
220: SDL(gate)->sdl_index = rt->rt_ifp->if_index;
221: if (la != 0)
222: break; /* This happens on a route change */
223: /*
224: * Case 2: This route may come from cloning, or a manual route
225: * add with a LL address.
226: */
227: R_Malloc(la, struct llinfo_arp *, sizeof(*la));
228: rt->rt_llinfo = (caddr_t)la;
229: if (la == 0) {
230: log(LOG_DEBUG, "arp_rtrequest: malloc failed\n");
231: break;
232: }
233: arp_inuse++, arp_allocated++;
234: Bzero(la, sizeof(*la));
235: la->la_rt = rt;
236: rt->rt_flags |= RTF_LLINFO;
237: insque((queue_t)la, (queue_t)&llinfo_arp);
238: if (SIN(rt_key(rt))->sin_addr.s_addr ==
239: (IA_SIN(rt->rt_ifa))->sin_addr.s_addr) {
240: /*
241: * This test used to be
242: * if (loif.if_flags & IFF_UP)
243: * It allowed local traffic to be forced
244: * through the hardware by configuring the loopback down.
245: * However, it causes problems during network configuration
246: * for boards that can't receive packets they send.
247: * It is now necessary to clear "useloopback" and remove
248: * the route to force traffic out to the hardware.
249: */
250: rt->rt_expire = 0;
251: Bcopy(((struct arpcom *)rt->rt_ifp)->ac_enaddr,
252: LLADDR(SDL(gate)), SDL(gate)->sdl_alen = 6);
253: if (useloopback)
254: rt->rt_ifp = &loif;
255:
256: }
257: break;
258:
259: case RTM_DELETE:
260: if (la == 0)
261: break;
262: arp_inuse--;
263: remque((queue_t)la);
264: rt->rt_llinfo = 0;
265: rt->rt_flags &= ~RTF_LLINFO;
266: if (la->la_hold)
267: m_freem(la->la_hold);
268: Free((caddr_t)la);
269: }
270: }
271:
272: /*
273: * Broadcast an ARP packet, asking who has addr on interface ac.
274: */
275: void
276: arpwhohas(ac, addr)
277: register struct arpcom *ac;
278: register struct in_addr *addr;
279: { struct ifnet *ifp = (struct ifnet *)ac;
280: struct ifaddr *ifa = ifp->if_addrlist;
281:
282: while (ifa)
283: { if (ifa->ifa_addr->sa_family == AF_INET)
284: { arprequest(ac, &SIN(ifa->ifa_addr)->sin_addr.s_addr, &addr->s_addr, ac->ac_enaddr);
285: return;
286: }
287: ifa = ifa->ifa_next;
288: }
289: return; /* XXX */
290: }
291:
292: /*
293: * Broadcast an ARP request. Caller specifies:
294: * - arp header source ip address
295: * - arp header target ip address
296: * - arp header source ethernet address
297: */
298: static void
299: arprequest(ac, sip, tip, enaddr)
300: register struct arpcom *ac;
301: register u_long *sip, *tip;
302: register u_char *enaddr;
303: {
304: register struct mbuf *m;
305: register struct ether_header *eh;
306: register struct ether_arp *ea;
307: struct sockaddr sa;
308:
309: if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL)
310: return;
311: m->m_len = sizeof(*ea);
312: m->m_pkthdr.len = sizeof(*ea);
313: MH_ALIGN(m, sizeof(*ea));
314: ea = mtod(m, struct ether_arp *);
315: eh = (struct ether_header *)sa.sa_data;
316: bzero((caddr_t)ea, sizeof (*ea));
317: bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
318: sizeof(eh->ether_dhost));
319: eh->ether_type = htons(ETHERTYPE_ARP);
320: ea->arp_hrd = htons(ARPHRD_ETHER);
321: ea->arp_pro = htons(ETHERTYPE_IP);
322: ea->arp_hln = sizeof(ea->arp_sha); /* hardware address length */
323: ea->arp_pln = sizeof(ea->arp_spa); /* protocol address length */
324: ea->arp_op = htons(ARPOP_REQUEST);
325: bcopy((caddr_t)enaddr, (caddr_t)ea->arp_sha, sizeof(ea->arp_sha));
326: bcopy((caddr_t)sip, (caddr_t)ea->arp_spa, sizeof(ea->arp_spa));
327: bcopy((caddr_t)tip, (caddr_t)ea->arp_tpa, sizeof(ea->arp_tpa));
328: sa.sa_family = AF_UNSPEC;
329: sa.sa_len = sizeof(sa);
330: (*ac->ac_if.if_output)(&ac->ac_if, m, &sa, (struct rtentry *)0);
331: }
332:
333: /*
334: * Resolve an IP address into an ethernet address. If success,
335: * desten is filled in. If there is no entry in arptab,
336: * set one up and broadcast a request for the IP address.
337: * Hold onto this mbuf and resend it once the address
338: * is finally resolved. A return value of 1 indicates
339: * that desten has been filled in and the packet should be sent
340: * normally; a 0 return indicates that the packet has been
341: * taken over here, either now or for later transmission.
342: */
343: int
344: arpresolve(ac, rt, m, dst, desten)
345: register struct arpcom *ac;
346: register struct rtentry *rt;
347: struct mbuf *m;
348: register struct sockaddr *dst;
349: register u_char *desten;
350: {
351: register struct llinfo_arp *la;
352: struct sockaddr_dl *sdl;
353:
354: if (m->m_flags & M_BCAST) { /* broadcast */
355: bcopy((caddr_t)etherbroadcastaddr, (caddr_t)desten,
356: sizeof(etherbroadcastaddr));
357: return (1);
358: }
359: if (m->m_flags & M_MCAST) { /* multicast */
360: ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten);
361: return(1);
362: }
363: if (rt)
364: la = (struct llinfo_arp *)rt->rt_llinfo;
365: else {
366: if ((la = arplookup(SIN(dst)->sin_addr.s_addr, 1, 0)))
367: rt = la->la_rt;
368: }
369: if (la == 0 || rt == 0) {
370: log(LOG_DEBUG, "arpresolve: can't allocate llinfo");
371: m_freem(m);
372: return (0);
373: }
374: sdl = SDL(rt->rt_gateway);
375: /*
376: * Check the address family and length is valid, the address
377: * is resolved; otherwise, try to resolve.
378: */
379: if ((rt->rt_expire == 0 || rt->rt_expire > time.tv_sec) &&
380: sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) {
381: bcopy(LLADDR(sdl), desten, sdl->sdl_alen);
382:
383: return 1;
384: }
385: /*
386: * There is an arptab entry, but no ethernet address
387: * response yet. Replace the held mbuf with this
388: * latest one.
389: */
390: if (la->la_hold)
391: m_freem(la->la_hold);
392: la->la_hold = m;
393: /*
394: * Re-send the ARP request when appropriate.
395: */
396: #if DIAGNOSTIC
397: if (rt->rt_expire == 0) {
398: /* This should never happen. (Should it? -gwr) */
399: printf("arpresolve: unresolved and rt_expire == 0\n");
400: /* Set expiration time to now (expired). */
401: rt->rt_expire = time.tv_sec;
402: }
403: #endif
404: if (rt->rt_expire) {
405: rt->rt_flags &= ~RTF_REJECT;
406: if (la->la_asked == 0 || rt->rt_expire != time.tv_sec) {
407: rt->rt_expire = time.tv_sec;
408: if (la->la_asked++ < arp_maxtries)
409: arpwhohas(ac, &(SIN(dst)->sin_addr));
410: else {
411: rt->rt_flags |= RTF_REJECT;
412: rt->rt_expire += arpt_down;
413: la->la_asked = 0;
414: }
415: }
416: }
417: return (0);
418: }
419:
420: /*
421: * Common length and type checks are done here,
422: * then the protocol-specific routine is called.
423: */
424: void
425: arpintr()
426: {
427: register struct mbuf *m;
428: register struct arphdr *ar;
429: int s;
430:
431: while (arpintrq.ifq_head) {
432: s = splimp();
433: IF_DEQUEUE(&arpintrq, m);
434: splx(s);
435: if (m == 0 || (m->m_flags & M_PKTHDR) == 0)
436: panic("arpintr");
437: if (m->m_len >= sizeof(struct arphdr) &&
438: (ar = mtod(m, struct arphdr *)) &&
439: ntohs(ar->ar_hrd) == ARPHRD_ETHER &&
440: m->m_len >=
441: sizeof(struct arphdr) + 2 * (ar->ar_hln + ar->ar_pln))
442: switch (ntohs(ar->ar_pro)) {
443:
444: case ETHERTYPE_IP:
445: case ETHERTYPE_IPTRAILERS:
446: in_arpinput(m);
447: continue;
448: }
449:
450: m_freem(m);
451: }
452: }
453:
454: /*
455: * ARP for Internet protocols on 10 Mb/s Ethernet.
456: * Algorithm is that given in RFC 826.
457: * In addition, a sanity check is performed on the sender
458: * protocol address, to catch impersonators.
459: * We no longer handle negotiations for use of trailer protocol:
460: * Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent
461: * along with IP replies if we wanted trailers sent to us,
462: * and also sent them in response to IP replies.
463: * This allowed either end to announce the desire to receive
464: * trailer packets.
465: * We no longer reply to requests for ETHERTYPE_TRAIL protocol either,
466: * but formerly didn't normally send requests.
467: */
468: static void
469: in_arpinput(m)
470: struct mbuf *m;
471: {
472: register struct ether_arp *ea;
473: register struct arpcom *ac = (struct arpcom *)m->m_pkthdr.rcvif;
474: struct ether_header *eh;
475: register struct llinfo_arp *la = 0;
476: register struct rtentry *rt;
477: struct in_ifaddr *ia, *maybe_ia = 0;
478: struct sockaddr_dl *sdl;
479: struct sockaddr sa;
480: struct in_addr isaddr, itaddr, myaddr;
481: int op;
482: extern void kprintf( const char *, ...);
483:
484: ea = mtod(m, struct ether_arp *);
485: op = ntohs(ea->arp_op);
486: bcopy((caddr_t)ea->arp_spa, (caddr_t)&isaddr, sizeof (isaddr));
487: bcopy((caddr_t)ea->arp_tpa, (caddr_t)&itaddr, sizeof (itaddr));
488: for (ia = in_ifaddr; ia; ia = ia->ia_next)
489: if (ia->ia_ifp == &ac->ac_if) {
490: maybe_ia = ia;
491: if ((itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) ||
492: (isaddr.s_addr == ia->ia_addr.sin_addr.s_addr))
493: break;
494: }
495: if (maybe_ia == 0)
496: goto out;
497: myaddr = ia ? ia->ia_addr.sin_addr : maybe_ia->ia_addr.sin_addr;
498: #if 0
499: /*
500: * In order to support BlueBox networking, we need to allow
501: * "self-addressed" stamped envelopes
502: */
503: if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)ac->ac_enaddr,
504: sizeof (ea->arp_sha)))
505: goto out; /* it's from me, ignore it. */
506: #endif
507: if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)etherbroadcastaddr,
508: sizeof (ea->arp_sha))) {
509: log(LOG_ERR,
510: "arp: ether address is broadcast for IP address %x!\n",
511: ntohl(isaddr.s_addr));
512: goto out;
513: }
514: if (isaddr.s_addr == myaddr.s_addr) {
515: log(LOG_ERR,
516: "duplicate IP address %08x sent from ethernet address %s\n",
517: ntohl(isaddr.s_addr), ether_sprintf(ea->arp_sha));
518: itaddr = myaddr;
519: goto reply;
520: }
521: la = arplookup(isaddr.s_addr, itaddr.s_addr == myaddr.s_addr, 0);
522: if (la && (rt = la->la_rt) && (sdl = SDL(rt->rt_gateway))) {
523: if (sdl->sdl_alen &&
524: bcmp((caddr_t)ea->arp_sha, LLADDR(sdl), sdl->sdl_alen))
525: log(LOG_INFO, "arp info overwritten for %08x by %s\n",
526: ntohl(isaddr.s_addr), ether_sprintf(ea->arp_sha));
527: bcopy((caddr_t)ea->arp_sha, LLADDR(sdl),
528: sdl->sdl_alen = sizeof(ea->arp_sha));
529: if (rt->rt_expire)
530: rt->rt_expire = time.tv_sec + arpt_keep;
531: rt->rt_flags &= ~RTF_REJECT;
532: la->la_asked = 0;
533: if (la->la_hold) {
534: (*ac->ac_if.if_output)(&ac->ac_if, la->la_hold,
535: rt_key(rt), rt);
536: la->la_hold = 0;
537: }
538: }
539: reply:
540: if (op != ARPOP_REQUEST) {
541: out:
542: m_freem(m);
543: return;
544: }
545: if (itaddr.s_addr == myaddr.s_addr) {
546: /* I am the target */
547: bcopy((caddr_t)ea->arp_sha, (caddr_t)ea->arp_tha,
548: sizeof(ea->arp_sha));
549: bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha,
550: sizeof(ea->arp_sha));
551: } else {
552: la = arplookup(itaddr.s_addr, 0, SIN_PROXY);
553: if (la == NULL)
554: goto out;
555: rt = la->la_rt;
556: bcopy((caddr_t)ea->arp_sha, (caddr_t)ea->arp_tha,
557: sizeof(ea->arp_sha));
558: sdl = SDL(rt->rt_gateway);
559: bcopy(LLADDR(sdl), (caddr_t)ea->arp_sha, sizeof(ea->arp_sha));
560: }
561:
562: bcopy((caddr_t)ea->arp_spa, (caddr_t)ea->arp_tpa, sizeof(ea->arp_spa));
563: bcopy((caddr_t)&itaddr, (caddr_t)ea->arp_spa, sizeof(ea->arp_spa));
564: ea->arp_op = htons(ARPOP_REPLY);
565: ea->arp_pro = htons(ETHERTYPE_IP); /* let's be sure! */
566: eh = (struct ether_header *)sa.sa_data;
567: bcopy((caddr_t)ea->arp_tha, (caddr_t)eh->ether_dhost,
568: sizeof(eh->ether_dhost));
569: eh->ether_type = htons(ETHERTYPE_ARP);
570: sa.sa_family = AF_UNSPEC;
571: sa.sa_len = sizeof(sa);
572: (*ac->ac_if.if_output)(&ac->ac_if, m, &sa, (struct rtentry *)0);
573: return;
574: }
575:
576: /*
577: * Free an arp entry.
578: */
579: static void
580: arptfree(la)
581: register struct llinfo_arp *la;
582: {
583: register struct rtentry *rt = la->la_rt;
584: register struct sockaddr_dl *sdl;
585:
586: if (rt == 0)
587: panic("arptfree");
588: if (rt->rt_refcnt > 0 && (sdl = SDL(rt->rt_gateway)) &&
589: sdl->sdl_family == AF_LINK) {
590: sdl->sdl_alen = 0;
591: la->la_asked = 0;
592: rt->rt_flags &= ~RTF_REJECT;
593: return;
594: }
595: rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0, rt_mask(rt),
596: 0, (struct rtentry **)0);
597: }
598:
599: /*
600: * Lookup or enter a new address in arptab.
601: */
602: static struct llinfo_arp *
603: arplookup(addr, create, proxy)
604: u_long addr;
605: int create, proxy;
606: {
607: register struct rtentry *rt;
608: static struct sockaddr_inarp sin = {sizeof(sin), AF_INET };
609:
610: sin.sin_addr.s_addr = addr;
611: sin.sin_other = proxy ? SIN_PROXY : 0;
612: rt = rtalloc1((struct sockaddr *)&sin, create);
613: if (rt == 0)
614: return (0);
615: rt->rt_refcnt--;
616: if ((rt->rt_flags & RTF_GATEWAY) || (rt->rt_flags & RTF_LLINFO) == 0 ||
617: rt->rt_gateway->sa_family != AF_LINK) {
618: if (create)
619: log(LOG_DEBUG, "arplookup: unable to enter address for %x\n", ntohl(addr));
620: return (0);
621: }
622: return ((struct llinfo_arp *)rt->rt_llinfo);
623: }
624:
625: int
626: arpioctl(cmd, data)
627: u_long cmd;
628: caddr_t data;
629: {
630:
631: return (EOPNOTSUPP);
632: }
633:
634: void
635: arp_ifinit(ac, ifa)
636: struct arpcom *ac;
637: struct ifaddr *ifa;
638: {
639: ac->ac_ipaddr = IA_SIN(ifa)->sin_addr;
640: /* Warn the user if another station has this IP address. */
641: arpwhohas(ac, &ac->ac_ipaddr);
642: ifa->ifa_rtrequest = arp_rtrequest;
643: ifa->ifa_flags |= RTF_CLONING;
644: }
645:
646: /*
647: * Called from 10 Mb/s Ethernet interrupt handlers
648: * when ether packet type ETHERTYPE_REVARP
649: * is received. Common length and type checks are done here,
650: * then the protocol-specific routine is called.
651: */
652: void
653: revarpinput(m)
654: struct mbuf *m;
655: {
656: struct arphdr *ar;
657: extern int in_revarpinput(struct mbuf *);
658:
659: if (m->m_len < sizeof(struct arphdr)) {
660: goto out;
661: }
662: ar = mtod(m, struct arphdr *);
663: if (ntohs(ar->ar_hrd) != ARPHRD_ETHER) {
664: goto out;
665: }
666: if (m->m_len < sizeof(struct arphdr) + 2 * (ar->ar_hln + ar->ar_pln)) {
667: goto out;
668: }
669: switch (ntohs(ar->ar_pro)) {
670:
671: case ETHERTYPE_IP:
672: case ETHERTYPE_IPTRAILERS:
673: in_revarpinput(m);
674: return;
675:
676: default:
677: break;
678: }
679: out:
680: m_freem(m);
681: }
682:
683: /*
684: * RARP for Internet protocols on 10 Mb/s Ethernet.
685: * Algorithm is that given in RFC 903.
686: * We are only using for bootstrap purposes to get an ip address for one of
687: * our interfaces. Thus we support no user-interface.
688: *
689: * Since the contents of the RARP reply are specific to the interface that
690: * sent the request, this code must ensure that they are properly associated.
691: *
692: * Note: also supports ARP via RARP packets, per the RFC.
693: */
694: int
695: in_revarpinput(m)
696: struct mbuf *m;
697: {
698: struct ifnet *ifp;
699: struct ether_arp *ar;
700: int op;
701: extern void wakeup (void *);
702:
703: ar = mtod(m, struct ether_arp *);
704: op = ntohs(ar->arp_op);
705: switch (op) {
706: case ARPOP_REQUEST:
707: case ARPOP_REPLY: /* per RFC */
708: in_arpinput(m);
709: return(0);
710: case ARPOP_REVREPLY:
711: break;
712: case ARPOP_REVREQUEST: /* handled by rarpd(8) */
713: default:
714: goto out;
715: }
716: if (!revarp_in_progress)
717: goto out;
718: ifp = m->m_pkthdr.rcvif;
719: if (ifp != myip_ifp) /* !same interface */
720: goto out;
721: if (myip_initialized)
722: goto wake;
723: if (bcmp(ar->arp_tha, ((struct arpcom *)ifp)->ac_enaddr,
724: sizeof(ar->arp_tha)))
725: goto out;
726: bcopy((caddr_t)ar->arp_spa, (caddr_t)&srv_ip, sizeof(srv_ip));
727: bcopy((caddr_t)ar->arp_tpa, (caddr_t)&myip, sizeof(myip));
728: myip_initialized = 1;
729: wake: /* Do wakeup every time in case it was missed. */
730: wakeup((caddr_t)&myip);
731:
732: out:
733: m_freem(m);
734: return(0);
735: }
736:
737: /*
738: * Send a RARP request for the ip address of the specified interface.
739: * The request should be RFC 903-compliant.
740: */
741: void
742: revarprequest(ifp)
743: struct ifnet *ifp;
744: {
745: struct sockaddr sa;
746: struct mbuf *m;
747: struct ether_header *eh;
748: struct ether_arp *ea;
749: struct arpcom *ac = (struct arpcom *)ifp;
750:
751: if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL)
752: return;
753: m->m_len = sizeof(*ea);
754: m->m_pkthdr.len = sizeof(*ea);
755: MH_ALIGN(m, sizeof(*ea));
756: ea = mtod(m, struct ether_arp *);
757: eh = (struct ether_header *)sa.sa_data;
758: bzero((caddr_t)ea, sizeof(*ea));
759: bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
760: sizeof(eh->ether_dhost));
761: eh->ether_type = htons(ETHERTYPE_REVARP);
762: ea->arp_hrd = htons(ARPHRD_ETHER);
763: ea->arp_pro = htons(ETHERTYPE_IP);
764: ea->arp_hln = sizeof(ea->arp_sha); /* hardware address length */
765: ea->arp_pln = sizeof(ea->arp_spa); /* protocol address length */
766: ea->arp_op = htons(ARPOP_REVREQUEST);
767: bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha,
768: sizeof(ea->arp_sha));
769: bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_tha,
770: sizeof(ea->arp_tha));
771: sa.sa_family = AF_UNSPEC;
772: sa.sa_len = sizeof(sa);
773: ifp->if_output(ifp, m, &sa, (struct rtentry *)0);
774: }
775:
776: /*
777: * RARP for the ip address of the specified interface, but also
778: * save the ip address of the server that sent the answer.
779: * Timeout if no response is received.
780: */
781: int
782: revarpwhoarewe(ifp, serv_in, clnt_in)
783: struct ifnet *ifp;
784: struct in_addr *serv_in;
785: struct in_addr *clnt_in;
786: {
787: int result, count = 20;
788: extern int tsleep(void *, int, char *, int);
789:
790: if (myip_initialized)
791: return EIO;
792:
793: myip_ifp = ifp;
794: revarp_in_progress = 1;
795: while (count--) {
796: revarprequest(ifp);
797: result = tsleep((caddr_t)&myip, PSOCK, "revarp", hz/2);
798: if (result != EWOULDBLOCK)
799: break;
800: }
801: revarp_in_progress = 0;
802: if (!myip_initialized)
803: return ENETUNREACH;
804:
805: bcopy((caddr_t)&srv_ip, serv_in, sizeof(*serv_in));
806: bcopy((caddr_t)&myip, clnt_in, sizeof(*clnt_in));
807: return 0;
808: }
809:
810: /* For compatibility: only saves interface address. */
811: int
812: revarpwhoami(in, ifp)
813: struct in_addr *in;
814: struct ifnet *ifp;
815: {
816: struct in_addr server;
817: return (revarpwhoarewe(ifp, &server, in));
818: }
819:
820:
821: #ifdef DDB
822: static void
823: db_print_sa(sa)
824: struct sockaddr *sa;
825: {
826: int len;
827: u_char *p;
828:
829: if (sa == 0) {
830: db_printf("[NULL]");
831: return;
832: }
833:
834: p = (u_char*)sa;
835: len = sa->sa_len;
836: db_printf("[");
837: while (len > 0) {
838: db_printf("%d", *p);
839: p++; len--;
840: if (len) db_printf(",");
841: }
842: db_printf("]\n");
843: }
844: static void
845: db_print_ifa(ifa)
846: struct ifaddr *ifa;
847: {
848: if (ifa == 0)
849: return;
850: db_printf(" ifa_addr=");
851: db_print_sa(ifa->ifa_addr);
852: db_printf(" ifa_dsta=");
853: db_print_sa(ifa->ifa_dstaddr);
854: db_printf(" ifa_mask=");
855: db_print_sa(ifa->ifa_netmask);
856: db_printf(" flags=0x%x,refcnt=%d,metric=%d\n",
857: ifa->ifa_flags,
858: ifa->ifa_refcnt,
859: ifa->ifa_metric);
860: }
861: static void
862: db_print_llinfo(li)
863: caddr_t li;
864: {
865: struct llinfo_arp *la;
866:
867: if (li == 0)
868: return;
869: la = (struct llinfo_arp *)li;
870: db_printf(" la_rt=0x%x la_hold=0x%x, la_asked=0x%x\n",
871: la->la_rt, la->la_hold, la->la_asked);
872: }
873: /*
874: * Function to pass to rn_walktree().
875: * Return non-zero error to abort walk.
876: */
877: static int
878: db_show_radix_node(rn, w)
879: struct radix_node *rn;
880: void *w;
881: {
882: struct rtentry *rt = (struct rtentry *)rn;
883:
884: db_printf("rtentry=0x%x", rt);
885:
886: db_printf(" flags=0x%x refcnt=%d use=%d expire=%d\n",
887: rt->rt_flags, rt->rt_refcnt,
888: rt->rt_use, rt->rt_expire);
889:
890: db_printf(" key="); db_print_sa(rt_key(rt));
891: db_printf(" mask="); db_print_sa(rt_mask(rt));
892: db_printf(" gw="); db_print_sa(rt->rt_gateway);
893:
894: db_printf(" ifp=0x%x ", rt->rt_ifp);
895: if (rt->rt_ifp)
896: db_printf("(%s%d)",
897: rt->rt_ifp->if_name,
898: rt->rt_ifp->if_unit);
899: else
900: db_printf("(NULL)");
901:
902: db_printf(" ifa=0x%x\n", rt->rt_ifa);
903: db_print_ifa(rt->rt_ifa);
904:
905: db_printf(" genmask="); db_print_sa(rt->rt_genmask);
906:
907: db_printf(" gwroute=0x%x llinfo=0x%x\n",
908: rt->rt_gwroute, rt->rt_llinfo);
909: db_print_llinfo(rt->rt_llinfo);
910:
911: return (0);
912: }
913: /*
914: * Function to print all the route trees.
915: * Use this from ddb: "call db_show_arptab"
916: */
917: db_show_arptab()
918: {
919: struct radix_node_head *rnh;
920: rnh = rt_tables[AF_INET];
921: db_printf("Route tree for AF_INET\n");
922: if (rnh == NULL) {
923: db_printf(" (not initialized)\n");
924: return (0);
925: }
926: rn_walktree(rnh, db_show_radix_node, NULL);
927: return (0);
928: }
929: #endif
930: #endif /* INET */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.