OSDN Git Service

Add MS7619SE
[uclinux-h8/uClinux-dist.git] / user / routed / output.c
1 /*
2  * Copyright (c) 1983, 1988, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 /*
35  * From: @(#)output.c   5.15 (Berkeley) 2/28/91
36  * From: @(#)output.c   8.1 (Berkeley) 6/5/93
37  */
38 char output_rcsid[] = 
39   "$Id: output.c,v 1.7 1999/08/01 19:19:16 dholland Exp $";
40
41
42 /*
43  * Routing Table Management Daemon
44  */
45
46 #include "defs.h"
47
48 /*
49  * Apply the function "f" to all non-passive
50  * interfaces.  If the interface supports the
51  * use of broadcasting use it, otherwise address
52  * the output to the known router.
53  */
54
55 void toall(void (*f)(struct sockaddr *, int, struct interface *, int), 
56         int rtstate, struct interface *skipif)
57 {
58         struct interface *ifp;
59         struct sockaddr *dst;
60         int flags;
61
62         for (ifp = ifnet; ifp; ifp = ifp->int_next) {
63                 if (ifp->int_flags & IFF_PASSIVE || ifp == skipif)
64                         continue;
65                 dst = ifp->int_flags & IFF_BROADCAST ? &ifp->int_broadaddr :
66                       ifp->int_flags & IFF_POINTOPOINT ? &ifp->int_dstaddr :
67                       &ifp->int_addr;
68                 flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0;
69                 (*f)(dst, flags, ifp, rtstate);
70         }
71 }
72
73 /*
74  * Output a preformed packet.
75  */
76
77 void sndmsg(struct sockaddr *dst, int flags, struct interface *ifp, int rtstate)
78 {
79         (void)rtstate;
80
81         (*afswitch[dst->sa_family].af_output)(sock, flags,
82                                               dst, sizeof (struct rip));
83         TRACE_OUTPUT(ifp, dst, sizeof (struct rip));
84 }
85
86 /*
87  * Supply dst with the contents of the routing tables.
88  * If this won't fit in one packet, chop it up into several.
89  */
90  
91 void supply(struct sockaddr *dst, int flags, struct interface *ifp, int rtstate)
92 {
93         struct rt_entry *rt;
94         struct netinfo *n = msg->rip_nets;
95         struct rthash *rh;
96         struct rthash *base = hosthash;
97         int doinghost = 1, size;
98         void (*output)(int,int,struct sockaddr *,int) = 
99                 afswitch[dst->sa_family].af_output;
100         int (*sendroute)(struct rt_entry *, struct sockaddr *) = 
101                 afswitch[dst->sa_family].af_sendroute;
102         int npackets = 0;
103
104         msg->rip_cmd = RIPCMD_RESPONSE;
105         msg->rip_vers = RIPVERSION;
106         memset(&msg->rip_res1, 0, sizeof(msg->rip_res1));
107 again:
108         for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++)
109         for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
110                 /*
111                  * Don't resend the information on the network
112                  * from which it was received (unless sending
113                  * in response to a query).
114                  */
115                 if (ifp && rt->rt_ifp == ifp &&
116                     (rt->rt_state & RTS_INTERFACE) == 0)
117                         continue;
118                 if (rt->rt_state & RTS_EXTERNAL)
119                         continue;
120                 /*
121                  * For dynamic updates, limit update to routes
122                  * with the specified state.
123                  */
124                 if (rtstate && (rt->rt_state & rtstate) == 0)
125                         continue;
126                 /*
127                  * Limit the spread of subnet information
128                  * to those who are interested.
129                  */
130                 if (doinghost == 0 && rt->rt_state & RTS_SUBNET) {
131                         if (rt->rt_dst.sa_family != dst->sa_family)
132                                 continue;
133                         if ((*sendroute)(rt, dst) == 0)
134                                 continue;
135                 }
136                 size = (char *)n - packet;
137                 if (size > MAXPACKETSIZE - (int)sizeof (struct netinfo)) {
138                         TRACE_OUTPUT(ifp, dst, size);
139                         (*output)(sock, flags, dst, size);
140                         /*
141                          * If only sending to ourselves,
142                          * one packet is enough to monitor interface.
143                          */
144                         if (ifp && (ifp->int_flags &
145                            (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0)
146                                 return;
147                         n = msg->rip_nets;
148                         npackets++;
149                 }
150                 n->rip_dst = rt->rt_dst;
151 #if BSD < 198810
152                 if (sizeof(n->rip_dst.sa_family) > 1)   /* XXX */
153                         n->rip_dst.sa_family = htons(n->rip_dst.sa_family);
154 #else
155 #define osa(x) ((struct osockaddr *)(&(x)))
156                 osa(n->rip_dst)->sa_family = htons(n->rip_dst.sa_family);
157 #endif
158                 n->rip_metric = htonl(rt->rt_metric);
159                 n++;
160         }
161         if (doinghost) {
162                 doinghost = 0;
163                 base = nethash;
164                 goto again;
165         }
166         if (n != msg->rip_nets || (npackets == 0 && rtstate == 0)) {
167                 size = (char *)n - packet;
168                 TRACE_OUTPUT(ifp, dst, size);
169                 (*output)(sock, flags, dst, size);
170         }
171 }