+ return (1);
+do_link:
+ link_addr(s, &su->sdl);
+ return (1);
+}
+
+short ns_nullh[] = {0,0,0};
+short ns_bh[] = {-1,-1,-1};
+
+char *
+ns_print(sns)
+ struct sockaddr_ns *sns;
+{
+ 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)
+ return ("*.*");
+ (void) sprintf(mybuf, "*.%XH", port);
+ return (mybuf);
+ }
+
+ if (bcmp((char *)ns_bh, (char *)work.x_host.c_host, 6) == 0)
+ host = "any";
+ else if (bcmp((char *)ns_nullh, (char *)work.x_host.c_host, 6) == 0)
+ host = "*";
+ else {
+ q = work.x_host.c_host;
+ (void) 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++)
+ /* void */;
+ host = p;
+ }
+ if (port)
+ (void) sprintf(cport, ".%XH", htons(port));
+ else
+ *cport = 0;
+
+ (void) sprintf(mybuf,"%XH.%s%s", ntohl(net.long_e), host, cport);
+ return (mybuf);
+}
+
+void
+monitor()
+{
+ int n;
+ char msg[2048];
+
+ verbose = 1;
+ for(;;) {
+ n = read(s, msg, 2048);
+ (void) printf("got message of size %d\n", n);
+ print_rtmsg((struct rt_msghdr *)msg);
+ }
+}
+
+struct {
+ struct rt_msghdr m_rtm;
+ char m_space[512];
+} m_rtmsg;
+
+int
+rtmsg(cmd, flags)
+ int cmd, flags;
+{
+ static int seq;
+ int rlen;
+ register char *cp = m_rtmsg.m_space;
+ register int l;
+
+#define NEXTADDR(w, u) \
+ if (rtm_addrs & (w)) {\
+ l = ROUNDUP(u.sa.sa_len); bcopy((char *)&(u), cp, l); cp += l;\
+ if (verbose) sodump(&(u),"u");\
+ }
+
+ errno = 0;
+ bzero((char *)&m_rtmsg, sizeof(m_rtmsg));
+ if (cmd == 'a')
+ cmd = RTM_ADD;
+ else if (cmd == 'c')
+ cmd = RTM_CHANGE;
+ else if (cmd == 'g')
+ cmd = RTM_GET;
+ else
+ cmd = RTM_DELETE;
+#define rtm m_rtmsg.m_rtm
+ rtm.rtm_type = cmd;
+ rtm.rtm_flags = flags;
+ rtm.rtm_version = RTM_VERSION;
+ rtm.rtm_seq = ++seq;
+ rtm.rtm_addrs = rtm_addrs;
+ rtm.rtm_rmx = rt_metrics;
+ rtm.rtm_inits = rtm_inits;
+
+ NEXTADDR(RTA_DST, so_dst);
+ NEXTADDR(RTA_GATEWAY, so_gate);
+ NEXTADDR(RTA_NETMASK, so_mask);
+ NEXTADDR(RTA_GENMASK, so_genmask);
+ NEXTADDR(RTA_IFP, so_ifp);
+ NEXTADDR(RTA_IFA, so_ifa);
+ rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
+ if (verbose)
+ print_rtmsg(&rtm, l);
+ if (debugonly)
+ return 0;
+ if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) {
+ perror("writing to routing socket");
+ return (-1);
+ }
+ if (cmd == RTM_GET) {
+ do {
+ l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
+ } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
+ if (l < 0)
+ (void) fprintf(stderr,
+ "route: read from routing socket: %s\n",
+ strerror(errno));
+ else
+ print_getmsg(&rtm, l);
+ }
+#undef rtm
+ return (0);
+}
+
+char *msgtypes[] = {
+ "",
+ "RTM_ADD: Add Route",
+ "RTM_DELETE: Delete Route",
+ "RTM_CHANGE: Change Metrics or flags",
+ "RTM_GET: Report Metrics",
+ "RTM_LOSING: Kernel Suspects Partitioning",
+ "RTM_REDIRECT: Told to use different route",
+ "RTM_MISS: Lookup failed on this address",
+ "RTM_LOCK: fix specified metrics",
+ "RTM_OLDADD: caused by SIOCADDRT",
+ "RTM_OLDDEL: caused by SIOCDELRT",
+ 0,
+};
+
+char metricnames[] =
+"\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire\2hopcount\1mtu";
+char routeflags[] =
+"\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE\010MASK_PRESENT\011CLONING\012XRESOLVE";
+
+
+void
+print_rtmsg(rtm, msglen)
+ register struct rt_msghdr *rtm;
+ int msglen;
+{
+ if (verbose == 0)
+ return;
+ if (rtm->rtm_version != RTM_VERSION) {
+ (void) printf("routing message version %d not understood\n",
+ rtm->rtm_version);
+ return;
+ }
+ (void) printf("%s\npid: %d, len %d, seq %d, errno %d, flags:",
+ msgtypes[rtm->rtm_type], rtm->rtm_pid, rtm->rtm_msglen,
+ rtm->rtm_seq, rtm->rtm_errno);
+ bprintf(stdout, rtm->rtm_flags, routeflags);
+ pmsg_common(rtm);
+}
+
+void
+print_getmsg(rtm, msglen)
+ register struct rt_msghdr *rtm;
+ int msglen;
+{
+ if (rtm->rtm_version != RTM_VERSION) {
+ (void)printf("routing message version %d not understood\n",
+ rtm->rtm_version);
+ return;
+ }
+ if (rtm->rtm_msglen > msglen) {
+ (void)printf("get length mismatch, in packet %d, returned %d\n",
+ rtm->rtm_msglen, msglen);
+ }
+ (void) printf("RTM_GET: errno %d, flags:", rtm->rtm_errno);
+ bprintf(stdout, rtm->rtm_flags, routeflags);
+ (void) printf("\nmetric values:\n\n");
+#define metric(f, e) printf("\t%s:\t%d\n", "f", rtm->rtm_rmx.e)
+ metric(RTV_RPIPE, rmx_recvpipe);
+ metric(RTV_SPIPE, rmx_sendpipe);
+ metric(RTV_SSTHRESH, rmx_ssthresh);
+ metric(RTV_RTT, rmx_rtt);
+ metric(RTV_RTTVAR, rmx_rttvar);
+ metric(RTV_HOPCOUNT, rmx_hopcount);
+ metric(RTV_MTU, rmx_mtu);
+ metric(RTV_EXPIRE, rmx_expire);
+#undef metric
+ pmsg_common(rtm);
+}
+
+void
+pmsg_common(rtm)
+ register struct rt_msghdr *rtm;
+{
+ char *cp;
+ register struct sockaddr *sa;
+ int i;
+
+ (void) printf("\nlocks: ");
+ bprintf(stdout, rtm->rtm_rmx.rmx_locks, metricnames);
+ (void) printf(" inits: ");
+ bprintf(stdout, rtm->rtm_inits, metricnames);
+ (void) printf("\nsockaddrs: ");
+ bprintf(stdout, rtm->rtm_addrs,
+ "\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR");
+ (void) putchar('\n');
+ cp = ((char *)(rtm + 1));
+ if (rtm->rtm_addrs)
+ for (i = 1; i; i <<= 1)
+ if (i & rtm->rtm_addrs) {
+ sa = (struct sockaddr *)cp;
+ (void) printf(" %s", routename(sa));
+ ADVANCE(cp, sa);
+ }
+ (void) putchar('\n');
+ (void) fflush(stdout);
+}
+
+void
+bprintf(fp, b, s)
+ register FILE *fp;
+ register int b;
+ register u_char *s;
+{
+ register int i;
+ int gotsome = 0;
+
+ if (b == 0)
+ return;
+ while (i = *s++) {
+ if (b & (1 << (i-1))) {
+ if (gotsome == 0)
+ i = '<';
+ else
+ i = ',';
+ (void) putc(i, fp);
+ gotsome = 1;
+ for (; (i = *s) > 32; s++)
+ (void) putc(i, fp);
+ } else
+ while (*s > 32)
+ s++;
+ }
+ if (gotsome)
+ (void) putc('>', fp);
+}
+
+int
+keyword(cp)
+ char *cp;
+{
+ register struct keytab *kt = keywords;
+
+ while (kt->kt_cp && strcmp(kt->kt_cp, cp))
+ kt++;
+ return kt->kt_i;
+}
+
+void
+sodump(su, which)
+ register sup su;
+ char *which;
+{
+ switch (su->sa.sa_family) {
+ case AF_LINK:
+ (void) printf("%s: link %s; ",
+ which, link_ntoa(&su->sdl));
+ break;
+ case AF_ISO:
+ (void) printf("%s: iso %s; ",
+ which, iso_ntoa(&su->siso.siso_addr));
+ break;
+ case AF_INET:
+ (void) printf("%s: inet %s; ",
+ which, inet_ntoa(su->sin.sin_addr));
+ break;
+ case AF_NS:
+ (void) printf("%s: xns %s; ",
+ which, ns_ntoa(su->sns.sns_addr));
+ break;
+ }
+ (void) fflush(stdout);