OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [net/] [bsd_tcpip/] [v2_0/] [src/] [sys/] [netinet/] [if_ether.c] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      src/sys/netinet/if_ether.c
4
//
5
//==========================================================================
6
//####BSDCOPYRIGHTBEGIN####
7
//
8
// -------------------------------------------
9
//
10
// Portions of this software may have been derived from OpenBSD, 
11
// FreeBSD or other sources, and are covered by the appropriate
12
// copyright disclaimers included herein.
13
//
14
// Portions created by Red Hat are
15
// Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
16
//
17
// -------------------------------------------
18
//
19
//####BSDCOPYRIGHTEND####
20
//==========================================================================
21
 
22
/*
23
 * Copyright (c) 1982, 1986, 1988, 1993
24
 *      The Regents of the University of California.  All rights reserved.
25
 *
26
 * Redistribution and use in source and binary forms, with or without
27
 * modification, are permitted provided that the following conditions
28
 * are met:
29
 * 1. Redistributions of source code must retain the above copyright
30
 *    notice, this list of conditions and the following disclaimer.
31
 * 2. Redistributions in binary form must reproduce the above copyright
32
 *    notice, this list of conditions and the following disclaimer in the
33
 *    documentation and/or other materials provided with the distribution.
34
 * 3. All advertising materials mentioning features or use of this software
35
 *    must display the following acknowledgement:
36
 *      This product includes software developed by the University of
37
 *      California, Berkeley and its contributors.
38
 * 4. Neither the name of the University nor the names of its contributors
39
 *    may be used to endorse or promote products derived from this software
40
 *    without specific prior written permission.
41
 *
42
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
43
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
46
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52
 * SUCH DAMAGE.
53
 *
54
 *      @(#)if_ether.c  8.1 (Berkeley) 6/10/93
55
 * $FreeBSD: src/sys/netinet/if_ether.c,v 1.64.2.11 2001/07/25 17:27:56 jlemon Exp $
56
 */
57
 
58
/*
59
 * Ethernet address resolution protocol.
60
 * TODO:
61
 *      add "inuse/lock" bit (or ref. count) along with valid bit
62
 */
63
 
64
#include <sys/param.h>
65
#include <sys/queue.h>
66
#include <sys/mbuf.h>
67
#include <sys/malloc.h>
68
#include <sys/socket.h>
69
 
70
#include <net/if.h>
71
#include <net/if_dl.h>
72
#include <net/if_types.h>
73
#include <net/route.h>
74
#include <net/netisr.h>
75
#include <net/if_llc.h>
76
#ifdef BRIDGE
77
#include <net/ethernet.h>
78
#include <net/bridge.h>
79
#endif
80
 
81
#include <netinet/in.h>
82
#include <netinet/in_var.h>
83
#include <netinet/if_ether.h>
84
 
85
#include <net/iso88025.h>
86
 
87
#define SIN(s) ((struct sockaddr_in *)s)
88
#define SDL(s) ((struct sockaddr_dl *)s)
89
 
90
/* timer values */
91
static int arpt_prune = (5*60*1); /* walk list every 5 minutes */
92
static int arpt_keep = (20*60); /* once resolved, good for 20 more minutes */
93
static int arpt_down = 20;      /* once declared down, don't send for 20 sec */
94
 
95
#define rt_expire rt_rmx.rmx_expire
96
 
97
struct llinfo_arp {
98
        LIST_ENTRY(llinfo_arp) la_le;
99
        struct  rtentry *la_rt;
100
        struct  mbuf *la_hold;          /* last packet until resolved/timeout */
101
        long    la_asked;               /* last time we QUERIED for this addr */
102
#define la_timer la_rt->rt_rmx.rmx_expire /* deletion time in seconds */
103
};
104
 
105
static  LIST_HEAD(, llinfo_arp) llinfo_arp;
106
 
107
struct  ifqueue arpintrq = {0, 0, 0, 50};
108
static int      arp_inuse, arp_allocated;
109
 
110
static int      arp_maxtries = 5;
111
static int      useloopback = 1; /* use loopback interface for local traffic */
112
static int      arp_proxyall = 0;
113
 
114
static void     arp_rtrequest __P((int, struct rtentry *, struct sockaddr *));
115
static void     arprequest __P((struct arpcom *,
116
                        struct in_addr *, struct in_addr *, u_char *));
117
static void     arpintr __P((void));
118
static void     arptfree __P((struct llinfo_arp *));
119
static void     arptimer __P((void *));
120
static struct llinfo_arp
121
                *arplookup __P((u_long, int, int));
122
#ifdef INET
123
static void     in_arpinput __P((struct mbuf *));
124
#endif
125
 
126
/*
127
 * Timeout routine.  Age arp_tab entries periodically.
128
 */
129
/* ARGSUSED */
130
static void
131
arptimer(ignored_arg)
132
        void *ignored_arg;
133
{
134
        int s = splnet();
135
        register struct llinfo_arp *la = llinfo_arp.lh_first;
136
        struct llinfo_arp *ola;
137
 
138
        timeout(arptimer, (caddr_t)0, arpt_prune * hz);
139
        while ((ola = la) != 0) {
140
                register struct rtentry *rt = la->la_rt;
141
                la = la->la_le.le_next;
142
                if (rt->rt_expire && rt->rt_expire <= time_second)
143
                        arptfree(ola); /* timer has expired, clear */
144
        }
145
        splx(s);
146
}
147
 
148
/*
149
 * Parallel to llc_rtrequest.
150
 */
151
static void
152
arp_rtrequest(req, rt, sa)
153
        int req;
154
        register struct rtentry *rt;
155
        struct sockaddr *sa;
156
{
157
        register struct sockaddr *gate = rt->rt_gateway;
158
        register struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo;
159
        static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
160
        static int arpinit_done;
161
 
162
        if (!arpinit_done) {
163
                arpinit_done = 1;
164
                LIST_INIT(&llinfo_arp);
165
                timeout(arptimer, (caddr_t)0, hz);
166
                register_netisr(NETISR_ARP, arpintr);
167
        }
168
        if (rt->rt_flags & RTF_GATEWAY)
169
                return;
170
        switch (req) {
171
 
172
        case RTM_ADD:
173
                /*
174
                 * XXX: If this is a manually added route to interface
175
                 * such as older version of routed or gated might provide,
176
                 * restore cloning bit.
177
                 */
178
                if ((rt->rt_flags & RTF_HOST) == 0 &&
179
                    SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff)
180
                        rt->rt_flags |= RTF_CLONING;
181
                if (rt->rt_flags & RTF_CLONING) {
182
                        /*
183
                         * Case 1: This route should come from a route to iface.
184
                         */
185
                        rt_setgate(rt, rt_key(rt),
186
                                        (struct sockaddr *)&null_sdl);
187
                        gate = rt->rt_gateway;
188
                        SDL(gate)->sdl_type = rt->rt_ifp->if_type;
189
                        SDL(gate)->sdl_index = rt->rt_ifp->if_index;
190
                        rt->rt_expire = time_second;
191
                        break;
192
                }
193
                /* Announce a new entry if requested. */
194
                if (rt->rt_flags & RTF_ANNOUNCE)
195
                        arprequest((struct arpcom *)rt->rt_ifp,
196
                            &SIN(rt_key(rt))->sin_addr,
197
                            &SIN(rt_key(rt))->sin_addr,
198
                            (u_char *)LLADDR(SDL(gate)));
199
                /*FALLTHROUGH*/
200
        case RTM_RESOLVE:
201
                if (gate->sa_family != AF_LINK ||
202
                    gate->sa_len < sizeof(null_sdl)) {
203
                        log(LOG_DEBUG, "arp_rtrequest: bad gateway value\n");
204
                        break;
205
                }
206
                SDL(gate)->sdl_type = rt->rt_ifp->if_type;
207
                SDL(gate)->sdl_index = rt->rt_ifp->if_index;
208
                if (la != 0)
209
                        break; /* This happens on a route change */
210
                /*
211
                 * Case 2:  This route may come from cloning, or a manual route
212
                 * add with a LL address.
213
                 */
214
                R_Malloc(la, struct llinfo_arp *, sizeof(*la));
215
                rt->rt_llinfo = (caddr_t)la;
216
                if (la == 0) {
217
                        log(LOG_DEBUG, "arp_rtrequest: malloc failed\n");
218
                        break;
219
                }
220
                arp_inuse++, arp_allocated++;
221
                Bzero(la, sizeof(*la));
222
                la->la_rt = rt;
223
                rt->rt_flags |= RTF_LLINFO;
224
                LIST_INSERT_HEAD(&llinfo_arp, la, la_le);
225
 
226
#ifdef INET
227
                /*
228
                 * This keeps the multicast addresses from showing up
229
                 * in `arp -a' listings as unresolved.  It's not actually
230
                 * functional.  Then the same for broadcast.
231
                 */
232
                if (IN_MULTICAST(ntohl(SIN(rt_key(rt))->sin_addr.s_addr))) {
233
                        ETHER_MAP_IP_MULTICAST(&SIN(rt_key(rt))->sin_addr,
234
                                               LLADDR(SDL(gate)));
235
                        SDL(gate)->sdl_alen = 6;
236
                        rt->rt_expire = 0;
237
                }
238
                if (in_broadcast(SIN(rt_key(rt))->sin_addr, rt->rt_ifp)) {
239
                        memcpy(LLADDR(SDL(gate)), etherbroadcastaddr, 6);
240
                        SDL(gate)->sdl_alen = 6;
241
                        rt->rt_expire = 0;
242
                }
243
#endif
244
 
245
                if (SIN(rt_key(rt))->sin_addr.s_addr ==
246
                    (IA_SIN(rt->rt_ifa))->sin_addr.s_addr) {
247
                    /*
248
                     * This test used to be
249
                     *  if (loif.if_flags & IFF_UP)
250
                     * It allowed local traffic to be forced
251
                     * through the hardware by configuring the loopback down.
252
                     * However, it causes problems during network configuration
253
                     * for boards that can't receive packets they send.
254
                     * It is now necessary to clear "useloopback" and remove
255
                     * the route to force traffic out to the hardware.
256
                     */
257
                        rt->rt_expire = 0;
258
                        Bcopy(((struct arpcom *)rt->rt_ifp)->ac_enaddr,
259
                                LLADDR(SDL(gate)), SDL(gate)->sdl_alen = 6);
260
                        if (useloopback)
261
                                rt->rt_ifp = loif;
262
 
263
                }
264
                break;
265
 
266
        case RTM_DELETE:
267
                if (la == 0)
268
                        break;
269
                arp_inuse--;
270
                LIST_REMOVE(la, la_le);
271
                rt->rt_llinfo = 0;
272
                rt->rt_flags &= ~RTF_LLINFO;
273
                if (la->la_hold)
274
                        m_freem(la->la_hold);
275
                Free((caddr_t)la);
276
        }
277
}
278
 
279
/*
280
 * Broadcast an ARP request. Caller specifies:
281
 *      - arp header source ip address
282
 *      - arp header target ip address
283
 *      - arp header source ethernet address
284
 */
285
static void
286
arprequest(ac, sip, tip, enaddr)
287
        register struct arpcom *ac;
288
        register struct in_addr *sip, *tip;
289
        register u_char *enaddr;
290
{
291
        register struct mbuf *m;
292
        register struct ether_header *eh;
293
        register struct ether_arp *ea;
294
        struct sockaddr sa;
295
        static u_char   llcx[] = { 0x82, 0x40, LLC_SNAP_LSAP, LLC_SNAP_LSAP,
296
                                   LLC_UI, 0x00, 0x00, 0x00, 0x08, 0x06 };
297
 
298
        if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL)
299
                return;
300
        m->m_pkthdr.rcvif = (struct ifnet *)0;
301
        switch (ac->ac_if.if_type) {
302
        case IFT_ISO88025:
303
                m->m_len = sizeof(*ea) + sizeof(llcx);
304
                m->m_pkthdr.len = sizeof(*ea) + sizeof(llcx);
305
                MH_ALIGN(m, sizeof(*ea) + sizeof(llcx));
306
                (void)memcpy(mtod(m, caddr_t), llcx, sizeof(llcx));
307
                (void)memcpy(sa.sa_data, etherbroadcastaddr, 6);
308
                (void)memcpy(sa.sa_data + 6, enaddr, 6);
309
                sa.sa_data[6] |= TR_RII;
310
                sa.sa_data[12] = TR_AC;
311
                sa.sa_data[13] = TR_LLC_FRAME;
312
                ea = (struct ether_arp *)(mtod(m, char *) + sizeof(llcx));
313
                bzero((caddr_t)ea, sizeof (*ea));
314
                ea->arp_hrd = htons(ARPHRD_IEEE802);
315
                break;
316
        case IFT_FDDI:
317
        case IFT_ETHER:
318
                /*
319
                 * This may not be correct for types not explicitly
320
                 * listed, but this is our best guess
321
                 */
322
        default:
323
                m->m_len = sizeof(*ea);
324
                m->m_pkthdr.len = sizeof(*ea);
325
                MH_ALIGN(m, sizeof(*ea));
326
                ea = mtod(m, struct ether_arp *);
327
                eh = (struct ether_header *)sa.sa_data;
328
                bzero((caddr_t)ea, sizeof (*ea));
329
                /* if_output will not swap */
330
                eh->ether_type = htons(ETHERTYPE_ARP);
331
                (void)memcpy(eh->ether_dhost, etherbroadcastaddr,
332
                    sizeof(eh->ether_dhost));
333
                ea->arp_hrd = htons(ARPHRD_ETHER);
334
                break;
335
        }
336
        ea->arp_pro = htons(ETHERTYPE_IP);
337
        ea->arp_hln = sizeof(ea->arp_sha);      /* hardware address length */
338
        ea->arp_pln = sizeof(ea->arp_spa);      /* protocol address length */
339
        ea->arp_op = htons(ARPOP_REQUEST);
340
        (void)memcpy(ea->arp_sha, enaddr, sizeof(ea->arp_sha));
341
        (void)memcpy(ea->arp_spa, sip, sizeof(ea->arp_spa));
342
        (void)memcpy(ea->arp_tpa, tip, sizeof(ea->arp_tpa));
343
        sa.sa_family = AF_UNSPEC;
344
        sa.sa_len = sizeof(sa);
345
        (*ac->ac_if.if_output)(&ac->ac_if, m, &sa, (struct rtentry *)0);
346
}
347
 
348
/*
349
 * Resolve an IP address into an ethernet address.  If success,
350
 * desten is filled in.  If there is no entry in arptab,
351
 * set one up and broadcast a request for the IP address.
352
 * Hold onto this mbuf and resend it once the address
353
 * is finally resolved.  A return value of 1 indicates
354
 * that desten has been filled in and the packet should be sent
355
 * normally; a 0 return indicates that the packet has been
356
 * taken over here, either now or for later transmission.
357
 */
358
int
359
arpresolve(ac, rt, m, dst, desten, rt0)
360
        register struct arpcom *ac;
361
        register struct rtentry *rt;
362
        struct mbuf *m;
363
        register struct sockaddr *dst;
364
        register u_char *desten;
365
        struct rtentry *rt0;
366
{
367
        struct llinfo_arp *la = 0;
368
        struct sockaddr_dl *sdl;
369
 
370
        if (m->m_flags & M_BCAST) {     /* broadcast */
371
                (void)memcpy(desten, etherbroadcastaddr, sizeof(etherbroadcastaddr));
372
                return (1);
373
        }
374
        if (m->m_flags & M_MCAST) {     /* multicast */
375
                ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten);
376
                return(1);
377
        }
378
        if (rt)
379
                la = (struct llinfo_arp *)rt->rt_llinfo;
380
        if (la == 0) {
381
                la = arplookup(SIN(dst)->sin_addr.s_addr, 1, 0);
382
                if (la)
383
                        rt = la->la_rt;
384
        }
385
        if (la == 0 || rt == 0) {
386
                log(LOG_DEBUG, "arpresolve: can't allocate llinfo for %s%s%s\n",
387
                        inet_ntoa(SIN(dst)->sin_addr), la ? "la" : "",
388
                                rt ? "rt" : "");
389
                m_freem(m);
390
                return (0);
391
        }
392
        sdl = SDL(rt->rt_gateway);
393
        /*
394
         * Check the address family and length is valid, the address
395
         * is resolved; otherwise, try to resolve.
396
         */
397
        if ((rt->rt_expire == 0 || rt->rt_expire > time_second) &&
398
            sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) {
399
                bcopy(LLADDR(sdl), desten, sdl->sdl_alen);
400
                return 1;
401
        }
402
        /*
403
         * If ARP is disabled on this interface, stop.
404
         * XXX
405
         * Probably should not allocate empty llinfo struct if we are
406
         * not going to be sending out an arp request.
407
         */
408
        if (ac->ac_if.if_flags & IFF_NOARP)
409
                return (0);
410
        /*
411
         * There is an arptab entry, but no ethernet address
412
         * response yet.  Replace the held mbuf with this
413
         * latest one.
414
         */
415
        if (la->la_hold)
416
                m_freem(la->la_hold);
417
        la->la_hold = m;
418
        if (rt->rt_expire) {
419
                rt->rt_flags &= ~RTF_REJECT;
420
                if (la->la_asked == 0 || rt->rt_expire != time_second) {
421
                        rt->rt_expire = time_second;
422
                        if (la->la_asked++ < arp_maxtries)
423
                            arprequest(ac,
424
                                &SIN(rt->rt_ifa->ifa_addr)->sin_addr,
425
                                &SIN(dst)->sin_addr, ac->ac_enaddr);
426
                        else {
427
                                rt->rt_flags |= RTF_REJECT;
428
                                rt->rt_expire += arpt_down;
429
                                la->la_asked = 0;
430
                        }
431
 
432
                }
433
        }
434
        return (0);
435
}
436
 
437
/*
438
 * Common length and type checks are done here,
439
 * then the protocol-specific routine is called.
440
 */
441
static void
442
arpintr()
443
{
444
        register struct mbuf *m;
445
        register struct arphdr *ar;
446
        int s;
447
 
448
        while (arpintrq.ifq_head) {
449
                s = splimp();
450
                IF_DEQUEUE(&arpintrq, m);
451
                splx(s);
452
                if (m == 0 || (m->m_flags & M_PKTHDR) == 0)
453
                        panic("arpintr");
454
 
455
                if (m->m_len < sizeof(struct arphdr) &&
456
                    ((m = m_pullup(m, sizeof(struct arphdr))) == NULL)) {
457
                        log(LOG_ERR, "arp: runt packet -- m_pullup failed\n");
458
                        continue;
459
                }
460
                ar = mtod(m, struct arphdr *);
461
 
462
                if (ntohs(ar->ar_hrd) != ARPHRD_ETHER
463
                    && ntohs(ar->ar_hrd) != ARPHRD_IEEE802) {
464
                        log(LOG_ERR,
465
                            "arp: unknown hardware address format (0x%2D)\n",
466
                            (unsigned char *)&ar->ar_hrd, "");
467
                        m_freem(m);
468
                        continue;
469
                }
470
 
471
                if (m->m_pkthdr.len < sizeof(struct arphdr) + 2 * ar->ar_hln
472
                    + 2 * ar->ar_pln) {
473
                        log(LOG_ERR, "arp: runt packet\n");
474
                        m_freem(m);
475
                        continue;
476
                }
477
 
478
                switch (ntohs(ar->ar_pro)) {
479
#ifdef INET
480
                        case ETHERTYPE_IP:
481
                                in_arpinput(m);
482
                                continue;
483
#endif
484
                }
485
                m_freem(m);
486
        }
487
}
488
 
489
#ifdef INET
490
/*
491
 * ARP for Internet protocols on 10 Mb/s Ethernet.
492
 * Algorithm is that given in RFC 826.
493
 * In addition, a sanity check is performed on the sender
494
 * protocol address, to catch impersonators.
495
 * We no longer handle negotiations for use of trailer protocol:
496
 * Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent
497
 * along with IP replies if we wanted trailers sent to us,
498
 * and also sent them in response to IP replies.
499
 * This allowed either end to announce the desire to receive
500
 * trailer packets.
501
 * We no longer reply to requests for ETHERTYPE_TRAIL protocol either,
502
 * but formerly didn't normally send requests.
503
 */
504
static int log_arp_wrong_iface = 1;
505
 
506
//SYSCTL_INT(_net_link_ether_inet, OID_AUTO, log_arp_wrong_iface, CTLFLAG_RW,
507
//      &log_arp_wrong_iface, 0,
508
//      "log arp packets arriving on the wrong interface");
509
 
510
static void
511
in_arpinput(m)
512
        struct mbuf *m;
513
{
514
        register struct ether_arp *ea;
515
        register struct arpcom *ac = (struct arpcom *)m->m_pkthdr.rcvif;
516
        struct ether_header *eh;
517
        struct iso88025_header *th = (struct iso88025_header *)0;
518
        register struct llinfo_arp *la = 0;
519
        register struct rtentry *rt;
520
        struct in_ifaddr *ia, *maybe_ia = 0;
521
        struct sockaddr_dl *sdl;
522
        struct sockaddr sa;
523
        struct in_addr isaddr, itaddr, myaddr;
524
        int op, rif_len;
525
 
526
        if (m->m_len < sizeof(struct ether_arp) &&
527
            (m = m_pullup(m, sizeof(struct ether_arp))) == NULL) {
528
                log(LOG_ERR, "in_arp: runt packet -- m_pullup failed\n");
529
                return;
530
        }
531
 
532
        ea = mtod(m, struct ether_arp *);
533
        op = ntohs(ea->arp_op);
534
        (void)memcpy(&isaddr, ea->arp_spa, sizeof (isaddr));
535
        (void)memcpy(&itaddr, ea->arp_tpa, sizeof (itaddr));
536
        for (ia = in_ifaddrhead.tqh_first; ia; ia = ia->ia_link.tqe_next) {
537
                /*
538
                 * For a bridge, we want to check the address irrespective
539
                 * of the receive interface. (This will change slightly
540
                 * when we have clusters of interfaces).
541
                 */
542
#ifdef BRIDGE
543
#define BRIDGE_TEST (do_bridge)
544
#else
545
#define BRIDGE_TEST (0) /* cc will optimise the test away */
546
#endif
547
                if ((BRIDGE_TEST) || (ia->ia_ifp == &ac->ac_if)) {
548
                        maybe_ia = ia;
549
                        if ((itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) ||
550
                             (isaddr.s_addr == ia->ia_addr.sin_addr.s_addr)) {
551
                                break;
552
                        }
553
                }
554
        }
555
        if (maybe_ia == 0) {
556
                m_freem(m);
557
                return;
558
        }
559
        myaddr = ia ? ia->ia_addr.sin_addr : maybe_ia->ia_addr.sin_addr;
560
        if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)ac->ac_enaddr,
561
            sizeof (ea->arp_sha))) {
562
                m_freem(m);     /* it's from me, ignore it. */
563
                return;
564
        }
565
        if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)etherbroadcastaddr,
566
            sizeof (ea->arp_sha))) {
567
                log(LOG_ERR,
568
                    "arp: ether address is broadcast for IP address %s!\n",
569
                    inet_ntoa(isaddr));
570
                m_freem(m);
571
                return;
572
        }
573
        if (isaddr.s_addr == myaddr.s_addr) {
574
                log(LOG_ERR,
575
                   "arp: %6D is using my IP address %s!\n",
576
                   ea->arp_sha, ":", inet_ntoa(isaddr));
577
                itaddr = myaddr;
578
                goto reply;
579
        }
580
        la = arplookup(isaddr.s_addr, itaddr.s_addr == myaddr.s_addr, 0);
581
        if (la && (rt = la->la_rt) && (sdl = SDL(rt->rt_gateway))) {
582
                /* the following is not an error when doing bridging */
583
                if (!BRIDGE_TEST && rt->rt_ifp != &ac->ac_if) {
584
                    if (log_arp_wrong_iface)
585
                        log(LOG_ERR, "arp: %s is on %s%d but got reply from %6D on %s%d\n",
586
                            inet_ntoa(isaddr),
587
                            rt->rt_ifp->if_name, rt->rt_ifp->if_unit,
588
                            ea->arp_sha, ":",
589
                            ac->ac_if.if_name, ac->ac_if.if_unit);
590
                    goto reply;
591
                }
592
                if (sdl->sdl_alen &&
593
                    bcmp((caddr_t)ea->arp_sha, LLADDR(sdl), sdl->sdl_alen)) {
594
                        if (rt->rt_expire)
595
                            log(LOG_INFO, "arp: %s moved from %6D to %6D on %s%d\n",
596
                                inet_ntoa(isaddr), (u_char *)LLADDR(sdl), ":",
597
                                ea->arp_sha, ":",
598
                                ac->ac_if.if_name, ac->ac_if.if_unit);
599
                        else {
600
                            log(LOG_ERR,
601
                                "arp: %6D attempts to modify permanent entry for %s on %s%d\n",
602
                                ea->arp_sha, ":", inet_ntoa(isaddr),
603
                                ac->ac_if.if_name, ac->ac_if.if_unit);
604
                            goto reply;
605
                        }
606
                }
607
                (void)memcpy(LLADDR(sdl), ea->arp_sha, sizeof(ea->arp_sha));
608
                sdl->sdl_alen = sizeof(ea->arp_sha);
609
                sdl->sdl_rcf = (u_short)0;
610
                /*
611
                 * If we receive an arp from a token-ring station over
612
                 * a token-ring nic then try to save the source
613
                 * routing info.
614
                 */
615
                if (ac->ac_if.if_type == IFT_ISO88025) {
616
                        th = (struct iso88025_header *)m->m_pkthdr.header;
617
                        rif_len = TR_RCF_RIFLEN(th->rcf);
618
                        if ((th->iso88025_shost[0] & TR_RII) &&
619
                            (rif_len > 2)) {
620
                                sdl->sdl_rcf = th->rcf;
621
                                sdl->sdl_rcf ^= htons(TR_RCF_DIR);
622
                                memcpy(sdl->sdl_route, th->rd, rif_len - 2);
623
                                sdl->sdl_rcf &= ~htons(TR_RCF_BCST_MASK);
624
                                /*
625
                                 * Set up source routing information for
626
                                 * reply packet (XXX)
627
                                 */
628
                                m->m_data -= rif_len;
629
                                m->m_len  += rif_len;
630
                                m->m_pkthdr.len += rif_len;
631
                        } else {
632
                                th->iso88025_shost[0] &= ~TR_RII;
633
                        }
634
                        m->m_data -= 8;
635
                        m->m_len  += 8;
636
                        m->m_pkthdr.len += 8;
637
                        th->rcf = sdl->sdl_rcf;
638
                } else {
639
                        sdl->sdl_rcf = (u_short)0;
640
                }
641
                if (rt->rt_expire)
642
                        rt->rt_expire = time_second + arpt_keep;
643
                rt->rt_flags &= ~RTF_REJECT;
644
                la->la_asked = 0;
645
                if (la->la_hold) {
646
                        (*ac->ac_if.if_output)(&ac->ac_if, la->la_hold,
647
                                rt_key(rt), rt);
648
                        la->la_hold = 0;
649
                }
650
        }
651
reply:
652
        if (op != ARPOP_REQUEST) {
653
                m_freem(m);
654
                return;
655
        }
656
        if (itaddr.s_addr == myaddr.s_addr) {
657
                /* I am the target */
658
                (void)memcpy(ea->arp_tha, ea->arp_sha, sizeof(ea->arp_sha));
659
                (void)memcpy(ea->arp_sha, ac->ac_enaddr, sizeof(ea->arp_sha));
660
        } else {
661
                la = arplookup(itaddr.s_addr, 0, SIN_PROXY);
662
                if (la == NULL) {
663
                        struct sockaddr_in sin;
664
 
665
                        if (!arp_proxyall) {
666
                                m_freem(m);
667
                                return;
668
                        }
669
 
670
                        bzero(&sin, sizeof sin);
671
                        sin.sin_family = AF_INET;
672
                        sin.sin_len = sizeof sin;
673
                        sin.sin_addr = itaddr;
674
 
675
                        rt = rtalloc1((struct sockaddr *)&sin, 0, 0UL);
676
                        if (!rt) {
677
                                m_freem(m);
678
                                return;
679
                        }
680
                        /*
681
                         * Don't send proxies for nodes on the same interface
682
                         * as this one came out of, or we'll get into a fight
683
                         * over who claims what Ether address.
684
                         */
685
                        if (rt->rt_ifp == &ac->ac_if) {
686
                                rtfree(rt);
687
                                m_freem(m);
688
                                return;
689
                        }
690
                        (void)memcpy(ea->arp_tha, ea->arp_sha, sizeof(ea->arp_sha));
691
                        (void)memcpy(ea->arp_sha, ac->ac_enaddr, sizeof(ea->arp_sha));
692
                        rtfree(rt);
693
#ifdef DEBUG_PROXY
694
                        printf("arp: proxying for %s\n",
695
                               inet_ntoa(itaddr));
696
#endif
697
                } else {
698
                        rt = la->la_rt;
699
                        (void)memcpy(ea->arp_tha, ea->arp_sha, sizeof(ea->arp_sha));
700
                        sdl = SDL(rt->rt_gateway);
701
                        (void)memcpy(ea->arp_sha, LLADDR(sdl), sizeof(ea->arp_sha));
702
                }
703
        }
704
 
705
        (void)memcpy(ea->arp_tpa, ea->arp_spa, sizeof(ea->arp_spa));
706
        (void)memcpy(ea->arp_spa, &itaddr, sizeof(ea->arp_spa));
707
        ea->arp_op = htons(ARPOP_REPLY);
708
        ea->arp_pro = htons(ETHERTYPE_IP); /* let's be sure! */
709
        switch (ac->ac_if.if_type) {
710
        case IFT_ISO88025:
711
                /* Re-arrange the source/dest address */
712
                memcpy(th->iso88025_dhost, th->iso88025_shost,
713
                    sizeof(th->iso88025_dhost));
714
                memcpy(th->iso88025_shost, ac->ac_enaddr,
715
                    sizeof(th->iso88025_shost));
716
                /* Set the source routing bit if neccesary */
717
                if (th->iso88025_dhost[0] & TR_RII) {
718
                        th->iso88025_dhost[0] &= ~TR_RII;
719
                        if (TR_RCF_RIFLEN(th->rcf) > 2)
720
                                th->iso88025_shost[0] |= TR_RII;
721
                }
722
                /* Copy the addresses, ac and fc into sa_data */
723
                memcpy(sa.sa_data, th->iso88025_dhost,
724
                    sizeof(th->iso88025_dhost) * 2);
725
                sa.sa_data[(sizeof(th->iso88025_dhost) * 2)] = TR_AC;
726
                sa.sa_data[(sizeof(th->iso88025_dhost) * 2) + 1] = TR_LLC_FRAME;
727
                break;
728
        case IFT_ETHER:
729
        case IFT_FDDI:
730
        /*
731
         * May not be correct for types not explictly
732
         * listed, but it is our best guess.
733
         */
734
        default:
735
                eh = (struct ether_header *)sa.sa_data;
736
                (void)memcpy(eh->ether_dhost, ea->arp_tha,
737
                    sizeof(eh->ether_dhost));
738
                eh->ether_type = htons(ETHERTYPE_ARP);
739
                break;
740
        }
741
        sa.sa_family = AF_UNSPEC;
742
        sa.sa_len = sizeof(sa);
743
        (*ac->ac_if.if_output)(&ac->ac_if, m, &sa, (struct rtentry *)0);
744
        return;
745
}
746
#endif
747
 
748
/*
749
 * Free an arp entry.
750
 */
751
static void
752
arptfree(la)
753
        register struct llinfo_arp *la;
754
{
755
        register struct rtentry *rt = la->la_rt;
756
        register struct sockaddr_dl *sdl;
757
        if (rt == 0)
758
                panic("arptfree");
759
        if (rt->rt_refcnt > 0 && (sdl = SDL(rt->rt_gateway)) &&
760
            sdl->sdl_family == AF_LINK) {
761
                sdl->sdl_alen = 0;
762
                la->la_asked = 0;
763
                rt->rt_flags &= ~RTF_REJECT;
764
                return;
765
        }
766
        rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0, rt_mask(rt),
767
                        0, (struct rtentry **)0);
768
}
769
/*
770
 * Lookup or enter a new address in arptab.
771
 */
772
static struct llinfo_arp *
773
arplookup(addr, create, proxy)
774
        u_long addr;
775
        int create, proxy;
776
{
777
        register struct rtentry *rt;
778
        static struct sockaddr_inarp sin = {sizeof(sin), AF_INET };
779
        const char *why = 0;
780
 
781
        sin.sin_addr.s_addr = addr;
782
        sin.sin_other = proxy ? SIN_PROXY : 0;
783
        rt = rtalloc1((struct sockaddr *)&sin, create, 0UL);
784
        if (rt == 0)
785
                return (0);
786
        rt->rt_refcnt--;
787
 
788
        if (rt->rt_flags & RTF_GATEWAY)
789
                why = "host is not on local network";
790
        else if ((rt->rt_flags & RTF_LLINFO) == 0)
791
                why = "could not allocate llinfo";
792
        else if (rt->rt_gateway->sa_family != AF_LINK)
793
                why = "gateway route is not ours";
794
 
795
        if (why && create) {
796
                log(LOG_DEBUG, "arplookup %s failed: %s\n",
797
                    inet_ntoa(sin.sin_addr), why);
798
                return 0;
799
        } else if (why) {
800
                return 0;
801
        }
802
        return ((struct llinfo_arp *)rt->rt_llinfo);
803
}
804
 
805
void
806
arp_ifinit(ac, ifa)
807
        struct arpcom *ac;
808
        struct ifaddr *ifa;
809
{
810
        if (ntohl(IA_SIN(ifa)->sin_addr.s_addr) != INADDR_ANY)
811
                arprequest(ac, &IA_SIN(ifa)->sin_addr,
812
                               &IA_SIN(ifa)->sin_addr, ac->ac_enaddr);
813
        ifa->ifa_rtrequest = arp_rtrequest;
814
        ifa->ifa_flags |= RTF_CLONING;
815
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.