#include #include #include #include #include #include #include #include #include #include #include #include void print_route(struct in_rtmsg *nrt) { fprintf(stderr, "%08x/%d via %08x/%s tos %02x class %d metric %d flags %08x win %d mtu %d rtt %d\n", ntohl(nrt->rtmsg_prefix.s_addr), nrt->rtmsg_prefixlen, ntohl(nrt->rtmsg_gateway.s_addr), nrt->rtmsg_device, nrt->rtmsg_tos, nrt->rtmsg_class, nrt->rtmsg_metric, nrt->rtmsg_flags, nrt->rtmsg_window, nrt->rtmsg_mtu, nrt->rtmsg_rtt); } void print_dev(struct in_ifmsg *nrt) { fprintf(stderr, "%08x/%d brd %08x flags %08x mtu %d type %d\n", ntohl(nrt->ifmsg_prefix.s_addr), nrt->ifmsg_prefixlen, ntohl(nrt->ifmsg_brd.s_addr), nrt->ifmsg_flags, nrt->ifmsg_mtu, nrt->ifmsg_lladdr.sa_family); } int main(int argc, char **argv) { int status; int fd; char *buf[4096]; struct nlmsghdr *h; struct in_rtmsg *nrt; struct in_ifmsg *nif; int *p; int tim; int i; openlog ("rtmon", LOG_PID | LOG_CONS, LOG_DAEMON); fd = open("/dev/route", O_RDONLY); if (fd < 0) { syslog(LOG_CRIT, "cannot open /dev/route: %m\n"); exit(-1); } while (1) { status = read(fd, buf, sizeof(buf)); if (status < 0) { if (errno == EINTR) continue; syslog(LOG_CRIT, "cannot read /dev/route: %m\n"); exit(-1); } if (status == 0) { syslog(LOG_CRIT, "EOF /dev/route\n"); exit(-1); } time(&tim); fprintf(stderr, "==== Message %s", ctime(&tim)); for (h = (struct nlmsghdr*)buf, i=1; status >= sizeof(*h); i++) { unsigned long type= h->nlmsg_type; unsigned long pid=h->nlmsg_pid; int l= h->nlmsg_len-sizeof(*h); unsigned long seq= h->nlmsg_seq; if (l<0) { syslog(LOG_CRIT, "malformed message: len=%d\n", l); exit(-1); } nrt=(struct in_rtmsg*)h->nlmsg_data; nif=(struct in_ifmsg*)h->nlmsg_data; p=(int*)h->nlmsg_data; status -= NLMSG_ALIGN(h->nlmsg_len); h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(h->nlmsg_len)); fprintf(stderr, "%d(%d.%d):\t", i, pid, seq); switch (type) { case RTMSG_NEWDEVICE: if (l < sizeof(*nif)) fprintf(stderr, "UP truncated\n"); else { fprintf(stderr, "UP %s\n", nif->ifmsg_device); print_dev(nif); } break; case RTMSG_DELDEVICE: if (l < sizeof(*nif)) fprintf(stderr, "DOWN truncated\n"); else { fprintf(stderr, "DOWN %s\n", nif->ifmsg_device); print_dev(nif); } break; case RTMSG_NEWROUTE: if (l < sizeof(*nrt)) fprintf(stderr, "NEW ROUTE truncated\n"); else { fprintf(stderr, "NEW ROUTE\n"); print_route(nrt); } break; case RTMSG_DELROUTE: if (l < sizeof(*nrt)) fprintf(stderr, "DEL ROUTE truncated\n"); else { fprintf(stderr, "DEL ROUTE\n"); print_route(nrt); } break; case RTMSG_ACK: if (l < sizeof(int)) fprintf(stderr, "ERROR truncated\n"); else fprintf(stderr, "ERROR %d\n", p[0]); break; case RTMSG_OVERRUN: if (l < 2 * sizeof(int)) fprintf(stderr, "OVERRUN truncated\n"); else fprintf(stderr, "OVERRUN %d %d\n", p[0], p[1]); break; default: fprintf (stderr, "INVALID %08x\n", type); break; } } fprintf(stderr, "\n"); } return 0; }