]> git.saurik.com Git - apple/network_cmds.git/blame - netstat.tproj/route.c
network_cmds-85.tar.gz
[apple/network_cmds.git] / netstat.tproj / route.c
CommitLineData
b7080c8e
A
1/*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
12 * this file.
13 *
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
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24/*
25 * Copyright (c) 1983, 1988, 1993
26 * The Regents of the University of California. All rights reserved.
27 *
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
30 * are met:
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 acknowledgement:
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.
43 *
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
54 * SUCH DAMAGE.
55 */
56
57#ifndef lint
58#if 0
59static char sccsid[] = "From: @(#)route.c 8.6 (Berkeley) 4/28/95";
60#endif
61static const char rcsid[] =
62 "$Id: route.c,v 1.1.1.2 2000/01/11 01:48:53 wsanchez Exp $";
63#endif /* not lint */
64
65#include <sys/param.h>
66#include <sys/protosw.h>
67#include <sys/socket.h>
68#include <sys/time.h>
69
70#include <net/if.h>
71#include <net/if_var.h>
72#include <net/if_dl.h>
73#include <net/if_types.h>
74#include <net/route.h>
75
76#include <netinet/in.h>
77
78#ifdef IPX
79#include <netipx/ipx.h>
80#include <netatalk/at.h>
81#endif
82
83#ifdef NS
84#include <netns/ns.h>
85#endif
86
87#include <sys/sysctl.h>
88
89#include <netdb.h>
90#include <stdio.h>
91#include <stdlib.h>
92#include <string.h>
93#include <unistd.h>
94#include <err.h>
95#include <time.h>
96#include "netstat.h"
97
98#define kget(p, d) (kread((u_long)(p), (char *)&(d), sizeof (d)))
99
100/*
101 * Definitions for showing gateway flags.
102 */
103struct bits {
104 u_long b_mask;
105 char b_val;
106} bits[] = {
107 { RTF_UP, 'U' },
108 { RTF_GATEWAY, 'G' },
109 { RTF_HOST, 'H' },
110 { RTF_REJECT, 'R' },
111 { RTF_DYNAMIC, 'D' },
112 { RTF_MODIFIED, 'M' },
113 { RTF_DONE, 'd' }, /* Completed -- for routing messages only */
114 { RTF_CLONING, 'C' },
115 { RTF_XRESOLVE, 'X' },
116 { RTF_LLINFO, 'L' },
117 { RTF_STATIC, 'S' },
118 { RTF_PROTO1, '1' },
119 { RTF_PROTO2, '2' },
120 { RTF_WASCLONED,'W' },
121 { RTF_PRCLONING,'c' },
122 { RTF_PROTO3, '3' },
123 { RTF_BLACKHOLE,'B' },
124 { RTF_BROADCAST,'b' },
125 { 0 }
126};
127
128typedef union {
129 long dummy; /* Helps align structure. */
130 struct sockaddr u_sa;
131 u_short u_data[128];
132} sa_u;
133
134static sa_u pt_u;
135
136int do_rtent = 0;
137struct rtentry rtentry;
138struct radix_node rnode;
139struct radix_mask rmask;
140struct radix_node_head *rt_tables[AF_MAX+1];
141
142int NewTree = 0;
143
144static struct sockaddr *kgetsa __P((struct sockaddr *));
145static void p_tree __P((struct radix_node *));
146static void p_rtnode __P((void));
147static void ntreestuff __P((void));
148static void np_rtentry __P((struct rt_msghdr *));
149static void p_sockaddr __P((struct sockaddr *, struct sockaddr *, int, int));
150static void p_flags __P((int, char *));
151static void p_rtentry __P((struct rtentry *));
152static u_long forgemask __P((u_long));
153static void domask __P((char *, u_long, u_long));
154
155/*
156 * Print routing tables.
157 */
158void
159routepr(rtree)
160 u_long rtree;
161{
162 struct radix_node_head *rnh, head;
163 int i;
164
165 printf("Routing tables\n");
166
167 if (Aflag == 0 && NewTree)
168 ntreestuff();
169 else {
170 if (rtree == 0) {
171 printf("rt_tables: symbol not in namelist\n");
172 return;
173 }
174
175 kget(rtree, rt_tables);
176 for (i = 0; i <= AF_MAX; i++) {
177 if ((rnh = rt_tables[i]) == 0)
178 continue;
179 kget(rnh, head);
180 if (i == AF_UNSPEC) {
181 if (Aflag && af == 0) {
182 printf("Netmasks:\n");
183 p_tree(head.rnh_treetop);
184 }
185 } else if (af == AF_UNSPEC || af == i) {
186 pr_family(i);
187 do_rtent = 1;
188 pr_rthdr();
189 p_tree(head.rnh_treetop);
190 }
191 }
192 }
193}
194
195/*
196 * Print address family header before a section of the routing table.
197 */
198void
199pr_family(af)
200 int af;
201{
202 char *afname;
203
204 switch (af) {
205 case AF_INET:
206 afname = "Internet";
207 break;
208
209#ifdef IPX
210 case AF_IPX:
211 afname = "IPX";
212 break;
213#endif
214
215#ifdef NS
216 case AF_NS:
217 afname = "XNS";
218 break;
219#endif
220 case AF_ISO:
221 afname = "ISO";
222 break;
223 case AF_APPLETALK:
224 afname = "AppleTalk";
225 break;
226 case AF_CCITT:
227 afname = "X.25";
228 break;
229 default:
230 afname = NULL;
231 break;
232 }
233 if (afname)
234 printf("\n%s:\n", afname);
235 else
236 printf("\nProtocol Family %d:\n", af);
237}
238
239/* column widths; each followed by one space */
240#define WID_DST 18 /* width of destination column */
241#define WID_GW 18 /* width of gateway column */
242
243/*
244 * Print header for routing table columns.
245 */
246void
247pr_rthdr()
248{
249 if (Aflag)
250 printf("%-8.8s ","Address");
251 printf("%-*.*s %-*.*s %-6.6s %6.6s%8.8s %8.8s %6s\n",
252 WID_DST, WID_DST, "Destination",
253 WID_GW, WID_GW, "Gateway",
254 "Flags", "Refs", "Use", "Netif", "Expire");
255}
256
257static struct sockaddr *
258kgetsa(dst)
259 register struct sockaddr *dst;
260{
261
262 kget(dst, pt_u.u_sa);
263 if (pt_u.u_sa.sa_len > sizeof (pt_u.u_sa))
264 kread((u_long)dst, (char *)pt_u.u_data, pt_u.u_sa.sa_len);
265 return (&pt_u.u_sa);
266}
267
268static void
269p_tree(rn)
270 struct radix_node *rn;
271{
272
273again:
274 kget(rn, rnode);
275 if (rnode.rn_b < 0) {
276 if (Aflag)
277 printf("%-8.8lx ", (u_long)rn);
278 if (rnode.rn_flags & RNF_ROOT) {
279 if (Aflag)
280 printf("(root node)%s",
281 rnode.rn_dupedkey ? " =>\n" : "\n");
282 } else if (do_rtent) {
283 kget(rn, rtentry);
284 p_rtentry(&rtentry);
285 if (Aflag)
286 p_rtnode();
287 } else {
288 p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_key),
289 NULL, 0, 44);
290 putchar('\n');
291 }
292 if ((rn = rnode.rn_dupedkey))
293 goto again;
294 } else {
295 if (Aflag && do_rtent) {
296 printf("%-8.8lx ", (u_long)rn);
297 p_rtnode();
298 }
299 rn = rnode.rn_r;
300 p_tree(rnode.rn_l);
301 p_tree(rn);
302 }
303}
304
305char nbuf[20];
306
307static void
308p_rtnode()
309{
310 struct radix_mask *rm = rnode.rn_mklist;
311
312 if (rnode.rn_b < 0) {
313 if (rnode.rn_mask) {
314 printf("\t mask ");
315 p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_mask),
316 NULL, 0, -1);
317 } else if (rm == 0)
318 return;
319 } else {
320 sprintf(nbuf, "(%d)", rnode.rn_b);
321 printf("%6.6s %8.8lx : %8.8lx", nbuf, (u_long)rnode.rn_l, (u_long)rnode.rn_r);
322 }
323 while (rm) {
324 kget(rm, rmask);
325 sprintf(nbuf, " %d refs, ", rmask.rm_refs);
326 printf(" mk = %8.8lx {(%d),%s",
327 (u_long)rm, -1 - rmask.rm_b, rmask.rm_refs ? nbuf : " ");
328 if (rmask.rm_flags & RNF_NORMAL) {
329 struct radix_node rnode_aux;
330 printf(" <normal>, ");
331 kget(rmask.rm_leaf, rnode_aux);
332 p_sockaddr(kgetsa((struct sockaddr *)rnode_aux.rn_mask),
333 NULL, 0, -1);
334 } else
335 p_sockaddr(kgetsa((struct sockaddr *)rmask.rm_mask),
336 NULL, 0, -1);
337 putchar('}');
338 if ((rm = rmask.rm_mklist))
339 printf(" ->");
340 }
341 putchar('\n');
342}
343
344static void
345ntreestuff()
346{
347 size_t needed;
348 int mib[6];
349 char *buf, *next, *lim;
350 register struct rt_msghdr *rtm;
351
352 mib[0] = CTL_NET;
353 mib[1] = PF_ROUTE;
354 mib[2] = 0;
355 mib[3] = 0;
356 mib[4] = NET_RT_DUMP;
357 mib[5] = 0;
358 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
359 err(1, "sysctl: net.route.0.0.dump estimate");
360 }
361
362 if ((buf = malloc(needed)) == 0) {
363 err(2, "malloc(%lu)", (unsigned long)needed);
364 }
365 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
366 err(1, "sysctl: net.route.0.0.dump");
367 }
368 lim = buf + needed;
369 for (next = buf; next < lim; next += rtm->rtm_msglen) {
370 rtm = (struct rt_msghdr *)next;
371 np_rtentry(rtm);
372 }
373}
374
375static void
376np_rtentry(rtm)
377 register struct rt_msghdr *rtm;
378{
379 register struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
380#ifdef notdef
381 static int masks_done, banner_printed;
382#endif
383 static int old_af;
384 int af = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST;
385
386#ifdef notdef
387 /* for the moment, netmasks are skipped over */
388 if (!banner_printed) {
389 printf("Netmasks:\n");
390 banner_printed = 1;
391 }
392 if (masks_done == 0) {
393 if (rtm->rtm_addrs != RTA_DST ) {
394 masks_done = 1;
395 af = sa->sa_family;
396 }
397 } else
398#endif
399 af = sa->sa_family;
400 if (af != old_af) {
401 pr_family(af);
402 old_af = af;
403 }
404 if (rtm->rtm_addrs == RTA_DST)
405 p_sockaddr(sa, NULL, 0, 36);
406 else {
407 p_sockaddr(sa, NULL, rtm->rtm_flags, 16);
408 if (sa->sa_len == 0)
409 sa->sa_len = sizeof(long);
410 sa = (struct sockaddr *)(sa->sa_len + (char *)sa);
411 p_sockaddr(sa, NULL, 0, 18);
412 }
413 p_flags(rtm->rtm_flags & interesting, "%-6.6s ");
414 putchar('\n');
415}
416
417static void
418p_sockaddr(sa, mask, flags, width)
419 struct sockaddr *sa, *mask;
420 int flags, width;
421{
422 char workbuf[128], *cplim;
423 register char *cp = workbuf;
424
425 switch(sa->sa_family) {
426 case AF_INET:
427 {
428 register struct sockaddr_in *sin = (struct sockaddr_in *)sa;
429
430 if (sin->sin_addr.s_addr == INADDR_ANY)
431 cp = "default";
432 else if (flags & RTF_HOST)
433 cp = routename(sin->sin_addr.s_addr);
434 else if (mask)
435 cp = netname(sin->sin_addr.s_addr,
436 ntohl(((struct sockaddr_in *)mask)
437 ->sin_addr.s_addr));
438 else
439 cp = netname(sin->sin_addr.s_addr, 0L);
440 break;
441 }
442#ifdef IPX
443 case AF_IPX:
444 {
445 struct ipx_addr work = ((struct sockaddr_ipx *)sa)->sipx_addr;
446 if (ipx_nullnet(satoipx_addr(work)))
447 cp = "default";
448 else
449 cp = ipx_print(sa);
450 break;
451 }
452#endif
453
454#if 0
455 case AF_APPLETALK:
456 {
457 if (!(flags & RTF_HOST) && mask)
458 cp = atalk_print2(sa,mask,9);
459 else
460 cp = atalk_print(sa,11);
461 break;
462 }
463#endif
464
465#ifdef NS
466 case AF_NS:
467 cp = ns_print(sa);
468 break;
469#endif
470
471 case AF_LINK:
472 {
473 register struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
474
475 if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 &&
476 sdl->sdl_slen == 0)
477 (void) sprintf(workbuf, "link#%d", sdl->sdl_index);
478 else
479 switch (sdl->sdl_type) {
480
481 case IFT_ETHER:
482 {
483 register int i;
484 register u_char *lla = (u_char *)sdl->sdl_data +
485 sdl->sdl_nlen;
486
487 cplim = "";
488 for (i = 0; i < sdl->sdl_alen; i++, lla++) {
489 cp += sprintf(cp, "%s%x", cplim, *lla);
490 cplim = ":";
491 }
492 cp = workbuf;
493 break;
494 }
495
496 default:
497 cp = link_ntoa(sdl);
498 break;
499 }
500 break;
501 }
502
503 default:
504 {
505 register u_char *s = (u_char *)sa->sa_data, *slim;
506
507 slim = sa->sa_len + (u_char *) sa;
508 cplim = cp + sizeof(workbuf) - 6;
509 cp += sprintf(cp, "(%d)", sa->sa_family);
510 while (s < slim && cp < cplim) {
511 cp += sprintf(cp, " %02x", *s++);
512 if (s < slim)
513 cp += sprintf(cp, "%02x", *s++);
514 }
515 cp = workbuf;
516 }
517 }
518 if (width < 0 )
519 printf("%s ", cp);
520 else {
521 if (nflag)
522 printf("%-*s ", width, cp);
523 else
524 printf("%-*.*s ", width, width, cp);
525 }
526}
527
528static void
529p_flags(f, format)
530 register int f;
531 char *format;
532{
533 char name[33], *flags;
534 register struct bits *p = bits;
535
536 for (flags = name; p->b_mask; p++)
537 if (p->b_mask & f)
538 *flags++ = p->b_val;
539 *flags = '\0';
540 printf(format, name);
541}
542
543static void
544p_rtentry(rt)
545 register struct rtentry *rt;
546{
547 static struct ifnet ifnet, *lastif;
548 static char name[16];
549 static char prettyname[9];
550 struct sockaddr *sa;
551 sa_u addr, mask;
552
553 /*
554 * Don't print protocol-cloned routes unless -a.
555 */
556 if (rt->rt_parent && !aflag)
557 return;
558
559 bzero(&addr, sizeof(addr));
560 if ((sa = kgetsa(rt_key(rt))))
561 bcopy(sa, &addr, sa->sa_len);
562 bzero(&mask, sizeof(mask));
563 if (rt_mask(rt) && (sa = kgetsa(rt_mask(rt))))
564 bcopy(sa, &mask, sa->sa_len);
565 p_sockaddr(&addr.u_sa, &mask.u_sa, rt->rt_flags, WID_DST);
566 p_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST, WID_GW);
567 p_flags(rt->rt_flags, "%-6.6s ");
568 printf("%6d %8ld ", rt->rt_refcnt, rt->rt_use);
569 if (rt->rt_ifp) {
570 if (rt->rt_ifp != lastif) {
571 kget(rt->rt_ifp, ifnet);
572 kread((u_long)ifnet.if_name, name, 16);
573 lastif = rt->rt_ifp;
574 snprintf(prettyname, sizeof prettyname,
575 "%.6s%d", name, ifnet.if_unit);
576 }
577 printf("%8.8s", prettyname);
578 if (rt->rt_rmx.rmx_expire) {
579 time_t expire_time;
580
581 if ((expire_time =
582 rt->rt_rmx.rmx_expire - time((time_t *)0)) > 0)
583 printf(" %6d%s", (int)expire_time,
584 rt->rt_nodes[0].rn_dupedkey ? " =>" : "");
585 } else if (rt->rt_nodes[0].rn_dupedkey) {
586 printf(" =>");
587 }
588
589 }
590 putchar('\n');
591}
592
593char *
594routename(in)
595 u_long in;
596{
597 register char *cp;
598 static char line[MAXHOSTNAMELEN + 1];
599 struct hostent *hp;
600
601 cp = 0;
602 if (!nflag) {
603 hp = gethostbyaddr((char *)&in, sizeof (struct in_addr),
604 AF_INET);
605 if (hp) {
606 cp = hp->h_name;
607 trimdomain(cp);
608 }
609 }
610 if (cp) {
611 strncpy(line, cp, sizeof(line) - 1);
612 line[sizeof(line) - 1] = '\0';
613 } else {
614#define C(x) ((x) & 0xff)
615 in = ntohl(in);
616 sprintf(line, "%lu.%lu.%lu.%lu",
617 C(in >> 24), C(in >> 16), C(in >> 8), C(in));
618 }
619 return (line);
620}
621
622static u_long
623forgemask(a)
624 u_long a;
625{
626 u_long m;
627
628 if (IN_CLASSA(a))
629 m = IN_CLASSA_NET;
630 else if (IN_CLASSB(a))
631 m = IN_CLASSB_NET;
632 else
633 m = IN_CLASSC_NET;
634 return (m);
635}
636
637static void
638domask(dst, addr, mask)
639 char *dst;
640 u_long addr, mask;
641{
642 register int b, i;
643
644 if (!mask || (forgemask(addr) == mask)) {
645 *dst = '\0';
646 return;
647 }
648 i = 0;
649 for (b = 0; b < 32; b++)
650 if (mask & (1 << b)) {
651 register int bb;
652
653 i = b;
654 for (bb = b+1; bb < 32; bb++)
655 if (!(mask & (1 << bb))) {
656 i = -1; /* noncontig */
657 break;
658 }
659 break;
660 }
661 if (i == -1)
662 sprintf(dst, "&0x%lx", mask);
663 else
664 sprintf(dst, "/%d", 32-i);
665}
666
667/*
668 * Return the name of the network whose address is given.
669 * The address is assumed to be that of a net or subnet, not a host.
670 */
671char *
672netname(in, mask)
673 u_long in, mask;
674{
675 char *cp = 0;
676 static char line[MAXHOSTNAMELEN + 1];
677 struct netent *np = 0;
678 u_long net, omask, dmask;
679 register u_long i;
680
681 i = ntohl(in);
682 omask = mask;
683 if (!nflag && i) {
684 dmask = forgemask(i);
685 net = i & dmask;
686 if (!(np = getnetbyaddr(i, AF_INET)) && net != i)
687 np = getnetbyaddr(net, AF_INET);
688 if (np) {
689 cp = np->n_name;
690 trimdomain(cp);
691 }
692 }
693 if (cp)
694 strncpy(line, cp, sizeof(line) - 1);
695 else if ((i & 0xffffff) == 0)
696 sprintf(line, "%lu", C(i >> 24));
697 else if ((i & 0xffff) == 0)
698 sprintf(line, "%lu.%lu", C(i >> 24) , C(i >> 16));
699 else if ((i & 0xff) == 0)
700 sprintf(line, "%lu.%lu.%lu", C(i >> 24), C(i >> 16), C(i >> 8));
701 else
702 sprintf(line, "%lu.%lu.%lu.%lu", C(i >> 24),
703 C(i >> 16), C(i >> 8), C(i));
704 domask(line+strlen(line), i, omask);
705 return (line);
706}
707
708/*
709 * Print routing statistics
710 */
711void
712rt_stats(off)
713 u_long off;
714{
715 struct rtstat rtstat;
716
717 if (off == 0) {
718 printf("rtstat: symbol not in namelist\n");
719 return;
720 }
721 kread(off, (char *)&rtstat, sizeof (rtstat));
722 printf("routing:\n");
723 printf("\t%u bad routing redirect%s\n",
724 rtstat.rts_badredirect, plural(rtstat.rts_badredirect));
725 printf("\t%u dynamically created route%s\n",
726 rtstat.rts_dynamic, plural(rtstat.rts_dynamic));
727 printf("\t%u new gateway%s due to redirects\n",
728 rtstat.rts_newgateway, plural(rtstat.rts_newgateway));
729 printf("\t%u destination%s found unreachable\n",
730 rtstat.rts_unreach, plural(rtstat.rts_unreach));
731 printf("\t%u use%s of a wildcard route\n",
732 rtstat.rts_wildcard, plural(rtstat.rts_wildcard));
733}
734
735#ifdef IPX
736
737char *
738ipx_print(sa)
739 register struct sockaddr *sa;
740{
741 u_short port;
742 struct servent *sp = 0;
743 char *net = "", *host = "";
744 register char *p;
745 register u_char *q;
746 struct ipx_addr work = ((struct sockaddr_ipx *)sa)->sipx_addr;
747 static char mybuf[50];
748 char cport[10], chost[15], cnet[15];
749
750 port = ntohs(work.x_port);
751
752 if (ipx_nullnet(work) && ipx_nullhost(work)) {
753
754 if (port) {
755 if (sp)
756 sprintf(mybuf, "*.%s", sp->s_name);
757 else
758 sprintf(mybuf, "*.%x", port);
759 } else
760 sprintf(mybuf, "*.*");
761
762 return (mybuf);
763 }
764
765 if (ipx_wildnet(work))
766 net = "any";
767 else if (ipx_nullnet(work))
768 net = "*";
769 else {
770 q = work.x_net.c_net;
771 sprintf(cnet, "%02x%02x%02x%02x",
772 q[0], q[1], q[2], q[3]);
773 for (p = cnet; *p == '0' && p < cnet + 8; p++)
774 continue;
775 net = p;
776 }
777
778 if (ipx_wildhost(work))
779 host = "any";
780 else if (ipx_nullhost(work))
781 host = "*";
782 else {
783 q = work.x_host.c_host;
784 sprintf(chost, "%02x%02x%02x%02x%02x%02x",
785 q[0], q[1], q[2], q[3], q[4], q[5]);
786 for (p = chost; *p == '0' && p < chost + 12; p++)
787 continue;
788 host = p;
789 }
790
791 if (port) {
792 if (strcmp(host, "*") == 0)
793 host = "";
794 if (sp)
795 snprintf(cport, sizeof(cport),
796 "%s%s", *host ? "." : "", sp->s_name);
797 else
798 snprintf(cport, sizeof(cport),
799 "%s%x", *host ? "." : "", port);
800 } else
801 *cport = 0;
802
803 snprintf(mybuf, sizeof(mybuf), "%s.%s%s", net, host, cport);
804 return(mybuf);
805}
806
807char *
808ipx_phost(sa)
809 struct sockaddr *sa;
810{
811 register struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)sa;
812 struct sockaddr_ipx work;
813 static union ipx_net ipx_zeronet;
814 char *p;
815 struct ipx_addr in;
816
817 work = *sipx;
818 in = work.sipx_addr;
819
820 work.sipx_addr.x_port = 0;
821 work.sipx_addr.x_net = ipx_zeronet;
822 p = ipx_print((struct sockaddr *)&work);
823 if (strncmp("*.", p, 2) == 0) p += 2;
824
825 return(p);
826}
827#endif
828
829#ifdef NS
830short ns_nullh[] = {0,0,0};
831short ns_bh[] = {-1,-1,-1};
832
833char *
834ns_print(sa)
835 register struct sockaddr *sa;
836{
837 register struct sockaddr_ns *sns = (struct sockaddr_ns*)sa;
838 struct ns_addr work;
839 union { union ns_net net_e; u_long long_e; } net;
840 u_short port;
841 static char mybuf[50], cport[10], chost[25];
842 char *host = "";
843 register char *p; register u_char *q;
844
845 work = sns->sns_addr;
846 port = ntohs(work.x_port);
847 work.x_port = 0;
848 net.net_e = work.x_net;
849 if (ns_nullhost(work) && net.long_e == 0) {
850 if (port ) {
851 sprintf(mybuf, "*.%xH", port);
852 upHex(mybuf);
853 } else
854 sprintf(mybuf, "*.*");
855 return (mybuf);
856 }
857
858 if (bcmp(ns_bh, work.x_host.c_host, 6) == 0) {
859 host = "any";
860 } else if (bcmp(ns_nullh, work.x_host.c_host, 6) == 0) {
861 host = "*";
862 } else {
863 q = work.x_host.c_host;
864 sprintf(chost, "%02x%02x%02x%02x%02x%02xH",
865 q[0], q[1], q[2], q[3], q[4], q[5]);
866 for (p = chost; *p == '0' && p < chost + 12; p++)
867 continue;
868 host = p;
869 }
870 if (port)
871 sprintf(cport, ".%xH", htons(port));
872 else
873 *cport = 0;
874
875 sprintf(mybuf,"%xH.%s%s", ntohl(net.long_e), host, cport);
876 upHex(mybuf);
877 return(mybuf);
878}
879
880char *
881ns_phost(sa)
882 struct sockaddr *sa;
883{
884 register struct sockaddr_ns *sns = (struct sockaddr_ns *)sa;
885 struct sockaddr_ns work;
886 static union ns_net ns_zeronet;
887 char *p;
888
889 work = *sns;
890 work.sns_addr.x_port = 0;
891 work.sns_addr.x_net = ns_zeronet;
892
893 p = ns_print((struct sockaddr *)&work);
894 if (strncmp("0H.", p, 3) == 0)
895 p += 3;
896 return(p);
897}
898#endif
899
900void
901upHex(p0)
902 char *p0;
903{
904 register char *p = p0;
905
906 for (; *p; p++)
907 switch (*p) {
908
909 case 'a':
910 case 'b':
911 case 'c':
912 case 'd':
913 case 'e':
914 case 'f':
915 *p += ('A' - 'a');
916 break;
917 }
918}