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/] [net/] [rtsock.c] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      src/sys/net/rtsock.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) 1988, 1991, 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
 *      @(#)rtsock.c    8.5 (Berkeley) 11/2/94
55
 * $FreeBSD: src/sys/net/rtsock.c,v 1.44.2.4 2001/07/11 09:37:37 ume Exp $
56
 */
57
 
58
 
59
#include <sys/param.h>
60
#include <sys/malloc.h>
61
#include <sys/mbuf.h>
62
#include <sys/socket.h>
63
#include <sys/socketvar.h>
64
#include <sys/domain.h>
65
#include <sys/protosw.h>
66
 
67
#include <net/if.h>
68
#include <net/route.h>
69
#include <net/raw_cb.h>
70
 
71
static struct   sockaddr route_dst = { 2, PF_ROUTE, };
72
static struct   sockaddr route_src = { 2, PF_ROUTE, };
73
static struct   sockaddr sa_zero   = { sizeof(sa_zero), AF_INET, };
74
static struct   sockproto route_proto = { PF_ROUTE, };
75
 
76
struct walkarg {
77
        int     w_tmemsize;
78
        int     w_op, w_arg;
79
        caddr_t w_tmem;
80
        struct sysctl_req *w_req;
81
};
82
 
83
static struct mbuf *
84
                rt_msg1 __P((int, struct rt_addrinfo *));
85
static int      rt_msg2 __P((int,
86
                    struct rt_addrinfo *, caddr_t, struct walkarg *));
87
static int      rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *));
88
static int       route_output __P((struct mbuf *, struct socket *));
89
static void      rt_setmetrics __P((u_long, struct rt_metrics *, struct rt_metrics *));
90
 
91
/* Sleazy use of local variables throughout file, warning!!!! */
92
#define dst     info.rti_info[RTAX_DST]
93
#define gate    info.rti_info[RTAX_GATEWAY]
94
#define netmask info.rti_info[RTAX_NETMASK]
95
#define genmask info.rti_info[RTAX_GENMASK]
96
#define ifpaddr info.rti_info[RTAX_IFP]
97
#define ifaaddr info.rti_info[RTAX_IFA]
98
#define brdaddr info.rti_info[RTAX_BRD]
99
 
100
/*
101
 * It really doesn't make any sense at all for this code to share much
102
 * with raw_usrreq.c, since its functionality is so restricted.  XXX
103
 */
104
static int
105
rts_abort(struct socket *so)
106
{
107
        int s, error;
108
        s = splnet();
109
        error = raw_usrreqs.pru_abort(so);
110
        splx(s);
111
        return error;
112
}
113
 
114
/* pru_accept is EOPNOTSUPP */
115
 
116
static int
117
rts_attach(struct socket *so, int proto, struct proc *p)
118
{
119
        struct rawcb *rp;
120
        int s, error;
121
 
122
        if (sotorawcb(so) != 0)
123
                return EISCONN; /* XXX panic? */
124
        MALLOC(rp, struct rawcb *, sizeof *rp, M_PCB, M_WAITOK); /* XXX */
125
        if (rp == 0)
126
                return ENOBUFS;
127
        bzero(rp, sizeof *rp);
128
 
129
        /*
130
         * The splnet() is necessary to block protocols from sending
131
         * error notifications (like RTM_REDIRECT or RTM_LOSING) while
132
         * this PCB is extant but incompletely initialized.
133
         * Probably we should try to do more of this work beforehand and
134
         * eliminate the spl.
135
         */
136
        s = splnet();
137
        so->so_pcb = (caddr_t)rp;
138
        error = raw_usrreqs.pru_attach(so, proto, p);
139
        rp = sotorawcb(so);
140
        if (error) {
141
                splx(s);
142
                free(rp, M_PCB);
143
                return error;
144
        }
145
        switch(rp->rcb_proto.sp_protocol) {
146
        case AF_INET:
147
                route_cb.ip_count++;
148
                break;
149
        case AF_INET6:
150
                route_cb.ip6_count++;
151
                break;
152
        case AF_IPX:
153
                route_cb.ipx_count++;
154
                break;
155
        case AF_NS:
156
                route_cb.ns_count++;
157
                break;
158
        }
159
        rp->rcb_faddr = &route_src;
160
        route_cb.any_count++;
161
        soisconnected(so);
162
        so->so_options |= SO_USELOOPBACK;
163
        splx(s);
164
        return 0;
165
}
166
 
167
static int
168
rts_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
169
{
170
        int s, error;
171
        s = splnet();
172
        error = raw_usrreqs.pru_bind(so, nam, p); /* xxx just EINVAL */
173
        splx(s);
174
        return error;
175
}
176
 
177
static int
178
rts_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
179
{
180
        int s, error;
181
        s = splnet();
182
        error = raw_usrreqs.pru_connect(so, nam, p); /* XXX just EINVAL */
183
        splx(s);
184
        return error;
185
}
186
 
187
/* pru_connect2 is EOPNOTSUPP */
188
/* pru_control is EOPNOTSUPP */
189
 
190
static int
191
rts_detach(struct socket *so)
192
{
193
        struct rawcb *rp = sotorawcb(so);
194
        int s, error;
195
 
196
        s = splnet();
197
        if (rp != 0) {
198
                switch(rp->rcb_proto.sp_protocol) {
199
                case AF_INET:
200
                        route_cb.ip_count--;
201
                        break;
202
                case AF_INET6:
203
                        route_cb.ip6_count--;
204
                        break;
205
                case AF_IPX:
206
                        route_cb.ipx_count--;
207
                        break;
208
                case AF_NS:
209
                        route_cb.ns_count--;
210
                        break;
211
                }
212
                route_cb.any_count--;
213
        }
214
        error = raw_usrreqs.pru_detach(so);
215
        splx(s);
216
        return error;
217
}
218
 
219
static int
220
rts_disconnect(struct socket *so)
221
{
222
        int s, error;
223
        s = splnet();
224
        error = raw_usrreqs.pru_disconnect(so);
225
        splx(s);
226
        return error;
227
}
228
 
229
/* pru_listen is EOPNOTSUPP */
230
 
231
static int
232
rts_peeraddr(struct socket *so, struct sockaddr **nam)
233
{
234
        int s, error;
235
        s = splnet();
236
        error = raw_usrreqs.pru_peeraddr(so, nam);
237
        splx(s);
238
        return error;
239
}
240
 
241
/* pru_rcvd is EOPNOTSUPP */
242
/* pru_rcvoob is EOPNOTSUPP */
243
 
244
static int
245
rts_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
246
         struct mbuf *control, struct proc *p)
247
{
248
        int s, error;
249
        s = splnet();
250
        error = raw_usrreqs.pru_send(so, flags, m, nam, control, p);
251
        splx(s);
252
        return error;
253
}
254
 
255
/* pru_sense is null */
256
 
257
static int
258
rts_shutdown(struct socket *so)
259
{
260
        int s, error;
261
        s = splnet();
262
        error = raw_usrreqs.pru_shutdown(so);
263
        splx(s);
264
        return error;
265
}
266
 
267
static int
268
rts_sockaddr(struct socket *so, struct sockaddr **nam)
269
{
270
        int s, error;
271
        s = splnet();
272
        error = raw_usrreqs.pru_sockaddr(so, nam);
273
        splx(s);
274
        return error;
275
}
276
 
277
static struct pr_usrreqs route_usrreqs = {
278
        rts_abort, pru_accept_notsupp, rts_attach, rts_bind, rts_connect,
279
        pru_connect2_notsupp, pru_control_notsupp, rts_detach, rts_disconnect,
280
        pru_listen_notsupp, rts_peeraddr, pru_rcvd_notsupp, pru_rcvoob_notsupp,
281
        rts_send, pru_sense_null, rts_shutdown, rts_sockaddr,
282
        sosend, soreceive, sopoll
283
};
284
 
285
/*ARGSUSED*/
286
static int
287
route_output(m, so)
288
        register struct mbuf *m;
289
        struct socket *so;
290
{
291
        register struct rt_msghdr *rtm = 0;
292
        register struct rtentry *rt = 0;
293
        struct rtentry *saved_nrt = 0;
294
        struct radix_node_head *rnh;
295
        struct rt_addrinfo info;
296
        int len, error = 0;
297
        struct ifnet *ifp = 0;
298
        struct ifaddr *ifa = 0;
299
 
300
#define senderr(e) { error = e; goto flush;}
301
        if (m == 0 || ((m->m_len < sizeof(long)) &&
302
                       (m = m_pullup(m, sizeof(long))) == 0))
303
                return (ENOBUFS);
304
        if ((m->m_flags & M_PKTHDR) == 0)
305
                panic("route_output");
306
        len = m->m_pkthdr.len;
307
        if (len < sizeof(*rtm) ||
308
            len != mtod(m, struct rt_msghdr *)->rtm_msglen) {
309
                dst = 0;
310
                senderr(EINVAL);
311
        }
312
        R_Malloc(rtm, struct rt_msghdr *, len);
313
        if (rtm == 0) {
314
                dst = 0;
315
                senderr(ENOBUFS);
316
        }
317
        m_copydata(m, 0, len, (caddr_t)rtm);
318
        if (rtm->rtm_version != RTM_VERSION) {
319
                dst = 0;
320
                senderr(EPROTONOSUPPORT);
321
        }
322
        rtm->rtm_pid = 0;
323
        info.rti_addrs = rtm->rtm_addrs;
324
        if (rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info)) {
325
                dst = 0;
326
                senderr(EINVAL);
327
        }
328
        if (dst == 0 || (dst->sa_family >= AF_MAX)
329
            || (gate != 0 && (gate->sa_family >= AF_MAX)))
330
                senderr(EINVAL);
331
        if (genmask) {
332
                struct radix_node *t;
333
                t = rn_addmask((caddr_t)genmask, 0, 1);
334
                if (t && genmask->sa_len >= ((struct sockaddr *)t->rn_key)->sa_len &&
335
                    Bcmp((caddr_t *)genmask + 1, (caddr_t *)t->rn_key + 1,
336
                    ((struct sockaddr *)t->rn_key)->sa_len) - 1)
337
                        genmask = (struct sockaddr *)(t->rn_key);
338
                else
339
                        senderr(ENOBUFS);
340
        }
341
        switch (rtm->rtm_type) {
342
 
343
        case RTM_ADD:
344
                if (gate == 0)
345
                        senderr(EINVAL);
346
                error = rtrequest(RTM_ADD, dst, gate, netmask,
347
                                        rtm->rtm_flags, &saved_nrt);
348
                if (error == 0 && saved_nrt) {
349
                        rt_setmetrics(rtm->rtm_inits,
350
                                &rtm->rtm_rmx, &saved_nrt->rt_rmx);
351
                        saved_nrt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
352
                        saved_nrt->rt_rmx.rmx_locks |=
353
                                (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
354
                        saved_nrt->rt_refcnt--;
355
                        saved_nrt->rt_genmask = genmask;
356
                }
357
                break;
358
 
359
        case RTM_DELETE:
360
                error = rtrequest(RTM_DELETE, dst, gate, netmask,
361
                                rtm->rtm_flags, &saved_nrt);
362
                if (error == 0) {
363
                        if ((rt = saved_nrt))
364
                                rt->rt_refcnt++;
365
                        goto report;
366
                }
367
                break;
368
 
369
        case RTM_GET:
370
        case RTM_CHANGE:
371
        case RTM_LOCK:
372
                if ((rnh = rt_tables[dst->sa_family]) == 0) {
373
                        senderr(EAFNOSUPPORT);
374
                } else if ((rt = (struct rtentry *)
375
                                rnh->rnh_lookup(dst, netmask, rnh)) != NULL)
376
                        rt->rt_refcnt++;
377
                else
378
                        senderr(ESRCH);
379
                switch(rtm->rtm_type) {
380
 
381
                case RTM_GET:
382
                report:
383
                        dst = rt_key(rt);
384
                        gate = rt->rt_gateway;
385
                        netmask = rt_mask(rt);
386
                        genmask = rt->rt_genmask;
387
                        if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
388
                                ifp = rt->rt_ifp;
389
                                if (ifp) {
390
                                        ifpaddr = ifp->if_addrhead.tqh_first->ifa_addr;
391
                                        ifaaddr = rt->rt_ifa->ifa_addr;
392
                                        rtm->rtm_index = ifp->if_index;
393
                                } else {
394
                                        ifpaddr = 0;
395
                                        ifaaddr = 0;
396
                            }
397
                        }
398
                        len = rt_msg2(rtm->rtm_type, &info, (caddr_t)0,
399
                                (struct walkarg *)0);
400
                        if (len > rtm->rtm_msglen) {
401
                                struct rt_msghdr *new_rtm;
402
                                R_Malloc(new_rtm, struct rt_msghdr *, len);
403
                                if (new_rtm == 0)
404
                                        senderr(ENOBUFS);
405
                                Bcopy(rtm, new_rtm, rtm->rtm_msglen);
406
                                Free(rtm); rtm = new_rtm;
407
                        }
408
                        (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm,
409
                                (struct walkarg *)0);
410
                        rtm->rtm_flags = rt->rt_flags;
411
                        rtm->rtm_rmx = rt->rt_rmx;
412
                        rtm->rtm_addrs = info.rti_addrs;
413
                        break;
414
 
415
                case RTM_CHANGE:
416
                        if (gate && (error = rt_setgate(rt, rt_key(rt), gate)))
417
                                senderr(error);
418
 
419
                        /*
420
                         * If they tried to change things but didn't specify
421
                         * the required gateway, then just use the old one.
422
                         * This can happen if the user tries to change the
423
                         * flags on the default route without changing the
424
                         * default gateway.  Changing flags still doesn't work.
425
                         */
426
                        if ((rt->rt_flags & RTF_GATEWAY) && !gate)
427
                                gate = rt->rt_gateway;
428
 
429
                        /* new gateway could require new ifaddr, ifp;
430
                           flags may also be different; ifp may be specified
431
                           by ll sockaddr when protocol address is ambiguous */
432
                        if (ifpaddr && (ifa = ifa_ifwithnet(ifpaddr)) &&
433
                            (ifp = ifa->ifa_ifp) && (ifaaddr || gate))
434
                                ifa = ifaof_ifpforaddr(ifaaddr ? ifaaddr : gate,
435
                                                        ifp);
436
                        else if ((ifaaddr && (ifa = ifa_ifwithaddr(ifaaddr))) ||
437
                                 (gate && (ifa = ifa_ifwithroute(rt->rt_flags,
438
                                                        rt_key(rt), gate))))
439
                                ifp = ifa->ifa_ifp;
440
                        if (ifa) {
441
                                register struct ifaddr *oifa = rt->rt_ifa;
442
                                if (oifa != ifa) {
443
                                    if (oifa && oifa->ifa_rtrequest)
444
                                        oifa->ifa_rtrequest(RTM_DELETE,
445
                                                                rt, gate);
446
                                    IFAFREE(rt->rt_ifa);
447
                                    rt->rt_ifa = ifa;
448
                                    ifa->ifa_refcnt++;
449
                                    rt->rt_ifp = ifp;
450
                                }
451
                        }
452
                        rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
453
                                        &rt->rt_rmx);
454
                        if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
455
                               rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate);
456
                        if (genmask)
457
                                rt->rt_genmask = genmask;
458
                        /*
459
                         * Fall into
460
                         */
461
                case RTM_LOCK:
462
                        rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
463
                        rt->rt_rmx.rmx_locks |=
464
                                (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
465
                        break;
466
                }
467
                break;
468
 
469
        default:
470
                senderr(EOPNOTSUPP);
471
        }
472
 
473
flush:
474
        if (rtm) {
475
                if (error)
476
                        rtm->rtm_errno = error;
477
                else
478
                        rtm->rtm_flags |= RTF_DONE;
479
        }
480
        if (rt)
481
                rtfree(rt);
482
    {
483
        register struct rawcb *rp = 0;
484
        /*
485
         * Check to see if we don't want our own messages.
486
         */
487
        if ((so->so_options & SO_USELOOPBACK) == 0) {
488
                if (route_cb.any_count <= 1) {
489
                        if (rtm)
490
                                Free(rtm);
491
                        m_freem(m);
492
                        return (error);
493
                }
494
                /* There is another listener, so construct message */
495
                rp = sotorawcb(so);
496
        }
497
        if (rtm) {
498
                m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);
499
                if (m->m_pkthdr.len < rtm->rtm_msglen) {
500
                        m_freem(m);
501
                        m = NULL;
502
                } else if (m->m_pkthdr.len > rtm->rtm_msglen)
503
                        m_adj(m, rtm->rtm_msglen - m->m_pkthdr.len);
504
                Free(rtm);
505
        }
506
        if (rp)
507
                rp->rcb_proto.sp_family = 0; /* Avoid us */
508
        if (dst)
509
                route_proto.sp_protocol = dst->sa_family;
510
        if (m)
511
                raw_input(m, &route_proto, &route_src, &route_dst);
512
        if (rp)
513
                rp->rcb_proto.sp_family = PF_ROUTE;
514
    }
515
        return (error);
516
}
517
 
518
static void
519
rt_setmetrics(which, in, out)
520
        u_long which;
521
        register struct rt_metrics *in, *out;
522
{
523
#define metric(f, e) if (which & (f)) out->e = in->e;
524
        metric(RTV_RPIPE, rmx_recvpipe);
525
        metric(RTV_SPIPE, rmx_sendpipe);
526
        metric(RTV_SSTHRESH, rmx_ssthresh);
527
        metric(RTV_RTT, rmx_rtt);
528
        metric(RTV_RTTVAR, rmx_rttvar);
529
        metric(RTV_HOPCOUNT, rmx_hopcount);
530
        metric(RTV_MTU, rmx_mtu);
531
        metric(RTV_EXPIRE, rmx_expire);
532
#undef metric
533
}
534
 
535
#define ROUNDUP(a) \
536
        ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
537
#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
538
 
539
 
540
/*
541
 * Extract the addresses of the passed sockaddrs.
542
 * Do a little sanity checking so as to avoid bad memory references.
543
 * This data is derived straight from userland.
544
 */
545
static int
546
rt_xaddrs(cp, cplim, rtinfo)
547
        register caddr_t cp, cplim;
548
        register struct rt_addrinfo *rtinfo;
549
{
550
        register struct sockaddr *sa;
551
        register int i;
552
 
553
        bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info));
554
        for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
555
                if ((rtinfo->rti_addrs & (1 << i)) == 0)
556
                        continue;
557
                sa = (struct sockaddr *)cp;
558
                /*
559
                 * It won't fit.
560
                 */
561
                if ( (cp + sa->sa_len) > cplim ) {
562
                        return (EINVAL);
563
                }
564
 
565
                /*
566
                 * there are no more.. quit now
567
                 * If there are more bits, they are in error.
568
                 * I've seen this. route(1) can evidently generate these.
569
                 * This causes kernel to core dump.
570
                 * for compatibility, If we see this, point to a safe address.
571
                 */
572
                if (sa->sa_len == 0) {
573
                        rtinfo->rti_info[i] = &sa_zero;
574
                        return (0); /* should be EINVAL but for compat */
575
                }
576
 
577
                /* accept it */
578
                rtinfo->rti_info[i] = sa;
579
                ADVANCE(cp, sa);
580
        }
581
        return (0);
582
}
583
 
584
static struct mbuf *
585
rt_msg1(type, rtinfo)
586
        int type;
587
        register struct rt_addrinfo *rtinfo;
588
{
589
        register struct rt_msghdr *rtm;
590
        register struct mbuf *m;
591
        register int i;
592
        register struct sockaddr *sa;
593
        int len, dlen;
594
 
595
        switch (type) {
596
 
597
        case RTM_DELADDR:
598
        case RTM_NEWADDR:
599
                len = sizeof(struct ifa_msghdr);
600
                break;
601
 
602
        case RTM_DELMADDR:
603
        case RTM_NEWMADDR:
604
                len = sizeof(struct ifma_msghdr);
605
                break;
606
 
607
        case RTM_IFINFO:
608
                len = sizeof(struct if_msghdr);
609
                break;
610
 
611
        default:
612
                len = sizeof(struct rt_msghdr);
613
        }
614
        if (len > MCLBYTES)
615
                panic("rt_msg1");
616
        m = m_gethdr(M_DONTWAIT, MT_DATA);
617
        if (m && len > MHLEN) {
618
                MCLGET(m, M_DONTWAIT);
619
                if ((m->m_flags & M_EXT) == 0) {
620
                        m_free(m);
621
                        m = NULL;
622
                }
623
        }
624
        if (m == 0)
625
                return (m);
626
        m->m_pkthdr.len = m->m_len = len;
627
        m->m_pkthdr.rcvif = 0;
628
        rtm = mtod(m, struct rt_msghdr *);
629
        bzero((caddr_t)rtm, len);
630
        for (i = 0; i < RTAX_MAX; i++) {
631
                if ((sa = rtinfo->rti_info[i]) == NULL)
632
                        continue;
633
                rtinfo->rti_addrs |= (1 << i);
634
                dlen = ROUNDUP(sa->sa_len);
635
                m_copyback(m, len, dlen, (caddr_t)sa);
636
                len += dlen;
637
        }
638
        if (m->m_pkthdr.len != len) {
639
                m_freem(m);
640
                return (NULL);
641
        }
642
        rtm->rtm_msglen = len;
643
        rtm->rtm_version = RTM_VERSION;
644
        rtm->rtm_type = type;
645
        return (m);
646
}
647
 
648
static int
649
rt_msg2(type, rtinfo, cp, w)
650
        int type;
651
        register struct rt_addrinfo *rtinfo;
652
        caddr_t cp;
653
        struct walkarg *w;
654
{
655
        register int i;
656
        int len, dlen, second_time = 0;
657
        caddr_t cp0;
658
 
659
        rtinfo->rti_addrs = 0;
660
again:
661
        switch (type) {
662
 
663
        case RTM_DELADDR:
664
        case RTM_NEWADDR:
665
                len = sizeof(struct ifa_msghdr);
666
                break;
667
 
668
        case RTM_IFINFO:
669
                len = sizeof(struct if_msghdr);
670
                break;
671
 
672
        default:
673
                len = sizeof(struct rt_msghdr);
674
        }
675
        cp0 = cp;
676
        if (cp0)
677
                cp += len;
678
        for (i = 0; i < RTAX_MAX; i++) {
679
                register struct sockaddr *sa;
680
 
681
                if ((sa = rtinfo->rti_info[i]) == 0)
682
                        continue;
683
                rtinfo->rti_addrs |= (1 << i);
684
                dlen = ROUNDUP(sa->sa_len);
685
                if (cp) {
686
                        bcopy((caddr_t)sa, cp, (unsigned)dlen);
687
                        cp += dlen;
688
                }
689
                len += dlen;
690
        }
691
        if (cp == 0 && w != NULL && !second_time) {
692
                register struct walkarg *rw = w;
693
 
694
                if (rw->w_req) {
695
                        if (rw->w_tmemsize < len) {
696
                                if (rw->w_tmem)
697
                                        free(rw->w_tmem, M_RTABLE);
698
                                rw->w_tmem = (caddr_t)
699
                                        malloc(len, M_RTABLE, M_NOWAIT);
700
                                if (rw->w_tmem)
701
                                        rw->w_tmemsize = len;
702
                        }
703
                        if (rw->w_tmem) {
704
                                cp = rw->w_tmem;
705
                                second_time = 1;
706
                                goto again;
707
                        }
708
                }
709
        }
710
        if (cp) {
711
                register struct rt_msghdr *rtm = (struct rt_msghdr *)cp0;
712
 
713
                rtm->rtm_version = RTM_VERSION;
714
                rtm->rtm_type = type;
715
                rtm->rtm_msglen = len;
716
        }
717
        return (len);
718
}
719
 
720
/*
721
 * This routine is called to generate a message from the routing
722
 * socket indicating that a redirect has occured, a routing lookup
723
 * has failed, or that a protocol has detected timeouts to a particular
724
 * destination.
725
 */
726
void
727
rt_missmsg(type, rtinfo, flags, error)
728
        int type, flags, error;
729
        register struct rt_addrinfo *rtinfo;
730
{
731
        register struct rt_msghdr *rtm;
732
        register struct mbuf *m;
733
        struct sockaddr *sa = rtinfo->rti_info[RTAX_DST];
734
 
735
        if (route_cb.any_count == 0)
736
                return;
737
        m = rt_msg1(type, rtinfo);
738
        if (m == 0)
739
                return;
740
        rtm = mtod(m, struct rt_msghdr *);
741
        rtm->rtm_flags = RTF_DONE | flags;
742
        rtm->rtm_errno = error;
743
        rtm->rtm_addrs = rtinfo->rti_addrs;
744
        route_proto.sp_protocol = sa ? sa->sa_family : 0;
745
        raw_input(m, &route_proto, &route_src, &route_dst);
746
}
747
 
748
/*
749
 * This routine is called to generate a message from the routing
750
 * socket indicating that the status of a network interface has changed.
751
 */
752
void
753
rt_ifmsg(ifp)
754
        register struct ifnet *ifp;
755
{
756
        register struct if_msghdr *ifm;
757
        struct mbuf *m;
758
        struct rt_addrinfo info;
759
 
760
        if (route_cb.any_count == 0)
761
                return;
762
        bzero((caddr_t)&info, sizeof(info));
763
        m = rt_msg1(RTM_IFINFO, &info);
764
        if (m == 0)
765
                return;
766
        ifm = mtod(m, struct if_msghdr *);
767
        ifm->ifm_index = ifp->if_index;
768
        ifm->ifm_flags = (u_short)ifp->if_flags;
769
        ifm->ifm_data = ifp->if_data;
770
        ifm->ifm_addrs = 0;
771
        route_proto.sp_protocol = 0;
772
        raw_input(m, &route_proto, &route_src, &route_dst);
773
}
774
 
775
/*
776
 * This is called to generate messages from the routing socket
777
 * indicating a network interface has had addresses associated with it.
778
 * if we ever reverse the logic and replace messages TO the routing
779
 * socket indicate a request to configure interfaces, then it will
780
 * be unnecessary as the routing socket will automatically generate
781
 * copies of it.
782
 */
783
void
784
rt_newaddrmsg(cmd, ifa, error, rt)
785
        int cmd, error;
786
        register struct ifaddr *ifa;
787
        register struct rtentry *rt;
788
{
789
        struct rt_addrinfo info;
790
        struct sockaddr *sa = 0;
791
        int pass;
792
        struct mbuf *m = 0;
793
        struct ifnet *ifp = ifa->ifa_ifp;
794
 
795
        if (route_cb.any_count == 0)
796
                return;
797
        for (pass = 1; pass < 3; pass++) {
798
                bzero((caddr_t)&info, sizeof(info));
799
                if ((cmd == RTM_ADD && pass == 1) ||
800
                    (cmd == RTM_DELETE && pass == 2)) {
801
                        register struct ifa_msghdr *ifam;
802
                        int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR;
803
 
804
                        ifaaddr = sa = ifa->ifa_addr;
805
                        ifpaddr = ifp->if_addrhead.tqh_first->ifa_addr;
806
                        netmask = ifa->ifa_netmask;
807
                        brdaddr = ifa->ifa_dstaddr;
808
                        if ((m = rt_msg1(ncmd, &info)) == NULL)
809
                                continue;
810
                        ifam = mtod(m, struct ifa_msghdr *);
811
                        ifam->ifam_index = ifp->if_index;
812
                        ifam->ifam_metric = ifa->ifa_metric;
813
                        ifam->ifam_flags = ifa->ifa_flags;
814
                        ifam->ifam_addrs = info.rti_addrs;
815
                }
816
                if ((cmd == RTM_ADD && pass == 2) ||
817
                    (cmd == RTM_DELETE && pass == 1)) {
818
                        register struct rt_msghdr *rtm;
819
 
820
                        if (rt == 0)
821
                                continue;
822
                        netmask = rt_mask(rt);
823
                        dst = sa = rt_key(rt);
824
                        gate = rt->rt_gateway;
825
                        if ((m = rt_msg1(cmd, &info)) == NULL)
826
                                continue;
827
                        rtm = mtod(m, struct rt_msghdr *);
828
                        rtm->rtm_index = ifp->if_index;
829
                        rtm->rtm_flags |= rt->rt_flags;
830
                        rtm->rtm_errno = error;
831
                        rtm->rtm_addrs = info.rti_addrs;
832
                }
833
                route_proto.sp_protocol = sa ? sa->sa_family : 0;
834
                raw_input(m, &route_proto, &route_src, &route_dst);
835
        }
836
}
837
 
838
/*
839
 * This is the analogue to the rt_newaddrmsg which performs the same
840
 * function but for multicast group memberhips.  This is easier since
841
 * there is no route state to worry about.
842
 */
843
void
844
rt_newmaddrmsg(cmd, ifma)
845
        int cmd;
846
        struct ifmultiaddr *ifma;
847
{
848
        struct rt_addrinfo info;
849
        struct mbuf *m = 0;
850
        struct ifnet *ifp = ifma->ifma_ifp;
851
        struct ifma_msghdr *ifmam;
852
 
853
        if (route_cb.any_count == 0)
854
                return;
855
 
856
        bzero((caddr_t)&info, sizeof(info));
857
        ifaaddr = ifma->ifma_addr;
858
        if (ifp && ifp->if_addrhead.tqh_first)
859
                ifpaddr = ifp->if_addrhead.tqh_first->ifa_addr;
860
        else
861
                ifpaddr = NULL;
862
        /*
863
         * If a link-layer address is present, present it as a ``gateway''
864
         * (similarly to how ARP entries, e.g., are presented).
865
         */
866
        gate = ifma->ifma_lladdr;
867
        if ((m = rt_msg1(cmd, &info)) == NULL)
868
                return;
869
        ifmam = mtod(m, struct ifma_msghdr *);
870
        ifmam->ifmam_index = ifp->if_index;
871
        ifmam->ifmam_addrs = info.rti_addrs;
872
        route_proto.sp_protocol = ifma->ifma_addr->sa_family;
873
        raw_input(m, &route_proto, &route_src, &route_dst);
874
}
875
 
876
/*
877
 * Definitions of protocols supported in the ROUTE domain.
878
 */
879
 
880
extern struct domain routedomain;               /* or at least forward */
881
 
882
static struct protosw routesw[] = {
883
{ SOCK_RAW,     &routedomain,   0,               PR_ATOMIC|PR_ADDR,
884
  0,             route_output,   raw_ctlinput,   0,
885
  0,
886
  raw_init,     0,               0,               0,
887
  &route_usrreqs
888
}
889
};
890
 
891
static struct domain routedomain =
892
    { PF_ROUTE, "route", 0, 0, 0,
893
      routesw, &routesw[sizeof(routesw)/sizeof(routesw[0])] };
894
 
895
DOMAIN_SET(route);

powered by: WebSVN 2.1.0

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