]>
git.saurik.com Git - apple/network_cmds.git/blob - routed.tproj/tables.c
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
25 * Copyright (c) 1983, 1988, 1993
26 * The Regents of the University of California. All rights reserved.
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. All advertising materials mentioning features or use of this software
37 * must display the following acknowledgment:
38 * This product includes software developed by the University of
39 * California, Berkeley and its contributors.
40 * 4. Neither the name of the University nor the names of its contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
44 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * @(#)defs.h 8.1 (Berkeley) 6/5/93
61 * Routing Table Management Daemon
64 #include <sys/ioctl.h>
66 #include <sys/syslog.h>
73 #define FIXLEN(s) {if ((s)->sa_len == 0) (s)->sa_len = sizeof *(s);}
78 int install
= !DEBUG
; /* if 1 call kernel */
81 * Lookup dst in the tables for an exact match.
87 register struct rt_entry
*rt
;
88 register struct rthash
*rh
;
93 if (dst
->sa_family
>= af_max
)
95 (*afswitch
[dst
->sa_family
].af_hash
)(dst
, &h
);
96 hash
= h
.afh_hosthash
;
97 rh
= &hosthash
[hash
& ROUTEHASHMASK
];
99 for (rt
= rh
->rt_forw
; rt
!= (struct rt_entry
*)rh
; rt
= rt
->rt_forw
) {
100 if (rt
->rt_hash
!= hash
)
102 if (equal(&rt
->rt_dst
, dst
))
107 hash
= h
.afh_nethash
;
108 rh
= &nethash
[hash
& ROUTEHASHMASK
];
114 struct sockaddr wildcard
; /* zero valued cookie for wildcard searches */
117 * Find a route to dst as the kernel would.
121 struct sockaddr
*dst
;
123 register struct rt_entry
*rt
;
124 register struct rthash
*rh
;
127 int af
= dst
->sa_family
;
128 int doinghost
= 1, (*match
)();
132 (*afswitch
[af
].af_hash
)(dst
, &h
);
133 hash
= h
.afh_hosthash
;
134 rh
= &hosthash
[hash
& ROUTEHASHMASK
];
137 for (rt
= rh
->rt_forw
; rt
!= (struct rt_entry
*)rh
; rt
= rt
->rt_forw
) {
138 if (rt
->rt_hash
!= hash
)
141 if (equal(&rt
->rt_dst
, dst
))
144 if (rt
->rt_dst
.sa_family
== af
&&
145 (*match
)(&rt
->rt_dst
, dst
))
151 hash
= h
.afh_nethash
;
152 rh
= &nethash
[hash
& ROUTEHASHMASK
];
153 match
= afswitch
[af
].af_netmatch
;
158 * Check for wildcard gateway, by convention network 0.
160 if (dst
!= &wildcard
) {
161 dst
= &wildcard
, hash
= 0;
168 rtadd(dst
, gate
, metric
, state
)
169 struct sockaddr
*dst
, *gate
;
173 register struct rt_entry
*rt
;
175 int af
= dst
->sa_family
, flags
;
180 (*afswitch
[af
].af_hash
)(dst
, &h
);
181 flags
= (*afswitch
[af
].af_rtflags
)(dst
);
183 * Subnet flag isn't visible to kernel, move to state. XXX
187 if (flags
& RTF_SUBNET
) {
189 flags
&= ~RTF_SUBNET
;
191 if (flags
& RTF_HOST
) {
192 hash
= h
.afh_hosthash
;
193 rh
= &hosthash
[hash
& ROUTEHASHMASK
];
195 hash
= h
.afh_nethash
;
196 rh
= &nethash
[hash
& ROUTEHASHMASK
];
198 rt
= (struct rt_entry
*)malloc(sizeof (*rt
));
203 rt
->rt_router
= *gate
;
205 rt
->rt_flags
= RTF_UP
| flags
;
206 rt
->rt_state
= state
| RTS_CHANGED
;
207 rt
->rt_ifp
= if_ifwithdstaddr(&rt
->rt_dst
);
209 rt
->rt_ifp
= if_ifwithnet(&rt
->rt_router
);
210 if ((state
& RTS_INTERFACE
) == 0)
211 rt
->rt_flags
|= RTF_GATEWAY
;
212 rt
->rt_metric
= metric
;
214 TRACE_ACTION("ADD", rt
);
216 * If the ioctl fails because the gateway is unreachable
217 * from this host, discard the entry. This should only
218 * occur because of an incorrect entry in /etc/gateways.
220 if ((rt
->rt_state
& (RTS_INTERNAL
| RTS_EXTERNAL
)) == 0 &&
221 rtioctl(ADD
, &rt
->rt_rt
) < 0) {
222 if (errno
!= EEXIST
&& gate
->sa_family
< af_max
)
224 "adding route to net/host %s through gateway %s: %m\n",
225 (*afswitch
[dst
->sa_family
].af_format
)(dst
),
226 (*afswitch
[gate
->sa_family
].af_format
)(gate
));
228 if (errno
== ENETUNREACH
) {
229 TRACE_ACTION("DELETE", rt
);
236 rtchange(rt
, gate
, metric
)
238 struct sockaddr
*gate
;
241 int add
= 0, delete = 0, newgateway
= 0;
242 struct rtuentry oldroute
;
245 FIXLEN(&(rt
->rt_router
));
246 FIXLEN(&(rt
->rt_dst
));
247 if (!equal(&rt
->rt_router
, gate
)) {
249 TRACE_ACTION("CHANGE FROM ", rt
);
250 } else if (metric
!= rt
->rt_metric
)
251 TRACE_NEWMETRIC(rt
, metric
);
252 if ((rt
->rt_state
& RTS_INTERNAL
) == 0) {
254 * If changing to different router, we need to add
255 * new route and delete old one if in the kernel.
256 * If the router is the same, we need to delete
257 * the route if has become unreachable, or re-add
258 * it if it had been unreachable.
262 if (rt
->rt_metric
!= HOPCNT_INFINITY
)
264 } else if (metric
== HOPCNT_INFINITY
)
266 else if (rt
->rt_metric
== HOPCNT_INFINITY
)
270 oldroute
= rt
->rt_rt
;
271 if ((rt
->rt_state
& RTS_INTERFACE
) && delete) {
272 rt
->rt_state
&= ~RTS_INTERFACE
;
273 rt
->rt_flags
|= RTF_GATEWAY
;
274 if (metric
> rt
->rt_metric
&& delete)
275 syslog(LOG_ERR
, "%s route to interface %s (timed out)",
276 add
? "changing" : "deleting",
277 rt
->rt_ifp
? rt
->rt_ifp
->int_name
: "?");
280 rt
->rt_router
= *gate
;
281 rt
->rt_ifp
= if_ifwithdstaddr(&rt
->rt_router
);
283 rt
->rt_ifp
= if_ifwithnet(&rt
->rt_router
);
285 rt
->rt_metric
= metric
;
286 rt
->rt_state
|= RTS_CHANGED
;
288 TRACE_ACTION("CHANGE TO ", rt
);
290 if (add
&& rtioctl(ADD
, &rt
->rt_rt
) < 0)
292 if (delete && rtioctl(DELETE
, &oldroute
) < 0)
293 perror("DELETE ROUTE");
295 if (delete && !add
) {
296 if (rtioctl(DELETE
, &oldroute
) < 0)
297 perror("DELETE ROUTE");
298 } else if (!delete && add
) {
299 if (rtioctl(ADD
, &rt
->rt_rt
) < 0)
301 } else if (delete && add
) {
302 if (rtioctl(CHANGE
, &rt
->rt_rt
) < 0)
303 perror("CHANGE ROUTE");
312 TRACE_ACTION("DELETE", rt
);
313 FIXLEN(&(rt
->rt_router
));
314 FIXLEN(&(rt
->rt_dst
));
315 if (rt
->rt_metric
< HOPCNT_INFINITY
) {
316 if ((rt
->rt_state
& (RTS_INTERFACE
|RTS_INTERNAL
)) == RTS_INTERFACE
)
318 "deleting route to interface %s? (timed out?)",
319 rt
->rt_ifp
->int_name
);
320 if ((rt
->rt_state
& (RTS_INTERNAL
| RTS_EXTERNAL
)) == 0 &&
321 rtioctl(DELETE
, &rt
->rt_rt
) < 0)
331 register struct rthash
*rh
;
332 register struct rt_entry
*rt
;
333 struct rthash
*base
= hosthash
;
337 for (rh
= base
; rh
< &base
[ROUTEHASHSIZ
]; rh
++) {
339 for (; rt
!= (struct rt_entry
*)rh
; rt
= rt
->rt_forw
) {
340 if (rt
->rt_state
& RTS_INTERFACE
||
341 rt
->rt_metric
>= HOPCNT_INFINITY
)
343 TRACE_ACTION("DELETE", rt
);
344 if ((rt
->rt_state
& (RTS_INTERNAL
|RTS_EXTERNAL
)) == 0 &&
345 rtioctl(DELETE
, &rt
->rt_rt
) < 0)
346 perror("rtdeleteall");
358 * If we have an interface to the wide, wide world,
359 * add an entry for an Internet default route (wildcard) to the internal
360 * tables and advertise it. This route is not added to the kernel routes,
361 * but this entry prevents us from listening to other people's defaults
362 * and installing them in the kernel here.
366 extern struct sockaddr inet_default
;
368 rtadd(&inet_default
, &inet_default
, 1,
369 RTS_CHANGED
| RTS_PASSIVE
| RTS_INTERNAL
);
374 register struct rthash
*rh
;
376 for (rh
= nethash
; rh
< &nethash
[ROUTEHASHSIZ
]; rh
++)
377 rh
->rt_forw
= rh
->rt_back
= (struct rt_entry
*)rh
;
378 for (rh
= hosthash
; rh
< &hosthash
[ROUTEHASHSIZ
]; rh
++)
379 rh
->rt_forw
= rh
->rt_back
= (struct rt_entry
*)rh
;
384 struct rtuentry
*ort
;
389 ort
->rtu_rtflags
= ort
->rtu_flags
;
393 return (ioctl(s
, SIOCADDRT
, (char *)ort
));
396 return (ioctl(s
, SIOCDELRT
, (char *)ort
));
403 struct rt_msghdr w_rtm
;
404 struct sockaddr_in w_dst
;
405 struct sockaddr w_gate
;
406 struct sockaddr_in w_netmask
;
410 memset(&w
, 0, sizeof(w
));
411 rtm
.rtm_msglen
= sizeof(w
);
412 rtm
.rtm_version
= RTM_VERSION
;
413 rtm
.rtm_type
= (action
== ADD
? RTM_ADD
:
414 (action
== DELETE
? RTM_DELETE
: RTM_CHANGE
));
416 rtm
.rtm_flags
= ort
->rtu_flags
;
417 rtm
.rtm_seq
= ++seqno
;
418 rtm
.rtm_addrs
= RTA_DST
|RTA_GATEWAY
;
419 memmove(&w
.w_dst
, &ort
->rtu_dst
, sizeof(w
.w_dst
));
420 memmove(&w
.w_gate
, &ort
->rtu_router
, sizeof(w
.w_gate
));
421 w
.w_dst
.sin_family
= AF_INET
;
422 w
.w_dst
.sin_len
= sizeof(w
.w_dst
);
423 w
.w_gate
.sa_family
= AF_INET
;
424 w
.w_gate
.sa_len
= sizeof(w
.w_gate
);
425 if (rtm
.rtm_flags
& RTF_HOST
) {
426 rtm
.rtm_msglen
-= sizeof(w
.w_netmask
);
431 rtm
.rtm_addrs
|= RTA_NETMASK
;
432 w
.w_netmask
.sin_addr
.s_addr
=
433 inet_maskof(w
.w_dst
.sin_addr
.s_addr
);
434 for (cp
= (char *)(1 + &w
.w_netmask
.sin_addr
);
435 --cp
> (char *) &w
.w_netmask
; )
438 len
= cp
- (char *)&w
.w_netmask
;
441 w
.w_netmask
.sin_len
= len
;
442 len
= 1 + ((len
- 1) | (sizeof(long) - 1));
445 rtm
.rtm_msglen
-= (sizeof(w
.w_netmask
) - len
);
448 return (install
? write(r
, (char *)&w
, rtm
.rtm_msglen
) : (errno
= 0));