source: rtems/cpukit/libnetworking/net/rtsock.c @ 36799d4

4.104.114.84.95
Last change on this file since 36799d4 was 36799d4, checked in by Joel Sherrill <joel.sherrill@…>, on Jan 3, 2003 at 6:09:57 PM

2002-11-26 Chris Johns <cjohns@…>

  • Makefile.am: Added sys/linker_set.h
  • kern/Makefile.am: Added kern_mib.c and kern_sysctl.c.
  • kern/uipc_socket.c: OID changed from KERN_SOMAXCONN to KIPC_SOMAXCONN.
  • kern/uipc_socket2.c: OID changed from KERN_MAXSOCKBUF to KIPC_MAXSOCKBUF.
  • net/if_ethersubr.c: FreeBSD 2.2.2 does not have a _net_link node while 5.0 does.
  • net/if_ppp.c: Removed the TEXT_SET define as these macros are now implemented.
  • net/rtsock.c: Enable sysctl support plus fix the bug with the lastest FreeBSD sysctl header file.
  • netinet/icmp_var.h: FreeBSD 2.2.2 does not have a _net_inet_icmp node while 5.0 does.
  • netinet/if_ether.c: FreeBSD 2.2.2 does not have a _net_link_ether node while 5.0 does.
  • netinet/igmp_var.h: FreeBSD 2.2.2 does not have a _net_inet_igmp node while 5.0 does.
  • netinet/in_pcb.c: Fixed the arguments to the sysctl call. Add inp_gencnt and ipi_count. These are used when listing connections.
  • netinet/in_pcb.h: Added counters to aid the listing of connections.
  • netinet/in_var.h: Provide the _net_inet_ip and _net_inet_raw nodes.
  • netinet/ip_fw.c: Disable the firewall sysctl calls.
  • netinet/tcp_subr.c: Merge tcp_pcblist from the lastest FreeBSD source.
  • netinet/tcp_var.h: Add structures needed by net-snmp to list connections.
  • netinet/udp_usrreq.c: Merged udp_pcblist from the lastest FreeBSD source.
  • netinet/udp_var.h: Added the sysctl id UDPCTL_PCBLIST. Used by net-snmp.
  • rtems_glue.c: Call sysctl_register_all when initialising the network stack to register all the sysctl calls. These are in the special sections and required an updated linker script.
  • rtems/rtems_syscall.c: Add the sysctl call.
  • sys/kernel.h: Use the lastest FreeBSD method of handling sysctl structures. This now held in the sys/linker_set.h file.
  • sys/queue.h: This is from the lastest FreeBSD code with the circular code merged back in as it is not used in the lastest FreeBSD kernel.
  • sys/sysctl.h: The lastest sysctl. This was needed to use with the new linker set method. The FreeBSD 2.2.2 version has asm hacks. The lastest version of the FreeBSD does not have these hacks. It uses gcc attribute directives.
  • Property mode set to 100644
File size: 20.8 KB
Line 
1/*
2 * Copyright (c) 1988, 1991, 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 *      @(#)rtsock.c    8.5 (Berkeley) 11/2/94
34 *      $Id$
35 */
36
37#include <sys/param.h>
38#include <sys/queue.h>
39#include <sys/systm.h>
40#include <sys/kernel.h>
41#include <sys/sysctl.h>
42#include <sys/proc.h>
43#include <sys/mbuf.h>
44#include <sys/socket.h>
45#include <sys/socketvar.h>
46#include <sys/domain.h>
47#include <sys/protosw.h>
48
49#include <net/if.h>
50#include <net/route.h>
51#include <net/raw_cb.h>
52
53static struct   sockaddr route_dst = { 2, PF_ROUTE, };
54static struct   sockaddr route_src = { 2, PF_ROUTE, };
55static struct   sockaddr sa_zero   = { sizeof(sa_zero), AF_INET, };
56static struct   sockproto route_proto = { PF_ROUTE, };
57
58struct walkarg {
59        int     w_tmemsize;
60        int     w_op, w_arg;
61        caddr_t w_tmem;
62        struct sysctl_req *w_req;
63};
64
65static struct mbuf *
66                rt_msg1 __P((int, struct rt_addrinfo *));
67static int      rt_msg2 __P((int,
68                    struct rt_addrinfo *, caddr_t, struct walkarg *));
69static int      rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *));
70static int      sysctl_dumpentry __P((struct radix_node *rn, void *vw));
71static int      sysctl_iflist __P((int af, struct walkarg *w));
72static int       route_output __P((struct mbuf *, struct socket *));
73static int       route_usrreq __P((struct socket *,
74            int, struct mbuf *, struct mbuf *, struct mbuf *));
75static void      rt_setmetrics __P((u_long, struct rt_metrics *, struct rt_metrics *));
76
77/* Sleazy use of local variables throughout file, warning!!!! */
78#define dst     info.rti_info[RTAX_DST]
79#define gate    info.rti_info[RTAX_GATEWAY]
80#define netmask info.rti_info[RTAX_NETMASK]
81#define genmask info.rti_info[RTAX_GENMASK]
82#define ifpaddr info.rti_info[RTAX_IFP]
83#define ifaaddr info.rti_info[RTAX_IFA]
84#define brdaddr info.rti_info[RTAX_BRD]
85
86/*ARGSUSED*/
87static int
88route_usrreq(so, req, m, nam, control)
89        register struct socket *so;
90        int req;
91        struct mbuf *m, *nam, *control;
92{
93        register int error = 0;
94        register struct rawcb *rp = sotorawcb(so);
95        int s;
96
97        if (req == PRU_ATTACH) {
98                MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK);
99                so->so_pcb = (caddr_t)rp;
100                if (so->so_pcb)
101                        bzero(so->so_pcb, sizeof(*rp));
102        }
103        if (req == PRU_DETACH && rp) {
104                int af = rp->rcb_proto.sp_protocol;
105                if (af == AF_INET)
106                        route_cb.ip_count--;
107                else if (af == AF_IPX)
108                        route_cb.ipx_count--;
109                else if (af == AF_NS)
110                        route_cb.ns_count--;
111                else if (af == AF_ISO)
112                        route_cb.iso_count--;
113                route_cb.any_count--;
114        }
115        s = splnet();
116        error = raw_usrreq(so, req, m, nam, control);
117        rp = sotorawcb(so);
118        if (req == PRU_ATTACH && rp) {
119                int af = rp->rcb_proto.sp_protocol;
120                if (error) {
121                        free((caddr_t)rp, M_PCB);
122                        splx(s);
123                        return (error);
124                }
125                if (af == AF_INET)
126                        route_cb.ip_count++;
127                else if (af == AF_IPX)
128                        route_cb.ipx_count++;
129                else if (af == AF_NS)
130                        route_cb.ns_count++;
131                else if (af == AF_ISO)
132                        route_cb.iso_count++;
133                rp->rcb_faddr = &route_src;
134                route_cb.any_count++;
135                soisconnected(so);
136                so->so_options |= SO_USELOOPBACK;
137        }
138        splx(s);
139        return (error);
140}
141
142/*ARGSUSED*/
143static int
144route_output(m, so)
145        register struct mbuf *m;
146        struct socket *so;
147{
148        register struct rt_msghdr *rtm = 0;
149        register struct rtentry *rt = 0;
150        struct rtentry *saved_nrt = 0;
151        struct radix_node_head *rnh;
152        struct rt_addrinfo info;
153        int len, error = 0;
154        struct ifnet *ifp = 0;
155        struct ifaddr *ifa = 0;
156
157#define senderr(e) { error = e; goto flush;}
158        if (m == 0 || ((m->m_len < sizeof(long)) &&
159                       (m = m_pullup(m, sizeof(long))) == 0))
160                return (ENOBUFS);
161        if ((m->m_flags & M_PKTHDR) == 0)
162                panic("route_output");
163        len = m->m_pkthdr.len;
164        if (len < sizeof(*rtm) ||
165            len != mtod(m, struct rt_msghdr *)->rtm_msglen) {
166                dst = 0;
167                senderr(EINVAL);
168        }
169        R_Malloc(rtm, struct rt_msghdr *, len);
170        if (rtm == 0) {
171                dst = 0;
172                senderr(ENOBUFS);
173        }
174        m_copydata(m, 0, len, (caddr_t)rtm);
175        if (rtm->rtm_version != RTM_VERSION) {
176                dst = 0;
177                senderr(EPROTONOSUPPORT);
178        }
179        info.rti_addrs = rtm->rtm_addrs;
180        if (rt_xaddrs((caddr_t)(rtm + 1), len + (caddr_t)rtm, &info)) {
181                dst = 0;
182                senderr(EINVAL);
183        }
184        if (dst == 0 || (dst->sa_family >= AF_MAX)
185            || (gate != 0 && (gate->sa_family >= AF_MAX)))
186                senderr(EINVAL);
187        if (genmask) {
188                struct radix_node *t;
189                t = rn_addmask((caddr_t)genmask, 0, 1);
190                if (t && Bcmp(genmask, t->rn_key, *(u_char *)genmask) == 0)
191                        genmask = (struct sockaddr *)(t->rn_key);
192                else
193                        senderr(ENOBUFS);
194        }
195        switch (rtm->rtm_type) {
196
197        case RTM_ADD:
198                if (gate == 0)
199                        senderr(EINVAL);
200                error = rtrequest(RTM_ADD, dst, gate, netmask,
201                                        rtm->rtm_flags, &saved_nrt);
202                if (error == 0 && saved_nrt) {
203                        rt_setmetrics(rtm->rtm_inits,
204                                &rtm->rtm_rmx, &saved_nrt->rt_rmx);
205                        saved_nrt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
206                        saved_nrt->rt_rmx.rmx_locks |=
207                                (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
208                        saved_nrt->rt_refcnt--;
209                        saved_nrt->rt_genmask = genmask;
210                }
211                break;
212
213        case RTM_DELETE:
214                error = rtrequest(RTM_DELETE, dst, gate, netmask,
215                                rtm->rtm_flags, &saved_nrt);
216                if (error == 0) {
217                        if ((rt = saved_nrt))
218                                rt->rt_refcnt++;
219                        goto report;
220                }
221                break;
222
223        case RTM_GET:
224        case RTM_CHANGE:
225        case RTM_LOCK:
226                if ((rnh = rt_tables[dst->sa_family]) == 0) {
227                        senderr(EAFNOSUPPORT);
228                } else if ((rt = (struct rtentry *)
229                                rnh->rnh_lookup(dst, netmask, rnh)))
230                        rt->rt_refcnt++;
231                else
232                        senderr(ESRCH);
233                switch(rtm->rtm_type) {
234
235                case RTM_GET:
236                report:
237                        dst = rt_key(rt);
238                        gate = rt->rt_gateway;
239                        netmask = rt_mask(rt);
240                        genmask = rt->rt_genmask;
241                        if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
242                                ifp = rt->rt_ifp;
243                                if (ifp) {
244                                        ifpaddr = ifp->if_addrlist->ifa_addr;
245                                        ifaaddr = rt->rt_ifa->ifa_addr;
246                                        rtm->rtm_index = ifp->if_index;
247                                } else {
248                                        ifpaddr = 0;
249                                        ifaaddr = 0;
250                            }
251                        }
252                        len = rt_msg2(rtm->rtm_type, &info, (caddr_t)0,
253                                (struct walkarg *)0);
254                        if (len > rtm->rtm_msglen) {
255                                struct rt_msghdr *new_rtm;
256                                R_Malloc(new_rtm, struct rt_msghdr *, len);
257                                if (new_rtm == 0)
258                                        senderr(ENOBUFS);
259                                Bcopy(rtm, new_rtm, rtm->rtm_msglen);
260                                Free(rtm); rtm = new_rtm;
261                        }
262                        (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm,
263                                (struct walkarg *)0);
264                        rtm->rtm_flags = rt->rt_flags;
265                        rtm->rtm_rmx = rt->rt_rmx;
266                        rtm->rtm_addrs = info.rti_addrs;
267                        break;
268
269                case RTM_CHANGE:
270                        if (gate && (error = rt_setgate(rt, rt_key(rt), gate)))
271                                senderr(error);
272
273                        /*
274                         * If they tried to change things but didn't specify
275                         * the required gateway, then just use the old one.
276                         * This can happen if the user tries to change the
277                         * flags on the default route without changing the
278                         * default gateway.  Changing flags still doesn't work.
279                         */
280                        if ((rt->rt_flags & RTF_GATEWAY) && !gate)
281                                gate = rt->rt_gateway;
282
283                        /* new gateway could require new ifaddr, ifp;
284                           flags may also be different; ifp may be specified
285                           by ll sockaddr when protocol address is ambiguous */
286                        if (ifpaddr && (ifa = ifa_ifwithnet(ifpaddr)) &&
287                            (ifp = ifa->ifa_ifp) && (ifaaddr || gate))
288                                ifa = ifaof_ifpforaddr(ifaaddr ? ifaaddr : gate,
289                                                        ifp);
290                        else if ((ifaaddr && (ifa = ifa_ifwithaddr(ifaaddr))) ||
291                                 (gate && (ifa = ifa_ifwithroute(rt->rt_flags,
292                                                        rt_key(rt), gate))))
293                                ifp = ifa->ifa_ifp;
294                        if (ifa) {
295                                register struct ifaddr *oifa = rt->rt_ifa;
296                                if (oifa != ifa) {
297                                    if (oifa && oifa->ifa_rtrequest)
298                                        oifa->ifa_rtrequest(RTM_DELETE,
299                                                                rt, gate);
300                                    IFAFREE(rt->rt_ifa);
301                                    rt->rt_ifa = ifa;
302                                    ifa->ifa_refcnt++;
303                                    rt->rt_ifp = ifp;
304                                }
305                        }
306                        rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
307                                        &rt->rt_rmx);
308                        if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
309                               rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate);
310                        if (genmask)
311                                rt->rt_genmask = genmask;
312                        /*
313                         * Fall into
314                         */
315                case RTM_LOCK:
316                        rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
317                        rt->rt_rmx.rmx_locks |=
318                                (rtm->rtm_inits & rtm->rtm_rmx.rmx_locks);
319                        break;
320                }
321                break;
322
323        default:
324                senderr(EOPNOTSUPP);
325        }
326
327flush:
328        if (rtm) {
329                if (error)
330                        rtm->rtm_errno = error;
331                else
332                        rtm->rtm_flags |= RTF_DONE;
333        }
334        if (rt)
335                rtfree(rt);
336    {
337        register struct rawcb *rp = 0;
338        /*
339         * Check to see if we don't want our own messages.
340         */
341        if ((so->so_options & SO_USELOOPBACK) == 0) {
342                if (route_cb.any_count <= 1) {
343                        if (rtm)
344                                Free(rtm);
345                        m_freem(m);
346                        return (error);
347                }
348                /* There is another listener, so construct message */
349                rp = sotorawcb(so);
350        }
351        if (rtm) {
352                m_copyback(m, 0, rtm->rtm_msglen, (caddr_t)rtm);
353                Free(rtm);
354        }
355        if (rp)
356                rp->rcb_proto.sp_family = 0; /* Avoid us */
357        if (dst)
358                route_proto.sp_protocol = dst->sa_family;
359        raw_input(m, &route_proto, &route_src, &route_dst);
360        if (rp)
361                rp->rcb_proto.sp_family = PF_ROUTE;
362    }
363        return (error);
364}
365
366static void
367rt_setmetrics(which, in, out)
368        u_long which;
369        register struct rt_metrics *in, *out;
370{
371#define metric(f, e) if (which & (f)) out->e = in->e;
372        metric(RTV_RPIPE, rmx_recvpipe);
373        metric(RTV_SPIPE, rmx_sendpipe);
374        metric(RTV_SSTHRESH, rmx_ssthresh);
375        metric(RTV_RTT, rmx_rtt);
376        metric(RTV_RTTVAR, rmx_rttvar);
377        metric(RTV_HOPCOUNT, rmx_hopcount);
378        metric(RTV_MTU, rmx_mtu);
379        metric(RTV_EXPIRE, rmx_expire);
380#undef metric
381}
382
383#define ROUNDUP(a) \
384        ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
385#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
386
387
388/*
389 * Extract the addresses of the passed sockaddrs.
390 * Do a little sanity checking so as to avoid bad memory references.
391 * This data is derived straight from userland.
392 */
393static int
394rt_xaddrs(cp, cplim, rtinfo)
395        register caddr_t cp, cplim;
396        register struct rt_addrinfo *rtinfo;
397{
398        register struct sockaddr *sa;
399        register int i;
400
401        bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info));
402        for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
403                if ((rtinfo->rti_addrs & (1 << i)) == 0)
404                        continue;
405                sa = (struct sockaddr *)cp;
406                /*
407                 * It won't fit.
408                 */
409                if ( (cp + sa->sa_len) > cplim ) {
410                        return (EINVAL);
411                }
412
413                /*
414                 * there are no more.. quit now
415                 * If there are more bits, they are in error.
416                 * I've seen this. route(1) can evidently generate these.
417                 * This causes kernel to core dump.
418                 * for compatibility, If we see this, point to a safe address.
419                 */
420                if (sa->sa_len == 0) {
421                        rtinfo->rti_info[i] = &sa_zero;
422                        return (0); /* should be EINVAL but for compat */
423                }
424
425                /* accept it */
426                rtinfo->rti_info[i] = sa;
427                ADVANCE(cp, sa);
428        }
429        return (0);
430}
431
432static struct mbuf *
433rt_msg1(type, rtinfo)
434        int type;
435        register struct rt_addrinfo *rtinfo;
436{
437        register struct rt_msghdr *rtm;
438        register struct mbuf *m;
439        register int i;
440        register struct sockaddr *sa;
441        int len, dlen;
442
443        m = m_gethdr(M_DONTWAIT, MT_DATA);
444        if (m == 0)
445                return (m);
446        switch (type) {
447
448        case RTM_DELADDR:
449        case RTM_NEWADDR:
450                len = sizeof(struct ifa_msghdr);
451                break;
452
453        case RTM_IFINFO:
454                len = sizeof(struct if_msghdr);
455                break;
456
457        default:
458                len = sizeof(struct rt_msghdr);
459        }
460        if (len > MHLEN)
461                panic("rt_msg1");
462        m->m_pkthdr.len = m->m_len = len;
463        m->m_pkthdr.rcvif = 0;
464        rtm = mtod(m, struct rt_msghdr *);
465        bzero((caddr_t)rtm, len);
466        for (i = 0; i < RTAX_MAX; i++) {
467                if ((sa = rtinfo->rti_info[i]) == NULL)
468                        continue;
469                rtinfo->rti_addrs |= (1 << i);
470                dlen = ROUNDUP(sa->sa_len);
471                m_copyback(m, len, dlen, (caddr_t)sa);
472                len += dlen;
473        }
474        if (m->m_pkthdr.len != len) {
475                m_freem(m);
476                return (NULL);
477        }
478        rtm->rtm_msglen = len;
479        rtm->rtm_version = RTM_VERSION;
480        rtm->rtm_type = type;
481        return (m);
482}
483
484static int
485rt_msg2(type, rtinfo, cp, w)
486        int type;
487        register struct rt_addrinfo *rtinfo;
488        caddr_t cp;
489        struct walkarg *w;
490{
491        register int i;
492        int len, dlen, second_time = 0;
493        caddr_t cp0;
494
495        rtinfo->rti_addrs = 0;
496again:
497        switch (type) {
498
499        case RTM_DELADDR:
500        case RTM_NEWADDR:
501                len = sizeof(struct ifa_msghdr);
502                break;
503
504        case RTM_IFINFO:
505                len = sizeof(struct if_msghdr);
506                break;
507
508        default:
509                len = sizeof(struct rt_msghdr);
510        }
511        cp0 = cp;
512        if (cp0)
513                cp += len;
514        for (i = 0; i < RTAX_MAX; i++) {
515                register struct sockaddr *sa;
516
517                if ((sa = rtinfo->rti_info[i]) == 0)
518                        continue;
519                rtinfo->rti_addrs |= (1 << i);
520                dlen = ROUNDUP(sa->sa_len);
521                if (cp) {
522                        bcopy((caddr_t)sa, cp, (unsigned)dlen);
523                        cp += dlen;
524                }
525                len += dlen;
526        }
527        if (cp == 0 && w != NULL && !second_time) {
528                register struct walkarg *rw = w;
529
530                if (rw->w_req) {
531                        if (rw->w_tmemsize < len) {
532                                if (rw->w_tmem)
533                                        free(rw->w_tmem, M_RTABLE);
534                                rw->w_tmem = (caddr_t)
535                                        malloc(len, M_RTABLE, M_NOWAIT);
536                                if (rw->w_tmem)
537                                        rw->w_tmemsize = len;
538                        }
539                        if (rw->w_tmem) {
540                                cp = rw->w_tmem;
541                                second_time = 1;
542                                goto again;
543                        }
544                }
545        }
546        if (cp) {
547                register struct rt_msghdr *rtm = (struct rt_msghdr *)cp0;
548
549                rtm->rtm_version = RTM_VERSION;
550                rtm->rtm_type = type;
551                rtm->rtm_msglen = len;
552        }
553        return (len);
554}
555
556/*
557 * This routine is called to generate a message from the routing
558 * socket indicating that a redirect has occured, a routing lookup
559 * has failed, or that a protocol has detected timeouts to a particular
560 * destination.
561 */
562void
563rt_missmsg(type, rtinfo, flags, error)
564        int type, flags, error;
565        register struct rt_addrinfo *rtinfo;
566{
567        register struct rt_msghdr *rtm;
568        register struct mbuf *m;
569        struct sockaddr *sa = rtinfo->rti_info[RTAX_DST];
570
571        if (route_cb.any_count == 0)
572                return;
573        m = rt_msg1(type, rtinfo);
574        if (m == 0)
575                return;
576        rtm = mtod(m, struct rt_msghdr *);
577        rtm->rtm_flags = RTF_DONE | flags;
578        rtm->rtm_errno = error;
579        rtm->rtm_addrs = rtinfo->rti_addrs;
580        route_proto.sp_protocol = sa ? sa->sa_family : 0;
581        raw_input(m, &route_proto, &route_src, &route_dst);
582}
583
584/*
585 * This routine is called to generate a message from the routing
586 * socket indicating that the status of a network interface has changed.
587 */
588void
589rt_ifmsg(ifp)
590        register struct ifnet *ifp;
591{
592        register struct if_msghdr *ifm;
593        struct mbuf *m;
594        struct rt_addrinfo info;
595
596        if (route_cb.any_count == 0)
597                return;
598        bzero((caddr_t)&info, sizeof(info));
599        m = rt_msg1(RTM_IFINFO, &info);
600        if (m == 0)
601                return;
602        ifm = mtod(m, struct if_msghdr *);
603        ifm->ifm_index = ifp->if_index;
604        ifm->ifm_flags = (u_short)ifp->if_flags;
605        ifm->ifm_data = ifp->if_data;
606        ifm->ifm_addrs = 0;
607        route_proto.sp_protocol = 0;
608        raw_input(m, &route_proto, &route_src, &route_dst);
609}
610
611/*
612 * This is called to generate messages from the routing socket
613 * indicating a network interface has had addresses associated with it.
614 * if we ever reverse the logic and replace messages TO the routing
615 * socket indicate a request to configure interfaces, then it will
616 * be unnecessary as the routing socket will automatically generate
617 * copies of it.
618 */
619void
620rt_newaddrmsg(cmd, ifa, error, rt)
621        int cmd, error;
622        register struct ifaddr *ifa;
623        register struct rtentry *rt;
624{
625        struct rt_addrinfo info;
626        struct sockaddr *sa = 0;
627        int pass;
628        struct mbuf *m = 0;
629        struct ifnet *ifp = ifa->ifa_ifp;
630
631        if (route_cb.any_count == 0)
632                return;
633        for (pass = 1; pass < 3; pass++) {
634                bzero((caddr_t)&info, sizeof(info));
635                if ((cmd == RTM_ADD && pass == 1) ||
636                    (cmd == RTM_DELETE && pass == 2)) {
637                        register struct ifa_msghdr *ifam;
638                        int ncmd = cmd == RTM_ADD ? RTM_NEWADDR : RTM_DELADDR;
639
640                        ifaaddr = sa = ifa->ifa_addr;
641                        ifpaddr = ifp->if_addrlist->ifa_addr;
642                        netmask = ifa->ifa_netmask;
643                        brdaddr = ifa->ifa_dstaddr;
644                        if ((m = rt_msg1(ncmd, &info)) == NULL)
645                                continue;
646                        ifam = mtod(m, struct ifa_msghdr *);
647                        ifam->ifam_index = ifp->if_index;
648                        ifam->ifam_metric = ifa->ifa_metric;
649                        ifam->ifam_flags = ifa->ifa_flags;
650                        ifam->ifam_addrs = info.rti_addrs;
651                }
652                if ((cmd == RTM_ADD && pass == 2) ||
653                    (cmd == RTM_DELETE && pass == 1)) {
654                        register struct rt_msghdr *rtm;
655
656                        if (rt == 0)
657                                continue;
658                        netmask = rt_mask(rt);
659                        dst = sa = rt_key(rt);
660                        gate = rt->rt_gateway;
661                        if ((m = rt_msg1(cmd, &info)) == NULL)
662                                continue;
663                        rtm = mtod(m, struct rt_msghdr *);
664                        rtm->rtm_index = ifp->if_index;
665                        rtm->rtm_flags |= rt->rt_flags;
666                        rtm->rtm_errno = error;
667                        rtm->rtm_addrs = info.rti_addrs;
668                }
669                route_proto.sp_protocol = sa ? sa->sa_family : 0;
670                raw_input(m, &route_proto, &route_src, &route_dst);
671        }
672}
673
674
675/*
676 * This is used in dumping the kernel table via sysctl().
677 */
678int
679sysctl_dumpentry(rn, vw)
680        struct radix_node *rn;
681        void *vw;
682{
683        register struct walkarg *w = vw;
684        register struct rtentry *rt = (struct rtentry *)rn;
685        int error = 0, size;
686        struct rt_addrinfo info;
687
688        if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
689                return 0;
690        bzero((caddr_t)&info, sizeof(info));
691        dst = rt_key(rt);
692        gate = rt->rt_gateway;
693        netmask = rt_mask(rt);
694        genmask = rt->rt_genmask;
695        size = rt_msg2(RTM_GET, &info, 0, w);
696        if (w->w_req && w->w_tmem) {
697                register struct rt_msghdr *rtm = (struct rt_msghdr *)w->w_tmem;
698
699                rtm->rtm_flags = rt->rt_flags;
700                rtm->rtm_use = rt->rt_use;
701                rtm->rtm_rmx = rt->rt_rmx;
702                rtm->rtm_index = rt->rt_ifp->if_index;
703                rtm->rtm_errno = rtm->rtm_pid = rtm->rtm_seq = 0;
704                rtm->rtm_addrs = info.rti_addrs;
705                error = 0;
706                return (error);
707        }
708        return (error);
709}
710
711int
712sysctl_iflist(af, w)
713        int     af;
714        register struct walkarg *w;
715{
716        register struct ifnet *ifp;
717        register struct ifaddr *ifa;
718        struct  rt_addrinfo info;
719        int     len, error = 0;
720
721        bzero((caddr_t)&info, sizeof(info));
722        for (ifp = ifnet; ifp; ifp = ifp->if_next) {
723                if (w->w_arg && w->w_arg != ifp->if_index)
724                        continue;
725                ifa = ifp->if_addrlist;
726                ifpaddr = ifa->ifa_addr;
727                len = rt_msg2(RTM_IFINFO, &info, (caddr_t)0, w);
728                ifpaddr = 0;
729                if (w->w_req && w->w_tmem) {
730                        register struct if_msghdr *ifm;
731
732                        ifm = (struct if_msghdr *)w->w_tmem;
733                        ifm->ifm_index = ifp->if_index;
734                        ifm->ifm_flags = (u_short)ifp->if_flags;
735                        ifm->ifm_data = ifp->if_data;
736                        ifm->ifm_addrs = info.rti_addrs;
737                        error = SYSCTL_OUT(w->w_req,(caddr_t)ifm, len);
738                        if (error)
739                                return (error);
740                }
741                while ((ifa = ifa->ifa_next) != 0) {
742                        if (af && af != ifa->ifa_addr->sa_family)
743                                continue;
744                        ifaaddr = ifa->ifa_addr;
745                        netmask = ifa->ifa_netmask;
746                        brdaddr = ifa->ifa_dstaddr;
747                        len = rt_msg2(RTM_NEWADDR, &info, 0, w);
748                        if (w->w_req && w->w_tmem) {
749                                register struct ifa_msghdr *ifam;
750
751                                ifam = (struct ifa_msghdr *)w->w_tmem;
752                                ifam->ifam_index = ifa->ifa_ifp->if_index;
753                                ifam->ifam_flags = ifa->ifa_flags;
754                                ifam->ifam_metric = ifa->ifa_metric;
755                                ifam->ifam_addrs = info.rti_addrs;
756                                error = SYSCTL_OUT(w->w_req, w->w_tmem, len);
757                                if (error)
758                                        return (error);
759                        }
760                }
761                ifaaddr = netmask = brdaddr = 0;
762        }
763        return (0);
764}
765
766static int
767sysctl_rtsock(SYSCTL_HANDLER_ARGS)
768{
769        int     *name = (int *)arg1;
770        u_int   namelen = arg2;
771        register struct radix_node_head *rnh;
772        int     i, s, error = EINVAL;
773        u_char  af;
774        struct  walkarg w;
775
776        name ++;
777        namelen--;
778        if (req->newptr)
779                return (EPERM);
780        if (namelen != 3)
781                return (EINVAL);
782        af = name[0];
783        Bzero(&w, sizeof(w));
784        w.w_op = name[1];
785        w.w_arg = name[2];
786        w.w_req = req;
787
788        s = splnet();
789        switch (w.w_op) {
790
791        case NET_RT_DUMP:
792        case NET_RT_FLAGS:
793                for (i = 1; i <= AF_MAX; i++)
794                        if ((rnh = rt_tables[i]) && (af == 0 || af == i) &&
795                            (error = rnh->rnh_walktree(rnh,
796                                                        sysctl_dumpentry, &w)))
797                                break;
798                break;
799
800        case NET_RT_IFLIST:
801                error = sysctl_iflist(af, &w);
802        }
803        splx(s);
804        if (w.w_tmem)
805                free(w.w_tmem, M_RTABLE);
806        return (error);
807}
808
809SYSCTL_NODE(_net, PF_ROUTE, routetable, CTLFLAG_RD, sysctl_rtsock,"");
810
811/*
812 * Definitions of protocols supported in the ROUTE domain.
813 */
814
815extern struct domain routedomain;               /* or at least forward */
816
817static struct protosw routesw[] = {
818{ SOCK_RAW,     &routedomain,   0,              PR_ATOMIC|PR_ADDR,
819  0,            route_output,   raw_ctlinput,   0,
820  route_usrreq,
821  raw_init
822}
823};
824
825struct domain routedomain =
826    { PF_ROUTE, "route", route_init, 0, 0,
827      routesw, &routesw[sizeof(routesw)/sizeof(routesw[0])] };
828
829DOMAIN_SET(route);
Note: See TracBrowser for help on using the repository browser.