]>
git.saurik.com Git - apple/network_cmds.git/blob - routed.tproj/tables.c
9d6e578c19bd6c9205f337b21310a7393f156567
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 * Copyright (c) 1983, 1988, 1993
25 * The Regents of the University of California. All rights reserved.
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
30 * 1. Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
35 * 3. All advertising materials mentioning features or use of this software
36 * must display the following acknowledgment:
37 * This product includes software developed by the University of
38 * California, Berkeley and its contributors.
39 * 4. Neither the name of the University nor the names of its contributors
40 * may be used to endorse or promote products derived from this software
41 * without specific prior written permission.
43 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * @(#)defs.h 8.1 (Berkeley) 6/5/93
60 * Routing Table Management Daemon
63 #include <sys/ioctl.h>
65 #include <sys/syslog.h>
72 #define FIXLEN(s) {if ((s)->sa_len == 0) (s)->sa_len = sizeof *(s);}
77 int install
= !DEBUG
; /* if 1 call kernel */
80 * Lookup dst in the tables for an exact match.
86 register struct rt_entry
*rt
;
87 register struct rthash
*rh
;
92 if (dst
->sa_family
>= af_max
)
94 (*afswitch
[dst
->sa_family
].af_hash
)(dst
, &h
);
95 hash
= h
.afh_hosthash
;
96 rh
= &hosthash
[hash
& ROUTEHASHMASK
];
98 for (rt
= rh
->rt_forw
; rt
!= (struct rt_entry
*)rh
; rt
= rt
->rt_forw
) {
99 if (rt
->rt_hash
!= hash
)
101 if (equal(&rt
->rt_dst
, dst
))
106 hash
= h
.afh_nethash
;
107 rh
= &nethash
[hash
& ROUTEHASHMASK
];
113 struct sockaddr wildcard
; /* zero valued cookie for wildcard searches */
116 * Find a route to dst as the kernel would.
120 struct sockaddr
*dst
;
122 register struct rt_entry
*rt
;
123 register struct rthash
*rh
;
126 int af
= dst
->sa_family
;
127 int doinghost
= 1, (*match
)();
131 (*afswitch
[af
].af_hash
)(dst
, &h
);
132 hash
= h
.afh_hosthash
;
133 rh
= &hosthash
[hash
& ROUTEHASHMASK
];
136 for (rt
= rh
->rt_forw
; rt
!= (struct rt_entry
*)rh
; rt
= rt
->rt_forw
) {
137 if (rt
->rt_hash
!= hash
)
140 if (equal(&rt
->rt_dst
, dst
))
143 if (rt
->rt_dst
.sa_family
== af
&&
144 (*match
)(&rt
->rt_dst
, dst
))
150 hash
= h
.afh_nethash
;
151 rh
= &nethash
[hash
& ROUTEHASHMASK
];
152 match
= afswitch
[af
].af_netmatch
;
157 * Check for wildcard gateway, by convention network 0.
159 if (dst
!= &wildcard
) {
160 dst
= &wildcard
, hash
= 0;
167 rtadd(dst
, gate
, metric
, state
)
168 struct sockaddr
*dst
, *gate
;
172 register struct rt_entry
*rt
;
174 int af
= dst
->sa_family
, flags
;
179 (*afswitch
[af
].af_hash
)(dst
, &h
);
180 flags
= (*afswitch
[af
].af_rtflags
)(dst
);
182 * Subnet flag isn't visible to kernel, move to state. XXX
186 if (flags
& RTF_SUBNET
) {
188 flags
&= ~RTF_SUBNET
;
190 if (flags
& RTF_HOST
) {
191 hash
= h
.afh_hosthash
;
192 rh
= &hosthash
[hash
& ROUTEHASHMASK
];
194 hash
= h
.afh_nethash
;
195 rh
= &nethash
[hash
& ROUTEHASHMASK
];
197 rt
= (struct rt_entry
*)malloc(sizeof (*rt
));
202 rt
->rt_router
= *gate
;
204 rt
->rt_flags
= RTF_UP
| flags
;
205 rt
->rt_state
= state
| RTS_CHANGED
;
206 rt
->rt_ifp
= if_ifwithdstaddr(&rt
->rt_dst
);
208 rt
->rt_ifp
= if_ifwithnet(&rt
->rt_router
);
209 if ((state
& RTS_INTERFACE
) == 0)
210 rt
->rt_flags
|= RTF_GATEWAY
;
211 rt
->rt_metric
= metric
;
213 TRACE_ACTION("ADD", rt
);
215 * If the ioctl fails because the gateway is unreachable
216 * from this host, discard the entry. This should only
217 * occur because of an incorrect entry in /etc/gateways.
219 if ((rt
->rt_state
& (RTS_INTERNAL
| RTS_EXTERNAL
)) == 0 &&
220 rtioctl(ADD
, &rt
->rt_rt
) < 0) {
221 if (errno
!= EEXIST
&& gate
->sa_family
< af_max
)
223 "adding route to net/host %s through gateway %s: %m\n",
224 (*afswitch
[dst
->sa_family
].af_format
)(dst
),
225 (*afswitch
[gate
->sa_family
].af_format
)(gate
));
227 if (errno
== ENETUNREACH
) {
228 TRACE_ACTION("DELETE", rt
);
235 rtchange(rt
, gate
, metric
)
237 struct sockaddr
*gate
;
240 int add
= 0, delete = 0, newgateway
= 0;
241 struct rtuentry oldroute
;
244 FIXLEN(&(rt
->rt_router
));
245 FIXLEN(&(rt
->rt_dst
));
246 if (!equal(&rt
->rt_router
, gate
)) {
248 TRACE_ACTION("CHANGE FROM ", rt
);
249 } else if (metric
!= rt
->rt_metric
)
250 TRACE_NEWMETRIC(rt
, metric
);
251 if ((rt
->rt_state
& RTS_INTERNAL
) == 0) {
253 * If changing to different router, we need to add
254 * new route and delete old one if in the kernel.
255 * If the router is the same, we need to delete
256 * the route if has become unreachable, or re-add
257 * it if it had been unreachable.
261 if (rt
->rt_metric
!= HOPCNT_INFINITY
)
263 } else if (metric
== HOPCNT_INFINITY
)
265 else if (rt
->rt_metric
== HOPCNT_INFINITY
)
269 oldroute
= rt
->rt_rt
;
270 if ((rt
->rt_state
& RTS_INTERFACE
) && delete) {
271 rt
->rt_state
&= ~RTS_INTERFACE
;
272 rt
->rt_flags
|= RTF_GATEWAY
;
273 if (metric
> rt
->rt_metric
&& delete)
274 syslog(LOG_ERR
, "%s route to interface %s (timed out)",
275 add
? "changing" : "deleting",
276 rt
->rt_ifp
? rt
->rt_ifp
->int_name
: "?");
279 rt
->rt_router
= *gate
;
280 rt
->rt_ifp
= if_ifwithdstaddr(&rt
->rt_router
);
282 rt
->rt_ifp
= if_ifwithnet(&rt
->rt_router
);
284 rt
->rt_metric
= metric
;
285 rt
->rt_state
|= RTS_CHANGED
;
287 TRACE_ACTION("CHANGE TO ", rt
);
289 if (add
&& rtioctl(ADD
, &rt
->rt_rt
) < 0)
291 if (delete && rtioctl(DELETE
, &oldroute
) < 0)
292 perror("DELETE ROUTE");
294 if (delete && !add
) {
295 if (rtioctl(DELETE
, &oldroute
) < 0)
296 perror("DELETE ROUTE");
297 } else if (!delete && add
) {
298 if (rtioctl(ADD
, &rt
->rt_rt
) < 0)
300 } else if (delete && add
) {
301 if (rtioctl(CHANGE
, &rt
->rt_rt
) < 0)
302 perror("CHANGE ROUTE");
311 TRACE_ACTION("DELETE", rt
);
312 FIXLEN(&(rt
->rt_router
));
313 FIXLEN(&(rt
->rt_dst
));
314 if (rt
->rt_metric
< HOPCNT_INFINITY
) {
315 if ((rt
->rt_state
& (RTS_INTERFACE
|RTS_INTERNAL
)) == RTS_INTERFACE
)
317 "deleting route to interface %s? (timed out?)",
318 rt
->rt_ifp
->int_name
);
319 if ((rt
->rt_state
& (RTS_INTERNAL
| RTS_EXTERNAL
)) == 0 &&
320 rtioctl(DELETE
, &rt
->rt_rt
) < 0)
330 register struct rthash
*rh
;
331 register struct rt_entry
*rt
;
332 struct rthash
*base
= hosthash
;
336 for (rh
= base
; rh
< &base
[ROUTEHASHSIZ
]; rh
++) {
338 for (; rt
!= (struct rt_entry
*)rh
; rt
= rt
->rt_forw
) {
339 if (rt
->rt_state
& RTS_INTERFACE
||
340 rt
->rt_metric
>= HOPCNT_INFINITY
)
342 TRACE_ACTION("DELETE", rt
);
343 if ((rt
->rt_state
& (RTS_INTERNAL
|RTS_EXTERNAL
)) == 0 &&
344 rtioctl(DELETE
, &rt
->rt_rt
) < 0)
345 perror("rtdeleteall");
357 * If we have an interface to the wide, wide world,
358 * add an entry for an Internet default route (wildcard) to the internal
359 * tables and advertise it. This route is not added to the kernel routes,
360 * but this entry prevents us from listening to other people's defaults
361 * and installing them in the kernel here.
365 extern struct sockaddr inet_default
;
367 rtadd(&inet_default
, &inet_default
, 1,
368 RTS_CHANGED
| RTS_PASSIVE
| RTS_INTERNAL
);
373 register struct rthash
*rh
;
375 for (rh
= nethash
; rh
< &nethash
[ROUTEHASHSIZ
]; rh
++)
376 rh
->rt_forw
= rh
->rt_back
= (struct rt_entry
*)rh
;
377 for (rh
= hosthash
; rh
< &hosthash
[ROUTEHASHSIZ
]; rh
++)
378 rh
->rt_forw
= rh
->rt_back
= (struct rt_entry
*)rh
;
383 struct rtuentry
*ort
;
388 ort
->rtu_rtflags
= ort
->rtu_flags
;
392 return (ioctl(s
, SIOCADDRT
, (char *)ort
));
395 return (ioctl(s
, SIOCDELRT
, (char *)ort
));
402 struct rt_msghdr w_rtm
;
403 struct sockaddr_in w_dst
;
404 struct sockaddr w_gate
;
405 struct sockaddr_in w_netmask
;
409 memset(&w
, 0, sizeof(w
));
410 rtm
.rtm_msglen
= sizeof(w
);
411 rtm
.rtm_version
= RTM_VERSION
;
412 rtm
.rtm_type
= (action
== ADD
? RTM_ADD
:
413 (action
== DELETE
? RTM_DELETE
: RTM_CHANGE
));
415 rtm
.rtm_flags
= ort
->rtu_flags
;
416 rtm
.rtm_seq
= ++seqno
;
417 rtm
.rtm_addrs
= RTA_DST
|RTA_GATEWAY
;
418 memmove(&w
.w_dst
, &ort
->rtu_dst
, sizeof(w
.w_dst
));
419 memmove(&w
.w_gate
, &ort
->rtu_router
, sizeof(w
.w_gate
));
420 w
.w_dst
.sin_family
= AF_INET
;
421 w
.w_dst
.sin_len
= sizeof(w
.w_dst
);
422 w
.w_gate
.sa_family
= AF_INET
;
423 w
.w_gate
.sa_len
= sizeof(w
.w_gate
);
424 if (rtm
.rtm_flags
& RTF_HOST
) {
425 rtm
.rtm_msglen
-= sizeof(w
.w_netmask
);
430 rtm
.rtm_addrs
|= RTA_NETMASK
;
431 w
.w_netmask
.sin_addr
.s_addr
=
432 inet_maskof(w
.w_dst
.sin_addr
.s_addr
);
433 for (cp
= (char *)(1 + &w
.w_netmask
.sin_addr
);
434 --cp
> (char *) &w
.w_netmask
; )
437 len
= cp
- (char *)&w
.w_netmask
;
440 w
.w_netmask
.sin_len
= len
;
441 len
= 1 + ((len
- 1) | (sizeof(long) - 1));
444 rtm
.rtm_msglen
-= (sizeof(w
.w_netmask
) - len
);
447 return (install
? write(r
, (char *)&w
, rtm
.rtm_msglen
) : (errno
= 0));