+
+monitor()
+{
+ int n;
+ char msg[2048];
+ verbose = 1;
+ for(;;) {
+ n = read(s, msg, 2048);
+ 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;
+
+rtmsg(cmd, flags)
+{
+ static int seq;
+ int rlen;
+ extern int errno;
+ register char *cp = m_rtmsg.m_space;
+ register int l;
+
+ errno = 0;
+ bzero((char *)&m_rtmsg, sizeof(m_rtmsg));
+ if (cmd == 'a')
+ cmd = RTM_ADD;
+ else if (cmd == 'c')
+ cmd = RTM_CHANGE;
+ else
+ cmd = RTM_DELETE;
+ m_rtmsg.m_rtm.rtm_flags = flags;
+ m_rtmsg.m_rtm.rtm_version = RTM_VERSION;
+ m_rtmsg.m_rtm.rtm_seq = ++seq;
+ m_rtmsg.m_rtm.rtm_addrs = rtm_addrs;
+ m_rtmsg.m_rtm.rtm_rmx = rt_metrics;
+ m_rtmsg.m_rtm.rtm_inits = rtm_inits;
+
+#define ROUND(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
+#define NEXTADDR(w, u) { if (rtm_addrs & (w)) {l = (u).sa.sa_len;\
+ if(verbose)sodump(&(u),"u");if(l == 0) l = sizeof(int); l = ROUND(l);\
+ bcopy((char *)&(u), cp, l); cp += l;}}
+
+ NEXTADDR(RTA_DST, so_dst);
+ NEXTADDR(RTA_GATEWAY, so_gate);
+ NEXTADDR(RTA_NETMASK, so_mask);
+ NEXTADDR(RTA_GENMASK, so_genmask);
+ m_rtmsg.m_rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
+ m_rtmsg.m_rtm.rtm_type = cmd;
+ if (verbose)
+ print_rtmsg(&m_rtmsg.m_rtm, l);
+ if (debugonly)
+ return 0;
+ if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) {
+ perror("writing to routing socket");
+ printf("got only %d for rlen\n", rlen);
+ return (-1);
+ }
+again:
+ if ((rlen = read(s, (char *)&m_rtmsg, l)) < 0) {
+ perror("reading from routing socket");
+ printf("got only %d for rlen\n", rlen);
+ return (-1);
+ }
+ if ((m_rtmsg.m_rtm.rtm_pid != pid) ||
+ (m_rtmsg.m_rtm.rtm_seq != seq)) {
+ printf("Got response for somebody else's request");
+ goto again;
+ }
+ if (qflag == 0)
+ print_rtmsg( &m_rtmsg.m_rtm, rlen);
+ if ((m_rtmsg.m_rtm.rtm_flags & RTF_DONE) == 0) {
+ errno = m_rtmsg.m_rtm.rtm_errno;
+ perror("response from routing socket turned down");
+ return (-1);
+ }
+ 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\5DYNAMIC\6MODIFIED\7DONE\010MASK_PRESENT\011CLONING\012XRESOLVE";
+
+#define ROUNDUP(a) ((char *)(1 + (((((int)a)) - 1) | (sizeof(long) - 1))))
+
+print_rtmsg(rtm, n)
+register struct rt_msghdr *rtm;
+{
+ char *cp;
+ register struct sockaddr *sa;
+ int i;
+
+ if (verbose == 0)
+ return;
+ if (rtm->rtm_version != RTM_VERSION) {
+ printf("routing message version %d not understood\n",
+ rtm->rtm_version);
+ } else {
+ 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);
+ printf("\nlocks: "); bprintf(stdout, rtm->rtm_rmx.rmx_locks, metricnames);
+ printf(" inits: "); bprintf(stdout, rtm->rtm_inits, metricnames);
+ printf("\nsockaddrs: ");
+ bprintf(stdout, rtm->rtm_addrs,
+ "\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR");
+ 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;
+ printf(" %s", routename(sa));
+ cp = ROUNDUP(cp + sa->sa_len);
+ }
+ putchar('\n');
+ }
+ fflush(stdout);
+}
+
+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 = ',';
+ putc(i, fp);
+ gotsome = 1;
+ for (; (i = *s) > 32; s++)
+ putc(i, fp);
+ } else
+ while (*s > 32)
+ s++;
+ }
+ if (gotsome)
+ 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;
+}
+
+sodump(su, which)
+register union sockunion *su;
+char *which;
+{
+ switch (su->sa.sa_family) {
+ case AF_LINK:
+ printf("%s: link %s; ", which, link_ntoa(&su->sdl));
+ break;
+ case AF_ISO:
+ printf("%s: iso %s; ", which, iso_ntoa(&su->siso.siso_addr));
+ break;
+ case AF_INET:
+ printf("%s: inet %s; ", which, inet_ntoa(su->sin.sin_addr));
+ break;
+ case AF_NS:
+ printf("%s: xns %s; ", which, ns_ntoa(&su->sns.sns_addr));
+ break;
+ }
+ fflush(stdout);
+}