optimization for normal masks requires keeping ptr
[unix-history] / usr / src / usr.bin / netstat / route.c
CommitLineData
5ff67f98 1/*
2839532b
KB
2 * Copyright (c) 1983, 1988, 1993
3 * The Regents of the University of California. All rights reserved.
ee3f90a5 4 *
42841feb 5 * %sccs.include.redist.c%
5ff67f98
DF
6 */
7
3537c4ea 8#ifndef lint
326544ba 9static char sccsid[] = "@(#)route.c 8.4 (Berkeley) %G%";
b36fc510 10#endif /* not lint */
3537c4ea 11
6c5bed6c 12#include <sys/param.h>
6e549c8f 13#include <sys/protosw.h>
3537c4ea
SL
14#include <sys/socket.h>
15#include <sys/mbuf.h>
44906619 16
3537c4ea 17#include <net/if.h>
a6dd7faa
MK
18#include <net/if_dl.h>
19#include <net/if_types.h>
4b68c469 20#define KERNEL
3537c4ea 21#include <net/route.h>
4b68c469 22#undef KERNEL
44906619
SL
23#include <netinet/in.h>
24
f1fbb01b
KS
25#include <netns/ns.h>
26
ab2a5ff0 27#include <sys/sysctl.h>
3537c4ea 28
6e549c8f 29#include <netdb.h>
42841feb 30#include <stdio.h>
6e549c8f 31#include <stdlib.h>
42841feb 32#include <string.h>
27788811 33#include <unistd.h>
6e549c8f 34#include "netstat.h"
42841feb 35
d1cfb820 36#define kget(p, d) (kread((u_long)(p), (char *)&(d), sizeof (d)))
3537c4ea
SL
37
38/*
39 * Definitions for showing gateway flags.
40 */
41struct bits {
42 short b_mask;
43 char b_val;
44} bits[] = {
45 { RTF_UP, 'U' },
46 { RTF_GATEWAY, 'G' },
47 { RTF_HOST, 'H' },
27788811 48 { RTF_REJECT, 'R' },
6c5bed6c 49 { RTF_DYNAMIC, 'D' },
3273bd86 50 { RTF_MODIFIED, 'M' },
27788811
KS
51 { RTF_DONE, 'd' }, /* Completed -- for routing messages only */
52 { RTF_MASK, 'm' }, /* Mask Present -- for routing messages only */
56492e5a 53 { RTF_CLONING, 'C' },
b8442d18 54 { RTF_XRESOLVE, 'X' },
56492e5a 55 { RTF_LLINFO, 'L' },
4e64fa9b 56 { RTF_STATIC, 'S' },
27788811
KS
57 { RTF_PROTO1, '1' },
58 { RTF_PROTO2, '2' },
3537c4ea
SL
59 { 0 }
60};
61
a6dd7faa
MK
62static union {
63 struct sockaddr u_sa;
64 u_short u_data[128];
65} pt_u;
66
67int do_rtent = 0;
68struct rtentry rtentry;
69struct radix_node rnode;
70struct radix_mask rmask;
71
72int NewTree = 0;
73
6e549c8f
KS
74static struct sockaddr *kgetsa __P((struct sockaddr *));
75static void p_tree __P((struct radix_node *));
76static void p_rtnode __P(());
77static void ntreestuff __P(());
78static void np_rtentry __P((struct rt_msghdr *));
79static void p_sockaddr __P((struct sockaddr *, int, int));
80static void p_flags __P((int, char *));
81static void p_rtentry __P((struct rtentry *));
82
3537c4ea
SL
83/*
84 * Print routing tables.
85 */
6e549c8f 86void
a6dd7faa 87routepr(rtree)
d1cfb820 88 u_long rtree;
3537c4ea 89{
a6dd7faa 90 struct radix_node_head *rnh, head;
4e64fa9b 91 int i;
3537c4ea 92
4b68c469 93 printf("Routing tables\n");
a6dd7faa
MK
94
95 if (Aflag == 0 && NewTree)
96 ntreestuff();
97 else {
98 if (rtree == 0) {
4e64fa9b 99 printf("rt_tables: symbol not in namelist\n");
a6dd7faa
MK
100 return;
101 }
102
4e64fa9b
KS
103 kget(rtree, rt_tables);
104 for (i = 0; i <= AF_MAX; i++) {
105 if ((rnh = rt_tables[i]) == 0)
106 continue;
a6dd7faa 107 kget(rnh, head);
4e64fa9b 108 if (i == AF_UNSPEC) {
6e549c8f 109 if (Aflag && af == 0) {
a6dd7faa
MK
110 printf("Netmasks:\n");
111 p_tree(head.rnh_treetop);
112 }
4e64fa9b
KS
113 } else if (af == AF_UNSPEC || af == i) {
114 pr_family(i);
a6dd7faa
MK
115 do_rtent = 1;
116 pr_rthdr();
117 p_tree(head.rnh_treetop);
118 }
3537c4ea
SL
119 }
120 }
4b68c469
MK
121}
122
a6dd7faa
MK
123/*
124 * Print address family header before a section of the routing table.
125 */
6e549c8f 126void
a6dd7faa
MK
127pr_family(af)
128 int af;
4b68c469 129{
a6dd7faa 130 char *afname;
56492e5a 131
a6dd7faa
MK
132 switch (af) {
133 case AF_INET:
134 afname = "Internet";
135 break;
136 case AF_NS:
137 afname = "XNS";
138 break;
139 case AF_ISO:
140 afname = "ISO";
141 break;
4e64fa9b
KS
142 case AF_CCITT:
143 afname = "X.25";
144 break;
a6dd7faa
MK
145 default:
146 afname = NULL;
147 break;
4b68c469 148 }
a6dd7faa
MK
149 if (afname)
150 printf("\n%s:\n", afname);
151 else
152 printf("\nProtocol Family %d:\n", af);
153}
154
155/* column widths; each followed by one space */
156#define WID_DST 16 /* width of destination column */
157#define WID_GW 18 /* width of gateway column */
158
159/*
160 * Print header for routing table columns.
161 */
6e549c8f 162void
a6dd7faa
MK
163pr_rthdr()
164{
165
166 if (Aflag)
167 printf("%-8.8s ","Address");
168 printf("%-*.*s %-*.*s %-6.6s %6.6s%8.8s %s\n",
169 WID_DST, WID_DST, "Destination",
170 WID_GW, WID_GW, "Gateway",
171 "Flags", "Refs", "Use", "Interface");
4b68c469
MK
172}
173
6e549c8f 174static struct sockaddr *
4d9e18da 175kgetsa(dst)
a6dd7faa 176 register struct sockaddr *dst;
4d9e18da 177{
a6dd7faa 178
4d9e18da 179 kget(dst, pt_u.u_sa);
a6dd7faa 180 if (pt_u.u_sa.sa_len > sizeof (pt_u.u_sa))
d1cfb820 181 kread((u_long)dst, (char *)pt_u.u_data, pt_u.u_sa.sa_len);
4d9e18da
KS
182 return (&pt_u.u_sa);
183}
184
6e549c8f 185static void
b8442d18 186p_tree(rn)
a6dd7faa 187 struct radix_node *rn;
4b68c469 188{
4b68c469
MK
189
190again:
191 kget(rn, rnode);
192 if (rnode.rn_b < 0) {
b8442d18
KS
193 if (Aflag)
194 printf("%-8.8x ", rn);
a6dd7faa
MK
195 if (rnode.rn_flags & RNF_ROOT) {
196 if (Aflag)
197 printf("(root node)%s",
b8442d18 198 rnode.rn_dupedkey ? " =>\n" : "\n");
a6dd7faa 199 } else if (do_rtent) {
4b68c469
MK
200 kget(rn, rtentry);
201 p_rtentry(&rtentry);
b8442d18
KS
202 if (Aflag)
203 p_rtnode();
4b68c469 204 } else {
4d9e18da 205 p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_key),
a6dd7faa 206 0, 44);
4b68c469
MK
207 putchar('\n');
208 }
209 if (rn = rnode.rn_dupedkey)
210 goto again;
211 } else {
b8442d18
KS
212 if (Aflag && do_rtent) {
213 printf("%-8.8x ", rn);
214 p_rtnode();
215 }
216 rn = rnode.rn_r;
217 p_tree(rnode.rn_l);
218 p_tree(rn);
219 }
220}
a6dd7faa
MK
221
222char nbuf[20];
b8442d18 223
6e549c8f 224static void
b8442d18
KS
225p_rtnode()
226{
b8442d18 227 struct radix_mask *rm = rnode.rn_mklist;
a6dd7faa 228
b8442d18
KS
229 if (rnode.rn_b < 0) {
230 if (rnode.rn_mask) {
231 printf("\t mask ");
232 p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_mask),
233 0, -1);
234 } else if (rm == 0)
235 return;
236 } else {
237 sprintf(nbuf, "(%d)", rnode.rn_b);
238 printf("%6.6s %8.8x : %8.8x", nbuf, rnode.rn_l, rnode.rn_r);
4b68c469 239 }
b8442d18
KS
240 while (rm) {
241 kget(rm, rmask);
242 sprintf(nbuf, " %d refs, ", rmask.rm_refs);
243 printf(" mk = %8.8x {(%d),%s",
244 rm, -1 - rmask.rm_b, rmask.rm_refs ? nbuf : " ");
e754a85d
KS
245 if (rmask.rm_flags & RNF_NORMAL) {
246 struct radix_node rnode_aux;
247 printf(nbuf, " <normal>, ");
248 kget(rmask.rm_leaf, rnode_aux);
249 p_sockaddr(
250 kgetsa((struct sockaddr *)rnode_aux.rn_mask), 0, -1);
251 } else
252 p_sockaddr(kgetsa((struct sockaddr *)rmask.rm_mask), 0, -1);
b8442d18
KS
253 putchar('}');
254 if (rm = rmask.rm_mklist)
255 printf(" ->");
256 }
257 putchar('\n');
4b68c469
MK
258}
259
6e549c8f 260static void
4d9e18da 261ntreestuff()
4b68c469 262{
ab2a5ff0
KM
263 size_t needed;
264 int mib[6];
4d9e18da
KS
265 char *buf, *next, *lim;
266 register struct rt_msghdr *rtm;
267
ab2a5ff0
KM
268 mib[0] = CTL_NET;
269 mib[1] = PF_ROUTE;
270 mib[2] = 0;
271 mib[3] = 0;
272 mib[4] = NET_RT_DUMP;
273 mib[5] = 0;
274 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
275 { perror("route-sysctl-estimate"); exit(1);}
4d9e18da 276 if ((buf = malloc(needed)) == 0)
56492e5a 277 { printf("out of space\n"); exit(1);}
ab2a5ff0
KM
278 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
279 { perror("sysctl of routing table"); exit(1);}
4d9e18da
KS
280 lim = buf + needed;
281 for (next = buf; next < lim; next += rtm->rtm_msglen) {
282 rtm = (struct rt_msghdr *)next;
283 np_rtentry(rtm);
4b68c469 284 }
4b68c469
MK
285}
286
6e549c8f 287static void
4d9e18da 288np_rtentry(rtm)
a6dd7faa 289 register struct rt_msghdr *rtm;
4b68c469 290{
4d9e18da 291 register struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
6e549c8f
KS
292#ifdef notdef
293 static int masks_done, banner_printed;
294#endif
295 static int old_af;
4d9e18da 296 int af = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST;
4b68c469 297
4d9e18da
KS
298#ifdef notdef
299 /* for the moment, netmasks are skipped over */
300 if (!banner_printed) {
301 printf("Netmasks:\n");
302 banner_printed = 1;
303 }
304 if (masks_done == 0) {
305 if (rtm->rtm_addrs != RTA_DST ) {
306 masks_done = 1;
307 af = sa->sa_family;
308 }
309 } else
310#endif
311 af = sa->sa_family;
312 if (af != old_af) {
a6dd7faa 313 pr_family(af);
4d9e18da
KS
314 old_af = af;
315 }
316 if (rtm->rtm_addrs == RTA_DST)
56492e5a 317 p_sockaddr(sa, 0, 36);
4d9e18da 318 else {
56492e5a 319 p_sockaddr(sa, rtm->rtm_flags, 16);
4d9e18da
KS
320 if (sa->sa_len == 0)
321 sa->sa_len = sizeof(long);
322 sa = (struct sockaddr *)(sa->sa_len + (char *)sa);
56492e5a 323 p_sockaddr(sa, 0, 18);
4d9e18da
KS
324 }
325 p_flags(rtm->rtm_flags & interesting, "%-6.6s ");
326 putchar('\n');
327}
328
6e549c8f 329static void
56492e5a 330p_sockaddr(sa, flags, width)
a6dd7faa
MK
331 struct sockaddr *sa;
332 int flags, width;
4d9e18da 333{
6e549c8f 334 char workbuf[128], *cplim;
a6dd7faa 335 register char *cp = workbuf;
4d9e18da
KS
336
337 switch(sa->sa_family) {
4b68c469 338 case AF_INET:
4d9e18da
KS
339 {
340 register struct sockaddr_in *sin = (struct sockaddr_in *)sa;
341
342 cp = (sin->sin_addr.s_addr == 0) ? "default" :
343 ((flags & RTF_HOST) ?
6e549c8f
KS
344 routename(sin->sin_addr.s_addr) :
345 netname(sin->sin_addr.s_addr, 0L));
4b68c469 346 break;
a6dd7faa 347 }
4d9e18da 348
4b68c469 349 case AF_NS:
6e549c8f 350 cp = ns_print(sa);
4b68c469 351 break;
4d9e18da 352
a6dd7faa
MK
353 case AF_LINK:
354 {
355 register struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
a6dd7faa
MK
356
357 if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 &&
358 sdl->sdl_slen == 0)
359 (void) sprintf(workbuf, "link#%d", sdl->sdl_index);
360 else switch (sdl->sdl_type) {
361 case IFT_ETHER:
362 {
363 register int i;
364 register u_char *lla = (u_char *)sdl->sdl_data +
365 sdl->sdl_nlen;
366
367 cplim = "";
368 for (i = 0; i < sdl->sdl_alen; i++, lla++) {
369 cp += sprintf(cp, "%s%x", cplim, *lla);
370 cplim = ":";
371 }
372 cp = workbuf;
373 break;
374 }
375 default:
376 cp = link_ntoa(sdl);
377 break;
378 }
379 break;
380 }
381
4b68c469 382 default:
4d9e18da 383 {
8af5157f 384 register u_char *s = (u_char *)sa->sa_data, *slim;
4d9e18da 385
69cea8bf 386 slim = sa->sa_len + (u_char *) sa;
4d9e18da
KS
387 cplim = cp + sizeof(workbuf) - 6;
388 cp += sprintf(cp, "(%d)", sa->sa_family);
69cea8bf
KS
389 while (s < slim && cp < cplim) {
390 cp += sprintf(cp, " %02x", *s++);
391 if (s < slim)
392 cp += sprintf(cp, "%02x", *s++);
393 }
4d9e18da
KS
394 cp = workbuf;
395 }
4b68c469 396 }
b8442d18
KS
397 if (width < 0 )
398 printf("%s ", cp);
399 else {
400 if (nflag)
401 printf("%-*s ", width, cp);
402 else
403 printf("%-*.*s ", width, width, cp);
404 }
4d9e18da
KS
405}
406
6e549c8f 407static void
4d9e18da 408p_flags(f, format)
a6dd7faa
MK
409 register int f;
410 char *format;
4d9e18da
KS
411{
412 char name[33], *flags;
413 register struct bits *p = bits;
a6dd7faa 414
4d9e18da
KS
415 for (flags = name; p->b_mask; p++)
416 if (p->b_mask & f)
4b68c469
MK
417 *flags++ = p->b_val;
418 *flags = '\0';
4d9e18da
KS
419 printf(format, name);
420}
421
6e549c8f 422static void
4d9e18da 423p_rtentry(rt)
6e549c8f 424 register struct rtentry *rt;
4d9e18da 425{
a6dd7faa
MK
426 static struct ifnet ifnet, *lastif;
427 static char name[16];
4d9e18da 428
a6dd7faa 429 p_sockaddr(kgetsa(rt_key(rt)), rt->rt_flags, WID_DST);
dfacc100 430 p_sockaddr(kgetsa(rt->rt_gateway), RTF_HOST, WID_GW);
4d9e18da
KS
431 p_flags(rt->rt_flags, "%-6.6s ");
432 printf("%6d %8d ", rt->rt_refcnt, rt->rt_use);
a6dd7faa
MK
433 if (rt->rt_ifp) {
434 if (rt->rt_ifp != lastif) {
435 kget(rt->rt_ifp, ifnet);
d1cfb820 436 kread((u_long)ifnet.if_name, name, 16);
a6dd7faa
MK
437 lastif = rt->rt_ifp;
438 }
439 printf(" %.15s%d%s", name, ifnet.if_unit,
440 rt->rt_nodes[0].rn_dupedkey ? " =>" : "");
4b68c469 441 }
a6dd7faa 442 putchar('\n');
3537c4ea
SL
443}
444
445char *
446routename(in)
6e549c8f 447 u_long in;
3537c4ea 448{
6b9930b0 449 register char *cp;
cb646d4b 450 static char line[MAXHOSTNAMELEN + 1];
40f48772 451 struct hostent *hp;
6c5bed6c
MK
452 static char domain[MAXHOSTNAMELEN + 1];
453 static int first = 1;
3537c4ea 454
6c5bed6c
MK
455 if (first) {
456 first = 0;
457 if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
458 (cp = index(domain, '.')))
459 (void) strcpy(domain, cp + 1);
460 else
461 domain[0] = 0;
462 }
6b9930b0 463 cp = 0;
3537c4ea 464 if (!nflag) {
f7c99b06 465 hp = gethostbyaddr((char *)&in, sizeof (struct in_addr),
cab3a575 466 AF_INET);
6c5bed6c
MK
467 if (hp) {
468 if ((cp = index(hp->h_name, '.')) &&
469 !strcmp(cp + 1, domain))
470 *cp = 0;
cab3a575 471 cp = hp->h_name;
6c5bed6c 472 }
3537c4ea
SL
473 }
474 if (cp)
cb646d4b 475 strncpy(line, cp, sizeof(line) - 1);
3537c4ea 476 else {
cab3a575 477#define C(x) ((x) & 0xff)
6e549c8f
KS
478 in = ntohl(in);
479 sprintf(line, "%u.%u.%u.%u",
480 C(in >> 24), C(in >> 16), C(in >> 8), C(in));
cab3a575
MK
481 }
482 return (line);
483}
484
485/*
486 * Return the name of the network whose address is given.
487 * The address is assumed to be that of a net or subnet, not a host.
488 */
489char *
490netname(in, mask)
6e549c8f 491 u_long in, mask;
cab3a575
MK
492{
493 char *cp = 0;
cb646d4b 494 static char line[MAXHOSTNAMELEN + 1];
cab3a575
MK
495 struct netent *np = 0;
496 u_long net;
6e549c8f 497 register int i;
6c5bed6c 498 int subnetshift;
cab3a575 499
6e549c8f 500 i = ntohl(in);
a83ade01 501 if (!nflag && i) {
6c5bed6c
MK
502 if (mask == 0) {
503 if (IN_CLASSA(i)) {
504 mask = IN_CLASSA_NET;
505 subnetshift = 8;
506 } else if (IN_CLASSB(i)) {
507 mask = IN_CLASSB_NET;
508 subnetshift = 8;
509 } else {
510 mask = IN_CLASSC_NET;
511 subnetshift = 4;
512 }
cab3a575 513 /*
6c5bed6c
MK
514 * If there are more bits than the standard mask
515 * would suggest, subnets must be in use.
516 * Guess at the subnet mask, assuming reasonable
517 * width subnet fields.
cab3a575 518 */
a83ade01 519 while (i &~ mask)
6c5bed6c 520 mask = (long)mask >> subnetshift;
cab3a575 521 }
a83ade01 522 net = i & mask;
6c5bed6c
MK
523 while ((mask & 1) == 0)
524 mask >>= 1, net >>= 1;
525 np = getnetbyaddr(net, AF_INET);
cab3a575
MK
526 if (np)
527 cp = np->n_name;
6e549c8f 528 }
cab3a575 529 if (cp)
cb646d4b 530 strncpy(line, cp, sizeof(line) - 1);
a83ade01
MK
531 else if ((i & 0xffffff) == 0)
532 sprintf(line, "%u", C(i >> 24));
533 else if ((i & 0xffff) == 0)
534 sprintf(line, "%u.%u", C(i >> 24) , C(i >> 16));
535 else if ((i & 0xff) == 0)
536 sprintf(line, "%u.%u.%u", C(i >> 24), C(i >> 16), C(i >> 8));
cab3a575 537 else
a83ade01
MK
538 sprintf(line, "%u.%u.%u.%u", C(i >> 24),
539 C(i >> 16), C(i >> 8), C(i));
3537c4ea
SL
540 return (line);
541}
6c5bed6c 542
bbd2d21e
SL
543/*
544 * Print routing statistics
545 */
6e549c8f 546void
bbd2d21e 547rt_stats(off)
d1cfb820 548 u_long off;
bbd2d21e
SL
549{
550 struct rtstat rtstat;
551
552 if (off == 0) {
553 printf("rtstat: symbol not in namelist\n");
554 return;
555 }
6e549c8f 556 kread(off, (char *)&rtstat, sizeof (rtstat));
bbd2d21e 557 printf("routing:\n");
bd91d3f9 558 printf("\t%u bad routing redirect%s\n",
bbd2d21e 559 rtstat.rts_badredirect, plural(rtstat.rts_badredirect));
bd91d3f9 560 printf("\t%u dynamically created route%s\n",
bbd2d21e 561 rtstat.rts_dynamic, plural(rtstat.rts_dynamic));
bd91d3f9 562 printf("\t%u new gateway%s due to redirects\n",
bbd2d21e 563 rtstat.rts_newgateway, plural(rtstat.rts_newgateway));
bd91d3f9 564 printf("\t%u destination%s found unreachable\n",
bbd2d21e 565 rtstat.rts_unreach, plural(rtstat.rts_unreach));
bd91d3f9 566 printf("\t%u use%s of a wildcard route\n",
bbd2d21e
SL
567 rtstat.rts_wildcard, plural(rtstat.rts_wildcard));
568}
2ff355d6 569short ns_nullh[] = {0,0,0};
f1fbb01b
KS
570short ns_bh[] = {-1,-1,-1};
571
572char *
6e549c8f
KS
573ns_print(sa)
574 register struct sockaddr *sa;
f1fbb01b 575{
6e549c8f 576 register struct sockaddr_ns *sns = (struct sockaddr_ns*)sa;
2ff355d6
MK
577 struct ns_addr work;
578 union { union ns_net net_e; u_long long_e; } net;
579 u_short port;
580 static char mybuf[50], cport[10], chost[25];
581 char *host = "";
f7c99b06 582 register char *p; register u_char *q;
f1fbb01b 583
2ff355d6
MK
584 work = sns->sns_addr;
585 port = ntohs(work.x_port);
586 work.x_port = 0;
587 net.net_e = work.x_net;
588 if (ns_nullhost(work) && net.long_e == 0) {
589 if (port ) {
590 sprintf(mybuf, "*.%xH", port);
591 upHex(mybuf);
592 } else
593 sprintf(mybuf, "*.*");
594 return (mybuf);
595 }
f1fbb01b 596
56492e5a 597 if (bcmp(ns_bh, work.x_host.c_host, 6) == 0) {
2ff355d6
MK
598 host = "any";
599 } else if (bcmp(ns_nullh, work.x_host.c_host, 6) == 0) {
600 host = "*";
601 } else {
602 q = work.x_host.c_host;
603 sprintf(chost, "%02x%02x%02x%02x%02x%02xH",
604 q[0], q[1], q[2], q[3], q[4], q[5]);
6e549c8f
KS
605 for (p = chost; *p == '0' && p < chost + 12; p++)
606 continue;
2ff355d6 607 host = p;
f1fbb01b 608 }
2ff355d6
MK
609 if (port)
610 sprintf(cport, ".%xH", htons(port));
611 else
612 *cport = 0;
613
614 sprintf(mybuf,"%xH.%s%s", ntohl(net.long_e), host, cport);
615 upHex(mybuf);
f1fbb01b
KS
616 return(mybuf);
617}
2ff355d6 618
f1fbb01b 619char *
6e549c8f
KS
620ns_phost(sa)
621 struct sockaddr *sa;
f1fbb01b 622{
6e549c8f 623 register struct sockaddr_ns *sns = (struct sockaddr_ns *)sa;
2ff355d6
MK
624 struct sockaddr_ns work;
625 static union ns_net ns_zeronet;
626 char *p;
6e549c8f 627
2ff355d6
MK
628 work = *sns;
629 work.sns_addr.x_port = 0;
630 work.sns_addr.x_net = ns_zeronet;
631
6e549c8f 632 p = ns_print((struct sockaddr *)&work);
2ff355d6
MK
633 if (strncmp("0H.", p, 3) == 0) p += 3;
634 return(p);
635}
6e549c8f
KS
636
637void
2ff355d6 638upHex(p0)
6e549c8f 639 char *p0;
2ff355d6
MK
640{
641 register char *p = p0;
642 for (; *p; p++) switch (*p) {
643
644 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
645 *p += ('A' - 'a');
646 }
f1fbb01b 647}