]>
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>
67 #include <sys/syslog.h>
74 #define FIXLEN(s) {if ((s)->sa_len == 0) (s)->sa_len = sizeof *(s);}
79 int install
= !DEBUG
; /* if 1 call kernel */
82 * Lookup dst in the tables for an exact match.
88 register struct rt_entry
*rt
;
89 register struct rthash
*rh
;
94 if (dst
->sa_family
>= af_max
)
96 (*afswitch
[dst
->sa_family
].af_hash
)(dst
, &h
);
97 hash
= h
.afh_hosthash
;
98 rh
= &hosthash
[hash
& ROUTEHASHMASK
];
100 for (rt
= rh
->rt_forw
; rt
!= (struct rt_entry
*)rh
; rt
= rt
->rt_forw
) {
101 if (rt
->rt_hash
!= hash
)
103 if (equal(&rt
->rt_dst
, dst
))
108 hash
= h
.afh_nethash
;
109 rh
= &nethash
[hash
& ROUTEHASHMASK
];
115 struct sockaddr wildcard
; /* zero valued cookie for wildcard searches */
118 * Find a route to dst as the kernel would.
122 struct sockaddr
*dst
;
124 register struct rt_entry
*rt
;
125 register struct rthash
*rh
;
128 int af
= dst
->sa_family
;
129 int doinghost
= 1, (*match
)() = NULL
;
133 (*afswitch
[af
].af_hash
)(dst
, &h
);
134 hash
= h
.afh_hosthash
;
135 rh
= &hosthash
[hash
& ROUTEHASHMASK
];
138 for (rt
= rh
->rt_forw
; rt
!= (struct rt_entry
*)rh
; rt
= rt
->rt_forw
) {
139 if (rt
->rt_hash
!= hash
)
142 if (equal(&rt
->rt_dst
, dst
))
145 if (rt
->rt_dst
.sa_family
== af
&&
146 (*match
)(&rt
->rt_dst
, dst
))
152 hash
= h
.afh_nethash
;
153 rh
= &nethash
[hash
& ROUTEHASHMASK
];
154 match
= afswitch
[af
].af_netmatch
;
159 * Check for wildcard gateway, by convention network 0.
161 if (dst
!= &wildcard
) {
162 dst
= &wildcard
, hash
= 0;
170 rtadd(dst
, gate
, metric
, state
)
171 struct sockaddr
*dst
, *gate
;
175 register struct rt_entry
*rt
;
177 int af
= dst
->sa_family
, flags
;
182 (*afswitch
[af
].af_hash
)(dst
, &h
);
183 flags
= (*afswitch
[af
].af_rtflags
)(dst
);
185 * Subnet flag isn't visible to kernel, move to state. XXX
189 if (flags
& RTF_SUBNET
) {
191 flags
&= ~RTF_SUBNET
;
193 if (flags
& RTF_HOST
) {
194 hash
= h
.afh_hosthash
;
195 rh
= &hosthash
[hash
& ROUTEHASHMASK
];
197 hash
= h
.afh_nethash
;
198 rh
= &nethash
[hash
& ROUTEHASHMASK
];
200 rt
= (struct rt_entry
*)malloc(sizeof (*rt
));
205 rt
->rt_router
= *gate
;
207 rt
->rt_flags
= RTF_UP
| flags
;
208 rt
->rt_state
= state
| RTS_CHANGED
;
209 rt
->rt_ifp
= if_ifwithdstaddr(&rt
->rt_dst
);
211 rt
->rt_ifp
= if_ifwithnet(&rt
->rt_router
);
212 if ((state
& RTS_INTERFACE
) == 0)
213 rt
->rt_flags
|= RTF_GATEWAY
;
214 rt
->rt_metric
= metric
;
216 TRACE_ACTION("ADD", rt
);
218 * If the ioctl fails because the gateway is unreachable
219 * from this host, discard the entry. This should only
220 * occur because of an incorrect entry in /etc/gateways.
222 if ((rt
->rt_state
& (RTS_INTERNAL
| RTS_EXTERNAL
)) == 0 &&
223 rtioctl(ADD
, &rt
->rt_rt
) < 0) {
224 if (errno
!= EEXIST
&& gate
->sa_family
< af_max
)
226 "adding route to net/host %s through gateway %s: %m\n",
227 (*afswitch
[dst
->sa_family
].af_format
)(dst
),
228 (*afswitch
[gate
->sa_family
].af_format
)(gate
));
230 if (errno
== ENETUNREACH
) {
231 TRACE_ACTION("DELETE", rt
);
239 rtchange(rt
, gate
, metric
)
241 struct sockaddr
*gate
;
244 int add
= 0, delete = 0, newgateway
= 0;
245 struct rtuentry oldroute
;
248 FIXLEN(&(rt
->rt_router
));
249 FIXLEN(&(rt
->rt_dst
));
250 if (!equal(&rt
->rt_router
, gate
)) {
252 TRACE_ACTION("CHANGE FROM ", rt
);
253 } else if (metric
!= rt
->rt_metric
)
254 TRACE_NEWMETRIC(rt
, metric
);
255 if ((rt
->rt_state
& RTS_INTERNAL
) == 0) {
257 * If changing to different router, we need to add
258 * new route and delete old one if in the kernel.
259 * If the router is the same, we need to delete
260 * the route if has become unreachable, or re-add
261 * it if it had been unreachable.
265 if (rt
->rt_metric
!= HOPCNT_INFINITY
)
267 } else if (metric
== HOPCNT_INFINITY
)
269 else if (rt
->rt_metric
== HOPCNT_INFINITY
)
273 oldroute
= rt
->rt_rt
;
274 if ((rt
->rt_state
& RTS_INTERFACE
) && delete) {
275 rt
->rt_state
&= ~RTS_INTERFACE
;
276 rt
->rt_flags
|= RTF_GATEWAY
;
277 if (metric
> rt
->rt_metric
&& delete)
278 syslog(LOG_ERR
, "%s route to interface %s (timed out)",
279 add
? "changing" : "deleting",
280 rt
->rt_ifp
? rt
->rt_ifp
->int_name
: "?");
283 rt
->rt_router
= *gate
;
284 rt
->rt_ifp
= if_ifwithdstaddr(&rt
->rt_router
);
286 rt
->rt_ifp
= if_ifwithnet(&rt
->rt_router
);
288 rt
->rt_metric
= metric
;
289 rt
->rt_state
|= RTS_CHANGED
;
291 TRACE_ACTION("CHANGE TO ", rt
);
293 if (add
&& rtioctl(ADD
, &rt
->rt_rt
) < 0)
295 if (delete && rtioctl(DELETE
, &oldroute
) < 0)
296 perror("DELETE ROUTE");
298 if (delete && !add
) {
299 if (rtioctl(DELETE
, &oldroute
) < 0)
300 perror("DELETE ROUTE");
301 } else if (!delete && add
) {
302 if (rtioctl(ADD
, &rt
->rt_rt
) < 0)
304 } else if (delete && add
) {
305 if (rtioctl(CHANGE
, &rt
->rt_rt
) < 0)
306 perror("CHANGE ROUTE");
316 TRACE_ACTION("DELETE", rt
);
317 FIXLEN(&(rt
->rt_router
));
318 FIXLEN(&(rt
->rt_dst
));
319 if (rt
->rt_metric
< HOPCNT_INFINITY
) {
320 if ((rt
->rt_state
& (RTS_INTERFACE
|RTS_INTERNAL
)) == RTS_INTERFACE
)
322 "deleting route to interface %s? (timed out?)",
323 rt
->rt_ifp
->int_name
);
324 if ((rt
->rt_state
& (RTS_INTERNAL
| RTS_EXTERNAL
)) == 0 &&
325 rtioctl(DELETE
, &rt
->rt_rt
) < 0)
336 register struct rthash
*rh
;
337 register struct rt_entry
*rt
;
338 struct rthash
*base
= hosthash
;
342 for (rh
= base
; rh
< &base
[ROUTEHASHSIZ
]; rh
++) {
344 for (; rt
!= (struct rt_entry
*)rh
; rt
= rt
->rt_forw
) {
345 if (rt
->rt_state
& RTS_INTERFACE
||
346 rt
->rt_metric
>= HOPCNT_INFINITY
)
348 TRACE_ACTION("DELETE", rt
);
349 if ((rt
->rt_state
& (RTS_INTERNAL
|RTS_EXTERNAL
)) == 0 &&
350 rtioctl(DELETE
, &rt
->rt_rt
) < 0)
351 perror("rtdeleteall");
363 * If we have an interface to the wide, wide world,
364 * add an entry for an Internet default route (wildcard) to the internal
365 * tables and advertise it. This route is not added to the kernel routes,
366 * but this entry prevents us from listening to other people's defaults
367 * and installing them in the kernel here.
372 extern struct sockaddr inet_default
;
374 rtadd(&inet_default
, &inet_default
, 1,
375 RTS_CHANGED
| RTS_PASSIVE
| RTS_INTERNAL
);
381 register struct rthash
*rh
;
383 for (rh
= nethash
; rh
< &nethash
[ROUTEHASHSIZ
]; rh
++)
384 rh
->rt_forw
= rh
->rt_back
= (struct rt_entry
*)rh
;
385 for (rh
= hosthash
; rh
< &hosthash
[ROUTEHASHSIZ
]; rh
++)
386 rh
->rt_forw
= rh
->rt_back
= (struct rt_entry
*)rh
;
392 struct rtuentry
*ort
;
397 ort
->rtu_rtflags
= ort
->rtu_flags
;
401 return (ioctl(s
, SIOCADDRT
, (char *)ort
));
404 return (ioctl(s
, SIOCDELRT
, (char *)ort
));
411 struct rt_msghdr w_rtm
;
412 struct sockaddr_in w_dst
;
413 struct sockaddr w_gate
;
414 struct sockaddr_in w_netmask
;
418 memset(&w
, 0, sizeof(w
));
419 rtm
.rtm_msglen
= sizeof(w
);
420 rtm
.rtm_version
= RTM_VERSION
;
421 rtm
.rtm_type
= (action
== ADD
? RTM_ADD
:
422 (action
== DELETE
? RTM_DELETE
: RTM_CHANGE
));
424 rtm
.rtm_flags
= ort
->rtu_flags
;
425 rtm
.rtm_seq
= ++seqno
;
426 rtm
.rtm_addrs
= RTA_DST
|RTA_GATEWAY
;
427 memmove(&w
.w_dst
, &ort
->rtu_dst
, sizeof(w
.w_dst
));
428 memmove(&w
.w_gate
, &ort
->rtu_router
, sizeof(w
.w_gate
));
429 w
.w_dst
.sin_family
= AF_INET
;
430 w
.w_dst
.sin_len
= sizeof(w
.w_dst
);
431 w
.w_gate
.sa_family
= AF_INET
;
432 w
.w_gate
.sa_len
= sizeof(w
.w_gate
);
433 if (rtm
.rtm_flags
& RTF_HOST
) {
434 rtm
.rtm_msglen
-= sizeof(w
.w_netmask
);
439 rtm
.rtm_addrs
|= RTA_NETMASK
;
440 w
.w_netmask
.sin_addr
.s_addr
=
441 inet_maskof(w
.w_dst
.sin_addr
.s_addr
);
442 for (cp
= (char *)(1 + &w
.w_netmask
.sin_addr
);
443 --cp
> (char *) &w
.w_netmask
; )
446 len
= cp
- (char *)&w
.w_netmask
;
449 w
.w_netmask
.sin_len
= len
;
450 len
= 1 + ((len
- 1) | (sizeof(long) - 1));
453 rtm
.rtm_msglen
-= (sizeof(w
.w_netmask
) - len
);
456 return (install
? write(r
, (char *)&w
, rtm
.rtm_msglen
) : (errno
= 0));