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