+
+static u_long
+forgemask(a)
+ u_long a;
+{
+ u_long m;
+
+ if (IN_CLASSA(a))
+ m = IN_CLASSA_NET;
+ else if (IN_CLASSB(a))
+ m = IN_CLASSB_NET;
+ else
+ m = IN_CLASSC_NET;
+ return (m);
+}
+
+static void
+domask(dst, addr, mask)
+ char *dst;
+ u_long addr, mask;
+{
+ register int b, i;
+
+ if (!mask || (forgemask(addr) == mask)) {
+ *dst = '\0';
+ return;
+ }
+ i = 0;
+ for (b = 0; b < 32; b++)
+ if (mask & (1 << b)) {
+ register int bb;
+
+ i = b;
+ for (bb = b+1; bb < 32; bb++)
+ if (!(mask & (1 << bb))) {
+ i = -1; /* noncontig */
+ break;
+ }
+ break;
+ }
+ if (i == -1)
+ sprintf(dst, "&0x%lx", mask);
+ else
+ sprintf(dst, "/%d", 32-i);
+}
+
+/*
+ * Return the name of the network whose address is given.
+ * The address is assumed to be that of a net or subnet, not a host.
+ */
+char *
+netname(in, mask)
+ u_long in, mask;
+{
+ char *cp = 0;
+ static char line[MAXHOSTNAMELEN + 1];
+ struct netent *np = 0;
+ u_long net, omask;
+ register u_long i;
+ int subnetshift;
+
+ i = ntohl(in);
+ omask = mask;
+ if (!nflag && i) {
+ if (mask == 0) {
+ switch (mask = forgemask(i)) {
+ case IN_CLASSA_NET:
+ subnetshift = 8;
+ break;
+ case IN_CLASSB_NET:
+ subnetshift = 8;
+ break;
+ case IN_CLASSC_NET:
+ subnetshift = 4;
+ break;
+ default:
+ abort();
+ }
+ /*
+ * If there are more bits than the standard mask
+ * would suggest, subnets must be in use.
+ * Guess at the subnet mask, assuming reasonable
+ * width subnet fields.
+ */
+ while (i &~ mask)
+ mask = (long)mask >> subnetshift;
+ }
+ net = i & mask;
+ while ((mask & 1) == 0)
+ mask >>= 1, net >>= 1;
+ np = getnetbyaddr(net, AF_INET);
+ if (np)
+ cp = np->n_name;
+ }
+ if (cp)
+ strncpy(line, cp, sizeof(line) - 1);
+ else if ((i & 0xffffff) == 0)
+ sprintf(line, "%u", C(i >> 24));
+ else if ((i & 0xffff) == 0)
+ sprintf(line, "%u.%u", C(i >> 24) , C(i >> 16));
+ else if ((i & 0xff) == 0)
+ sprintf(line, "%u.%u.%u", C(i >> 24), C(i >> 16), C(i >> 8));
+ else
+ sprintf(line, "%u.%u.%u.%u", C(i >> 24),
+ C(i >> 16), C(i >> 8), C(i));
+ domask(line+strlen(line), i, omask);
+ return (line);
+}
+
+/*
+ * Print routing statistics
+ */
+void
+rt_stats(off)
+ u_long off;
+{
+ struct rtstat rtstat;
+
+ if (off == 0) {
+ printf("rtstat: symbol not in namelist\n");
+ return;
+ }
+ kread(off, (char *)&rtstat, sizeof (rtstat));
+ printf("routing:\n");
+ printf("\t%u bad routing redirect%s\n",
+ rtstat.rts_badredirect, plural(rtstat.rts_badredirect));
+ printf("\t%u dynamically created route%s\n",
+ rtstat.rts_dynamic, plural(rtstat.rts_dynamic));
+ printf("\t%u new gateway%s due to redirects\n",
+ rtstat.rts_newgateway, plural(rtstat.rts_newgateway));
+ printf("\t%u destination%s found unreachable\n",
+ rtstat.rts_unreach, plural(rtstat.rts_unreach));
+ printf("\t%u use%s of a wildcard route\n",
+ rtstat.rts_wildcard, plural(rtstat.rts_wildcard));
+}
+short ns_nullh[] = {0,0,0};
+short ns_bh[] = {-1,-1,-1};
+
+char *
+ns_print(sa)
+ register struct sockaddr *sa;
+{
+ register struct sockaddr_ns *sns = (struct sockaddr_ns*)sa;
+ struct ns_addr work;
+ union { union ns_net net_e; u_long long_e; } net;
+ u_short port;
+ static char mybuf[50], cport[10], chost[25];
+ char *host = "";
+ register char *p; register u_char *q;
+
+ work = sns->sns_addr;
+ port = ntohs(work.x_port);
+ work.x_port = 0;
+ net.net_e = work.x_net;
+ if (ns_nullhost(work) && net.long_e == 0) {
+ if (port ) {
+ sprintf(mybuf, "*.%xH", port);
+ upHex(mybuf);
+ } else
+ sprintf(mybuf, "*.*");
+ return (mybuf);
+ }
+
+ if (bcmp(ns_bh, work.x_host.c_host, 6) == 0) {
+ host = "any";
+ } else if (bcmp(ns_nullh, work.x_host.c_host, 6) == 0) {
+ host = "*";
+ } else {
+ q = work.x_host.c_host;
+ sprintf(chost, "%02x%02x%02x%02x%02x%02xH",
+ q[0], q[1], q[2], q[3], q[4], q[5]);
+ for (p = chost; *p == '0' && p < chost + 12; p++)
+ continue;
+ host = p;
+ }
+ if (port)
+ sprintf(cport, ".%xH", htons(port));
+ else
+ *cport = 0;
+
+ sprintf(mybuf,"%xH.%s%s", ntohl(net.long_e), host, cport);
+ upHex(mybuf);
+ return(mybuf);
+}
+
+char *
+ns_phost(sa)
+ struct sockaddr *sa;
+{
+ register struct sockaddr_ns *sns = (struct sockaddr_ns *)sa;
+ struct sockaddr_ns work;
+ static union ns_net ns_zeronet;
+ char *p;
+
+ work = *sns;
+ work.sns_addr.x_port = 0;
+ work.sns_addr.x_net = ns_zeronet;
+
+ p = ns_print((struct sockaddr *)&work);
+ if (strncmp("0H.", p, 3) == 0) p += 3;
+ return(p);
+}
+
+void
+upHex(p0)
+ char *p0;
+{
+ register char *p = p0;
+ for (; *p; p++) switch (*p) {
+
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ *p += ('A' - 'a');
+ }
+}