/* $Id: inet_gr.c,v 1.14 2009/07/08 00:24:03 ecki Exp $ Modifications: 1998-07-01 - Arnaldo Carvalho de Melo - GNU gettext instead of catgets 1999-01-01 - Bernd Eckenfels - fixed the routing cache printouts 1999-10-07 - Kurt Garloff - do host (instead of network) name lookup for gws and hosts */ #include "config.h" #if HAVE_AFINET #include #include #include #include #include /* #include realy broken */ #include #include #include #include #include #include #include #include #include "version.h" #include "net-support.h" #include "pathnames.h" #include "intl.h" #include "net-features.h" #include "proc.h" #include "util.h" extern struct aftype inet_aftype; extern char *INET_sprintmask(const struct sockaddr_storage *sap, int numeric, unsigned int netmask); int rprint_fib(int ext, int numeric) { char buff[1024], iface[17], flags[64]; char gate_addr[128], net_addr[128]; char mask_addr[128]; int num, iflags, metric, refcnt, use, mss, window, irtt; FILE *fp = fopen(_PATH_PROCNET_ROUTE, "r"); char *fmt; if (!fp) { perror(_PATH_PROCNET_ROUTE); printf(_("INET (IPv4) not configured in this system.\n")); return 1; } printf(_("Kernel IP routing table\n")); if (ext == 1) printf(_("Destination Gateway Genmask " "Flags Metric Ref Use Iface\n")); if (ext == 2) printf(_("Destination Gateway Genmask " "Flags MSS Window irtt Iface\n")); if (ext >= 3) printf(_("Destination Gateway Genmask " "Flags Metric Ref Use Iface " "MSS Window irtt\n")); irtt = 0; window = 0; mss = 0; fmt = proc_gen_fmt(_PATH_PROCNET_ROUTE, 0, fp, "Iface", "%15s", "Destination", "%127s", "Gateway", "%127s", "Flags", "%X", "RefCnt", "%d", "Use", "%d", "Metric", "%d", "Mask", "%127s", "MTU", "%d", "Window", "%d", "IRTT", "%d", NULL); /* "%15s %127s %127s %X %d %d %d %127s %d %d %d\n" */ if (!fmt) return 1; while (fgets(buff, 1023, fp)) { struct sockaddr_storage snet_target, snet_gateway, snet_mask; struct sockaddr_in *sin_netmask; num = sscanf(buff, fmt, iface, net_addr, gate_addr, &iflags, &refcnt, &use, &metric, mask_addr, &mss, &window, &irtt); if (num < 10 || !(iflags & RTF_UP)) continue; /* Fetch and resolve the target address. */ (void) inet_aftype.input(1, net_addr, &snet_target); /* Fetch and resolve the gateway address. */ (void) inet_aftype.input(1, gate_addr, &snet_gateway); /* Fetch and resolve the genmask. */ (void) inet_aftype.input(1, mask_addr, &snet_mask); sin_netmask = (struct sockaddr_in *)&snet_mask; safe_strncpy(net_addr, INET_sprintmask(&snet_target, (numeric | 0x8000 | (iflags & RTF_HOST? 0x4000: 0)), sin_netmask->sin_addr.s_addr), sizeof(net_addr)); net_addr[15] = '\0'; safe_strncpy(gate_addr, inet_aftype.sprint(&snet_gateway, numeric | 0x4000), sizeof(gate_addr)); gate_addr[15] = '\0'; safe_strncpy(mask_addr, inet_aftype.sprint(&snet_mask, 1), sizeof(mask_addr)); mask_addr[15] = '\0'; /* Decode the flags. */ flags[0] = '\0'; if (iflags & RTF_UP) strcat(flags, "U"); if (iflags & RTF_GATEWAY) strcat(flags, "G"); #if HAVE_RTF_REJECT if (iflags & RTF_REJECT) safe_strncpy(flags, "!", sizeof(flags)); #endif if (iflags & RTF_HOST) strcat(flags, "H"); if (iflags & RTF_REINSTATE) strcat(flags, "R"); if (iflags & RTF_DYNAMIC) strcat(flags, "D"); if (iflags & RTF_MODIFIED) strcat(flags, "M"); if (iflags & RTF_DEFAULT) strcat(flags, "d"); if (iflags & RTF_ALLONLINK) strcat(flags, "a"); if (iflags & RTF_ADDRCONF) strcat(flags, "c"); if (iflags & RTF_NONEXTHOP) strcat(flags, "o"); if (iflags & RTF_EXPIRES) strcat(flags, "e"); if (iflags & RTF_CACHE) strcat(flags, "c"); if (iflags & RTF_FLOW) strcat(flags, "f"); if (iflags & RTF_POLICY) strcat(flags, "p"); if (iflags & RTF_LOCAL) strcat(flags, "l"); if (iflags & RTF_MTU) strcat(flags, "u"); if (iflags & RTF_WINDOW) strcat(flags, "w"); if (iflags & RTF_IRTT) strcat(flags, "i"); if (iflags & RTF_NOTCACHED) /* 2.0.36 */ strcat(flags, "n"); /* Print the info. */ if (ext == 1) { #if HAVE_RTF_REJECT if (iflags & RTF_REJECT) printf("%-15s - %-15s %-5s %-6d - %7d -\n", net_addr, mask_addr, flags, metric, use); else #endif printf("%-15s %-15s %-15s %-5s %-6d %-2d %7d %s\n", net_addr, gate_addr, mask_addr, flags, metric, refcnt, use, iface); } if (ext == 2) { #if HAVE_RTF_REJECT if (iflags & RTF_REJECT) printf("%-15s - %-15s %-5s - - - -\n", net_addr, mask_addr, flags); else #endif printf("%-15s %-15s %-15s %-5s %5d %-5d %6d %s\n", net_addr, gate_addr, mask_addr, flags, mss, window, irtt, iface); } if (ext >= 3) { #if HAVE_RTF_REJECT if (iflags & RTF_REJECT) printf("%-15s - %-15s %-5s %-6d - %7d - - - -\n", net_addr, mask_addr, flags, metric, use); else #endif printf("%-15s %-15s %-15s %-5s %-6d %-3d %6d %-6.6s %-5d %-6d %d\n", net_addr, gate_addr, mask_addr, flags, metric, refcnt, use, iface, mss, window, irtt); } } free(fmt); (void) fclose(fp); return (0); } int rprint_cache(int ext, int numeric) { char buff[1024], iface[17], flags[64]; char gate_addr[128], dest_addr[128], specdst[128]; char src_addr[128]; struct sockaddr_storage snet; unsigned int iflags; int num, format, metric, refcnt, use, mss, window, irtt, hh, hhref, hhuptod, arp, tos; char *fmt = NULL; FILE *fp = fopen(_PATH_PROCNET_RTCACHE, "r"); if (!fp) { perror(_PATH_PROCNET_RTCACHE); printf(_("INET (IPv4) not configured in this system.\n")); return 1; } /* Okay, first thing we need to know is the format of the rt_cache. * I am aware of two possible layouts: * 2.2.0 * "Iface\tDestination\tGateway \tFlags\t\tRefCnt\tUse\tMetric\tSource\t\tMTU\tWindow\tIRTT\tTOS\tHHRef\tHHUptod\tSpecDst" * "%s\t%08lX\t%08lX\t%8X\t%d\t%u\t%d\t%08lX\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X" * * 2.0.36 * "Iface\tDestination\tGateway \tFlags\tRefCnt\tUse\tMetric\tSource\t\tMTU\tWindow\tIRTT\tHH\tARP" * "%s\t%08lX\t%08lX\t%02X\t%d\t%u\t%d\t%08lX\t%d\t%lu\t%u\t%d\t%1d" */ format = proc_guess_fmt(_PATH_PROCNET_RTCACHE, fp, "IRTT",1,"TOS",2,"HHRef",4,"HHUptod",8,"SpecDst",16,"HH",32,"ARP",64,NULL); printf(_("Kernel IP routing cache\n")); switch(format) { case -1: /* I/O Error */ perror(_PATH_PROCNET_RTCACHE); exit(-1); break; case 63: /* 2.2.0 Format */ format = 2; break; case 97: /* 2.0.36 Format */ format = 1; break; default: printf("ERROR: proc_guess_fmt(%s,... returned: %d\n",_PATH_PROCNET_RTCACHE, format); break; } rewind(fp); if (ext == 1) printf(_("Source Destination Gateway " "Flags Metric Ref Use Iface\n")); if (ext == 2) printf(_("Source Destination Gateway " "Flags MSS Window irtt Iface\n")); if (format == 1) { if (ext >= 3) printf(_("Source Destination Gateway " "Flags Metric Ref Use Iface " "MSS Window irtt HH Arp\n")); fmt = proc_gen_fmt(_PATH_PROCNET_RTCACHE, 0, fp, "Iface", "%15s", "Destination", "%127s", "Gateway", "%127s", "Flags", "%X", "RefCnt", "%d", "Use", "%d", "Metric", "%d", "Source", "%127s", "MTU", "%d", "Window", "%d", "IRTT", "%d", "HH", "%d", "ARP", "%d", NULL); /* "%15s %127s %127s %X %d %d %d %127s %d %d %d %d %d\n" */ } if (format == 2) { if (ext >= 3) printf(_("Source Destination Gateway " "Flags Metric Ref Use Iface " "MSS Window irtt TOS HHRef HHUptod SpecDst\n")); fmt = proc_gen_fmt(_PATH_PROCNET_RTCACHE, 0, fp, "Iface", "%15s", "Destination", "%127s", "Gateway", "%127s", "Flags", "%X", "RefCnt", "%d", "Use", "%d", "Metric", "%d", "Source", "%127s", "MTU", "%d", "Window", "%d", "IRTT", "%d", "TOS", "%d", "HHRef", "%d", "HHUptod", "%d", "SpecDst", "%127s", NULL); /* "%15s %127s %127s %X %d %d %d %127s %d %d %d %d %d %127s\n" */ } irtt = 0; window = 0; mss = 0; hh = 0; hhref = 0; hhuptod = 0; arp = 0; tos = 0; while (fgets(buff, 1023, fp)) { if (format == 1) { num = sscanf(buff, fmt, iface, dest_addr, gate_addr, &iflags, &refcnt, &use, &metric, src_addr, &mss, &window, &irtt, &hh, &arp); if (num < 12) continue; } if (format == 2) { num = sscanf(buff, fmt, iface, dest_addr, gate_addr, &iflags, &refcnt, &use, &metric, src_addr, &mss, &window, &irtt, &tos, &hhref, &hhuptod, &specdst); if (num < 12) continue; } /* Fetch and resolve the target address. */ (void) inet_aftype.input(1, dest_addr, &snet); safe_strncpy(dest_addr, inet_aftype.sprint(&snet, numeric), sizeof(dest_addr)); /* Fetch and resolve the gateway address. */ (void) inet_aftype.input(1, gate_addr, &snet); safe_strncpy(gate_addr, inet_aftype.sprint(&snet, numeric), sizeof(gate_addr)); /* Fetch and resolve the source. */ (void) inet_aftype.input(1, src_addr, &snet); safe_strncpy(src_addr, inet_aftype.sprint(&snet, numeric), sizeof(src_addr)); /* Fetch and resolve the SpecDst addrerss. */ (void) inet_aftype.input(1, specdst, &snet); safe_strncpy(specdst, inet_aftype.sprint(&snet, numeric), sizeof(specdst)); /* Decode the flags. */ flags[0] = '\0'; if (format == 1) { if (iflags & RTF_UP) strcat(flags, "U"); if (iflags & RTF_HOST) strcat(flags, "H"); } if (iflags & RTF_GATEWAY) strcat(flags, "G"); #if HAVE_RTF_REJECT if (iflags & RTF_REJECT) safe_strncpy(flags, "!", sizeof(flags)); #endif if (iflags & RTF_REINSTATE) strcat(flags, "R"); if (iflags & RTF_DYNAMIC) strcat(flags, "D"); if (iflags & RTF_MODIFIED) strcat(flags, "M"); /* possible collision with 2.0 flags U and H */ if (format == 2) { if (iflags & RTCF_DEAD) strcat(flags, "-"); if (iflags & RTCF_ONLINK) strcat(flags, "o"); } if (iflags & RTCF_NOTIFY) strcat(flags, "n"); if (iflags & RTCF_DIRECTDST) strcat(flags, "d"); if (iflags & RTCF_TPROXY) strcat(flags, "t"); if (iflags & RTCF_FAST) strcat(flags, "f"); if (iflags & RTCF_MASQ) strcat(flags, "q"); if (iflags & RTCF_SNAT) strcat(flags, "Ns"); if (iflags & RTCF_DOREDIRECT) strcat(flags, "r"); if (iflags & RTCF_DIRECTSRC) strcat(flags, "i"); if (iflags & RTCF_DNAT) strcat(flags, "Nd"); if (iflags & RTCF_BROADCAST) strcat(flags, "b"); if (iflags & RTCF_MULTICAST) strcat(flags, "m"); if (iflags & RTCF_REJECT) strcat(flags, "#"); if (iflags & RTCF_LOCAL) strcat(flags, "l"); /* Print the info. */ if (ext == 1) { printf("%-15s %-15s %-15s %-5s %-6d %-2d %7d %s\n", src_addr, dest_addr, gate_addr, flags, metric, refcnt, use, iface); } if (ext == 2) { printf("%-15s %-15s %-15s %-5s %5d %-5d %6d %s\n", src_addr, dest_addr, gate_addr, flags, mss, window, irtt, iface); } if (format == 1) { if (ext >= 3) { printf("%-15s %-15s %-15s %-5s %-6d %-3d %6d %-6.6s %-5d %-6d %-5d %-3d %d\n", src_addr, dest_addr, gate_addr, flags, metric, refcnt, use, iface, mss, window, irtt, hh, arp); } } if (format == 2) { if (ext >= 3) { printf("%-15s %-15s %-15s %-5s %-6d %-3d %6d %-6.6s %-5d %-6d %-5d %-3d %-3d %-3d %15s\n", src_addr, dest_addr, gate_addr, flags, metric, refcnt, use, iface, mss, window, irtt, tos, hhref, hhuptod, specdst); } } } free(fmt); (void) fclose(fp); return (0); } int INET_rprint(int options) { int ext = options & FLAG_EXT; int numeric = options & (FLAG_NUM_HOST | FLAG_SYM); int rc = E_INTERN; if (options & FLAG_FIB) if ((rc = rprint_fib(ext, numeric))) return (rc); if (options & FLAG_CACHE) rc = rprint_cache(ext, numeric); return (rc); } #endif /* HAVE_AFINET */