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

Subversion Repositories openrisc_me

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

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

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

powered by: WebSVN 2.1.0

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