Fix netstat -- don't print all v4 addresses as v4-mapped-in-v6.
[oss-qm-packages.git] / lib / inet_gr.c
blobd1e5efc160f0b65ea0634a4f98d90d7132259b0b
1 /*
2 $Id: inet_gr.c,v 1.13 2000/10/08 01:00:44 ecki Exp $
4 Modifications:
5 1998-07-01 - Arnaldo Carvalho de Melo - GNU gettext instead of catgets
6 1999-01-01 - Bernd Eckenfels - fixed the routing cache printouts
7 1999-10-07 - Kurt Garloff <garloff@suse.de> - do host (instead of network) name
8 lookup for gws and hosts
9 */
11 #include "config.h"
13 #if HAVE_AFINET
14 #include <sys/types.h>
15 #include <sys/socket.h>
16 #include <netinet/in.h>
17 #include <arpa/inet.h>
18 #include <arpa/nameser.h>
19 /* #include <net/route.h> realy broken */
20 #include <ctype.h>
21 #include <errno.h>
22 #include <netdb.h>
23 #include <resolv.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdio.h>
27 #include <unistd.h>
28 #include "version.h"
29 #include "net-support.h"
30 #include "pathnames.h"
31 #include "intl.h"
32 #include "net-features.h"
33 #include "proc.h"
34 extern struct aftype inet_aftype;
36 extern char *INET_sprintmask(struct sockaddr *sap, int numeric,
37 unsigned int netmask);
39 int rprint_fib(int ext, int numeric)
41 char buff[1024], iface[16], flags[64];
42 char gate_addr[128], net_addr[128];
43 char mask_addr[128];
44 int num, iflags, metric, refcnt, use, mss, window, irtt;
45 FILE *fp = fopen(_PATH_PROCNET_ROUTE, "r");
46 char *fmt;
48 if (!fp) {
49 perror(_PATH_PROCNET_ROUTE);
50 printf(_("INET (IPv4) not configured in this system.\n"));
51 return 1;
53 printf(_("Kernel IP routing table\n"));
55 if (ext == 1)
56 printf(_("Destination Gateway Genmask "
57 "Flags Metric Ref Use Iface\n"));
58 if (ext == 2)
59 printf(_("Destination Gateway Genmask "
60 "Flags MSS Window irtt Iface\n"));
61 if (ext >= 3)
62 printf(_("Destination Gateway Genmask "
63 "Flags Metric Ref Use Iface "
64 "MSS Window irtt\n"));
66 irtt = 0;
67 window = 0;
68 mss = 0;
70 fmt = proc_gen_fmt(_PATH_PROCNET_ROUTE, 0, fp,
71 "Iface", "%16s",
72 "Destination", "%128s",
73 "Gateway", "%128s",
74 "Flags", "%X",
75 "RefCnt", "%d",
76 "Use", "%d",
77 "Metric", "%d",
78 "Mask", "%128s",
79 "MTU", "%d",
80 "Window", "%d",
81 "IRTT", "%d",
82 NULL);
83 /* "%16s %128s %128s %X %d %d %d %128s %d %d %d\n" */
85 if (!fmt)
86 return 1;
88 while (fgets(buff, 1023, fp)) {
89 struct sockaddr snet_target, snet_gateway, snet_mask;
90 struct sockaddr_in *sin_netmask;
92 num = sscanf(buff, fmt,
93 iface, net_addr, gate_addr,
94 &iflags, &refcnt, &use, &metric, mask_addr,
95 &mss, &window, &irtt);
96 if (num < 10 || !(iflags & RTF_UP))
97 continue;
99 /* Fetch and resolve the target address. */
100 (void) inet_aftype.input(1, net_addr, &snet_target);
102 /* Fetch and resolve the gateway address. */
103 (void) inet_aftype.input(1, gate_addr, &snet_gateway);
105 /* Fetch and resolve the genmask. */
106 (void) inet_aftype.input(1, mask_addr, &snet_mask);
108 sin_netmask = (struct sockaddr_in *)&snet_mask;
109 strcpy(net_addr, INET_sprintmask(&snet_target,
110 (numeric | 0x8000 | (iflags & RTF_HOST? 0x4000: 0)),
111 sin_netmask->sin_addr.s_addr));
112 net_addr[15] = '\0';
114 strcpy(gate_addr, inet_aftype.sprint(&snet_gateway, numeric | 0x4000));
115 gate_addr[15] = '\0';
117 strcpy(mask_addr, inet_aftype.sprint(&snet_mask, 1));
118 mask_addr[15] = '\0';
120 /* Decode the flags. */
121 flags[0] = '\0';
122 if (iflags & RTF_UP)
123 strcat(flags, "U");
124 if (iflags & RTF_GATEWAY)
125 strcat(flags, "G");
126 #if HAVE_RTF_REJECT
127 if (iflags & RTF_REJECT)
128 strcpy(flags, "!");
129 #endif
130 if (iflags & RTF_HOST)
131 strcat(flags, "H");
132 if (iflags & RTF_REINSTATE)
133 strcat(flags, "R");
134 if (iflags & RTF_DYNAMIC)
135 strcat(flags, "D");
136 if (iflags & RTF_MODIFIED)
137 strcat(flags, "M");
138 if (iflags & RTF_DEFAULT)
139 strcat(flags, "d");
140 if (iflags & RTF_ALLONLINK)
141 strcat(flags, "a");
142 if (iflags & RTF_ADDRCONF)
143 strcat(flags, "c");
144 if (iflags & RTF_NONEXTHOP)
145 strcat(flags, "o");
146 if (iflags & RTF_EXPIRES)
147 strcat(flags, "e");
148 if (iflags & RTF_CACHE)
149 strcat(flags, "c");
150 if (iflags & RTF_FLOW)
151 strcat(flags, "f");
152 if (iflags & RTF_POLICY)
153 strcat(flags, "p");
154 if (iflags & RTF_LOCAL)
155 strcat(flags, "l");
156 if (iflags & RTF_MTU)
157 strcat(flags, "u");
158 if (iflags & RTF_WINDOW)
159 strcat(flags, "w");
160 if (iflags & RTF_IRTT)
161 strcat(flags, "i");
162 if (iflags & RTF_NOTCACHED) /* 2.0.36 */
163 strcat(flags, "n");
165 /* Print the info. */
166 if (ext == 1) {
167 #if HAVE_RTF_REJECT
168 if (iflags & RTF_REJECT)
169 printf("%-15s - %-15s %-5s %-6d - %7d -\n",
170 net_addr, mask_addr, flags, metric, use);
171 else
172 #endif
173 printf("%-15s %-15s %-15s %-5s %-6d %-2d %7d %s\n",
174 net_addr, gate_addr, mask_addr, flags,
175 metric, refcnt, use, iface);
177 if (ext == 2) {
178 #if HAVE_RTF_REJECT
179 if (iflags & RTF_REJECT)
180 printf("%-15s - %-15s %-5s - - - -\n",
181 net_addr, mask_addr, flags);
182 else
183 #endif
184 printf("%-15s %-15s %-15s %-5s %5d %-5d %6d %s\n",
185 net_addr, gate_addr, mask_addr, flags,
186 mss, window, irtt, iface);
188 if (ext >= 3) {
189 #if HAVE_RTF_REJECT
190 if (iflags & RTF_REJECT)
191 printf("%-15s - %-15s %-5s %-6d - %7d - - - -\n",
192 net_addr, mask_addr, flags, metric, use);
193 else
194 #endif
195 printf("%-15s %-15s %-15s %-5s %-6d %-3d %6d %-6.6s %-5d %-6d %d\n",
196 net_addr, gate_addr, mask_addr, flags,
197 metric, refcnt, use, iface, mss, window, irtt);
201 free(fmt);
202 (void) fclose(fp);
203 return (0);
206 int rprint_cache(int ext, int numeric)
208 char buff[1024], iface[16], flags[64];
209 char gate_addr[128], dest_addr[128], specdst[128];
210 char src_addr[128];
211 struct sockaddr snet;
212 unsigned int iflags;
213 int num, format, metric, refcnt, use, mss, window, irtt, hh, hhref, hhuptod, arp, tos;
214 char *fmt = NULL;
216 FILE *fp = fopen(_PATH_PROCNET_RTCACHE, "r");
218 if (!fp) {
219 perror(_PATH_PROCNET_RTCACHE);
220 printf(_("INET (IPv4) not configured in this system.\n"));
221 return 1;
224 /* Okay, first thing we need to know is the format of the rt_cache.
225 * I am aware of two possible layouts:
226 * 2.2.0
227 * "Iface\tDestination\tGateway \tFlags\t\tRefCnt\tUse\tMetric\tSource\t\tMTU\tWindow\tIRTT\tTOS\tHHRef\tHHUptod\tSpecDst"
228 * "%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"
230 * 2.0.36
231 * "Iface\tDestination\tGateway \tFlags\tRefCnt\tUse\tMetric\tSource\t\tMTU\tWindow\tIRTT\tHH\tARP"
232 * "%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"
235 format = proc_guess_fmt(_PATH_PROCNET_RTCACHE, fp, "IRTT",1,"TOS",2,"HHRef",4,"HHUptod",8,"SpecDst",16,"HH",32,"ARP",64,NULL);
237 printf(_("Kernel IP routing cache\n"));
239 switch(format) {
240 case -1: /* I/O Error */
241 perror(_PATH_PROCNET_RTCACHE);
242 exit(-1);
243 break;
244 case 63: /* 2.2.0 Format */
245 format = 2;
246 break;
247 case 97: /* 2.0.36 Format */
248 format = 1;
249 break;
250 default:
251 printf("ERROR: proc_guess_fmt(%s,... returned: %d\n",_PATH_PROCNET_RTCACHE, format);
252 break;
255 rewind(fp);
257 if (ext == 1)
258 printf(_("Source Destination Gateway "
259 "Flags Metric Ref Use Iface\n"));
260 if (ext == 2)
261 printf(_("Source Destination Gateway "
262 "Flags MSS Window irtt Iface\n"));
264 if (format == 1) {
265 if (ext >= 3)
266 printf(_("Source Destination Gateway "
267 "Flags Metric Ref Use Iface "
268 "MSS Window irtt HH Arp\n"));
270 fmt = proc_gen_fmt(_PATH_PROCNET_RTCACHE, 0, fp,
271 "Iface", "%16s",
272 "Destination", "%128s",
273 "Gateway", "%128s",
274 "Flags", "%X",
275 "RefCnt", "%d",
276 "Use", "%d",
277 "Metric", "%d",
278 "Source", "%128s",
279 "MTU", "%d",
280 "Window", "%d",
281 "IRTT", "%d",
282 "HH", "%d",
283 "ARP", "%d",
284 NULL);
285 /* "%16s %128s %128s %X %d %d %d %128s %d %d %d %d %d\n" */
288 if (format == 2) {
289 if (ext >= 3)
290 printf(_("Source Destination Gateway "
291 "Flags Metric Ref Use Iface "
292 "MSS Window irtt TOS HHRef HHUptod SpecDst\n"));
293 fmt = proc_gen_fmt(_PATH_PROCNET_RTCACHE, 0, fp,
294 "Iface", "%16s",
295 "Destination", "%128s",
296 "Gateway", "%128s",
297 "Flags", "%X",
298 "RefCnt", "%d",
299 "Use", "%d",
300 "Metric", "%d",
301 "Source", "%128s",
302 "MTU", "%d",
303 "Window", "%d",
304 "IRTT", "%d",
305 "TOS", "%d",
306 "HHRef", "%d",
307 "HHUptod", "%d",
308 "SpecDst", "%128s",
309 NULL);
310 /* "%16s %128s %128s %X %d %d %d %128s %d %d %d %d %d %128s\n" */
314 irtt = 0;
315 window = 0;
316 mss = 0;
317 hh = 0; hhref = 0; hhuptod = 0;
318 arp = 0; tos = 0;
319 while (fgets(buff, 1023, fp)) {
320 if (format == 1) {
321 num = sscanf(buff, fmt,
322 iface, dest_addr, gate_addr,
323 &iflags, &refcnt, &use, &metric, src_addr,
324 &mss, &window, &irtt, &hh, &arp);
325 if (num < 12)
326 continue;
328 if (format == 2) {
329 num = sscanf(buff, fmt,
330 iface, dest_addr, gate_addr,
331 &iflags, &refcnt, &use, &metric, src_addr,
332 &mss, &window, &irtt, &tos, &hhref, &hhuptod, &specdst);
333 if (num < 12)
334 continue;
338 /* Fetch and resolve the target address. */
339 (void) inet_aftype.input(1, dest_addr, &snet);
340 strcpy(dest_addr, inet_aftype.sprint(&snet, numeric));
341 dest_addr[15] = '\0';
343 /* Fetch and resolve the gateway address. */
344 (void) inet_aftype.input(1, gate_addr, &snet);
345 strcpy(gate_addr, inet_aftype.sprint(&snet, numeric));
346 gate_addr[15] = '\0';
348 /* Fetch and resolve the source. */
349 (void) inet_aftype.input(1, src_addr, &snet);
350 strcpy(src_addr, inet_aftype.sprint(&snet, numeric));
351 src_addr[15] = '\0';
353 /* Fetch and resolve the SpecDst addrerss. */
354 (void) inet_aftype.input(1, specdst, &snet);
355 strcpy(specdst, inet_aftype.sprint(&snet, numeric));
356 specdst[15] = '\0';
358 /* Decode the flags. */
359 flags[0] = '\0';
360 if (format == 1) {
361 if (iflags & RTF_UP)
362 strcat(flags, "U");
363 if (iflags & RTF_HOST)
364 strcat(flags, "H");
366 if (iflags & RTF_GATEWAY)
367 strcat(flags, "G");
368 #if HAVE_RTF_REJECT
369 if (iflags & RTF_REJECT)
370 strcpy(flags, "!");
371 #endif
372 if (iflags & RTF_REINSTATE)
373 strcat(flags, "R");
374 if (iflags & RTF_DYNAMIC)
375 strcat(flags, "D");
376 if (iflags & RTF_MODIFIED)
377 strcat(flags, "M");
379 /* possible collision with 2.0 flags U and H */
380 if (format == 2) {
381 if (iflags & RTCF_DEAD)
382 strcat(flags, "-");
383 if (iflags & RTCF_ONLINK)
384 strcat(flags, "o");
386 if (iflags & RTCF_NOTIFY)
387 strcat(flags, "n");
388 if (iflags & RTCF_DIRECTDST)
389 strcat(flags, "d");
390 if (iflags & RTCF_TPROXY)
391 strcat(flags, "t");
392 if (iflags & RTCF_FAST)
393 strcat(flags, "f");
394 if (iflags & RTCF_MASQ)
395 strcat(flags, "q");
396 if (iflags & RTCF_SNAT)
397 strcat(flags, "Ns");
398 if (iflags & RTCF_DOREDIRECT)
399 strcat(flags, "r");
400 if (iflags & RTCF_DIRECTSRC)
401 strcat(flags, "i");
402 if (iflags & RTCF_DNAT)
403 strcat(flags, "Nd");
404 if (iflags & RTCF_BROADCAST)
405 strcat(flags, "b");
406 if (iflags & RTCF_MULTICAST)
407 strcat(flags, "m");
408 if (iflags & RTCF_REJECT)
409 strcat(flags, "#");
410 if (iflags & RTCF_LOCAL)
411 strcat(flags, "l");
412 /* Print the info. */
413 if (ext == 1) {
414 printf("%-15s %-15s %-15s %-5s %-6d %-2d %7d %s\n",
415 src_addr, dest_addr, gate_addr, flags,
416 metric, refcnt, use, iface);
418 if (ext == 2) {
419 printf("%-15s %-15s %-15s %-5s %5d %-5d %6d %s\n",
420 src_addr, dest_addr, gate_addr, flags,
421 mss, window, irtt, iface);
423 if (format == 1) {
424 if (ext >= 3) {
425 printf("%-15s %-15s %-15s %-5s %-6d %-3d %6d %-6.6s %-5d %-6d %-5d %-3d %d\n",
426 src_addr, dest_addr, gate_addr, flags,
427 metric, refcnt, use, iface, mss, window, irtt, hh, arp);
430 if (format == 2) {
431 if (ext >= 3) {
432 printf("%-15s %-15s %-15s %-5s %-6d %-3d %6d %-6.6s %-5d %-6d %-5d %-3d %-3d %-3d %15s\n",
433 src_addr, dest_addr, gate_addr, flags,
434 metric, refcnt, use, iface, mss, window, irtt, tos, hhref, hhuptod, specdst);
439 free(fmt);
440 (void) fclose(fp);
441 return (0);
444 int INET_rprint(int options)
446 int ext = options & FLAG_EXT;
447 int numeric = options & (FLAG_NUM_HOST | FLAG_SYM);
448 int rc = E_INTERN;
450 if (options & FLAG_FIB)
451 if ((rc = rprint_fib(ext, numeric)))
452 return (rc);
453 if (options & FLAG_CACHE)
454 rc = rprint_cache(ext, numeric);
456 return (rc);
459 #endif /* HAVE_AFINET */