Annotation of sys/netinet/if_ether.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_ether.c,v 1.68 2007/03/25 16:43:22 claudio Exp $ */
2: /* $NetBSD: if_ether.c,v 1.31 1996/05/11 12:59:58 mycroft Exp $ */
3:
4: /*
5: * Copyright (c) 1982, 1986, 1988, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. Neither the name of the University nor the names of its contributors
17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: *
32: * @(#)if_ether.c 8.1 (Berkeley) 6/10/93
33: */
34:
35: /*
36: * Ethernet address resolution protocol.
37: * TODO:
38: * add "inuse/lock" bit (or ref. count) along with valid bit
39: */
40:
41: #ifdef INET
42: #include "carp.h"
43:
44: #include "bridge.h"
45:
46: #include <sys/param.h>
47: #include <sys/systm.h>
48: #include <sys/mbuf.h>
49: #include <sys/socket.h>
50: #include <sys/kernel.h>
51: #include <sys/syslog.h>
52: #include <sys/proc.h>
53:
54: #include <net/if.h>
55: #include <net/if_dl.h>
56: #include <net/route.h>
57: #include <net/if_fddi.h>
58: #include <net/if_types.h>
59:
60: #include <netinet/in.h>
61: #include <netinet/in_var.h>
62: #include <netinet/if_ether.h>
63: #if NCARP > 0
64: #include <netinet/ip_carp.h>
65: #endif
66:
67: #define SIN(s) ((struct sockaddr_in *)s)
68: #define SDL(s) ((struct sockaddr_dl *)s)
69: #define SRP(s) ((struct sockaddr_inarp *)s)
70:
71: /*
72: * ARP trailer negotiation. Trailer protocol is not IP specific,
73: * but ARP request/response use IP addresses.
74: */
75: #define ETHERTYPE_IPTRAILERS ETHERTYPE_TRAIL
76:
77: /* timer values */
78: int arpt_prune = (5*60*1); /* walk list every 5 minutes */
79: int arpt_keep = (20*60); /* once resolved, good for 20 more minutes */
80: int arpt_down = 20; /* once declared down, don't send for 20 secs */
81: #define rt_expire rt_rmx.rmx_expire
82:
83: void arptfree(struct llinfo_arp *);
84: void arptimer(void *);
85: struct llinfo_arp *arplookup(u_int32_t, int, int);
86: void in_arpinput(struct mbuf *);
87:
88: LIST_HEAD(, llinfo_arp) llinfo_arp;
89: struct ifqueue arpintrq = {0, 0, 0, 50};
90: int arp_inuse, arp_allocated, arp_intimer;
91: int arp_maxtries = 5;
92: int useloopback = 1; /* use loopback interface for local traffic */
93: int arpinit_done = 0;
94:
95: /* revarp state */
96: struct in_addr myip, srv_ip;
97: int myip_initialized = 0;
98: int revarp_in_progress = 0;
99: struct ifnet *myip_ifp = NULL;
100:
101: #ifdef DDB
102: #include <uvm/uvm_extern.h>
103:
104: void db_print_sa(struct sockaddr *);
105: void db_print_ifa(struct ifaddr *);
106: void db_print_llinfo(caddr_t);
107: int db_show_radix_node(struct radix_node *, void *);
108: #endif
109:
110: /*
111: * Timeout routine. Age arp_tab entries periodically.
112: */
113: /* ARGSUSED */
114: void
115: arptimer(arg)
116: void *arg;
117: {
118: struct timeout *to = (struct timeout *)arg;
119: int s;
120: struct llinfo_arp *la, *nla;
121:
122: s = splsoftnet();
123: timeout_add(to, arpt_prune * hz);
124: for (la = LIST_FIRST(&llinfo_arp); la != LIST_END(&llinfo_arp);
125: la = nla) {
126: struct rtentry *rt = la->la_rt;
127:
128: nla = LIST_NEXT(la, la_list);
129: if (rt->rt_expire && rt->rt_expire <= time_second)
130: arptfree(la); /* timer has expired; clear */
131: }
132: splx(s);
133: }
134:
135: /*
136: * Parallel to llc_rtrequest.
137: */
138: void
139: arp_rtrequest(req, rt, info)
140: int req;
141: struct rtentry *rt;
142: struct rt_addrinfo *info;
143: {
144: struct sockaddr *gate = rt->rt_gateway;
145: struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo;
146: static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
147: struct in_ifaddr *ia;
148: struct ifaddr *ifa;
149:
150: if (!arpinit_done) {
151: static struct timeout arptimer_to;
152:
153: arpinit_done = 1;
154: /*
155: * We generate expiration times from time.tv_sec
156: * so avoid accidently creating permanent routes.
157: */
158: if (time_second == 0) {
159: time_second++;
160: }
161:
162: timeout_set(&arptimer_to, arptimer, &arptimer_to);
163: timeout_add(&arptimer_to, hz);
164: }
165:
166: if (rt->rt_flags & RTF_GATEWAY) {
167: if (req != RTM_ADD)
168: return;
169:
170: /*
171: * linklayers with particular link MTU limitation. it is a bit
172: * awkward to have FDDI handling here, we should split ARP from
173: * netinet/if_ether.c like NetBSD does.
174: */
175: switch (rt->rt_ifp->if_type) {
176: case IFT_FDDI:
177: if (rt->rt_ifp->if_mtu > FDDIIPMTU)
178: rt->rt_rmx.rmx_mtu = FDDIIPMTU;
179: break;
180: }
181:
182: return;
183: }
184:
185: switch (req) {
186:
187: case RTM_ADD:
188: /*
189: * XXX: If this is a manually added route to interface
190: * such as older version of routed or gated might provide,
191: * restore cloning bit.
192: */
193: if ((rt->rt_flags & RTF_HOST) == 0 &&
194: SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff)
195: rt->rt_flags |= RTF_CLONING;
196: if (rt->rt_flags & RTF_CLONING) {
197: /*
198: * Case 1: This route should come from a route to iface.
199: */
200: rt_setgate(rt, rt_key(rt),
201: (struct sockaddr *)&null_sdl, 0);
202: gate = rt->rt_gateway;
203: SDL(gate)->sdl_type = rt->rt_ifp->if_type;
204: SDL(gate)->sdl_index = rt->rt_ifp->if_index;
205: /*
206: * Give this route an expiration time, even though
207: * it's a "permanent" route, so that routes cloned
208: * from it do not need their expiration time set.
209: */
210: rt->rt_expire = time_second;
211: /*
212: * linklayers with particular link MTU limitation.
213: */
214: switch (rt->rt_ifp->if_type) {
215: case IFT_FDDI:
216: if ((rt->rt_rmx.rmx_locks & RTV_MTU) == 0 &&
217: (rt->rt_rmx.rmx_mtu > FDDIIPMTU ||
218: (rt->rt_rmx.rmx_mtu == 0 &&
219: rt->rt_ifp->if_mtu > FDDIIPMTU)))
220: rt->rt_rmx.rmx_mtu = FDDIIPMTU;
221: break;
222: }
223: break;
224: }
225: /* Announce a new entry if requested. */
226: if (rt->rt_flags & RTF_ANNOUNCE)
227: arprequest(rt->rt_ifp,
228: &SIN(rt_key(rt))->sin_addr.s_addr,
229: &SIN(rt_key(rt))->sin_addr.s_addr,
230: (u_char *)LLADDR(SDL(gate)));
231: /*FALLTHROUGH*/
232: case RTM_RESOLVE:
233: if (gate->sa_family != AF_LINK ||
234: gate->sa_len < sizeof(null_sdl)) {
235: log(LOG_DEBUG, "arp_rtrequest: bad gateway value\n");
236: break;
237: }
238: SDL(gate)->sdl_type = rt->rt_ifp->if_type;
239: SDL(gate)->sdl_index = rt->rt_ifp->if_index;
240: if (la != 0)
241: break; /* This happens on a route change */
242: /*
243: * Case 2: This route may come from cloning, or a manual route
244: * add with a LL address.
245: */
246: R_Malloc(la, struct llinfo_arp *, sizeof(*la));
247: rt->rt_llinfo = (caddr_t)la;
248: if (la == 0) {
249: log(LOG_DEBUG, "arp_rtrequest: malloc failed\n");
250: break;
251: }
252: arp_inuse++, arp_allocated++;
253: Bzero(la, sizeof(*la));
254: la->la_rt = rt;
255: rt->rt_flags |= RTF_LLINFO;
256: LIST_INSERT_HEAD(&llinfo_arp, la, la_list);
257:
258: TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
259: if (ia->ia_ifp == rt->rt_ifp &&
260: SIN(rt_key(rt))->sin_addr.s_addr ==
261: (IA_SIN(ia))->sin_addr.s_addr)
262: break;
263: }
264: if (ia) {
265: /*
266: * This test used to be
267: * if (lo0ifp->if_flags & IFF_UP)
268: * It allowed local traffic to be forced through
269: * the hardware by configuring the loopback down.
270: * However, it causes problems during network
271: * configuration for boards that can't receive
272: * packets they send. It is now necessary to clear
273: * "useloopback" and remove the route to force
274: * traffic out to the hardware.
275: *
276: * In 4.4BSD, the above "if" statement checked
277: * rt->rt_ifa against rt_key(rt). It was changed
278: * to the current form so that we can provide a
279: * better support for multiple IPv4 addresses on a
280: * interface.
281: */
282: rt->rt_expire = 0;
283: Bcopy(((struct arpcom *)rt->rt_ifp)->ac_enaddr,
284: LLADDR(SDL(gate)),
285: SDL(gate)->sdl_alen = ETHER_ADDR_LEN);
286: if (useloopback)
287: rt->rt_ifp = lo0ifp;
288: /*
289: * make sure to set rt->rt_ifa to the interface
290: * address we are using, otherwise we will have trouble
291: * with source address selection.
292: */
293: ifa = &ia->ia_ifa;
294: if (ifa != rt->rt_ifa) {
295: IFAFREE(rt->rt_ifa);
296: ifa->ifa_refcnt++;
297: rt->rt_ifa = ifa;
298: }
299: }
300: break;
301:
302: case RTM_DELETE:
303: if (la == 0)
304: break;
305: arp_inuse--;
306: LIST_REMOVE(la, la_list);
307: rt->rt_llinfo = 0;
308: rt->rt_flags &= ~RTF_LLINFO;
309: if (la->la_hold)
310: m_freem(la->la_hold);
311: Free((caddr_t)la);
312: }
313: }
314:
315: /*
316: * Broadcast an ARP request. Caller specifies:
317: * - arp header source ip address
318: * - arp header target ip address
319: * - arp header source ethernet address
320: */
321: void
322: arprequest(ifp, sip, tip, enaddr)
323: struct ifnet *ifp;
324: u_int32_t *sip, *tip;
325: u_int8_t *enaddr;
326: {
327: struct mbuf *m;
328: struct ether_header *eh;
329: struct ether_arp *ea;
330: struct sockaddr sa;
331:
332: if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL)
333: return;
334: m->m_len = sizeof(*ea);
335: m->m_pkthdr.len = sizeof(*ea);
336: MH_ALIGN(m, sizeof(*ea));
337: ea = mtod(m, struct ether_arp *);
338: eh = (struct ether_header *)sa.sa_data;
339: bzero((caddr_t)ea, sizeof (*ea));
340: bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
341: sizeof(eh->ether_dhost));
342: eh->ether_type = htons(ETHERTYPE_ARP); /* if_output will not swap */
343: ea->arp_hrd = htons(ARPHRD_ETHER);
344: ea->arp_pro = htons(ETHERTYPE_IP);
345: ea->arp_hln = sizeof(ea->arp_sha); /* hardware address length */
346: ea->arp_pln = sizeof(ea->arp_spa); /* protocol address length */
347: ea->arp_op = htons(ARPOP_REQUEST);
348: bcopy((caddr_t)enaddr, (caddr_t)eh->ether_shost,
349: sizeof(eh->ether_shost));
350: bcopy((caddr_t)enaddr, (caddr_t)ea->arp_sha, sizeof(ea->arp_sha));
351: bcopy((caddr_t)sip, (caddr_t)ea->arp_spa, sizeof(ea->arp_spa));
352: bcopy((caddr_t)tip, (caddr_t)ea->arp_tpa, sizeof(ea->arp_tpa));
353: sa.sa_family = pseudo_AF_HDRCMPLT;
354: sa.sa_len = sizeof(sa);
355: (*ifp->if_output)(ifp, m, &sa, (struct rtentry *)0);
356: }
357:
358: /*
359: * Resolve an IP address into an ethernet address. If success,
360: * desten is filled in. If there is no entry in arptab,
361: * set one up and broadcast a request for the IP address.
362: * Hold onto this mbuf and resend it once the address
363: * is finally resolved. A return value of 1 indicates
364: * that desten has been filled in and the packet should be sent
365: * normally; a 0 return indicates that the packet has been
366: * taken over here, either now or for later transmission.
367: */
368: int
369: arpresolve(ac, rt, m, dst, desten)
370: struct arpcom *ac;
371: struct rtentry *rt;
372: struct mbuf *m;
373: struct sockaddr *dst;
374: u_char *desten;
375: {
376: struct llinfo_arp *la;
377: struct sockaddr_dl *sdl;
378:
379: if (m->m_flags & M_BCAST) { /* broadcast */
380: bcopy((caddr_t)etherbroadcastaddr, (caddr_t)desten,
381: sizeof(etherbroadcastaddr));
382: return (1);
383: }
384: if (m->m_flags & M_MCAST) { /* multicast */
385: ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten);
386: return (1);
387: }
388: if (rt) {
389: la = (struct llinfo_arp *)rt->rt_llinfo;
390: if (la == NULL)
391: log(LOG_DEBUG, "arpresolve: %s: route without link "
392: "local address\n", inet_ntoa(SIN(dst)->sin_addr));
393: } else {
394: if ((la = arplookup(SIN(dst)->sin_addr.s_addr, 1, 0)) != NULL)
395: rt = la->la_rt;
396: else
397: log(LOG_DEBUG,
398: "arpresolve: %s: can't allocate llinfo\n",
399: inet_ntoa(SIN(dst)->sin_addr));
400: }
401: if (la == 0 || rt == 0) {
402: m_freem(m);
403: return (0);
404: }
405: sdl = SDL(rt->rt_gateway);
406: /*
407: * Check the address family and length is valid, the address
408: * is resolved; otherwise, try to resolve.
409: */
410: if ((rt->rt_expire == 0 || rt->rt_expire > time_second) &&
411: sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) {
412: bcopy(LLADDR(sdl), desten, sdl->sdl_alen);
413: return 1;
414: }
415: if (((struct ifnet *)ac)->if_flags & IFF_NOARP)
416: return 0;
417:
418: /*
419: * There is an arptab entry, but no ethernet address
420: * response yet. Replace the held mbuf with this
421: * latest one.
422: */
423: if (la->la_hold)
424: m_freem(la->la_hold);
425: la->la_hold = m;
426: /*
427: * Re-send the ARP request when appropriate.
428: */
429: #ifdef DIAGNOSTIC
430: if (rt->rt_expire == 0) {
431: /* This should never happen. (Should it? -gwr) */
432: printf("arpresolve: unresolved and rt_expire == 0\n");
433: /* Set expiration time to now (expired). */
434: rt->rt_expire = time_second;
435: }
436: #endif
437: if (rt->rt_expire) {
438: rt->rt_flags &= ~RTF_REJECT;
439: if (la->la_asked == 0 || rt->rt_expire != time_second) {
440: rt->rt_expire = time_second;
441: if (la->la_asked++ < arp_maxtries)
442: arprequest(&ac->ac_if,
443: &(SIN(rt->rt_ifa->ifa_addr)->sin_addr.s_addr),
444: &(SIN(dst)->sin_addr.s_addr),
445: #if NCARP > 0
446: (rt->rt_ifp->if_type == IFT_CARP) ?
447: ((struct arpcom *) rt->rt_ifp->if_softc
448: )->ac_enaddr :
449: #endif
450: ac->ac_enaddr);
451: else {
452: rt->rt_flags |= RTF_REJECT;
453: rt->rt_expire += arpt_down;
454: la->la_asked = 0;
455: }
456: }
457: }
458: return (0);
459: }
460:
461: /*
462: * Common length and type checks are done here,
463: * then the protocol-specific routine is called.
464: */
465: void
466: arpintr()
467: {
468: struct mbuf *m;
469: struct arphdr *ar;
470: int s, len;
471:
472: while (arpintrq.ifq_head) {
473: s = splnet();
474: IF_DEQUEUE(&arpintrq, m);
475: splx(s);
476: if (m == 0 || (m->m_flags & M_PKTHDR) == 0)
477: panic("arpintr");
478:
479: len = sizeof(struct arphdr);
480: if (m->m_len < len && (m = m_pullup(m, len)) == NULL)
481: continue;
482:
483: ar = mtod(m, struct arphdr *);
484: if (ntohs(ar->ar_hrd) != ARPHRD_ETHER) {
485: m_freem(m);
486: continue;
487: }
488:
489: len += 2 * (ar->ar_hln + ar->ar_pln);
490: if (m->m_len < len && (m = m_pullup(m, len)) == NULL)
491: continue;
492:
493: switch (ntohs(ar->ar_pro)) {
494: case ETHERTYPE_IP:
495: case ETHERTYPE_IPTRAILERS:
496: in_arpinput(m);
497: continue;
498: }
499: m_freem(m);
500: }
501: }
502:
503: /*
504: * ARP for Internet protocols on Ethernet.
505: * Algorithm is that given in RFC 826.
506: * In addition, a sanity check is performed on the sender
507: * protocol address, to catch impersonators.
508: * We no longer handle negotiations for use of trailer protocol:
509: * Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent
510: * along with IP replies if we wanted trailers sent to us,
511: * and also sent them in response to IP replies.
512: * This allowed either end to announce the desire to receive
513: * trailer packets.
514: * We no longer reply to requests for ETHERTYPE_TRAIL protocol either,
515: * but formerly didn't normally send requests.
516: */
517: void
518: in_arpinput(m)
519: struct mbuf *m;
520: {
521: struct ether_arp *ea;
522: struct arpcom *ac = (struct arpcom *)m->m_pkthdr.rcvif;
523: struct ether_header *eh;
524: struct llinfo_arp *la = 0;
525: struct rtentry *rt;
526: struct in_ifaddr *ia;
527: #if NBRIDGE > 0
528: struct in_ifaddr *bridge_ia = NULL;
529: #endif
530: #if NCARP > 0
531: u_int32_t count = 0, index = 0;
532: #endif
533: struct sockaddr_dl *sdl;
534: struct sockaddr sa;
535: struct in_addr isaddr, itaddr, myaddr;
536: u_int8_t *enaddr = NULL;
537: int op;
538:
539: ea = mtod(m, struct ether_arp *);
540: op = ntohs(ea->arp_op);
541: if ((op != ARPOP_REQUEST) && (op != ARPOP_REPLY))
542: goto out;
543: #if notyet
544: if ((op == ARPOP_REPLY) && (m->m_flags & (M_BCAST|M_MCAST))) {
545: log(LOG_ERR,
546: "arp: received reply to broadcast or multicast address\n");
547: goto out;
548: }
549: #endif
550:
551: bcopy((caddr_t)ea->arp_tpa, (caddr_t)&itaddr, sizeof(itaddr));
552: bcopy((caddr_t)ea->arp_spa, (caddr_t)&isaddr, sizeof(isaddr));
553:
554: TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
555: if (itaddr.s_addr != ia->ia_addr.sin_addr.s_addr)
556: continue;
557:
558: #if NCARP > 0
559: if (ia->ia_ifp->if_type == IFT_CARP &&
560: ((ia->ia_ifp->if_flags & (IFF_UP|IFF_RUNNING)) ==
561: (IFF_UP|IFF_RUNNING))) {
562: index++;
563: if (ia->ia_ifp == m->m_pkthdr.rcvif &&
564: carp_iamatch(ia, ea->arp_sha,
565: &count, index))
566: break;
567: } else
568: #endif
569: if (ia->ia_ifp == m->m_pkthdr.rcvif)
570: break;
571: #if NBRIDGE > 0
572: /*
573: * If the interface we received the packet on
574: * is part of a bridge, check to see if we need
575: * to "bridge" the packet to ourselves at this
576: * layer. Note we still prefer a perfect match,
577: * but allow this weaker match if necessary.
578: */
579: if (m->m_pkthdr.rcvif->if_bridge != NULL) {
580: if (m->m_pkthdr.rcvif->if_bridge ==
581: ia->ia_ifp->if_bridge)
582: bridge_ia = ia;
583: #if NCARP > 0
584: else if (ia->ia_ifp->if_carpdev != NULL &&
585: m->m_pkthdr.rcvif->if_bridge ==
586: ia->ia_ifp->if_carpdev->if_bridge &&
587: carp_iamatch(ia, ea->arp_sha,
588: &count, index))
589: bridge_ia = ia;
590: #endif
591: }
592: #endif
593: }
594:
595: #if NBRIDGE > 0
596: if (ia == NULL && bridge_ia != NULL) {
597: ia = bridge_ia;
598: ac = (struct arpcom *)bridge_ia->ia_ifp;
599: }
600: #endif
601:
602: if (ia == NULL) {
603: TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
604: if (isaddr.s_addr != ia->ia_addr.sin_addr.s_addr)
605: continue;
606: if (ia->ia_ifp == m->m_pkthdr.rcvif)
607: break;
608: }
609: }
610:
611: if (ia == NULL && m->m_pkthdr.rcvif->if_type != IFT_CARP) {
612: struct ifaddr *ifa;
613:
614: TAILQ_FOREACH(ifa, &m->m_pkthdr.rcvif->if_addrlist, ifa_list) {
615: if (ifa->ifa_addr->sa_family == AF_INET)
616: break;
617: }
618: if (ifa)
619: ia = (struct in_ifaddr *)ifa;
620: }
621:
622: if (ia == NULL)
623: goto out;
624:
625: if (!enaddr)
626: enaddr = ac->ac_enaddr;
627: myaddr = ia->ia_addr.sin_addr;
628:
629: if (!bcmp((caddr_t)ea->arp_sha, enaddr, sizeof (ea->arp_sha)))
630: goto out; /* it's from me, ignore it. */
631: if (ETHER_IS_MULTICAST (&ea->arp_sha[0]))
632: if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)etherbroadcastaddr,
633: sizeof (ea->arp_sha))) {
634: log(LOG_ERR, "arp: ether address is broadcast for "
635: "IP address %s!\n", inet_ntoa(isaddr));
636: goto out;
637: }
638: if (myaddr.s_addr && isaddr.s_addr == myaddr.s_addr) {
639: log(LOG_ERR,
640: "duplicate IP address %s sent from ethernet address %s\n",
641: inet_ntoa(isaddr), ether_sprintf(ea->arp_sha));
642: itaddr = myaddr;
643: goto reply;
644: }
645: la = arplookup(isaddr.s_addr, itaddr.s_addr == myaddr.s_addr, 0);
646: if (la && (rt = la->la_rt) && (sdl = SDL(rt->rt_gateway))) {
647: if (sdl->sdl_alen) {
648: if (bcmp(ea->arp_sha, LLADDR(sdl), sdl->sdl_alen)) {
649: if (rt->rt_flags & RTF_PERMANENT_ARP) {
650: log(LOG_WARNING,
651: "arp: attempt to overwrite permanent "
652: "entry for %s by %s on %s\n",
653: inet_ntoa(isaddr),
654: ether_sprintf(ea->arp_sha),
655: ac->ac_if.if_xname);
656: goto out;
657: } else if (rt->rt_ifp != &ac->ac_if) {
658: log(LOG_WARNING,
659: "arp: attempt to overwrite entry for %s "
660: "on %s by %s on %s\n",
661: inet_ntoa(isaddr), rt->rt_ifp->if_xname,
662: ether_sprintf(ea->arp_sha),
663: ac->ac_if.if_xname);
664: goto out;
665: } else {
666: log(LOG_INFO,
667: "arp info overwritten for %s by %s on %s\n",
668: inet_ntoa(isaddr),
669: ether_sprintf(ea->arp_sha),
670: ac->ac_if.if_xname);
671: rt->rt_expire = 1; /* no longer static */
672: }
673: }
674: } else if (rt->rt_ifp != &ac->ac_if && !(ac->ac_if.if_bridge &&
675: (rt->rt_ifp->if_bridge == ac->ac_if.if_bridge)) &&
676: !(rt->rt_ifp->if_type == IFT_CARP &&
677: rt->rt_ifp->if_carpdev == &ac->ac_if) &&
678: !(ac->ac_if.if_type == IFT_CARP &&
679: ac->ac_if.if_carpdev == rt->rt_ifp)) {
680: log(LOG_WARNING,
681: "arp: attempt to add entry for %s "
682: "on %s by %s on %s\n",
683: inet_ntoa(isaddr), rt->rt_ifp->if_xname,
684: ether_sprintf(ea->arp_sha),
685: ac->ac_if.if_xname);
686: goto out;
687: }
688: bcopy(ea->arp_sha, LLADDR(sdl),
689: sdl->sdl_alen = sizeof(ea->arp_sha));
690: if (rt->rt_expire)
691: rt->rt_expire = time_second + arpt_keep;
692: rt->rt_flags &= ~RTF_REJECT;
693: la->la_asked = 0;
694: if (la->la_hold) {
695: (*ac->ac_if.if_output)(&ac->ac_if, la->la_hold,
696: rt_key(rt), rt);
697: la->la_hold = 0;
698: }
699: }
700: reply:
701: if (op != ARPOP_REQUEST) {
702: out:
703: m_freem(m);
704: return;
705: }
706: if (itaddr.s_addr == myaddr.s_addr) {
707: /* I am the target */
708: bcopy(ea->arp_sha, ea->arp_tha, sizeof(ea->arp_sha));
709: bcopy(enaddr, ea->arp_sha, sizeof(ea->arp_sha));
710: } else {
711: la = arplookup(itaddr.s_addr, 0, SIN_PROXY);
712: if (la == 0)
713: goto out;
714: rt = la->la_rt;
715: if (rt->rt_ifp->if_type == IFT_CARP &&
716: m->m_pkthdr.rcvif->if_type != IFT_CARP)
717: goto out;
718: bcopy(ea->arp_sha, ea->arp_tha, sizeof(ea->arp_sha));
719: sdl = SDL(rt->rt_gateway);
720: bcopy(LLADDR(sdl), ea->arp_sha, sizeof(ea->arp_sha));
721: }
722:
723: bcopy(ea->arp_spa, ea->arp_tpa, sizeof(ea->arp_spa));
724: bcopy(&itaddr, ea->arp_spa, sizeof(ea->arp_spa));
725: ea->arp_op = htons(ARPOP_REPLY);
726: ea->arp_pro = htons(ETHERTYPE_IP); /* let's be sure! */
727: eh = (struct ether_header *)sa.sa_data;
728: bcopy(ea->arp_tha, eh->ether_dhost, sizeof(eh->ether_dhost));
729: #if NCARP > 0
730: if (ac->ac_if.if_type == IFT_CARP && ac->ac_if.if_flags & IFF_LINK1)
731: bcopy(((struct arpcom *)ac->ac_if.if_carpdev)->ac_enaddr,
732: eh->ether_shost, sizeof(eh->ether_shost));
733: else
734: #endif
735: bcopy(enaddr, eh->ether_shost, sizeof(eh->ether_shost));
736:
737: eh->ether_type = htons(ETHERTYPE_ARP);
738: sa.sa_family = pseudo_AF_HDRCMPLT;
739: sa.sa_len = sizeof(sa);
740: (*ac->ac_if.if_output)(&ac->ac_if, m, &sa, (struct rtentry *)0);
741: return;
742: }
743:
744: /*
745: * Free an arp entry.
746: */
747: void
748: arptfree(la)
749: struct llinfo_arp *la;
750: {
751: struct rtentry *rt = la->la_rt;
752: struct sockaddr_dl *sdl;
753:
754: if (rt == 0)
755: panic("arptfree");
756: if (rt->rt_refcnt > 0 && (sdl = SDL(rt->rt_gateway)) &&
757: sdl->sdl_family == AF_LINK) {
758: sdl->sdl_alen = 0;
759: la->la_asked = 0;
760: rt->rt_flags &= ~RTF_REJECT;
761: return;
762: }
763: rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0, rt_mask(rt),
764: 0, (struct rtentry **)0, 0);
765: }
766:
767: /*
768: * Lookup or enter a new address in arptab.
769: */
770: struct llinfo_arp *
771: arplookup(addr, create, proxy)
772: u_int32_t addr;
773: int create, proxy;
774: {
775: struct rtentry *rt;
776: static struct sockaddr_inarp sin;
777:
778: sin.sin_len = sizeof(sin);
779: sin.sin_family = AF_INET;
780: sin.sin_addr.s_addr = addr;
781: sin.sin_other = proxy ? SIN_PROXY : 0;
782: rt = rtalloc1(sintosa(&sin), create, 0);
783: if (rt == 0)
784: return (0);
785: rt->rt_refcnt--;
786: if ((rt->rt_flags & RTF_GATEWAY) || (rt->rt_flags & RTF_LLINFO) == 0 ||
787: rt->rt_gateway->sa_family != AF_LINK) {
788: if (create) {
789: if (rt->rt_refcnt <= 0 &&
790: (rt->rt_flags & RTF_CLONED) != 0) {
791: rtrequest(RTM_DELETE,
792: (struct sockaddr *)rt_key(rt),
793: rt->rt_gateway, rt_mask(rt), rt->rt_flags,
794: 0, 0);
795: }
796: }
797: return (0);
798: }
799: return ((struct llinfo_arp *)rt->rt_llinfo);
800: }
801:
802: int
803: arpioctl(cmd, data)
804: u_long cmd;
805: caddr_t data;
806: {
807:
808: return (EOPNOTSUPP);
809: }
810:
811: void
812: arp_ifinit(ac, ifa)
813: struct arpcom *ac;
814: struct ifaddr *ifa;
815: {
816:
817: /* Warn the user if another station has this IP address. */
818: arprequest(&ac->ac_if,
819: &(IA_SIN(ifa)->sin_addr.s_addr),
820: &(IA_SIN(ifa)->sin_addr.s_addr),
821: ac->ac_enaddr);
822: ifa->ifa_rtrequest = arp_rtrequest;
823: ifa->ifa_flags |= RTF_CLONING;
824: }
825:
826: /*
827: * Called from Ethernet interrupt handlers
828: * when ether packet type ETHERTYPE_REVARP
829: * is received. Common length and type checks are done here,
830: * then the protocol-specific routine is called.
831: */
832: void
833: revarpinput(m)
834: struct mbuf *m;
835: {
836: struct arphdr *ar;
837:
838: if (m->m_len < sizeof(struct arphdr))
839: goto out;
840: ar = mtod(m, struct arphdr *);
841: if (ntohs(ar->ar_hrd) != ARPHRD_ETHER)
842: goto out;
843: if (m->m_len < sizeof(struct arphdr) + 2 * (ar->ar_hln + ar->ar_pln))
844: goto out;
845: switch (ntohs(ar->ar_pro)) {
846:
847: case ETHERTYPE_IP:
848: case ETHERTYPE_IPTRAILERS:
849: in_revarpinput(m);
850: return;
851:
852: default:
853: break;
854: }
855: out:
856: m_freem(m);
857: }
858:
859: /*
860: * RARP for Internet protocols on Ethernet.
861: * Algorithm is that given in RFC 903.
862: * We are only using for bootstrap purposes to get an ip address for one of
863: * our interfaces. Thus we support no user-interface.
864: *
865: * Since the contents of the RARP reply are specific to the interface that
866: * sent the request, this code must ensure that they are properly associated.
867: *
868: * Note: also supports ARP via RARP packets, per the RFC.
869: */
870: void
871: in_revarpinput(m)
872: struct mbuf *m;
873: {
874: struct ifnet *ifp;
875: struct ether_arp *ar;
876: int op;
877:
878: ar = mtod(m, struct ether_arp *);
879: op = ntohs(ar->arp_op);
880: switch (op) {
881: case ARPOP_REQUEST:
882: case ARPOP_REPLY: /* per RFC */
883: in_arpinput(m);
884: return;
885: case ARPOP_REVREPLY:
886: break;
887: case ARPOP_REVREQUEST: /* handled by rarpd(8) */
888: default:
889: goto out;
890: }
891: if (!revarp_in_progress)
892: goto out;
893: ifp = m->m_pkthdr.rcvif;
894: if (ifp != myip_ifp) /* !same interface */
895: goto out;
896: if (myip_initialized)
897: goto wake;
898: if (bcmp(ar->arp_tha, ((struct arpcom *)ifp)->ac_enaddr,
899: sizeof(ar->arp_tha)))
900: goto out;
901: bcopy((caddr_t)ar->arp_spa, (caddr_t)&srv_ip, sizeof(srv_ip));
902: bcopy((caddr_t)ar->arp_tpa, (caddr_t)&myip, sizeof(myip));
903: myip_initialized = 1;
904: wake: /* Do wakeup every time in case it was missed. */
905: wakeup((caddr_t)&myip);
906:
907: out:
908: m_freem(m);
909: }
910:
911: /*
912: * Send a RARP request for the ip address of the specified interface.
913: * The request should be RFC 903-compliant.
914: */
915: void
916: revarprequest(ifp)
917: struct ifnet *ifp;
918: {
919: struct sockaddr sa;
920: struct mbuf *m;
921: struct ether_header *eh;
922: struct ether_arp *ea;
923: struct arpcom *ac = (struct arpcom *)ifp;
924:
925: if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL)
926: return;
927: m->m_len = sizeof(*ea);
928: m->m_pkthdr.len = sizeof(*ea);
929: MH_ALIGN(m, sizeof(*ea));
930: ea = mtod(m, struct ether_arp *);
931: eh = (struct ether_header *)sa.sa_data;
932: bzero((caddr_t)ea, sizeof(*ea));
933: bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
934: sizeof(eh->ether_dhost));
935: eh->ether_type = htons(ETHERTYPE_REVARP);
936: ea->arp_hrd = htons(ARPHRD_ETHER);
937: ea->arp_pro = htons(ETHERTYPE_IP);
938: ea->arp_hln = sizeof(ea->arp_sha); /* hardware address length */
939: ea->arp_pln = sizeof(ea->arp_spa); /* protocol address length */
940: ea->arp_op = htons(ARPOP_REVREQUEST);
941: bcopy((caddr_t)ac->ac_enaddr, (caddr_t)eh->ether_shost,
942: sizeof(ea->arp_tha));
943: bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha,
944: sizeof(ea->arp_sha));
945: bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_tha,
946: sizeof(ea->arp_tha));
947: sa.sa_family = pseudo_AF_HDRCMPLT;
948: sa.sa_len = sizeof(sa);
949: ifp->if_output(ifp, m, &sa, (struct rtentry *)0);
950: }
951:
952: /*
953: * RARP for the ip address of the specified interface, but also
954: * save the ip address of the server that sent the answer.
955: * Timeout if no response is received.
956: */
957: int
958: revarpwhoarewe(ifp, serv_in, clnt_in)
959: struct ifnet *ifp;
960: struct in_addr *serv_in;
961: struct in_addr *clnt_in;
962: {
963: int result, count = 20;
964:
965: if (myip_initialized)
966: return EIO;
967:
968: myip_ifp = ifp;
969: revarp_in_progress = 1;
970: while (count--) {
971: revarprequest(ifp);
972: result = tsleep((caddr_t)&myip, PSOCK, "revarp", hz/2);
973: if (result != EWOULDBLOCK)
974: break;
975: }
976: revarp_in_progress = 0;
977: if (!myip_initialized)
978: return ENETUNREACH;
979:
980: bcopy((caddr_t)&srv_ip, serv_in, sizeof(*serv_in));
981: bcopy((caddr_t)&myip, clnt_in, sizeof(*clnt_in));
982: return 0;
983: }
984:
985: /* For compatibility: only saves interface address. */
986: int
987: revarpwhoami(in, ifp)
988: struct in_addr *in;
989: struct ifnet *ifp;
990: {
991: struct in_addr server;
992: return (revarpwhoarewe(ifp, &server, in));
993: }
994:
995:
996: #ifdef DDB
997:
998: #include <machine/db_machdep.h>
999: #include <ddb/db_interface.h>
1000: #include <ddb/db_output.h>
1001:
1002: void
1003: db_print_sa(sa)
1004: struct sockaddr *sa;
1005: {
1006: int len;
1007: u_char *p;
1008:
1009: if (sa == 0) {
1010: db_printf("[NULL]");
1011: return;
1012: }
1013:
1014: p = (u_char *)sa;
1015: len = sa->sa_len;
1016: db_printf("[");
1017: while (len > 0) {
1018: db_printf("%d", *p);
1019: p++;
1020: len--;
1021: if (len)
1022: db_printf(",");
1023: }
1024: db_printf("]\n");
1025: }
1026:
1027: void
1028: db_print_ifa(ifa)
1029: struct ifaddr *ifa;
1030: {
1031: if (ifa == 0)
1032: return;
1033: db_printf(" ifa_addr=");
1034: db_print_sa(ifa->ifa_addr);
1035: db_printf(" ifa_dsta=");
1036: db_print_sa(ifa->ifa_dstaddr);
1037: db_printf(" ifa_mask=");
1038: db_print_sa(ifa->ifa_netmask);
1039: db_printf(" flags=0x%x, refcnt=%d, metric=%d\n",
1040: ifa->ifa_flags, ifa->ifa_refcnt, ifa->ifa_metric);
1041: }
1042:
1043: void
1044: db_print_llinfo(li)
1045: caddr_t li;
1046: {
1047: struct llinfo_arp *la;
1048:
1049: if (li == 0)
1050: return;
1051: la = (struct llinfo_arp *)li;
1052: db_printf(" la_rt=%p la_hold=%p, la_asked=0x%lx\n",
1053: la->la_rt, la->la_hold, la->la_asked);
1054: }
1055:
1056: /*
1057: * Function to pass to rn_walktree().
1058: * Return non-zero error to abort walk.
1059: */
1060: int
1061: db_show_radix_node(rn, w)
1062: struct radix_node *rn;
1063: void *w;
1064: {
1065: struct rtentry *rt = (struct rtentry *)rn;
1066:
1067: db_printf("rtentry=%p", rt);
1068:
1069: db_printf(" flags=0x%x refcnt=%d use=%ld expire=%ld\n",
1070: rt->rt_flags, rt->rt_refcnt, rt->rt_use, rt->rt_expire);
1071:
1072: db_printf(" key="); db_print_sa(rt_key(rt));
1073: db_printf(" mask="); db_print_sa(rt_mask(rt));
1074: db_printf(" gw="); db_print_sa(rt->rt_gateway);
1075:
1076: db_printf(" ifp=%p ", rt->rt_ifp);
1077: if (rt->rt_ifp)
1078: db_printf("(%s)", rt->rt_ifp->if_xname);
1079: else
1080: db_printf("(NULL)");
1081:
1082: db_printf(" ifa=%p\n", rt->rt_ifa);
1083: db_print_ifa(rt->rt_ifa);
1084:
1085: db_printf(" genmask="); db_print_sa(rt->rt_genmask);
1086:
1087: db_printf(" gwroute=%p llinfo=%p\n", rt->rt_gwroute, rt->rt_llinfo);
1088: db_print_llinfo(rt->rt_llinfo);
1089: return (0);
1090: }
1091:
1092: /*
1093: * Function to print all the route trees.
1094: * Use this from ddb: "call db_show_arptab"
1095: */
1096: int
1097: db_show_arptab()
1098: {
1099: struct radix_node_head *rnh;
1100: rnh = rt_gettable(AF_INET, 0);
1101: db_printf("Route tree for AF_INET\n");
1102: if (rnh == NULL) {
1103: db_printf(" (not initialized)\n");
1104: return (0);
1105: }
1106: rn_walktree(rnh, db_show_radix_node, NULL);
1107: return (0);
1108: }
1109: #endif
1110: #endif /* INET */
CVSweb