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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [libnetworking/] [netinet/] [if_ether.c] - Blame information for rev 227

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 30 unneback
/*
2
 * Copyright (c) 1982, 1986, 1988, 1993
3
 *      The Regents of the University of California.  All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 * 3. All advertising materials mentioning features or use of this software
14
 *    must display the following acknowledgement:
15
 *      This product includes software developed by the University of
16
 *      California, Berkeley and its contributors.
17
 * 4. Neither the name of the University nor the names of its contributors
18
 *    may be used to endorse or promote products derived from this software
19
 *    without specific prior written permission.
20
 *
21
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31
 * SUCH DAMAGE.
32
 *
33
 *      @(#)if_ether.c  8.1 (Berkeley) 6/10/93
34
 * $Id: if_ether.c,v 1.2 2001-09-27 12:01:55 chris Exp $
35
 */
36
 
37
/*
38
 * Ethernet address resolution protocol.
39
 * TODO:
40
 *      add "inuse/lock" bit (or ref. count) along with valid bit
41
 */
42
 
43
#include <sys/param.h>
44
#include <sys/kernel.h>
45
#include <sys/sysctl.h>
46
#include <sys/queue.h>
47
#include <sys/systm.h>
48
#include <sys/mbuf.h>
49
#include <sys/malloc.h>
50
#include <sys/socket.h>
51
#include <sys/syslog.h>
52
 
53
#include <net/if.h>
54
#include <net/if_dl.h>
55
#include <net/route.h>
56
#include <net/netisr.h>
57
 
58
#include <netinet/in.h>
59
#include <netinet/in_var.h>
60
#include <netinet/if_ether.h>
61
 
62
#define SIN(s) ((struct sockaddr_in *)s)
63
#define SDL(s) ((struct sockaddr_dl *)s)
64
 
65
SYSCTL_NODE(_net_link_ether, PF_INET, inet, CTLFLAG_RW, 0, "");
66
 
67
/* timer values */
68
static int arpt_prune = (5*60*1); /* walk list every 5 minutes */
69
static int arpt_keep = (20*60); /* once resolved, good for 20 more minutes */
70
static int arpt_down = 20;      /* once declared down, don't send for 20 sec */
71
 
72
SYSCTL_INT(_net_link_ether_inet, OID_AUTO, prune_intvl, CTLFLAG_RW,
73
           &arpt_prune, 0, "");
74
SYSCTL_INT(_net_link_ether_inet, OID_AUTO, max_age, CTLFLAG_RW,
75
           &arpt_keep, 0, "");
76
SYSCTL_INT(_net_link_ether_inet, OID_AUTO, host_down_time, CTLFLAG_RW,
77
           &arpt_down, 0, "");
78
 
79
#define rt_expire rt_rmx.rmx_expire
80
 
81
struct llinfo_arp {
82
        LIST_ENTRY(llinfo_arp) la_le;
83
        struct  rtentry *la_rt;
84
        struct  mbuf *la_hold;          /* last packet until resolved/timeout */
85
        long    la_asked;               /* last time we QUERIED for this addr */
86
#define la_timer la_rt->rt_rmx.rmx_expire /* deletion time in seconds */
87
};
88
 
89
static  LIST_HEAD(, llinfo_arp) llinfo_arp;
90
 
91
struct  ifqueue arpintrq = {0, 0, 0, 50};
92
static int      arp_inuse, arp_allocated;
93
 
94
static int      arp_maxtries = 5;
95
static int      useloopback = 1; /* use loopback interface for local traffic */
96
static int      arp_proxyall = 0;
97
 
98
SYSCTL_INT(_net_link_ether_inet, OID_AUTO, maxtries, CTLFLAG_RW,
99
           &arp_maxtries, 0, "");
100
SYSCTL_INT(_net_link_ether_inet, OID_AUTO, useloopback, CTLFLAG_RW,
101
           &useloopback, 0, "");
102
SYSCTL_INT(_net_link_ether_inet, OID_AUTO, proxyall, CTLFLAG_RW,
103
           &arp_proxyall, 0, "");
104
 
105
static void     arp_rtrequest __P((int, struct rtentry *, struct sockaddr *));
106
static void     arprequest __P((struct arpcom *, u_long *, u_long *, u_char *));
107
void    arpintr __P((void));
108
static void     arptfree __P((struct llinfo_arp *));
109
static void     arptimer __P((void *));
110
static struct llinfo_arp
111
                *arplookup __P((u_long, int, int));
112
static void     in_arpinput __P((struct mbuf *));
113
 
114
/*
115
 * Timeout routine.  Age arp_tab entries periodically.
116
 */
117
/* ARGSUSED */
118
static void
119
arptimer(ignored_arg)
120
        void *ignored_arg;
121
{
122
        int s = splnet();
123
        register struct llinfo_arp *la = llinfo_arp.lh_first;
124
        struct llinfo_arp *ola;
125
 
126
        timeout(arptimer, (caddr_t)0, arpt_prune * hz);
127
        while ((ola = la) != 0) {
128
                register struct rtentry *rt = la->la_rt;
129
                la = la->la_le.le_next;
130
                if (rt->rt_expire && rt->rt_expire <= rtems_bsdnet_seconds_since_boot())
131
                        arptfree(ola); /* timer has expired, clear */
132
        }
133
        splx(s);
134
}
135
 
136
/*
137
 * Parallel to llc_rtrequest.
138
 */
139
static void
140
arp_rtrequest(req, rt, sa)
141
        int req;
142
        register struct rtentry *rt;
143
        struct sockaddr *sa;
144
{
145
        register struct sockaddr *gate = rt->rt_gateway;
146
        register struct llinfo_arp *la = (struct llinfo_arp *)rt->rt_llinfo;
147
        static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
148
        static int arpinit_done;
149
 
150
        if (!arpinit_done) {
151
                arpinit_done = 1;
152
                LIST_INIT(&llinfo_arp);
153
                timeout(arptimer, (caddr_t)0, hz);
154
        }
155
        if (rt->rt_flags & RTF_GATEWAY)
156
                return;
157
        switch (req) {
158
 
159
        case RTM_ADD:
160
                /*
161
                 * XXX: If this is a manually added route to interface
162
                 * such as older version of routed or gated might provide,
163
                 * restore cloning bit.
164
                 */
165
                if ((rt->rt_flags & RTF_HOST) == 0 &&
166
                    SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff)
167
                        rt->rt_flags |= RTF_CLONING;
168
                if (rt->rt_flags & RTF_CLONING) {
169
                        /*
170
                         * Case 1: This route should come from a route to iface.
171
                         */
172
                        rt_setgate(rt, rt_key(rt),
173
                                        (struct sockaddr *)&null_sdl);
174
                        gate = rt->rt_gateway;
175
                        SDL(gate)->sdl_type = rt->rt_ifp->if_type;
176
                        SDL(gate)->sdl_index = rt->rt_ifp->if_index;
177
                        rt->rt_expire = rtems_bsdnet_seconds_since_boot();
178
                        break;
179
                }
180
                /* Announce a new entry if requested. */
181
                if (rt->rt_flags & RTF_ANNOUNCE)
182
                        arprequest((struct arpcom *)rt->rt_ifp,
183
                            &SIN(rt_key(rt))->sin_addr.s_addr,
184
                            &SIN(rt_key(rt))->sin_addr.s_addr,
185
                            (u_char *)LLADDR(SDL(gate)));
186
                /*FALLTHROUGH*/
187
        case RTM_RESOLVE:
188
                if (gate->sa_family != AF_LINK ||
189
                    gate->sa_len < sizeof(null_sdl)) {
190
                        log(LOG_DEBUG, "arp_rtrequest: bad gateway value\n");
191
                        break;
192
                }
193
                SDL(gate)->sdl_type = rt->rt_ifp->if_type;
194
                SDL(gate)->sdl_index = rt->rt_ifp->if_index;
195
                if (la != 0)
196
                        break; /* This happens on a route change */
197
                /*
198
                 * Case 2:  This route may come from cloning, or a manual route
199
                 * add with a LL address.
200
                 */
201
                R_Malloc(la, struct llinfo_arp *, sizeof(*la));
202
                rt->rt_llinfo = (caddr_t)la;
203
                if (la == 0) {
204
                        log(LOG_DEBUG, "arp_rtrequest: malloc failed\n");
205
                        break;
206
                }
207
                arp_inuse++, arp_allocated++;
208
                Bzero(la, sizeof(*la));
209
                la->la_rt = rt;
210
                rt->rt_flags |= RTF_LLINFO;
211
                LIST_INSERT_HEAD(&llinfo_arp, la, la_le);
212
 
213
                /*
214
                 * This keeps the multicast addresses from showing up
215
                 * in `arp -a' listings as unresolved.  It's not actually
216
                 * functional.  Then the same for broadcast.
217
                 */
218
                if (IN_MULTICAST(ntohl(SIN(rt_key(rt))->sin_addr.s_addr))) {
219
                        ETHER_MAP_IP_MULTICAST(&SIN(rt_key(rt))->sin_addr,
220
                                               LLADDR(SDL(gate)));
221
                        SDL(gate)->sdl_alen = 6;
222
                        rt->rt_expire = 0;
223
                }
224
                if (in_broadcast(SIN(rt_key(rt))->sin_addr, rt->rt_ifp)) {
225
                        memcpy(LLADDR(SDL(gate)), etherbroadcastaddr, 6);
226
                        SDL(gate)->sdl_alen = 6;
227
                        rt->rt_expire = 0;
228
                }
229
 
230
                if (SIN(rt_key(rt))->sin_addr.s_addr ==
231
                    (IA_SIN(rt->rt_ifa))->sin_addr.s_addr) {
232
                    /*
233
                     * This test used to be
234
                     *  if (loif.if_flags & IFF_UP)
235
                     * It allowed local traffic to be forced
236
                     * through the hardware by configuring the loopback down.
237
                     * However, it causes problems during network configuration
238
                     * for boards that can't receive packets they send.
239
                     * It is now necessary to clear "useloopback" and remove
240
                     * the route to force traffic out to the hardware.
241
                     */
242
                        rt->rt_expire = 0;
243
                        Bcopy(((struct arpcom *)rt->rt_ifp)->ac_enaddr,
244
                                LLADDR(SDL(gate)), SDL(gate)->sdl_alen = 6);
245
                        if (useloopback)
246
                                rt->rt_ifp = loif;
247
 
248
                }
249
                break;
250
 
251
        case RTM_DELETE:
252
                if (la == 0)
253
                        break;
254
                arp_inuse--;
255
                LIST_REMOVE(la, la_le);
256
                rt->rt_llinfo = 0;
257
                rt->rt_flags &= ~RTF_LLINFO;
258
                if (la->la_hold)
259
                        m_freem(la->la_hold);
260
                Free((caddr_t)la);
261
        }
262
}
263
 
264
/*
265
 * Broadcast an ARP request. Caller specifies:
266
 *      - arp header source ip address
267
 *      - arp header target ip address
268
 *      - arp header source ethernet address
269
 */
270
static void
271
arprequest(ac, sip, tip, enaddr)
272
        register struct arpcom *ac;
273
        register u_long *sip, *tip;
274
        register u_char *enaddr;
275
{
276
        register struct mbuf *m;
277
        register struct ether_header *eh;
278
        register struct ether_arp *ea;
279
        struct sockaddr sa;
280
 
281
        if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL)
282
                return;
283
        m->m_len = sizeof(*ea);
284
        m->m_pkthdr.len = sizeof(*ea);
285
        MH_ALIGN(m, sizeof(*ea));
286
        ea = mtod(m, struct ether_arp *);
287
        eh = (struct ether_header *)sa.sa_data;
288
        bzero((caddr_t)ea, sizeof (*ea));
289
        (void)memcpy(eh->ether_dhost, etherbroadcastaddr, sizeof(eh->ether_dhost));
290
        eh->ether_type = htons(ETHERTYPE_ARP);  /* if_output will not swap */
291
        ea->arp_hrd = htons(ARPHRD_ETHER);
292
        ea->arp_pro = htons(ETHERTYPE_IP);
293
        ea->arp_hln = sizeof(ea->arp_sha);      /* hardware address length */
294
        ea->arp_pln = sizeof(ea->arp_spa);      /* protocol address length */
295
        ea->arp_op = htons(ARPOP_REQUEST);
296
        (void)memcpy(ea->arp_sha, enaddr, sizeof(ea->arp_sha));
297
        (void)memcpy(ea->arp_spa, sip, sizeof(ea->arp_spa));
298
        (void)memcpy(ea->arp_tpa, tip, sizeof(ea->arp_tpa));
299
        sa.sa_family = AF_UNSPEC;
300
        sa.sa_len = sizeof(sa);
301
        (*ac->ac_if.if_output)(&ac->ac_if, m, &sa, (struct rtentry *)0);
302
}
303
 
304
/*
305
 * Resolve an IP address into an ethernet address.  If success,
306
 * desten is filled in.  If there is no entry in arptab,
307
 * set one up and broadcast a request for the IP address.
308
 * Hold onto this mbuf and resend it once the address
309
 * is finally resolved.  A return value of 1 indicates
310
 * that desten has been filled in and the packet should be sent
311
 * normally; a 0 return indicates that the packet has been
312
 * taken over here, either now or for later transmission.
313
 */
314
int
315
arpresolve(ac, rt, m, dst, desten, rt0)
316
        register struct arpcom *ac;
317
        register struct rtentry *rt;
318
        struct mbuf *m;
319
        register struct sockaddr *dst;
320
        register u_char *desten;
321
        struct rtentry *rt0;
322
{
323
        register struct llinfo_arp *la;
324
        struct sockaddr_dl *sdl;
325
 
326
        if (m->m_flags & M_BCAST) {     /* broadcast */
327
                (void)memcpy(desten, etherbroadcastaddr, sizeof(etherbroadcastaddr));
328
                return (1);
329
        }
330
        if (m->m_flags & M_MCAST) {     /* multicast */
331
                ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten);
332
                return(1);
333
        }
334
        if (rt)
335
                la = (struct llinfo_arp *)rt->rt_llinfo;
336
        else {
337
                la = arplookup(SIN(dst)->sin_addr.s_addr, 1, 0);
338
                if (la)
339
                        rt = la->la_rt;
340
        }
341
        if (la == 0 || rt == 0) {
342
                log(LOG_DEBUG, "arpresolve: can't allocate llinfo for %s\n",
343
                        inet_ntoa(SIN(dst)->sin_addr));
344
                m_freem(m);
345
                return (0);
346
        }
347
        sdl = SDL(rt->rt_gateway);
348
        /*
349
         * Check the address family and length is valid, the address
350
         * is resolved; otherwise, try to resolve.
351
         */
352
        if ((rt->rt_expire == 0 || rt->rt_expire > rtems_bsdnet_seconds_since_boot()) &&
353
            sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) {
354
                bcopy(LLADDR(sdl), desten, sdl->sdl_alen);
355
                return 1;
356
        }
357
        /*
358
         * There is an arptab entry, but no ethernet address
359
         * response yet.  Replace the held mbuf with this
360
         * latest one.
361
         */
362
        if (la->la_hold)
363
                m_freem(la->la_hold);
364
        la->la_hold = m;
365
        if (rt->rt_expire) {
366
                rt->rt_flags &= ~RTF_REJECT;
367
                if (la->la_asked == 0 || rt->rt_expire != rtems_bsdnet_seconds_since_boot()) {
368
                        rt->rt_expire = rtems_bsdnet_seconds_since_boot();
369
                        if (la->la_asked++ < arp_maxtries)
370
                            arprequest(ac,
371
                                &(SIN(rt->rt_ifa->ifa_addr)->sin_addr.s_addr),
372
                                &(SIN(dst)->sin_addr.s_addr),
373
                                ac->ac_enaddr);
374
                        else {
375
                                rt->rt_flags |= RTF_REJECT;
376
                                rt->rt_expire += arpt_down;
377
                                la->la_asked = 0;
378
                        }
379
 
380
                }
381
        }
382
        return (0);
383
}
384
 
385
/*
386
 * Common length and type checks are done here,
387
 * then the protocol-specific routine is called.
388
 */
389
void
390
arpintr(void)
391
{
392
        register struct mbuf *m;
393
        register struct arphdr *ar;
394
        int s;
395
 
396
        while (arpintrq.ifq_head) {
397
                s = splimp();
398
                IF_DEQUEUE(&arpintrq, m);
399
                splx(s);
400
                if (m == 0 || (m->m_flags & M_PKTHDR) == 0)
401
                        panic("arpintr");
402
                if (m->m_len >= sizeof(struct arphdr) &&
403
                    (ar = mtod(m, struct arphdr *)) &&
404
                    ntohs(ar->ar_hrd) == ARPHRD_ETHER &&
405
                    m->m_len >=
406
                      sizeof(struct arphdr) + 2 * ar->ar_hln + 2 * ar->ar_pln)
407
 
408
                            switch (ntohs(ar->ar_pro)) {
409
 
410
                            case ETHERTYPE_IP:
411
                                    in_arpinput(m);
412
                                    continue;
413
                            }
414
                m_freem(m);
415
        }
416
}
417
 
418
NETISR_SET(NETISR_ARP, arpintr);
419
 
420
/*
421
 * ARP for Internet protocols on 10 Mb/s Ethernet.
422
 * Algorithm is that given in RFC 826.
423
 * In addition, a sanity check is performed on the sender
424
 * protocol address, to catch impersonators.
425
 * We no longer handle negotiations for use of trailer protocol:
426
 * Formerly, ARP replied for protocol type ETHERTYPE_TRAIL sent
427
 * along with IP replies if we wanted trailers sent to us,
428
 * and also sent them in response to IP replies.
429
 * This allowed either end to announce the desire to receive
430
 * trailer packets.
431
 * We no longer reply to requests for ETHERTYPE_TRAIL protocol either,
432
 * but formerly didn't normally send requests.
433
 */
434
static void
435
in_arpinput(m)
436
        struct mbuf *m;
437
{
438
        register struct ether_arp *ea;
439
        register struct arpcom *ac = (struct arpcom *)m->m_pkthdr.rcvif;
440
        struct ether_header *eh;
441
        register struct llinfo_arp *la = 0;
442
        register struct rtentry *rt;
443
        struct in_ifaddr *ia, *maybe_ia = 0;
444
        struct sockaddr_dl *sdl;
445
        struct sockaddr sa;
446
        struct in_addr isaddr, itaddr, myaddr;
447
        int op;
448
 
449
        ea = mtod(m, struct ether_arp *);
450
        op = ntohs(ea->arp_op);
451
        (void)memcpy(&isaddr, ea->arp_spa, sizeof (isaddr));
452
        (void)memcpy(&itaddr, ea->arp_tpa, sizeof (itaddr));
453
        for (ia = in_ifaddr; ia; ia = ia->ia_next)
454
                if (ia->ia_ifp == &ac->ac_if) {
455
                        maybe_ia = ia;
456
                        if ((itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) ||
457
                             (isaddr.s_addr == ia->ia_addr.sin_addr.s_addr))
458
                                break;
459
                }
460
        if (maybe_ia == 0) {
461
                m_freem(m);
462
                return;
463
        }
464
        myaddr = ia ? ia->ia_addr.sin_addr : maybe_ia->ia_addr.sin_addr;
465
        if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)ac->ac_enaddr,
466
            sizeof (ea->arp_sha))) {
467
                m_freem(m);     /* it's from me, ignore it. */
468
                return;
469
        }
470
        if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)etherbroadcastaddr,
471
            sizeof (ea->arp_sha))) {
472
                log(LOG_ERR,
473
                    "arp: ether address is broadcast for IP address %s!\n",
474
                    inet_ntoa(isaddr));
475
                m_freem(m);
476
                return;
477
        }
478
        if (isaddr.s_addr == myaddr.s_addr) {
479
                log(LOG_ERR,
480
                   "arp: %6D is using my IP address %s!\n",
481
                   ea->arp_sha, ":", inet_ntoa(isaddr));
482
                itaddr = myaddr;
483
                goto reply;
484
        }
485
        la = arplookup(isaddr.s_addr, itaddr.s_addr == myaddr.s_addr, 0);
486
        if (la && (rt = la->la_rt) && (sdl = SDL(rt->rt_gateway))) {
487
                if (sdl->sdl_alen &&
488
                    bcmp((caddr_t)ea->arp_sha, LLADDR(sdl), sdl->sdl_alen))
489
                        log(LOG_INFO, "arp: %s moved from %6D to %6D\n",
490
                            inet_ntoa(isaddr), (u_char *)LLADDR(sdl), ":",
491
                            ea->arp_sha, ":");
492
                (void)memcpy(LLADDR(sdl), ea->arp_sha, sizeof(ea->arp_sha));
493
                sdl->sdl_alen = sizeof(ea->arp_sha);
494
                if (rt->rt_expire)
495
                        rt->rt_expire = rtems_bsdnet_seconds_since_boot() + arpt_keep;
496
                rt->rt_flags &= ~RTF_REJECT;
497
                la->la_asked = 0;
498
                if (la->la_hold) {
499
                        (*ac->ac_if.if_output)(&ac->ac_if, la->la_hold,
500
                                rt_key(rt), rt);
501
                        la->la_hold = 0;
502
                }
503
        }
504
reply:
505
        if (op != ARPOP_REQUEST) {
506
                m_freem(m);
507
                return;
508
        }
509
        if (itaddr.s_addr == myaddr.s_addr) {
510
                /* I am the target */
511
                (void)memcpy(ea->arp_tha, ea->arp_sha, sizeof(ea->arp_sha));
512
                (void)memcpy(ea->arp_sha, ac->ac_enaddr, sizeof(ea->arp_sha));
513
        } else {
514
                la = arplookup(itaddr.s_addr, 0, SIN_PROXY);
515
                if (la == NULL) {
516
                        struct sockaddr_in sin;
517
 
518
                        if (!arp_proxyall) {
519
                                m_freem(m);
520
                                return;
521
                        }
522
 
523
                        bzero(&sin, sizeof sin);
524
                        sin.sin_family = AF_INET;
525
                        sin.sin_len = sizeof sin;
526
                        sin.sin_addr = itaddr;
527
 
528
                        rt = rtalloc1((struct sockaddr *)&sin, 0, 0UL);
529
                        if (!rt) {
530
                                m_freem(m);
531
                                return;
532
                        }
533
                        /*
534
                         * Don't send proxies for nodes on the same interface
535
                         * as this one came out of, or we'll get into a fight
536
                         * over who claims what Ether address.
537
                         */
538
                        if (rt->rt_ifp == &ac->ac_if) {
539
                                rtfree(rt);
540
                                m_freem(m);
541
                                return;
542
                        }
543
                        (void)memcpy(ea->arp_tha, ea->arp_sha, sizeof(ea->arp_sha));
544
                        (void)memcpy(ea->arp_sha, ac->ac_enaddr, sizeof(ea->arp_sha));
545
                        rtfree(rt);
546
#ifdef DEBUG_PROXY
547
                        printf("arp: proxying for %s\n",
548
                               inet_ntoa(itaddr));
549
#endif
550
                } else {
551
                        rt = la->la_rt;
552
                        (void)memcpy(ea->arp_tha, ea->arp_sha, sizeof(ea->arp_sha));
553
                        sdl = SDL(rt->rt_gateway);
554
                        (void)memcpy(ea->arp_sha, LLADDR(sdl), sizeof(ea->arp_sha));
555
                }
556
        }
557
 
558
        (void)memcpy(ea->arp_tpa, ea->arp_spa, sizeof(ea->arp_spa));
559
        (void)memcpy(ea->arp_spa, &itaddr, sizeof(ea->arp_spa));
560
        ea->arp_op = htons(ARPOP_REPLY);
561
        ea->arp_pro = htons(ETHERTYPE_IP); /* let's be sure! */
562
        eh = (struct ether_header *)sa.sa_data;
563
        (void)memcpy(eh->ether_dhost, ea->arp_tha, sizeof(eh->ether_dhost));
564
        eh->ether_type = htons(ETHERTYPE_ARP);
565
        sa.sa_family = AF_UNSPEC;
566
        sa.sa_len = sizeof(sa);
567
        (*ac->ac_if.if_output)(&ac->ac_if, m, &sa, (struct rtentry *)0);
568
        return;
569
}
570
 
571
/*
572
 * Free an arp entry.
573
 */
574
static void
575
arptfree(la)
576
        register struct llinfo_arp *la;
577
{
578
        register struct rtentry *rt = la->la_rt;
579
        register struct sockaddr_dl *sdl;
580
        if (rt == 0)
581
                panic("arptfree");
582
        if (rt->rt_refcnt > 0 && (sdl = SDL(rt->rt_gateway)) &&
583
            sdl->sdl_family == AF_LINK) {
584
                sdl->sdl_alen = 0;
585
                la->la_asked = 0;
586
                rt->rt_flags &= ~RTF_REJECT;
587
                return;
588
        }
589
        rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0, rt_mask(rt),
590
                        0, (struct rtentry **)0);
591
}
592
/*
593
 * Lookup or enter a new address in arptab.
594
 */
595
static struct llinfo_arp *
596
arplookup(addr, create, proxy)
597
        u_long addr;
598
        int create, proxy;
599
{
600
        register struct rtentry *rt;
601
        static struct sockaddr_inarp sin = {sizeof(sin), AF_INET };
602
        const char *why = 0;
603
 
604
        sin.sin_addr.s_addr = addr;
605
        sin.sin_other = proxy ? SIN_PROXY : 0;
606
        rt = rtalloc1((struct sockaddr *)&sin, create, 0UL);
607
        if (rt == 0)
608
                return (0);
609
        rt->rt_refcnt--;
610
 
611
        if (rt->rt_flags & RTF_GATEWAY)
612
                why = "host is not on local network";
613
        else if ((rt->rt_flags & RTF_LLINFO) == 0)
614
                why = "could not allocate llinfo";
615
        else if (rt->rt_gateway->sa_family != AF_LINK)
616
                why = "gateway route is not ours";
617
 
618
        if (why && create) {
619
                log(LOG_DEBUG, "arplookup %s failed: %s\n",
620
                    inet_ntoa(sin.sin_addr), why);
621
                return 0;
622
        } else if (why) {
623
                return 0;
624
        }
625
        return ((struct llinfo_arp *)rt->rt_llinfo);
626
}
627
 
628
void
629
arp_ifinit(ac, ifa)
630
        struct arpcom *ac;
631
        struct ifaddr *ifa;
632
{
633
        if (ntohl(IA_SIN(ifa)->sin_addr.s_addr) != INADDR_ANY)
634
                arprequest(ac, &(IA_SIN(ifa)->sin_addr.s_addr),
635
                               &(IA_SIN(ifa)->sin_addr.s_addr), ac->ac_enaddr);
636
        ifa->ifa_rtrequest = arp_rtrequest;
637
        ifa->ifa_flags |= RTF_CLONING;
638
}

powered by: WebSVN 2.1.0

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