1 | /*- |
---|
2 | * Copyright (c) 1983, 1988, 1993 |
---|
3 | * The Regents of the University of California. All rights reserved. |
---|
4 | * |
---|
5 | * Redistribution and use in source and binary forms, with or without |
---|
6 | * modification, are permitted provided that the following conditions |
---|
7 | * are met: |
---|
8 | * 1. Redistributions of source code must retain the above copyright |
---|
9 | * notice, this list of conditions and the following disclaimer. |
---|
10 | * 2. Redistributions in binary form must reproduce the above copyright |
---|
11 | * notice, this list of conditions and the following disclaimer in the |
---|
12 | * documentation and/or other materials provided with the distribution. |
---|
13 | * 3. All advertising materials mentioning features or use of this software |
---|
14 | * must display the following acknowledgement: |
---|
15 | * This product includes software developed by the University of |
---|
16 | * California, Berkeley and its contributors. |
---|
17 | * 4. Neither the name of the University nor the names of its contributors |
---|
18 | * may be used to endorse or promote products derived from this software |
---|
19 | * without specific prior written permission. |
---|
20 | * |
---|
21 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
---|
22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
---|
23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
---|
24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
---|
25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
---|
26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
---|
27 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
---|
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
---|
29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
---|
30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
---|
31 | * SUCH DAMAGE. |
---|
32 | */ |
---|
33 | |
---|
34 | #if 0 |
---|
35 | #ifndef lint |
---|
36 | static char sccsid[] = "From: @(#)route.c 8.6 (Berkeley) 4/28/95"; |
---|
37 | #endif /* not lint */ |
---|
38 | #endif |
---|
39 | |
---|
40 | #include <sys/cdefs.h> |
---|
41 | __FBSDID("$FreeBSD$"); |
---|
42 | |
---|
43 | #include <sys/param.h> |
---|
44 | #ifdef __rtems__ |
---|
45 | #include <freebsd/sys/protosw.h> |
---|
46 | #else |
---|
47 | #include <sys/protosw.h> |
---|
48 | #endif |
---|
49 | #include <sys/socket.h> |
---|
50 | #include <sys/socketvar.h> |
---|
51 | #include <sys/time.h> |
---|
52 | |
---|
53 | #include <net/ethernet.h> |
---|
54 | #include <net/if.h> |
---|
55 | #ifdef __rtems__ |
---|
56 | #include <freebsd/net/if_var.h> |
---|
57 | #else |
---|
58 | #include <net/if_var.h> |
---|
59 | #endif |
---|
60 | #include <net/if_dl.h> |
---|
61 | #include <net/if_types.h> |
---|
62 | #ifdef __rtems__ |
---|
63 | #include <freebsd/net/radix.h> |
---|
64 | #else |
---|
65 | #include <net/radix.h> |
---|
66 | #endif |
---|
67 | #include <net/route.h> |
---|
68 | |
---|
69 | #include <netinet/in.h> |
---|
70 | #ifdef __rtems__ |
---|
71 | /* no IPX on RTEMS */ |
---|
72 | /* no AppleTalk on RTEMS */ |
---|
73 | #else |
---|
74 | #include <netipx/ipx.h> |
---|
75 | #include <netatalk/at.h> |
---|
76 | #endif |
---|
77 | #ifdef __rtems__ |
---|
78 | /* why isn't this protected by a NETGRAPH define */ |
---|
79 | #else |
---|
80 | #include <netgraph/ng_socket.h> |
---|
81 | #endif |
---|
82 | |
---|
83 | #include <sys/sysctl.h> |
---|
84 | |
---|
85 | #include <arpa/inet.h> |
---|
86 | #ifdef __rtems__ |
---|
87 | /* apparently libutil.h is not needed */ |
---|
88 | #else |
---|
89 | #include <libutil.h> |
---|
90 | #endif |
---|
91 | #include <netdb.h> |
---|
92 | #include <stdint.h> |
---|
93 | #include <stdio.h> |
---|
94 | #include <stdlib.h> |
---|
95 | #include <string.h> |
---|
96 | #include <sysexits.h> |
---|
97 | #include <unistd.h> |
---|
98 | #include <err.h> |
---|
99 | #include "netstat.h" |
---|
100 | |
---|
101 | #define kget(p, d) (kread((u_long)(p), (char *)&(d), sizeof (d))) |
---|
102 | |
---|
103 | /* |
---|
104 | * Definitions for showing gateway flags. |
---|
105 | */ |
---|
106 | struct bits { |
---|
107 | u_long b_mask; |
---|
108 | char b_val; |
---|
109 | } bits[] = { |
---|
110 | { RTF_UP, 'U' }, |
---|
111 | { RTF_GATEWAY, 'G' }, |
---|
112 | { RTF_HOST, 'H' }, |
---|
113 | { RTF_REJECT, 'R' }, |
---|
114 | { RTF_DYNAMIC, 'D' }, |
---|
115 | { RTF_MODIFIED, 'M' }, |
---|
116 | { RTF_DONE, 'd' }, /* Completed -- for routing messages only */ |
---|
117 | { RTF_XRESOLVE, 'X' }, |
---|
118 | { RTF_STATIC, 'S' }, |
---|
119 | { RTF_PROTO1, '1' }, |
---|
120 | { RTF_PROTO2, '2' }, |
---|
121 | { RTF_PRCLONING,'c' }, |
---|
122 | { RTF_PROTO3, '3' }, |
---|
123 | { RTF_BLACKHOLE,'B' }, |
---|
124 | { RTF_BROADCAST,'b' }, |
---|
125 | #ifdef RTF_LLINFO |
---|
126 | { RTF_LLINFO, 'L' }, |
---|
127 | #endif |
---|
128 | #ifdef RTF_WASCLONED |
---|
129 | { RTF_WASCLONED,'W' }, |
---|
130 | #endif |
---|
131 | #ifdef RTF_CLONING |
---|
132 | { RTF_CLONING, 'C' }, |
---|
133 | #endif |
---|
134 | { 0 , 0 } |
---|
135 | }; |
---|
136 | |
---|
137 | typedef union { |
---|
138 | long dummy; /* Helps align structure. */ |
---|
139 | struct sockaddr u_sa; |
---|
140 | u_short u_data[128]; |
---|
141 | } sa_u; |
---|
142 | |
---|
143 | static sa_u pt_u; |
---|
144 | |
---|
145 | int fibnum; |
---|
146 | int do_rtent = 0; |
---|
147 | struct rtentry rtentry; |
---|
148 | struct radix_node rnode; |
---|
149 | struct radix_mask rmask; |
---|
150 | struct radix_node_head **rt_tables; |
---|
151 | |
---|
152 | int NewTree = 0; |
---|
153 | |
---|
154 | struct timespec uptime; |
---|
155 | |
---|
156 | static struct sockaddr *kgetsa(struct sockaddr *); |
---|
157 | static void size_cols(int ef, struct radix_node *rn); |
---|
158 | static void size_cols_tree(struct radix_node *rn); |
---|
159 | static void size_cols_rtentry(struct rtentry *rt); |
---|
160 | static void p_tree(struct radix_node *); |
---|
161 | static void p_rtnode(void); |
---|
162 | static void ntreestuff(void); |
---|
163 | static void np_rtentry(struct rt_msghdr *); |
---|
164 | static void p_sockaddr(struct sockaddr *, struct sockaddr *, int, int); |
---|
165 | static const char *fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask, |
---|
166 | int flags); |
---|
167 | static void p_flags(int, const char *); |
---|
168 | static const char *fmt_flags(int f); |
---|
169 | static void p_rtentry(struct rtentry *); |
---|
170 | static void domask(char *, in_addr_t, u_long); |
---|
171 | |
---|
172 | /* |
---|
173 | * Print routing tables. |
---|
174 | */ |
---|
175 | void |
---|
176 | routepr(u_long rtree) |
---|
177 | { |
---|
178 | struct radix_node_head **rnhp, *rnh, head; |
---|
179 | size_t intsize; |
---|
180 | int i; |
---|
181 | int numfibs; |
---|
182 | |
---|
183 | intsize = sizeof(int); |
---|
184 | if (sysctlbyname("net.my_fibnum", &fibnum, &intsize, NULL, 0) == -1) |
---|
185 | fibnum = 0; |
---|
186 | if (sysctlbyname("net.fibs", &numfibs, &intsize, NULL, 0) == -1) |
---|
187 | numfibs = 1; |
---|
188 | rt_tables = calloc(numfibs * (AF_MAX+1), |
---|
189 | sizeof(struct radix_node_head *)); |
---|
190 | if (rt_tables == NULL) |
---|
191 | err(EX_OSERR, "memory allocation failed"); |
---|
192 | /* |
---|
193 | * Since kernel & userland use different timebase |
---|
194 | * (time_uptime vs time_second) and we are reading kernel memory |
---|
195 | * directly we should do rt_rmx.rmx_expire --> expire_time conversion. |
---|
196 | */ |
---|
197 | #ifdef __rtems__ |
---|
198 | #warning "fix clock_gettime(CLOCK_UPTIME)" |
---|
199 | #else |
---|
200 | if (clock_gettime(CLOCK_UPTIME, &uptime) < 0) |
---|
201 | err(EX_OSERR, "clock_gettime() failed"); |
---|
202 | #endif |
---|
203 | |
---|
204 | printf("Routing tables\n"); |
---|
205 | |
---|
206 | if (Aflag == 0 && NewTree) |
---|
207 | ntreestuff(); |
---|
208 | else { |
---|
209 | if (rtree == 0) { |
---|
210 | printf("rt_tables: symbol not in namelist\n"); |
---|
211 | return; |
---|
212 | } |
---|
213 | |
---|
214 | if (kread((u_long)(rtree), (char *)(rt_tables), (numfibs * |
---|
215 | (AF_MAX+1) * sizeof(struct radix_node_head *))) != 0) |
---|
216 | return; |
---|
217 | for (i = 0; i <= AF_MAX; i++) { |
---|
218 | int tmpfib; |
---|
219 | if (i != AF_INET) |
---|
220 | tmpfib = 0; |
---|
221 | else |
---|
222 | tmpfib = fibnum; |
---|
223 | rnhp = (struct radix_node_head **)*rt_tables; |
---|
224 | /* Calculate the in-kernel address. */ |
---|
225 | rnhp += tmpfib * (AF_MAX+1) + i; |
---|
226 | /* Read the in kernel rhn pointer. */ |
---|
227 | if (kget(rnhp, rnh) != 0) |
---|
228 | continue; |
---|
229 | if (rnh == NULL) |
---|
230 | continue; |
---|
231 | /* Read the rnh data. */ |
---|
232 | if (kget(rnh, head) != 0) |
---|
233 | continue; |
---|
234 | if (i == AF_UNSPEC) { |
---|
235 | if (Aflag && af == 0) { |
---|
236 | printf("Netmasks:\n"); |
---|
237 | p_tree(head.rnh_treetop); |
---|
238 | } |
---|
239 | } else if (af == AF_UNSPEC || af == i) { |
---|
240 | size_cols(i, head.rnh_treetop); |
---|
241 | pr_family(i); |
---|
242 | do_rtent = 1; |
---|
243 | pr_rthdr(i); |
---|
244 | p_tree(head.rnh_treetop); |
---|
245 | } |
---|
246 | } |
---|
247 | } |
---|
248 | } |
---|
249 | |
---|
250 | /* |
---|
251 | * Print address family header before a section of the routing table. |
---|
252 | */ |
---|
253 | void |
---|
254 | pr_family(int af1) |
---|
255 | { |
---|
256 | const char *afname; |
---|
257 | |
---|
258 | switch (af1) { |
---|
259 | case AF_INET: |
---|
260 | afname = "Internet"; |
---|
261 | break; |
---|
262 | #ifdef INET6 |
---|
263 | case AF_INET6: |
---|
264 | afname = "Internet6"; |
---|
265 | break; |
---|
266 | #endif /*INET6*/ |
---|
267 | case AF_IPX: |
---|
268 | afname = "IPX"; |
---|
269 | break; |
---|
270 | case AF_ISO: |
---|
271 | afname = "ISO"; |
---|
272 | break; |
---|
273 | case AF_APPLETALK: |
---|
274 | afname = "AppleTalk"; |
---|
275 | break; |
---|
276 | case AF_CCITT: |
---|
277 | afname = "X.25"; |
---|
278 | break; |
---|
279 | case AF_NETGRAPH: |
---|
280 | afname = "Netgraph"; |
---|
281 | break; |
---|
282 | default: |
---|
283 | afname = NULL; |
---|
284 | break; |
---|
285 | } |
---|
286 | if (afname) |
---|
287 | printf("\n%s:\n", afname); |
---|
288 | else |
---|
289 | printf("\nProtocol Family %d:\n", af1); |
---|
290 | } |
---|
291 | |
---|
292 | /* column widths; each followed by one space */ |
---|
293 | #ifndef INET6 |
---|
294 | #define WID_DST_DEFAULT(af) 18 /* width of destination column */ |
---|
295 | #define WID_GW_DEFAULT(af) 18 /* width of gateway column */ |
---|
296 | #define WID_IF_DEFAULT(af) (Wflag ? 8 : 6) /* width of netif column */ |
---|
297 | #else |
---|
298 | #define WID_DST_DEFAULT(af) \ |
---|
299 | ((af) == AF_INET6 ? (numeric_addr ? 33: 18) : 18) |
---|
300 | #define WID_GW_DEFAULT(af) \ |
---|
301 | ((af) == AF_INET6 ? (numeric_addr ? 29 : 18) : 18) |
---|
302 | #define WID_IF_DEFAULT(af) ((af) == AF_INET6 ? 8 : (Wflag ? 8 : 6)) |
---|
303 | #endif /*INET6*/ |
---|
304 | |
---|
305 | static int wid_dst; |
---|
306 | static int wid_gw; |
---|
307 | static int wid_flags; |
---|
308 | static int wid_refs; |
---|
309 | static int wid_use; |
---|
310 | static int wid_mtu; |
---|
311 | static int wid_if; |
---|
312 | static int wid_expire; |
---|
313 | |
---|
314 | static void |
---|
315 | size_cols(int ef __unused, struct radix_node *rn) |
---|
316 | { |
---|
317 | wid_dst = WID_DST_DEFAULT(ef); |
---|
318 | wid_gw = WID_GW_DEFAULT(ef); |
---|
319 | wid_flags = 6; |
---|
320 | wid_refs = 6; |
---|
321 | wid_use = 8; |
---|
322 | wid_mtu = 6; |
---|
323 | wid_if = WID_IF_DEFAULT(ef); |
---|
324 | wid_expire = 6; |
---|
325 | |
---|
326 | if (Wflag) |
---|
327 | size_cols_tree(rn); |
---|
328 | } |
---|
329 | |
---|
330 | static void |
---|
331 | size_cols_tree(struct radix_node *rn) |
---|
332 | { |
---|
333 | again: |
---|
334 | if (kget(rn, rnode) != 0) |
---|
335 | return; |
---|
336 | if (!(rnode.rn_flags & RNF_ACTIVE)) |
---|
337 | return; |
---|
338 | if (rnode.rn_bit < 0) { |
---|
339 | if ((rnode.rn_flags & RNF_ROOT) == 0) { |
---|
340 | if (kget(rn, rtentry) != 0) |
---|
341 | return; |
---|
342 | size_cols_rtentry(&rtentry); |
---|
343 | } |
---|
344 | if ((rn = rnode.rn_dupedkey)) |
---|
345 | goto again; |
---|
346 | } else { |
---|
347 | rn = rnode.rn_right; |
---|
348 | size_cols_tree(rnode.rn_left); |
---|
349 | size_cols_tree(rn); |
---|
350 | } |
---|
351 | } |
---|
352 | |
---|
353 | static void |
---|
354 | size_cols_rtentry(struct rtentry *rt) |
---|
355 | { |
---|
356 | static struct ifnet ifnet, *lastif; |
---|
357 | static char buffer[100]; |
---|
358 | const char *bp; |
---|
359 | struct sockaddr *sa; |
---|
360 | sa_u addr, mask; |
---|
361 | int len; |
---|
362 | |
---|
363 | bzero(&addr, sizeof(addr)); |
---|
364 | if ((sa = kgetsa(rt_key(rt)))) |
---|
365 | bcopy(sa, &addr, sa->sa_len); |
---|
366 | bzero(&mask, sizeof(mask)); |
---|
367 | if (rt_mask(rt) && (sa = kgetsa(rt_mask(rt)))) |
---|
368 | bcopy(sa, &mask, sa->sa_len); |
---|
369 | bp = fmt_sockaddr(&addr.u_sa, &mask.u_sa, rt->rt_flags); |
---|
370 | len = strlen(bp); |
---|
371 | wid_dst = MAX(len, wid_dst); |
---|
372 | |
---|
373 | bp = fmt_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST); |
---|
374 | len = strlen(bp); |
---|
375 | wid_gw = MAX(len, wid_gw); |
---|
376 | |
---|
377 | bp = fmt_flags(rt->rt_flags); |
---|
378 | len = strlen(bp); |
---|
379 | wid_flags = MAX(len, wid_flags); |
---|
380 | |
---|
381 | if (addr.u_sa.sa_family == AF_INET || Wflag) { |
---|
382 | len = snprintf(buffer, sizeof(buffer), "%d", rt->rt_refcnt); |
---|
383 | wid_refs = MAX(len, wid_refs); |
---|
384 | len = snprintf(buffer, sizeof(buffer), "%lu", rt->rt_use); |
---|
385 | wid_use = MAX(len, wid_use); |
---|
386 | if (Wflag && rt->rt_rmx.rmx_mtu != 0) { |
---|
387 | len = snprintf(buffer, sizeof(buffer), |
---|
388 | "%lu", rt->rt_rmx.rmx_mtu); |
---|
389 | wid_mtu = MAX(len, wid_mtu); |
---|
390 | } |
---|
391 | } |
---|
392 | if (rt->rt_ifp) { |
---|
393 | if (rt->rt_ifp != lastif) { |
---|
394 | if (kget(rt->rt_ifp, ifnet) == 0) |
---|
395 | len = strlen(ifnet.if_xname); |
---|
396 | else |
---|
397 | len = strlen("---"); |
---|
398 | lastif = rt->rt_ifp; |
---|
399 | wid_if = MAX(len, wid_if); |
---|
400 | } |
---|
401 | if (rt->rt_rmx.rmx_expire) { |
---|
402 | time_t expire_time; |
---|
403 | |
---|
404 | if ((expire_time = |
---|
405 | rt->rt_rmx.rmx_expire - uptime.tv_sec) > 0) { |
---|
406 | len = snprintf(buffer, sizeof(buffer), "%d", |
---|
407 | (int)expire_time); |
---|
408 | wid_expire = MAX(len, wid_expire); |
---|
409 | } |
---|
410 | } |
---|
411 | } |
---|
412 | } |
---|
413 | |
---|
414 | |
---|
415 | /* |
---|
416 | * Print header for routing table columns. |
---|
417 | */ |
---|
418 | void |
---|
419 | pr_rthdr(int af1) |
---|
420 | { |
---|
421 | |
---|
422 | if (Aflag) |
---|
423 | printf("%-8.8s ","Address"); |
---|
424 | if (af1 == AF_INET || Wflag) { |
---|
425 | if (Wflag) { |
---|
426 | printf("%-*.*s %-*.*s %-*.*s %*.*s %*.*s %*.*s %*.*s %*s\n", |
---|
427 | wid_dst, wid_dst, "Destination", |
---|
428 | wid_gw, wid_gw, "Gateway", |
---|
429 | wid_flags, wid_flags, "Flags", |
---|
430 | wid_refs, wid_refs, "Refs", |
---|
431 | wid_use, wid_use, "Use", |
---|
432 | wid_mtu, wid_mtu, "Mtu", |
---|
433 | wid_if, wid_if, "Netif", |
---|
434 | wid_expire, "Expire"); |
---|
435 | } else { |
---|
436 | printf("%-*.*s %-*.*s %-*.*s %*.*s %*.*s %*.*s %*s\n", |
---|
437 | wid_dst, wid_dst, "Destination", |
---|
438 | wid_gw, wid_gw, "Gateway", |
---|
439 | wid_flags, wid_flags, "Flags", |
---|
440 | wid_refs, wid_refs, "Refs", |
---|
441 | wid_use, wid_use, "Use", |
---|
442 | wid_if, wid_if, "Netif", |
---|
443 | wid_expire, "Expire"); |
---|
444 | } |
---|
445 | } else { |
---|
446 | printf("%-*.*s %-*.*s %-*.*s %*.*s %*s\n", |
---|
447 | wid_dst, wid_dst, "Destination", |
---|
448 | wid_gw, wid_gw, "Gateway", |
---|
449 | wid_flags, wid_flags, "Flags", |
---|
450 | wid_if, wid_if, "Netif", |
---|
451 | wid_expire, "Expire"); |
---|
452 | } |
---|
453 | } |
---|
454 | |
---|
455 | static struct sockaddr * |
---|
456 | kgetsa(struct sockaddr *dst) |
---|
457 | { |
---|
458 | |
---|
459 | if (kget(dst, pt_u.u_sa) != 0) |
---|
460 | return (NULL); |
---|
461 | if (pt_u.u_sa.sa_len > sizeof (pt_u.u_sa)) |
---|
462 | kread((u_long)dst, (char *)pt_u.u_data, pt_u.u_sa.sa_len); |
---|
463 | return (&pt_u.u_sa); |
---|
464 | } |
---|
465 | |
---|
466 | static void |
---|
467 | p_tree(struct radix_node *rn) |
---|
468 | { |
---|
469 | |
---|
470 | again: |
---|
471 | if (kget(rn, rnode) != 0) |
---|
472 | return; |
---|
473 | if (!(rnode.rn_flags & RNF_ACTIVE)) |
---|
474 | return; |
---|
475 | if (rnode.rn_bit < 0) { |
---|
476 | if (Aflag) |
---|
477 | printf("%-8.8lx ", (u_long)rn); |
---|
478 | if (rnode.rn_flags & RNF_ROOT) { |
---|
479 | if (Aflag) |
---|
480 | printf("(root node)%s", |
---|
481 | rnode.rn_dupedkey ? " =>\n" : "\n"); |
---|
482 | } else if (do_rtent) { |
---|
483 | if (kget(rn, rtentry) == 0) { |
---|
484 | p_rtentry(&rtentry); |
---|
485 | if (Aflag) |
---|
486 | p_rtnode(); |
---|
487 | } |
---|
488 | } else { |
---|
489 | p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_key), |
---|
490 | NULL, 0, 44); |
---|
491 | putchar('\n'); |
---|
492 | } |
---|
493 | if ((rn = rnode.rn_dupedkey)) |
---|
494 | goto again; |
---|
495 | } else { |
---|
496 | if (Aflag && do_rtent) { |
---|
497 | printf("%-8.8lx ", (u_long)rn); |
---|
498 | p_rtnode(); |
---|
499 | } |
---|
500 | rn = rnode.rn_right; |
---|
501 | p_tree(rnode.rn_left); |
---|
502 | p_tree(rn); |
---|
503 | } |
---|
504 | } |
---|
505 | |
---|
506 | char nbuf[20]; |
---|
507 | |
---|
508 | static void |
---|
509 | p_rtnode(void) |
---|
510 | { |
---|
511 | struct radix_mask *rm = rnode.rn_mklist; |
---|
512 | |
---|
513 | if (rnode.rn_bit < 0) { |
---|
514 | if (rnode.rn_mask) { |
---|
515 | printf("\t mask "); |
---|
516 | p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_mask), |
---|
517 | NULL, 0, -1); |
---|
518 | } else if (rm == 0) |
---|
519 | return; |
---|
520 | } else { |
---|
521 | sprintf(nbuf, "(%d)", rnode.rn_bit); |
---|
522 | printf("%6.6s %8.8lx : %8.8lx", nbuf, (u_long)rnode.rn_left, (u_long)rnode.rn_right); |
---|
523 | } |
---|
524 | while (rm) { |
---|
525 | if (kget(rm, rmask) != 0) |
---|
526 | break; |
---|
527 | sprintf(nbuf, " %d refs, ", rmask.rm_refs); |
---|
528 | printf(" mk = %8.8lx {(%d),%s", |
---|
529 | (u_long)rm, -1 - rmask.rm_bit, rmask.rm_refs ? nbuf : " "); |
---|
530 | if (rmask.rm_flags & RNF_NORMAL) { |
---|
531 | struct radix_node rnode_aux; |
---|
532 | printf(" <normal>, "); |
---|
533 | if (kget(rmask.rm_leaf, rnode_aux) == 0) |
---|
534 | p_sockaddr(kgetsa((struct sockaddr *)rnode_aux.rn_mask), |
---|
535 | NULL, 0, -1); |
---|
536 | else |
---|
537 | p_sockaddr(NULL, NULL, 0, -1); |
---|
538 | } else |
---|
539 | p_sockaddr(kgetsa((struct sockaddr *)rmask.rm_mask), |
---|
540 | NULL, 0, -1); |
---|
541 | putchar('}'); |
---|
542 | if ((rm = rmask.rm_mklist)) |
---|
543 | printf(" ->"); |
---|
544 | } |
---|
545 | putchar('\n'); |
---|
546 | } |
---|
547 | |
---|
548 | static void |
---|
549 | ntreestuff(void) |
---|
550 | { |
---|
551 | size_t needed; |
---|
552 | int mib[6]; |
---|
553 | char *buf, *next, *lim; |
---|
554 | struct rt_msghdr *rtm; |
---|
555 | |
---|
556 | mib[0] = CTL_NET; |
---|
557 | mib[1] = PF_ROUTE; |
---|
558 | mib[2] = 0; |
---|
559 | mib[3] = 0; |
---|
560 | mib[4] = NET_RT_DUMP; |
---|
561 | mib[5] = 0; |
---|
562 | if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { |
---|
563 | err(1, "sysctl: net.route.0.0.dump estimate"); |
---|
564 | } |
---|
565 | |
---|
566 | if ((buf = malloc(needed)) == 0) { |
---|
567 | errx(2, "malloc(%lu)", (unsigned long)needed); |
---|
568 | } |
---|
569 | if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { |
---|
570 | err(1, "sysctl: net.route.0.0.dump"); |
---|
571 | } |
---|
572 | lim = buf + needed; |
---|
573 | for (next = buf; next < lim; next += rtm->rtm_msglen) { |
---|
574 | rtm = (struct rt_msghdr *)next; |
---|
575 | np_rtentry(rtm); |
---|
576 | } |
---|
577 | } |
---|
578 | |
---|
579 | static void |
---|
580 | np_rtentry(struct rt_msghdr *rtm) |
---|
581 | { |
---|
582 | struct sockaddr *sa = (struct sockaddr *)(rtm + 1); |
---|
583 | #ifdef notdef |
---|
584 | static int masks_done, banner_printed; |
---|
585 | #endif |
---|
586 | static int old_af; |
---|
587 | int af1 = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST; |
---|
588 | |
---|
589 | #ifdef notdef |
---|
590 | /* for the moment, netmasks are skipped over */ |
---|
591 | if (!banner_printed) { |
---|
592 | printf("Netmasks:\n"); |
---|
593 | banner_printed = 1; |
---|
594 | } |
---|
595 | if (masks_done == 0) { |
---|
596 | if (rtm->rtm_addrs != RTA_DST ) { |
---|
597 | masks_done = 1; |
---|
598 | af1 = sa->sa_family; |
---|
599 | } |
---|
600 | } else |
---|
601 | #endif |
---|
602 | af1 = sa->sa_family; |
---|
603 | if (af1 != old_af) { |
---|
604 | pr_family(af1); |
---|
605 | old_af = af1; |
---|
606 | } |
---|
607 | if (rtm->rtm_addrs == RTA_DST) |
---|
608 | p_sockaddr(sa, NULL, 0, 36); |
---|
609 | else { |
---|
610 | p_sockaddr(sa, NULL, rtm->rtm_flags, 16); |
---|
611 | sa = (struct sockaddr *)(SA_SIZE(sa) + (char *)sa); |
---|
612 | p_sockaddr(sa, NULL, 0, 18); |
---|
613 | } |
---|
614 | p_flags(rtm->rtm_flags & interesting, "%-6.6s "); |
---|
615 | putchar('\n'); |
---|
616 | } |
---|
617 | |
---|
618 | static void |
---|
619 | p_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags, int width) |
---|
620 | { |
---|
621 | const char *cp; |
---|
622 | |
---|
623 | cp = fmt_sockaddr(sa, mask, flags); |
---|
624 | |
---|
625 | if (width < 0 ) |
---|
626 | printf("%s ", cp); |
---|
627 | else { |
---|
628 | if (numeric_addr) |
---|
629 | printf("%-*s ", width, cp); |
---|
630 | else |
---|
631 | printf("%-*.*s ", width, width, cp); |
---|
632 | } |
---|
633 | } |
---|
634 | |
---|
635 | static const char * |
---|
636 | fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags) |
---|
637 | { |
---|
638 | static char workbuf[128]; |
---|
639 | const char *cp; |
---|
640 | |
---|
641 | if (sa == NULL) |
---|
642 | return ("null"); |
---|
643 | |
---|
644 | switch(sa->sa_family) { |
---|
645 | case AF_INET: |
---|
646 | { |
---|
647 | struct sockaddr_in *sockin = (struct sockaddr_in *)sa; |
---|
648 | |
---|
649 | if ((sockin->sin_addr.s_addr == INADDR_ANY) && |
---|
650 | mask && |
---|
651 | ntohl(((struct sockaddr_in *)mask)->sin_addr.s_addr) |
---|
652 | ==0L) |
---|
653 | cp = "default" ; |
---|
654 | else if (flags & RTF_HOST) |
---|
655 | cp = routename(sockin->sin_addr.s_addr); |
---|
656 | else if (mask) |
---|
657 | cp = netname(sockin->sin_addr.s_addr, |
---|
658 | ntohl(((struct sockaddr_in *)mask) |
---|
659 | ->sin_addr.s_addr)); |
---|
660 | else |
---|
661 | cp = netname(sockin->sin_addr.s_addr, 0L); |
---|
662 | break; |
---|
663 | } |
---|
664 | |
---|
665 | #ifdef INET6 |
---|
666 | case AF_INET6: |
---|
667 | { |
---|
668 | struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; |
---|
669 | struct in6_addr *in6 = &sa6->sin6_addr; |
---|
670 | |
---|
671 | /* |
---|
672 | * XXX: This is a special workaround for KAME kernels. |
---|
673 | * sin6_scope_id field of SA should be set in the future. |
---|
674 | */ |
---|
675 | if (IN6_IS_ADDR_LINKLOCAL(in6) || |
---|
676 | IN6_IS_ADDR_MC_LINKLOCAL(in6)) { |
---|
677 | /* XXX: override is ok? */ |
---|
678 | sa6->sin6_scope_id = (u_int32_t)ntohs(*(u_short *)&in6->s6_addr[2]); |
---|
679 | *(u_short *)&in6->s6_addr[2] = 0; |
---|
680 | } |
---|
681 | |
---|
682 | if (flags & RTF_HOST) |
---|
683 | cp = routename6(sa6); |
---|
684 | else if (mask) |
---|
685 | cp = netname6(sa6, |
---|
686 | &((struct sockaddr_in6 *)mask)->sin6_addr); |
---|
687 | else { |
---|
688 | cp = netname6(sa6, NULL); |
---|
689 | } |
---|
690 | break; |
---|
691 | } |
---|
692 | #endif /*INET6*/ |
---|
693 | |
---|
694 | #ifndef __rtems__ |
---|
695 | case AF_IPX: |
---|
696 | { |
---|
697 | struct ipx_addr work = ((struct sockaddr_ipx *)sa)->sipx_addr; |
---|
698 | if (ipx_nullnet(satoipx_addr(work))) |
---|
699 | cp = "default"; |
---|
700 | else |
---|
701 | cp = ipx_print(sa); |
---|
702 | break; |
---|
703 | } |
---|
704 | case AF_APPLETALK: |
---|
705 | { |
---|
706 | if (!(flags & RTF_HOST) && mask) |
---|
707 | cp = atalk_print2(sa,mask,9); |
---|
708 | else |
---|
709 | cp = atalk_print(sa,11); |
---|
710 | break; |
---|
711 | } |
---|
712 | #endif |
---|
713 | case AF_NETGRAPH: |
---|
714 | { |
---|
715 | #ifdef __rtems__ |
---|
716 | /* netgraph not supported yet */ |
---|
717 | err(EX_OSERR, "memory allocation failed"); |
---|
718 | #else |
---|
719 | strlcpy(workbuf, ((struct sockaddr_ng *)sa)->sg_data, |
---|
720 | sizeof(workbuf)); |
---|
721 | cp = workbuf; |
---|
722 | #endif |
---|
723 | break; |
---|
724 | } |
---|
725 | |
---|
726 | case AF_LINK: |
---|
727 | { |
---|
728 | struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa; |
---|
729 | |
---|
730 | if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 && |
---|
731 | sdl->sdl_slen == 0) { |
---|
732 | (void) sprintf(workbuf, "link#%d", sdl->sdl_index); |
---|
733 | cp = workbuf; |
---|
734 | } else |
---|
735 | switch (sdl->sdl_type) { |
---|
736 | |
---|
737 | case IFT_ETHER: |
---|
738 | case IFT_L2VLAN: |
---|
739 | case IFT_BRIDGE: |
---|
740 | if (sdl->sdl_alen == ETHER_ADDR_LEN) { |
---|
741 | cp = ether_ntoa((struct ether_addr *) |
---|
742 | (sdl->sdl_data + sdl->sdl_nlen)); |
---|
743 | break; |
---|
744 | } |
---|
745 | /* FALLTHROUGH */ |
---|
746 | default: |
---|
747 | cp = link_ntoa(sdl); |
---|
748 | break; |
---|
749 | } |
---|
750 | break; |
---|
751 | } |
---|
752 | |
---|
753 | default: |
---|
754 | { |
---|
755 | u_char *s = (u_char *)sa->sa_data, *slim; |
---|
756 | char *cq, *cqlim; |
---|
757 | |
---|
758 | cq = workbuf; |
---|
759 | slim = sa->sa_len + (u_char *) sa; |
---|
760 | cqlim = cq + sizeof(workbuf) - 6; |
---|
761 | cq += sprintf(cq, "(%d)", sa->sa_family); |
---|
762 | while (s < slim && cq < cqlim) { |
---|
763 | cq += sprintf(cq, " %02x", *s++); |
---|
764 | if (s < slim) |
---|
765 | cq += sprintf(cq, "%02x", *s++); |
---|
766 | } |
---|
767 | cp = workbuf; |
---|
768 | } |
---|
769 | } |
---|
770 | |
---|
771 | return (cp); |
---|
772 | } |
---|
773 | |
---|
774 | static void |
---|
775 | p_flags(int f, const char *format) |
---|
776 | { |
---|
777 | printf(format, fmt_flags(f)); |
---|
778 | } |
---|
779 | |
---|
780 | static const char * |
---|
781 | fmt_flags(int f) |
---|
782 | { |
---|
783 | static char name[33]; |
---|
784 | char *flags; |
---|
785 | struct bits *p = bits; |
---|
786 | |
---|
787 | for (flags = name; p->b_mask; p++) |
---|
788 | if (p->b_mask & f) |
---|
789 | *flags++ = p->b_val; |
---|
790 | *flags = '\0'; |
---|
791 | return (name); |
---|
792 | } |
---|
793 | |
---|
794 | static void |
---|
795 | p_rtentry(struct rtentry *rt) |
---|
796 | { |
---|
797 | static struct ifnet ifnet, *lastif; |
---|
798 | static char buffer[128]; |
---|
799 | static char prettyname[128]; |
---|
800 | struct sockaddr *sa; |
---|
801 | sa_u addr, mask; |
---|
802 | |
---|
803 | bzero(&addr, sizeof(addr)); |
---|
804 | if ((sa = kgetsa(rt_key(rt)))) |
---|
805 | bcopy(sa, &addr, sa->sa_len); |
---|
806 | bzero(&mask, sizeof(mask)); |
---|
807 | if (rt_mask(rt) && (sa = kgetsa(rt_mask(rt)))) |
---|
808 | bcopy(sa, &mask, sa->sa_len); |
---|
809 | p_sockaddr(&addr.u_sa, &mask.u_sa, rt->rt_flags, wid_dst); |
---|
810 | p_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST, wid_gw); |
---|
811 | snprintf(buffer, sizeof(buffer), "%%-%d.%ds ", wid_flags, wid_flags); |
---|
812 | p_flags(rt->rt_flags, buffer); |
---|
813 | if (addr.u_sa.sa_family == AF_INET || Wflag) { |
---|
814 | printf("%*d %*lu ", wid_refs, rt->rt_refcnt, |
---|
815 | wid_use, rt->rt_use); |
---|
816 | if (Wflag) { |
---|
817 | if (rt->rt_rmx.rmx_mtu != 0) |
---|
818 | printf("%*lu ", wid_mtu, rt->rt_rmx.rmx_mtu); |
---|
819 | else |
---|
820 | printf("%*s ", wid_mtu, ""); |
---|
821 | } |
---|
822 | } |
---|
823 | if (rt->rt_ifp) { |
---|
824 | if (rt->rt_ifp != lastif) { |
---|
825 | if (kget(rt->rt_ifp, ifnet) == 0) |
---|
826 | strlcpy(prettyname, ifnet.if_xname, |
---|
827 | sizeof(prettyname)); |
---|
828 | else |
---|
829 | strlcpy(prettyname, "---", sizeof(prettyname)); |
---|
830 | lastif = rt->rt_ifp; |
---|
831 | } |
---|
832 | printf("%*.*s", wid_if, wid_if, prettyname); |
---|
833 | if (rt->rt_rmx.rmx_expire) { |
---|
834 | time_t expire_time; |
---|
835 | |
---|
836 | if ((expire_time = |
---|
837 | rt->rt_rmx.rmx_expire - uptime.tv_sec) > 0) |
---|
838 | printf(" %*d", wid_expire, (int)expire_time); |
---|
839 | } |
---|
840 | if (rt->rt_nodes[0].rn_dupedkey) |
---|
841 | printf(" =>"); |
---|
842 | } |
---|
843 | putchar('\n'); |
---|
844 | } |
---|
845 | |
---|
846 | char * |
---|
847 | routename(in_addr_t in) |
---|
848 | { |
---|
849 | char *cp; |
---|
850 | static char line[MAXHOSTNAMELEN]; |
---|
851 | struct hostent *hp; |
---|
852 | |
---|
853 | cp = 0; |
---|
854 | if (!numeric_addr) { |
---|
855 | hp = gethostbyaddr(&in, sizeof (struct in_addr), AF_INET); |
---|
856 | if (hp) { |
---|
857 | cp = hp->h_name; |
---|
858 | trimdomain(cp, strlen(cp)); |
---|
859 | } |
---|
860 | } |
---|
861 | if (cp) { |
---|
862 | strlcpy(line, cp, sizeof(line)); |
---|
863 | } else { |
---|
864 | #define C(x) ((x) & 0xff) |
---|
865 | in = ntohl(in); |
---|
866 | sprintf(line, "%u.%u.%u.%u", |
---|
867 | C(in >> 24), C(in >> 16), C(in >> 8), C(in)); |
---|
868 | } |
---|
869 | return (line); |
---|
870 | } |
---|
871 | |
---|
872 | #define NSHIFT(m) ( \ |
---|
873 | (m) == IN_CLASSA_NET ? IN_CLASSA_NSHIFT : \ |
---|
874 | (m) == IN_CLASSB_NET ? IN_CLASSB_NSHIFT : \ |
---|
875 | (m) == IN_CLASSC_NET ? IN_CLASSC_NSHIFT : \ |
---|
876 | 0) |
---|
877 | |
---|
878 | static void |
---|
879 | domask(char *dst, in_addr_t addr __unused, u_long mask) |
---|
880 | { |
---|
881 | int b, i; |
---|
882 | |
---|
883 | if (mask == 0 || (!numeric_addr && NSHIFT(mask) != 0)) { |
---|
884 | *dst = '\0'; |
---|
885 | return; |
---|
886 | } |
---|
887 | i = 0; |
---|
888 | for (b = 0; b < 32; b++) |
---|
889 | if (mask & (1 << b)) { |
---|
890 | int bb; |
---|
891 | |
---|
892 | i = b; |
---|
893 | for (bb = b+1; bb < 32; bb++) |
---|
894 | if (!(mask & (1 << bb))) { |
---|
895 | i = -1; /* noncontig */ |
---|
896 | break; |
---|
897 | } |
---|
898 | break; |
---|
899 | } |
---|
900 | if (i == -1) |
---|
901 | sprintf(dst, "&0x%lx", mask); |
---|
902 | else |
---|
903 | sprintf(dst, "/%d", 32-i); |
---|
904 | } |
---|
905 | |
---|
906 | /* |
---|
907 | * Return the name of the network whose address is given. |
---|
908 | * The address is assumed to be that of a net or subnet, not a host. |
---|
909 | */ |
---|
910 | char * |
---|
911 | netname(in_addr_t in, u_long mask) |
---|
912 | { |
---|
913 | char *cp = 0; |
---|
914 | static char line[MAXHOSTNAMELEN]; |
---|
915 | struct netent *np = 0; |
---|
916 | in_addr_t i; |
---|
917 | |
---|
918 | i = ntohl(in); |
---|
919 | if (!numeric_addr && i) { |
---|
920 | np = getnetbyaddr(i >> NSHIFT(mask), AF_INET); |
---|
921 | if (np != NULL) { |
---|
922 | cp = np->n_name; |
---|
923 | trimdomain(cp, strlen(cp)); |
---|
924 | } |
---|
925 | } |
---|
926 | if (cp != NULL) { |
---|
927 | strlcpy(line, cp, sizeof(line)); |
---|
928 | } else { |
---|
929 | inet_ntop(AF_INET, &in, line, sizeof(line) - 1); |
---|
930 | } |
---|
931 | domask(line + strlen(line), i, mask); |
---|
932 | return (line); |
---|
933 | } |
---|
934 | |
---|
935 | #undef NSHIFT |
---|
936 | |
---|
937 | #ifdef INET6 |
---|
938 | const char * |
---|
939 | netname6(struct sockaddr_in6 *sa6, struct in6_addr *mask) |
---|
940 | { |
---|
941 | static char line[MAXHOSTNAMELEN]; |
---|
942 | u_char *p = (u_char *)mask; |
---|
943 | u_char *lim; |
---|
944 | int masklen, illegal = 0, flag = 0; |
---|
945 | |
---|
946 | if (mask) { |
---|
947 | for (masklen = 0, lim = p + 16; p < lim; p++) { |
---|
948 | switch (*p) { |
---|
949 | case 0xff: |
---|
950 | masklen += 8; |
---|
951 | break; |
---|
952 | case 0xfe: |
---|
953 | masklen += 7; |
---|
954 | break; |
---|
955 | case 0xfc: |
---|
956 | masklen += 6; |
---|
957 | break; |
---|
958 | case 0xf8: |
---|
959 | masklen += 5; |
---|
960 | break; |
---|
961 | case 0xf0: |
---|
962 | masklen += 4; |
---|
963 | break; |
---|
964 | case 0xe0: |
---|
965 | masklen += 3; |
---|
966 | break; |
---|
967 | case 0xc0: |
---|
968 | masklen += 2; |
---|
969 | break; |
---|
970 | case 0x80: |
---|
971 | masklen += 1; |
---|
972 | break; |
---|
973 | case 0x00: |
---|
974 | break; |
---|
975 | default: |
---|
976 | illegal ++; |
---|
977 | break; |
---|
978 | } |
---|
979 | } |
---|
980 | if (illegal) |
---|
981 | fprintf(stderr, "illegal prefixlen\n"); |
---|
982 | } |
---|
983 | else |
---|
984 | masklen = 128; |
---|
985 | |
---|
986 | if (masklen == 0 && IN6_IS_ADDR_UNSPECIFIED(&sa6->sin6_addr)) |
---|
987 | return("default"); |
---|
988 | |
---|
989 | if (numeric_addr) |
---|
990 | flag |= NI_NUMERICHOST; |
---|
991 | getnameinfo((struct sockaddr *)sa6, sa6->sin6_len, line, sizeof(line), |
---|
992 | NULL, 0, flag); |
---|
993 | |
---|
994 | if (numeric_addr) |
---|
995 | sprintf(&line[strlen(line)], "/%d", masklen); |
---|
996 | |
---|
997 | return line; |
---|
998 | } |
---|
999 | |
---|
1000 | char * |
---|
1001 | routename6(struct sockaddr_in6 *sa6) |
---|
1002 | { |
---|
1003 | static char line[MAXHOSTNAMELEN]; |
---|
1004 | int flag = 0; |
---|
1005 | /* use local variable for safety */ |
---|
1006 | struct sockaddr_in6 sa6_local; |
---|
1007 | |
---|
1008 | sa6_local.sin6_family = AF_INET6; |
---|
1009 | sa6_local.sin6_len = sizeof(sa6_local); |
---|
1010 | sa6_local.sin6_addr = sa6->sin6_addr; |
---|
1011 | sa6_local.sin6_scope_id = sa6->sin6_scope_id; |
---|
1012 | |
---|
1013 | if (numeric_addr) |
---|
1014 | flag |= NI_NUMERICHOST; |
---|
1015 | |
---|
1016 | getnameinfo((struct sockaddr *)&sa6_local, sa6_local.sin6_len, |
---|
1017 | line, sizeof(line), NULL, 0, flag); |
---|
1018 | |
---|
1019 | return line; |
---|
1020 | } |
---|
1021 | #endif /*INET6*/ |
---|
1022 | |
---|
1023 | /* |
---|
1024 | * Print routing statistics |
---|
1025 | */ |
---|
1026 | void |
---|
1027 | rt_stats(u_long rtsaddr, u_long rttaddr) |
---|
1028 | { |
---|
1029 | struct rtstat rtstat; |
---|
1030 | int rttrash; |
---|
1031 | |
---|
1032 | if (rtsaddr == 0) { |
---|
1033 | printf("rtstat: symbol not in namelist\n"); |
---|
1034 | return; |
---|
1035 | } |
---|
1036 | if (rttaddr == 0) { |
---|
1037 | printf("rttrash: symbol not in namelist\n"); |
---|
1038 | return; |
---|
1039 | } |
---|
1040 | kread(rtsaddr, (char *)&rtstat, sizeof (rtstat)); |
---|
1041 | kread(rttaddr, (char *)&rttrash, sizeof (rttrash)); |
---|
1042 | printf("routing:\n"); |
---|
1043 | |
---|
1044 | #define p(f, m) if (rtstat.f || sflag <= 1) \ |
---|
1045 | printf(m, rtstat.f, plural(rtstat.f)) |
---|
1046 | |
---|
1047 | p(rts_badredirect, "\t%hu bad routing redirect%s\n"); |
---|
1048 | p(rts_dynamic, "\t%hu dynamically created route%s\n"); |
---|
1049 | p(rts_newgateway, "\t%hu new gateway%s due to redirects\n"); |
---|
1050 | p(rts_unreach, "\t%hu destination%s found unreachable\n"); |
---|
1051 | p(rts_wildcard, "\t%hu use%s of a wildcard route\n"); |
---|
1052 | #undef p |
---|
1053 | |
---|
1054 | if (rttrash || sflag <= 1) |
---|
1055 | printf("\t%u route%s not in table but not freed\n", |
---|
1056 | rttrash, plural(rttrash)); |
---|
1057 | } |
---|
1058 | |
---|
1059 | #ifndef __rtems__ |
---|
1060 | char * |
---|
1061 | ipx_print(struct sockaddr *sa) |
---|
1062 | { |
---|
1063 | u_short port; |
---|
1064 | struct servent *sp = 0; |
---|
1065 | const char *net = "", *host = ""; |
---|
1066 | char *p; |
---|
1067 | u_char *q; |
---|
1068 | struct ipx_addr work = ((struct sockaddr_ipx *)sa)->sipx_addr; |
---|
1069 | static char mybuf[50]; |
---|
1070 | char cport[10], chost[15], cnet[15]; |
---|
1071 | |
---|
1072 | port = ntohs(work.x_port); |
---|
1073 | |
---|
1074 | if (ipx_nullnet(work) && ipx_nullhost(work)) { |
---|
1075 | |
---|
1076 | if (port) { |
---|
1077 | if (sp) |
---|
1078 | sprintf(mybuf, "*.%s", sp->s_name); |
---|
1079 | else |
---|
1080 | sprintf(mybuf, "*.%x", port); |
---|
1081 | } else |
---|
1082 | sprintf(mybuf, "*.*"); |
---|
1083 | |
---|
1084 | return (mybuf); |
---|
1085 | } |
---|
1086 | |
---|
1087 | if (ipx_wildnet(work)) |
---|
1088 | net = "any"; |
---|
1089 | else if (ipx_nullnet(work)) |
---|
1090 | net = "*"; |
---|
1091 | else { |
---|
1092 | q = work.x_net.c_net; |
---|
1093 | sprintf(cnet, "%02x%02x%02x%02x", |
---|
1094 | q[0], q[1], q[2], q[3]); |
---|
1095 | for (p = cnet; *p == '0' && p < cnet + 8; p++) |
---|
1096 | continue; |
---|
1097 | net = p; |
---|
1098 | } |
---|
1099 | |
---|
1100 | if (ipx_wildhost(work)) |
---|
1101 | host = "any"; |
---|
1102 | else if (ipx_nullhost(work)) |
---|
1103 | host = "*"; |
---|
1104 | else { |
---|
1105 | q = work.x_host.c_host; |
---|
1106 | sprintf(chost, "%02x%02x%02x%02x%02x%02x", |
---|
1107 | q[0], q[1], q[2], q[3], q[4], q[5]); |
---|
1108 | for (p = chost; *p == '0' && p < chost + 12; p++) |
---|
1109 | continue; |
---|
1110 | host = p; |
---|
1111 | } |
---|
1112 | |
---|
1113 | if (port) { |
---|
1114 | if (strcmp(host, "*") == 0) |
---|
1115 | host = ""; |
---|
1116 | if (sp) |
---|
1117 | snprintf(cport, sizeof(cport), |
---|
1118 | "%s%s", *host ? "." : "", sp->s_name); |
---|
1119 | else |
---|
1120 | snprintf(cport, sizeof(cport), |
---|
1121 | "%s%x", *host ? "." : "", port); |
---|
1122 | } else |
---|
1123 | *cport = 0; |
---|
1124 | |
---|
1125 | snprintf(mybuf, sizeof(mybuf), "%s.%s%s", net, host, cport); |
---|
1126 | return(mybuf); |
---|
1127 | } |
---|
1128 | |
---|
1129 | char * |
---|
1130 | ipx_phost(struct sockaddr *sa) |
---|
1131 | { |
---|
1132 | struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)sa; |
---|
1133 | struct sockaddr_ipx work; |
---|
1134 | static union ipx_net ipx_zeronet; |
---|
1135 | char *p; |
---|
1136 | struct ipx_addr in; |
---|
1137 | |
---|
1138 | work = *sipx; |
---|
1139 | in = work.sipx_addr; |
---|
1140 | |
---|
1141 | work.sipx_addr.x_port = 0; |
---|
1142 | work.sipx_addr.x_net = ipx_zeronet; |
---|
1143 | p = ipx_print((struct sockaddr *)&work); |
---|
1144 | if (strncmp("*.", p, 2) == 0) p += 2; |
---|
1145 | |
---|
1146 | return(p); |
---|
1147 | } |
---|
1148 | #endif |
---|
1149 | |
---|
1150 | void |
---|
1151 | upHex(char *p0) |
---|
1152 | { |
---|
1153 | char *p = p0; |
---|
1154 | |
---|
1155 | for (; *p; p++) |
---|
1156 | switch (*p) { |
---|
1157 | |
---|
1158 | case 'a': |
---|
1159 | case 'b': |
---|
1160 | case 'c': |
---|
1161 | case 'd': |
---|
1162 | case 'e': |
---|
1163 | case 'f': |
---|
1164 | *p += ('A' - 'a'); |
---|
1165 | break; |
---|
1166 | } |
---|
1167 | } |
---|