Commit | Line | Data |
---|---|---|
5ff67f98 | 1 | /* |
2d222ff5 | 2 | * Copyright (c) 1983, 1988 Regents of the University of California. |
0eb85d71 KB |
3 | * All rights reserved. |
4 | * | |
d60d530a | 5 | * %sccs.include.redist.c% |
5ff67f98 DF |
6 | */ |
7 | ||
7e7de0c9 | 8 | #ifndef lint |
49dac2b7 | 9 | static char sccsid[] = "@(#)output.c 5.15 (Berkeley) %G%"; |
0eb85d71 | 10 | #endif /* not lint */ |
7e7de0c9 SL |
11 | |
12 | /* | |
13 | * Routing Table Management Daemon | |
14 | */ | |
7fe7fe74 | 15 | #include "defs.h" |
7e7de0c9 SL |
16 | |
17 | /* | |
18 | * Apply the function "f" to all non-passive | |
19 | * interfaces. If the interface supports the | |
20 | * use of broadcasting use it, otherwise address | |
21 | * the output to the known router. | |
22 | */ | |
4033c8f6 | 23 | toall(f, rtstate, skipif) |
7e7de0c9 | 24 | int (*f)(); |
4033c8f6 MK |
25 | int rtstate; |
26 | struct interface *skipif; | |
7e7de0c9 SL |
27 | { |
28 | register struct interface *ifp; | |
29 | register struct sockaddr *dst; | |
7fe7fe74 | 30 | register int flags; |
7e7de0c9 SL |
31 | extern struct interface *ifnet; |
32 | ||
33 | for (ifp = ifnet; ifp; ifp = ifp->int_next) { | |
4033c8f6 | 34 | if (ifp->int_flags & IFF_PASSIVE || ifp == skipif) |
7e7de0c9 SL |
35 | continue; |
36 | dst = ifp->int_flags & IFF_BROADCAST ? &ifp->int_broadaddr : | |
37 | ifp->int_flags & IFF_POINTOPOINT ? &ifp->int_dstaddr : | |
38 | &ifp->int_addr; | |
55d340a4 | 39 | flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0; |
4033c8f6 | 40 | (*f)(dst, flags, ifp, rtstate); |
7e7de0c9 SL |
41 | } |
42 | } | |
43 | ||
44 | /* | |
45 | * Output a preformed packet. | |
46 | */ | |
47 | /*ARGSUSED*/ | |
49dac2b7 | 48 | sndmsg(dst, flags, ifp, rtstate) |
7e7de0c9 | 49 | struct sockaddr *dst; |
7fe7fe74 | 50 | int flags; |
7e7de0c9 | 51 | struct interface *ifp; |
4033c8f6 | 52 | int rtstate; |
7e7de0c9 SL |
53 | { |
54 | ||
7fe7fe74 | 55 | (*afswitch[dst->sa_family].af_output)(s, flags, |
7e7de0c9 SL |
56 | dst, sizeof (struct rip)); |
57 | TRACE_OUTPUT(ifp, dst, sizeof (struct rip)); | |
58 | } | |
59 | ||
60 | /* | |
61 | * Supply dst with the contents of the routing tables. | |
62 | * If this won't fit in one packet, chop it up into several. | |
63 | */ | |
4033c8f6 | 64 | supply(dst, flags, ifp, rtstate) |
7e7de0c9 | 65 | struct sockaddr *dst; |
7fe7fe74 | 66 | int flags; |
7892134c | 67 | register struct interface *ifp; |
4033c8f6 | 68 | int rtstate; |
7e7de0c9 SL |
69 | { |
70 | register struct rt_entry *rt; | |
7892134c | 71 | register struct netinfo *n = msg->rip_nets; |
7e7de0c9 SL |
72 | register struct rthash *rh; |
73 | struct rthash *base = hosthash; | |
74 | int doinghost = 1, size; | |
75 | int (*output)() = afswitch[dst->sa_family].af_output; | |
7892134c | 76 | int (*sendroute)() = afswitch[dst->sa_family].af_sendroute; |
f2ce7d44 | 77 | int npackets = 0; |
7e7de0c9 SL |
78 | |
79 | msg->rip_cmd = RIPCMD_RESPONSE; | |
55d340a4 | 80 | msg->rip_vers = RIPVERSION; |
eabc591a | 81 | bzero(msg->rip_res1, sizeof(msg->rip_res1)); |
7e7de0c9 SL |
82 | again: |
83 | for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) | |
84 | for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { | |
4fad5a6e | 85 | /* |
7892134c MK |
86 | * Don't resend the information on the network |
87 | * from which it was received (unless sending | |
88 | * in response to a query). | |
4fad5a6e | 89 | */ |
7127cc90 MK |
90 | if (ifp && rt->rt_ifp == ifp && |
91 | (rt->rt_state & RTS_INTERFACE) == 0) | |
4fad5a6e MK |
92 | continue; |
93 | if (rt->rt_state & RTS_EXTERNAL) | |
94 | continue; | |
4033c8f6 MK |
95 | /* |
96 | * For dynamic updates, limit update to routes | |
97 | * with the specified state. | |
98 | */ | |
99 | if (rtstate && (rt->rt_state & rtstate) == 0) | |
100 | continue; | |
4fad5a6e MK |
101 | /* |
102 | * Limit the spread of subnet information | |
103 | * to those who are interested. | |
104 | */ | |
105 | if (doinghost == 0 && rt->rt_state & RTS_SUBNET) { | |
4fad5a6e MK |
106 | if (rt->rt_dst.sa_family != dst->sa_family) |
107 | continue; | |
7892134c | 108 | if ((*sendroute)(rt, dst) == 0) |
4fad5a6e MK |
109 | continue; |
110 | } | |
7e7de0c9 SL |
111 | size = (char *)n - packet; |
112 | if (size > MAXPACKETSIZE - sizeof (struct netinfo)) { | |
7e7de0c9 | 113 | TRACE_OUTPUT(ifp, dst, size); |
4033c8f6 | 114 | (*output)(s, flags, dst, size); |
2d222ff5 MK |
115 | /* |
116 | * If only sending to ourselves, | |
117 | * one packet is enough to monitor interface. | |
118 | */ | |
4033c8f6 | 119 | if (ifp && (ifp->int_flags & |
2d222ff5 MK |
120 | (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0) |
121 | return; | |
7e7de0c9 | 122 | n = msg->rip_nets; |
f2ce7d44 | 123 | npackets++; |
7e7de0c9 SL |
124 | } |
125 | n->rip_dst = rt->rt_dst; | |
4033c8f6 MK |
126 | #if BSD < 198810 |
127 | if (sizeof(n->rip_dst.sa_family) > 1) /* XXX */ | |
55d340a4 | 128 | n->rip_dst.sa_family = htons(n->rip_dst.sa_family); |
a33a5c17 KS |
129 | #else |
130 | #define osa(x) ((struct osockaddr *)(&(x))) | |
131 | osa(n->rip_dst)->sa_family = htons(n->rip_dst.sa_family); | |
4033c8f6 | 132 | #endif |
2d222ff5 | 133 | n->rip_metric = htonl(rt->rt_metric); |
7e7de0c9 SL |
134 | n++; |
135 | } | |
136 | if (doinghost) { | |
137 | doinghost = 0; | |
138 | base = nethash; | |
139 | goto again; | |
140 | } | |
4033c8f6 | 141 | if (n != msg->rip_nets || (npackets == 0 && rtstate == 0)) { |
7e7de0c9 | 142 | size = (char *)n - packet; |
7e7de0c9 | 143 | TRACE_OUTPUT(ifp, dst, size); |
4033c8f6 | 144 | (*output)(s, flags, dst, size); |
7e7de0c9 SL |
145 | } |
146 | } |