Line data Source code
1 : /* $OpenBSD: if_ether.c,v 1.236 2018/06/11 08:48:54 mpi 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 : #include "carp.h"
42 :
43 : #include <sys/param.h>
44 : #include <sys/systm.h>
45 : #include <sys/mbuf.h>
46 : #include <sys/socket.h>
47 : #include <sys/timeout.h>
48 : #include <sys/kernel.h>
49 : #include <sys/syslog.h>
50 : #include <sys/queue.h>
51 : #include <sys/pool.h>
52 :
53 : #include <net/if.h>
54 : #include <net/if_var.h>
55 : #include <net/if_dl.h>
56 : #include <net/route.h>
57 : #include <net/if_types.h>
58 : #include <net/netisr.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 : struct llinfo_arp {
68 : LIST_ENTRY(llinfo_arp) la_list;
69 : struct rtentry *la_rt; /* backpointer to rtentry */
70 : long la_asked; /* last time we QUERIED */
71 : struct mbuf_list la_ml; /* packet hold queue */
72 : };
73 : #define LA_HOLD_QUEUE 10
74 : #define LA_HOLD_TOTAL 100
75 :
76 : /* timer values */
77 : int arpt_prune = (5 * 60); /* walk list every 5 minutes */
78 : int arpt_keep = (20 * 60); /* once resolved, cache for 20 minutes */
79 : int arpt_down = 20; /* once declared down, don't send for 20 secs */
80 :
81 : struct mbuf *arppullup(struct mbuf *m);
82 : void arpinvalidate(struct rtentry *);
83 : void arptfree(struct rtentry *);
84 : void arptimer(void *);
85 : struct rtentry *arplookup(struct in_addr *, int, int, unsigned int);
86 : void in_arpinput(struct ifnet *, struct mbuf *);
87 : void in_revarpinput(struct ifnet *, struct mbuf *);
88 : int arpcache(struct ifnet *, struct ether_arp *, struct rtentry *);
89 : void arpreply(struct ifnet *, struct mbuf *, struct in_addr *, uint8_t *,
90 : unsigned int);
91 :
92 : struct niqueue arpinq = NIQUEUE_INITIALIZER(50, NETISR_ARP);
93 :
94 : LIST_HEAD(, llinfo_arp) arp_list;
95 : struct pool arp_pool; /* pool for llinfo_arp structures */
96 : int arp_maxtries = 5;
97 : int arpinit_done;
98 : int la_hold_total;
99 :
100 : #ifdef NFSCLIENT
101 : /* revarp state */
102 : struct in_addr revarp_myip, revarp_srvip;
103 : int revarp_finished;
104 : unsigned int revarp_ifidx;
105 : #endif /* NFSCLIENT */
106 :
107 : /*
108 : * Timeout routine. Age arp_tab entries periodically.
109 : */
110 : /* ARGSUSED */
111 : void
112 0 : arptimer(void *arg)
113 : {
114 0 : struct timeout *to = (struct timeout *)arg;
115 : struct llinfo_arp *la, *nla;
116 :
117 0 : NET_LOCK();
118 0 : timeout_add_sec(to, arpt_prune);
119 0 : LIST_FOREACH_SAFE(la, &arp_list, la_list, nla) {
120 0 : struct rtentry *rt = la->la_rt;
121 :
122 0 : if (rt->rt_expire && rt->rt_expire <= time_uptime)
123 0 : arptfree(rt); /* timer has expired; clear */
124 : }
125 0 : NET_UNLOCK();
126 0 : }
127 :
128 : void
129 0 : arp_rtrequest(struct ifnet *ifp, int req, struct rtentry *rt)
130 : {
131 0 : struct sockaddr *gate = rt->rt_gateway;
132 0 : struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo;
133 : struct ifaddr *ifa;
134 :
135 0 : if (!arpinit_done) {
136 : static struct timeout arptimer_to;
137 :
138 0 : arpinit_done = 1;
139 0 : pool_init(&arp_pool, sizeof(struct llinfo_arp), 0,
140 : IPL_SOFTNET, 0, "arp", NULL);
141 :
142 0 : timeout_set_proc(&arptimer_to, arptimer, &arptimer_to);
143 0 : timeout_add_sec(&arptimer_to, 1);
144 0 : }
145 :
146 0 : if (ISSET(rt->rt_flags, RTF_GATEWAY|RTF_BROADCAST|RTF_MULTICAST))
147 0 : return;
148 :
149 0 : switch (req) {
150 :
151 : case RTM_ADD:
152 0 : if (rt->rt_flags & RTF_CLONING ||
153 0 : ((rt->rt_flags & (RTF_LLINFO | RTF_LOCAL)) && !la)) {
154 : /*
155 : * Give this route an expiration time, even though
156 : * it's a "permanent" route, so that routes cloned
157 : * from it do not need their expiration time set.
158 : */
159 0 : rt->rt_expire = time_uptime;
160 0 : if ((rt->rt_flags & RTF_CLONING) != 0)
161 : break;
162 : }
163 : /*
164 : * Announce a new entry if requested or warn the user
165 : * if another station has this IP address.
166 : */
167 0 : if (rt->rt_flags & (RTF_ANNOUNCE|RTF_LOCAL))
168 0 : arprequest(ifp,
169 0 : &satosin(rt_key(rt))->sin_addr.s_addr,
170 0 : &satosin(rt_key(rt))->sin_addr.s_addr,
171 0 : (u_char *)LLADDR(satosdl(gate)));
172 : /*FALLTHROUGH*/
173 : case RTM_RESOLVE:
174 0 : if (gate->sa_family != AF_LINK ||
175 0 : gate->sa_len < sizeof(struct sockaddr_dl)) {
176 0 : log(LOG_DEBUG, "%s: bad gateway value: %s\n", __func__,
177 0 : ifp->if_xname);
178 0 : break;
179 : }
180 0 : satosdl(gate)->sdl_type = ifp->if_type;
181 0 : satosdl(gate)->sdl_index = ifp->if_index;
182 0 : if (la != 0)
183 : break; /* This happens on a route change */
184 : /*
185 : * Case 2: This route may come from cloning, or a manual route
186 : * add with a LL address.
187 : */
188 0 : la = pool_get(&arp_pool, PR_NOWAIT | PR_ZERO);
189 0 : rt->rt_llinfo = (caddr_t)la;
190 0 : if (la == NULL) {
191 0 : log(LOG_DEBUG, "%s: pool get failed\n", __func__);
192 0 : break;
193 : }
194 :
195 0 : ml_init(&la->la_ml);
196 0 : la->la_rt = rt;
197 0 : rt->rt_flags |= RTF_LLINFO;
198 0 : LIST_INSERT_HEAD(&arp_list, la, la_list);
199 :
200 0 : TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
201 0 : if ((ifa->ifa_addr->sa_family == AF_INET) &&
202 0 : ifatoia(ifa)->ia_addr.sin_addr.s_addr ==
203 0 : satosin(rt_key(rt))->sin_addr.s_addr)
204 : break;
205 : }
206 0 : if (ifa) {
207 0 : KASSERT(ifa == rt->rt_ifa);
208 0 : rt->rt_expire = 0;
209 0 : }
210 : break;
211 :
212 : case RTM_DELETE:
213 0 : if (la == NULL)
214 : break;
215 0 : LIST_REMOVE(la, la_list);
216 0 : rt->rt_llinfo = NULL;
217 0 : rt->rt_flags &= ~RTF_LLINFO;
218 0 : la_hold_total -= ml_purge(&la->la_ml);
219 0 : pool_put(&arp_pool, la);
220 0 : break;
221 :
222 : case RTM_INVALIDATE:
223 0 : if (!ISSET(rt->rt_flags, RTF_LOCAL))
224 0 : arpinvalidate(rt);
225 : break;
226 : }
227 0 : }
228 :
229 : /*
230 : * Broadcast an ARP request. Caller specifies:
231 : * - arp header source ip address
232 : * - arp header target ip address
233 : * - arp header source ethernet address
234 : */
235 : void
236 0 : arprequest(struct ifnet *ifp, u_int32_t *sip, u_int32_t *tip, u_int8_t *enaddr)
237 : {
238 : struct mbuf *m;
239 : struct ether_header *eh;
240 : struct ether_arp *ea;
241 0 : struct sockaddr sa;
242 :
243 0 : if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL)
244 0 : return;
245 0 : m->m_len = sizeof(*ea);
246 0 : m->m_pkthdr.len = sizeof(*ea);
247 0 : m->m_pkthdr.ph_rtableid = ifp->if_rdomain;
248 0 : m->m_pkthdr.pf.prio = ifp->if_llprio;
249 0 : MH_ALIGN(m, sizeof(*ea));
250 0 : ea = mtod(m, struct ether_arp *);
251 0 : eh = (struct ether_header *)sa.sa_data;
252 0 : memset(ea, 0, sizeof(*ea));
253 0 : memcpy(eh->ether_dhost, etherbroadcastaddr, sizeof(eh->ether_dhost));
254 0 : eh->ether_type = htons(ETHERTYPE_ARP); /* if_output will not swap */
255 0 : ea->arp_hrd = htons(ARPHRD_ETHER);
256 0 : ea->arp_pro = htons(ETHERTYPE_IP);
257 0 : ea->arp_hln = sizeof(ea->arp_sha); /* hardware address length */
258 0 : ea->arp_pln = sizeof(ea->arp_spa); /* protocol address length */
259 0 : ea->arp_op = htons(ARPOP_REQUEST);
260 0 : memcpy(eh->ether_shost, enaddr, sizeof(eh->ether_shost));
261 0 : memcpy(ea->arp_sha, enaddr, sizeof(ea->arp_sha));
262 0 : memcpy(ea->arp_spa, sip, sizeof(ea->arp_spa));
263 0 : memcpy(ea->arp_tpa, tip, sizeof(ea->arp_tpa));
264 0 : sa.sa_family = pseudo_AF_HDRCMPLT;
265 0 : sa.sa_len = sizeof(sa);
266 0 : m->m_flags |= M_BCAST;
267 0 : ifp->if_output(ifp, m, &sa, NULL);
268 0 : }
269 :
270 : void
271 0 : arpreply(struct ifnet *ifp, struct mbuf *m, struct in_addr *sip, uint8_t *eaddr,
272 : unsigned int rdomain)
273 : {
274 : struct ether_header *eh;
275 : struct ether_arp *ea;
276 0 : struct sockaddr sa;
277 :
278 0 : m_resethdr(m);
279 0 : m->m_pkthdr.ph_rtableid = rdomain;
280 :
281 0 : ea = mtod(m, struct ether_arp *);
282 0 : ea->arp_op = htons(ARPOP_REPLY);
283 0 : ea->arp_pro = htons(ETHERTYPE_IP); /* let's be sure! */
284 :
285 : /* We're replying to a request. */
286 0 : memcpy(ea->arp_tha, ea->arp_sha, sizeof(ea->arp_sha));
287 0 : memcpy(ea->arp_tpa, ea->arp_spa, sizeof(ea->arp_spa));
288 :
289 0 : memcpy(ea->arp_sha, eaddr, sizeof(ea->arp_sha));
290 0 : memcpy(ea->arp_spa, sip, sizeof(ea->arp_spa));
291 :
292 0 : eh = (struct ether_header *)sa.sa_data;
293 0 : memcpy(eh->ether_dhost, ea->arp_tha, sizeof(eh->ether_dhost));
294 0 : memcpy(eh->ether_shost, eaddr, sizeof(eh->ether_shost));
295 0 : eh->ether_type = htons(ETHERTYPE_ARP);
296 0 : sa.sa_family = pseudo_AF_HDRCMPLT;
297 0 : sa.sa_len = sizeof(sa);
298 0 : ifp->if_output(ifp, m, &sa, NULL);
299 0 : }
300 :
301 : /*
302 : * Resolve an IP address into an ethernet address. If success,
303 : * desten is filled in. If there is no entry in arptab,
304 : * set one up and broadcast a request for the IP address.
305 : * Hold onto this mbuf and resend it once the address
306 : * is finally resolved. A return value of 0 indicates
307 : * that desten has been filled in and the packet should be sent
308 : * normally; A return value of EAGAIN indicates that the packet
309 : * has been taken over here, either now or for later transmission.
310 : * Any other return value indicates an error.
311 : */
312 : int
313 0 : arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
314 : struct sockaddr *dst, u_char *desten)
315 : {
316 0 : struct arpcom *ac = (struct arpcom *)ifp;
317 : struct llinfo_arp *la = NULL;
318 : struct sockaddr_dl *sdl;
319 : struct rtentry *rt = NULL;
320 0 : char addr[INET_ADDRSTRLEN];
321 :
322 0 : if (m->m_flags & M_BCAST) { /* broadcast */
323 0 : memcpy(desten, etherbroadcastaddr, sizeof(etherbroadcastaddr));
324 0 : return (0);
325 : }
326 0 : if (m->m_flags & M_MCAST) { /* multicast */
327 0 : ETHER_MAP_IP_MULTICAST(&satosin(dst)->sin_addr, desten);
328 0 : return (0);
329 : }
330 :
331 0 : rt = rt_getll(rt0);
332 :
333 0 : if (ISSET(rt->rt_flags, RTF_REJECT) &&
334 0 : (rt->rt_expire == 0 || time_uptime < rt->rt_expire)) {
335 0 : m_freem(m);
336 0 : return (rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
337 : }
338 :
339 0 : if (!ISSET(rt->rt_flags, RTF_LLINFO)) {
340 0 : log(LOG_DEBUG, "%s: %s: route contains no arp information\n",
341 0 : __func__, inet_ntop(AF_INET, &satosin(rt_key(rt))->sin_addr,
342 0 : addr, sizeof(addr)));
343 0 : m_freem(m);
344 0 : return (EINVAL);
345 : }
346 :
347 0 : sdl = satosdl(rt->rt_gateway);
348 0 : if (sdl->sdl_alen > 0 && sdl->sdl_alen != ETHER_ADDR_LEN) {
349 0 : log(LOG_DEBUG, "%s: %s: incorrect arp information\n", __func__,
350 0 : inet_ntop(AF_INET, &satosin(dst)->sin_addr,
351 0 : addr, sizeof(addr)));
352 0 : goto bad;
353 : }
354 :
355 : /*
356 : * Check the address family and length is valid, the address
357 : * is resolved; otherwise, try to resolve.
358 : */
359 0 : if ((rt->rt_expire == 0 || rt->rt_expire > time_uptime) &&
360 0 : sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) {
361 0 : memcpy(desten, LLADDR(sdl), sdl->sdl_alen);
362 0 : return (0);
363 : }
364 :
365 0 : if (ifp->if_flags & (IFF_NOARP|IFF_STATICARP))
366 : goto bad;
367 :
368 : /*
369 : * There is an arptab entry, but no ethernet address
370 : * response yet. Insert mbuf in hold queue if below limit
371 : * if above the limit free the queue without queuing the new packet.
372 : */
373 0 : la = (struct llinfo_arp *)rt->rt_llinfo;
374 0 : KASSERT(la != NULL);
375 0 : if (la_hold_total < LA_HOLD_TOTAL && la_hold_total < nmbclust / 64) {
376 : struct mbuf *mh;
377 :
378 0 : if (ml_len(&la->la_ml) >= LA_HOLD_QUEUE) {
379 0 : mh = ml_dequeue(&la->la_ml);
380 0 : la_hold_total--;
381 0 : m_freem(mh);
382 0 : }
383 0 : ml_enqueue(&la->la_ml, m);
384 0 : la_hold_total++;
385 0 : } else {
386 0 : la_hold_total -= ml_purge(&la->la_ml);
387 0 : m_freem(m);
388 : }
389 :
390 : /*
391 : * Re-send the ARP request when appropriate.
392 : */
393 : #ifdef DIAGNOSTIC
394 0 : if (rt->rt_expire == 0) {
395 : /* This should never happen. (Should it? -gwr) */
396 0 : printf("%s: unresolved and rt_expire == 0\n", __func__);
397 : /* Set expiration time to now (expired). */
398 0 : rt->rt_expire = time_uptime;
399 0 : }
400 : #endif
401 0 : if (rt->rt_expire) {
402 0 : rt->rt_flags &= ~RTF_REJECT;
403 0 : if (la->la_asked == 0 || rt->rt_expire != time_uptime) {
404 0 : rt->rt_expire = time_uptime;
405 0 : if (la->la_asked++ < arp_maxtries)
406 0 : arprequest(ifp,
407 0 : &satosin(rt->rt_ifa->ifa_addr)->sin_addr.s_addr,
408 0 : &satosin(dst)->sin_addr.s_addr,
409 0 : ac->ac_enaddr);
410 : else {
411 0 : rt->rt_flags |= RTF_REJECT;
412 0 : rt->rt_expire += arpt_down;
413 0 : la->la_asked = 0;
414 0 : la_hold_total -= ml_purge(&la->la_ml);
415 : }
416 : }
417 : }
418 :
419 0 : return (EAGAIN);
420 :
421 : bad:
422 0 : m_freem(m);
423 0 : return (EINVAL);
424 0 : }
425 :
426 : struct mbuf *
427 0 : arppullup(struct mbuf *m)
428 : {
429 : struct arphdr *ar;
430 : int len;
431 :
432 : #ifdef DIAGNOSTIC
433 0 : if ((m->m_flags & M_PKTHDR) == 0)
434 0 : panic("arp without packet header");
435 : #endif
436 :
437 : len = sizeof(struct arphdr);
438 0 : if (m->m_len < len && (m = m_pullup(m, len)) == NULL)
439 0 : return NULL;
440 :
441 0 : ar = mtod(m, struct arphdr *);
442 0 : if (ntohs(ar->ar_hrd) != ARPHRD_ETHER ||
443 0 : ntohs(ar->ar_pro) != ETHERTYPE_IP ||
444 0 : ar->ar_hln != ETHER_ADDR_LEN ||
445 0 : ar->ar_pln != sizeof(struct in_addr)) {
446 0 : m_freem(m);
447 0 : return NULL;
448 : }
449 :
450 0 : len += 2 * (ar->ar_hln + ar->ar_pln);
451 0 : if (m->m_len < len && (m = m_pullup(m, len)) == NULL)
452 0 : return NULL;
453 :
454 0 : return m;
455 0 : }
456 :
457 : /*
458 : * Common length and type checks are done here,
459 : * then the protocol-specific routine is called.
460 : */
461 : void
462 0 : arpinput(struct ifnet *ifp, struct mbuf *m)
463 : {
464 0 : if ((m = arppullup(m)) == NULL)
465 : return;
466 0 : niq_enqueue(&arpinq, m);
467 0 : }
468 :
469 : void
470 0 : arpintr(void)
471 : {
472 0 : struct mbuf_list ml;
473 : struct mbuf *m;
474 : struct ifnet *ifp;
475 :
476 0 : niq_delist(&arpinq, &ml);
477 :
478 0 : while ((m = ml_dequeue(&ml)) != NULL) {
479 0 : ifp = if_get(m->m_pkthdr.ph_ifidx);
480 :
481 0 : if (ifp != NULL)
482 0 : in_arpinput(ifp, m);
483 : else
484 0 : m_freem(m);
485 :
486 0 : if_put(ifp);
487 : }
488 0 : }
489 :
490 : /*
491 : * ARP for Internet protocols on Ethernet, RFC 826.
492 : * In addition, a sanity check is performed on the sender
493 : * protocol address, to catch impersonators.
494 : */
495 : void
496 0 : in_arpinput(struct ifnet *ifp, struct mbuf *m)
497 : {
498 : struct ether_arp *ea;
499 : struct rtentry *rt = NULL;
500 0 : struct sockaddr_in sin;
501 0 : struct in_addr isaddr, itaddr;
502 0 : char addr[INET_ADDRSTRLEN];
503 : int op, target = 0;
504 : unsigned int rdomain;
505 :
506 0 : rdomain = rtable_l2(m->m_pkthdr.ph_rtableid);
507 :
508 0 : ea = mtod(m, struct ether_arp *);
509 0 : op = ntohs(ea->arp_op);
510 0 : if ((op != ARPOP_REQUEST) && (op != ARPOP_REPLY))
511 : goto out;
512 :
513 0 : memcpy(&itaddr, ea->arp_tpa, sizeof(itaddr));
514 0 : memcpy(&isaddr, ea->arp_spa, sizeof(isaddr));
515 0 : memset(&sin, 0, sizeof(sin));
516 0 : sin.sin_len = sizeof(sin);
517 0 : sin.sin_family = AF_INET;
518 :
519 0 : if (ETHER_IS_MULTICAST(&ea->arp_sha[0]) &&
520 0 : !memcmp(ea->arp_sha, etherbroadcastaddr, sizeof(ea->arp_sha))) {
521 0 : inet_ntop(AF_INET, &isaddr, addr, sizeof(addr));
522 0 : log(LOG_ERR, "arp: ether address is broadcast for IP address "
523 : "%s!\n", addr);
524 0 : goto out;
525 : }
526 :
527 0 : if (!memcmp(ea->arp_sha, LLADDR(ifp->if_sadl), sizeof(ea->arp_sha)))
528 : goto out; /* it's from me, ignore it. */
529 :
530 : /* Check target against our interface addresses. */
531 0 : sin.sin_addr = itaddr;
532 0 : rt = rtalloc(sintosa(&sin), 0, rdomain);
533 0 : if (rtisvalid(rt) && ISSET(rt->rt_flags, RTF_LOCAL) &&
534 0 : rt->rt_ifidx == ifp->if_index)
535 0 : target = 1;
536 0 : rtfree(rt);
537 : rt = NULL;
538 :
539 : #if NCARP > 0
540 0 : if (target && op == ARPOP_REQUEST && ifp->if_type == IFT_CARP &&
541 0 : !carp_iamatch(ifp))
542 : goto out;
543 : #endif
544 :
545 : /* Do we have an ARP cache for the sender? Create if we are target. */
546 0 : rt = arplookup(&isaddr, target, 0, rdomain);
547 :
548 : /* Check sender against our interface addresses. */
549 0 : if (rtisvalid(rt) && ISSET(rt->rt_flags, RTF_LOCAL) &&
550 0 : rt->rt_ifidx == ifp->if_index && isaddr.s_addr != INADDR_ANY) {
551 0 : inet_ntop(AF_INET, &isaddr, addr, sizeof(addr));
552 0 : log(LOG_ERR, "duplicate IP address %s sent from ethernet "
553 0 : "address %s\n", addr, ether_sprintf(ea->arp_sha));
554 0 : itaddr = isaddr;
555 0 : } else if (rt != NULL) {
556 : int error;
557 :
558 0 : KERNEL_LOCK();
559 0 : error = arpcache(ifp, ea, rt);
560 0 : KERNEL_UNLOCK();
561 0 : if (error)
562 0 : goto out;
563 0 : }
564 :
565 0 : if (op == ARPOP_REQUEST) {
566 : uint8_t *eaddr;
567 :
568 0 : if (target) {
569 : /* We already have all info for the reply */
570 0 : eaddr = LLADDR(ifp->if_sadl);
571 0 : } else {
572 0 : rtfree(rt);
573 0 : rt = arplookup(&itaddr, 0, SIN_PROXY, rdomain);
574 : /*
575 : * Protect from possible duplicates, only owner
576 : * should respond
577 : */
578 0 : if ((rt == NULL) || (rt->rt_ifidx != ifp->if_index))
579 0 : goto out;
580 0 : eaddr = LLADDR(satosdl(rt->rt_gateway));
581 : }
582 0 : arpreply(ifp, m, &itaddr, eaddr, rdomain);
583 0 : rtfree(rt);
584 0 : return;
585 : }
586 :
587 : out:
588 0 : rtfree(rt);
589 0 : m_freem(m);
590 0 : }
591 :
592 : int
593 0 : arpcache(struct ifnet *ifp, struct ether_arp *ea, struct rtentry *rt)
594 : {
595 0 : struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo;
596 0 : struct sockaddr_dl *sdl = satosdl(rt->rt_gateway);
597 0 : struct in_addr *spa = (struct in_addr *)ea->arp_spa;
598 0 : char addr[INET_ADDRSTRLEN];
599 : struct ifnet *rifp;
600 : unsigned int len;
601 : int changed = 0;
602 :
603 0 : KERNEL_ASSERT_LOCKED();
604 0 : KASSERT(sdl != NULL);
605 :
606 : /*
607 : * This can happen if the entry has been deleted by another CPU
608 : * after we found it.
609 : */
610 0 : if (la == NULL)
611 0 : return (0);
612 :
613 0 : if (sdl->sdl_alen > 0) {
614 0 : if (memcmp(ea->arp_sha, LLADDR(sdl), sdl->sdl_alen)) {
615 0 : if (ISSET(rt->rt_flags, RTF_PERMANENT_ARP|RTF_LOCAL)) {
616 0 : inet_ntop(AF_INET, spa, addr, sizeof(addr));
617 0 : log(LOG_WARNING, "arp: attempt to overwrite "
618 : "permanent entry for %s by %s on %s\n", addr,
619 0 : ether_sprintf(ea->arp_sha), ifp->if_xname);
620 0 : return (-1);
621 0 : } else if (rt->rt_ifidx != ifp->if_index) {
622 : #if NCARP > 0
623 0 : if (ifp->if_type != IFT_CARP)
624 : #endif
625 : {
626 0 : rifp = if_get(rt->rt_ifidx);
627 0 : if (rifp == NULL)
628 0 : return (-1);
629 0 : inet_ntop(AF_INET, spa, addr,
630 : sizeof(addr));
631 0 : log(LOG_WARNING, "arp: attempt to "
632 : "overwrite entry for %s on %s by "
633 0 : "%s on %s\n", addr, rifp->if_xname,
634 0 : ether_sprintf(ea->arp_sha),
635 0 : ifp->if_xname);
636 0 : if_put(rifp);
637 0 : }
638 0 : return (-1);
639 : } else {
640 0 : inet_ntop(AF_INET, spa, addr, sizeof(addr));
641 0 : log(LOG_INFO, "arp info overwritten for %s by "
642 : "%s on %s\n", addr,
643 0 : ether_sprintf(ea->arp_sha), ifp->if_xname);
644 0 : rt->rt_expire = 1;/* no longer static */
645 : }
646 : changed = 1;
647 0 : }
648 0 : } else if (!if_isconnected(ifp, rt->rt_ifidx)) {
649 0 : rifp = if_get(rt->rt_ifidx);
650 0 : if (rifp == NULL)
651 0 : return (-1);
652 0 : inet_ntop(AF_INET, spa, addr, sizeof(addr));
653 0 : log(LOG_WARNING, "arp: attempt to add entry for %s on %s by %s"
654 0 : " on %s\n", addr, rifp->if_xname,
655 0 : ether_sprintf(ea->arp_sha), ifp->if_xname);
656 0 : if_put(rifp);
657 0 : return (-1);
658 : }
659 0 : sdl->sdl_alen = sizeof(ea->arp_sha);
660 0 : memcpy(LLADDR(sdl), ea->arp_sha, sizeof(ea->arp_sha));
661 0 : if (rt->rt_expire)
662 0 : rt->rt_expire = time_uptime + arpt_keep;
663 0 : rt->rt_flags &= ~RTF_REJECT;
664 :
665 : /* Notify userland that an ARP resolution has been done. */
666 0 : if (la->la_asked || changed) {
667 0 : rtm_send(rt, RTM_RESOLVE, 0, ifp->if_rdomain);
668 0 : }
669 :
670 0 : la->la_asked = 0;
671 0 : while ((len = ml_len(&la->la_ml)) != 0) {
672 : struct mbuf *mh;
673 :
674 0 : mh = ml_dequeue(&la->la_ml);
675 0 : la_hold_total--;
676 :
677 0 : ifp->if_output(ifp, mh, rt_key(rt), rt);
678 :
679 0 : if (ml_len(&la->la_ml) == len) {
680 : /* mbuf is back in queue. Discard. */
681 0 : while ((mh = ml_dequeue(&la->la_ml)) != NULL) {
682 0 : la_hold_total--;
683 0 : m_freem(mh);
684 : }
685 0 : break;
686 : }
687 0 : }
688 :
689 0 : return (0);
690 0 : }
691 :
692 : void
693 0 : arpinvalidate(struct rtentry *rt)
694 : {
695 0 : struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo;
696 0 : struct sockaddr_dl *sdl = satosdl(rt->rt_gateway);
697 :
698 0 : la_hold_total -= ml_purge(&la->la_ml);
699 0 : sdl->sdl_alen = 0;
700 0 : la->la_asked = 0;
701 0 : }
702 :
703 : /*
704 : * Free an arp entry.
705 : */
706 : void
707 0 : arptfree(struct rtentry *rt)
708 : {
709 : struct ifnet *ifp;
710 :
711 0 : KASSERT(!ISSET(rt->rt_flags, RTF_LOCAL));
712 0 : arpinvalidate(rt);
713 :
714 0 : ifp = if_get(rt->rt_ifidx);
715 0 : KASSERT(ifp != NULL);
716 0 : if (!ISSET(rt->rt_flags, RTF_STATIC|RTF_CACHED))
717 0 : rtdeletemsg(rt, ifp, ifp->if_rdomain);
718 0 : if_put(ifp);
719 0 : }
720 :
721 : /*
722 : * Lookup or enter a new address in arptab.
723 : */
724 : struct rtentry *
725 0 : arplookup(struct in_addr *inp, int create, int proxy, u_int tableid)
726 : {
727 : struct rtentry *rt;
728 0 : struct sockaddr_inarp sin;
729 : int flags;
730 :
731 0 : memset(&sin, 0, sizeof(sin));
732 0 : sin.sin_len = sizeof(sin);
733 0 : sin.sin_family = AF_INET;
734 0 : sin.sin_addr.s_addr = inp->s_addr;
735 0 : sin.sin_other = proxy ? SIN_PROXY : 0;
736 0 : flags = (create) ? RT_RESOLVE : 0;
737 :
738 0 : rt = rtalloc((struct sockaddr *)&sin, flags, tableid);
739 0 : if (!rtisvalid(rt) || ISSET(rt->rt_flags, RTF_GATEWAY) ||
740 0 : !ISSET(rt->rt_flags, RTF_LLINFO) ||
741 0 : rt->rt_gateway->sa_family != AF_LINK) {
742 0 : rtfree(rt);
743 0 : return (NULL);
744 : }
745 :
746 0 : if (proxy && !ISSET(rt->rt_flags, RTF_ANNOUNCE)) {
747 0 : while ((rt = rtable_iterate(rt)) != NULL) {
748 0 : if (ISSET(rt->rt_flags, RTF_ANNOUNCE)) {
749 : break;
750 : }
751 : }
752 : }
753 :
754 0 : return (rt);
755 0 : }
756 :
757 : /*
758 : * Check whether we do proxy ARP for this address and we point to ourselves.
759 : */
760 : int
761 0 : arpproxy(struct in_addr in, unsigned int rtableid)
762 : {
763 : struct sockaddr_dl *sdl;
764 : struct rtentry *rt;
765 : struct ifnet *ifp;
766 : int found = 0;
767 :
768 0 : rt = arplookup(&in, 0, SIN_PROXY, rtableid);
769 0 : if (!rtisvalid(rt)) {
770 0 : rtfree(rt);
771 0 : return (0);
772 : }
773 :
774 : /* Check that arp information are correct. */
775 0 : sdl = satosdl(rt->rt_gateway);
776 0 : if (sdl->sdl_alen != ETHER_ADDR_LEN) {
777 0 : rtfree(rt);
778 0 : return (0);
779 : }
780 :
781 0 : ifp = if_get(rt->rt_ifidx);
782 0 : if (ifp == NULL) {
783 0 : rtfree(rt);
784 0 : return (0);
785 : }
786 :
787 0 : if (!memcmp(LLADDR(sdl), LLADDR(ifp->if_sadl), sdl->sdl_alen))
788 0 : found = 1;
789 :
790 0 : if_put(ifp);
791 0 : rtfree(rt);
792 0 : return (found);
793 0 : }
794 :
795 : /*
796 : * Called from Ethernet interrupt handlers
797 : * when ether packet type ETHERTYPE_REVARP
798 : * is received. Common length and type checks are done here,
799 : * then the protocol-specific routine is called.
800 : */
801 : void
802 0 : revarpinput(struct ifnet *ifp, struct mbuf *m)
803 : {
804 0 : if ((m = arppullup(m)) == NULL)
805 : return;
806 0 : in_revarpinput(ifp, m);
807 0 : }
808 :
809 : /*
810 : * RARP for Internet protocols on Ethernet.
811 : * Algorithm is that given in RFC 903.
812 : * We are only using for bootstrap purposes to get an ip address for one of
813 : * our interfaces. Thus we support no user-interface.
814 : *
815 : * Since the contents of the RARP reply are specific to the interface that
816 : * sent the request, this code must ensure that they are properly associated.
817 : *
818 : * Note: also supports ARP via RARP packets, per the RFC.
819 : */
820 : void
821 0 : in_revarpinput(struct ifnet *ifp, struct mbuf *m)
822 : {
823 : struct ether_arp *ar;
824 : int op;
825 :
826 0 : ar = mtod(m, struct ether_arp *);
827 0 : op = ntohs(ar->arp_op);
828 0 : switch (op) {
829 : case ARPOP_REQUEST:
830 : case ARPOP_REPLY: /* per RFC */
831 0 : niq_enqueue(&arpinq, m);
832 0 : return;
833 : case ARPOP_REVREPLY:
834 : break;
835 : case ARPOP_REVREQUEST: /* handled by rarpd(8) */
836 : default:
837 : goto out;
838 : }
839 : #ifdef NFSCLIENT
840 0 : if (revarp_ifidx == 0)
841 : goto out;
842 0 : if (revarp_ifidx != m->m_pkthdr.ph_ifidx) /* !same interface */
843 : goto out;
844 0 : if (revarp_finished)
845 : goto wake;
846 0 : if (memcmp(ar->arp_tha, LLADDR(ifp->if_sadl), sizeof(ar->arp_tha)))
847 : goto out;
848 0 : memcpy(&revarp_srvip, ar->arp_spa, sizeof(revarp_srvip));
849 0 : memcpy(&revarp_myip, ar->arp_tpa, sizeof(revarp_myip));
850 0 : revarp_finished = 1;
851 : wake: /* Do wakeup every time in case it was missed. */
852 0 : wakeup((caddr_t)&revarp_myip);
853 : #endif /* NFSCLIENT */
854 :
855 : out:
856 0 : m_freem(m);
857 0 : }
858 :
859 : /*
860 : * Send a RARP request for the ip address of the specified interface.
861 : * The request should be RFC 903-compliant.
862 : */
863 : void
864 0 : revarprequest(struct ifnet *ifp)
865 : {
866 0 : struct sockaddr sa;
867 : struct mbuf *m;
868 : struct ether_header *eh;
869 : struct ether_arp *ea;
870 0 : struct arpcom *ac = (struct arpcom *)ifp;
871 :
872 0 : if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL)
873 0 : return;
874 0 : m->m_len = sizeof(*ea);
875 0 : m->m_pkthdr.len = sizeof(*ea);
876 0 : m->m_pkthdr.pf.prio = ifp->if_llprio;
877 0 : MH_ALIGN(m, sizeof(*ea));
878 0 : ea = mtod(m, struct ether_arp *);
879 0 : eh = (struct ether_header *)sa.sa_data;
880 0 : memset(ea, 0, sizeof(*ea));
881 0 : memcpy(eh->ether_dhost, etherbroadcastaddr, sizeof(eh->ether_dhost));
882 0 : eh->ether_type = htons(ETHERTYPE_REVARP);
883 0 : ea->arp_hrd = htons(ARPHRD_ETHER);
884 0 : ea->arp_pro = htons(ETHERTYPE_IP);
885 0 : ea->arp_hln = sizeof(ea->arp_sha); /* hardware address length */
886 0 : ea->arp_pln = sizeof(ea->arp_spa); /* protocol address length */
887 0 : ea->arp_op = htons(ARPOP_REVREQUEST);
888 0 : memcpy(eh->ether_shost, ac->ac_enaddr, sizeof(ea->arp_tha));
889 0 : memcpy(ea->arp_sha, ac->ac_enaddr, sizeof(ea->arp_sha));
890 0 : memcpy(ea->arp_tha, ac->ac_enaddr, sizeof(ea->arp_tha));
891 0 : sa.sa_family = pseudo_AF_HDRCMPLT;
892 0 : sa.sa_len = sizeof(sa);
893 0 : m->m_flags |= M_BCAST;
894 0 : ifp->if_output(ifp, m, &sa, NULL);
895 0 : }
896 :
897 : #ifdef NFSCLIENT
898 : /*
899 : * RARP for the ip address of the specified interface, but also
900 : * save the ip address of the server that sent the answer.
901 : * Timeout if no response is received.
902 : */
903 : int
904 0 : revarpwhoarewe(struct ifnet *ifp, struct in_addr *serv_in,
905 : struct in_addr *clnt_in)
906 : {
907 : int result, count = 20;
908 :
909 0 : if (revarp_finished)
910 0 : return EIO;
911 :
912 0 : revarp_ifidx = ifp->if_index;
913 0 : while (count--) {
914 0 : revarprequest(ifp);
915 0 : result = tsleep((caddr_t)&revarp_myip, PSOCK, "revarp", hz/2);
916 0 : if (result != EWOULDBLOCK)
917 : break;
918 : }
919 0 : revarp_ifidx = 0;
920 0 : if (!revarp_finished)
921 0 : return ENETUNREACH;
922 :
923 0 : memcpy(serv_in, &revarp_srvip, sizeof(*serv_in));
924 0 : memcpy(clnt_in, &revarp_myip, sizeof(*clnt_in));
925 0 : return 0;
926 0 : }
927 :
928 : /* For compatibility: only saves interface address. */
929 : int
930 0 : revarpwhoami(struct in_addr *in, struct ifnet *ifp)
931 : {
932 0 : struct in_addr server;
933 0 : return (revarpwhoarewe(ifp, &server, in));
934 0 : }
935 : #endif /* NFSCLIENT */
|