enable -fno-strict-aliasing until the code base gets a hefty clean up to fix all...
[platform/upstream/net-tools.git] / lib / inet6_gr.c
1  /*
2    Modifications:
3    1998-07-01 - Arnaldo Carvalho de Melo - GNU gettext instead of catgets,
4    snprintf instead of sprintf
5  */
6
7 #include "config.h"
8
9 #if HAVE_AFINET6
10 #include <asm/types.h>
11 #include <asm/param.h>
12 #include <sys/types.h>
13 #include <sys/socket.h>
14 #include <netinet/in.h>
15 #include <arpa/inet.h>
16 #include <arpa/nameser.h>
17 /* #include <net/route.h> realy broken */
18 #include <ctype.h>
19 #include <errno.h>
20 #include <netdb.h>
21 #include <resolv.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdio.h>
25 #include <unistd.h>
26 #ifndef __GLIBC__
27 #include <netinet6/ipv6_route.h>        /* glibc doesn't have this */
28 #endif
29 #include "version.h"
30 #include "net-support.h"
31 #include "pathnames.h"
32 #include "intl.h"
33 #include "net-features.h"
34
35 /* neighbour discovery from linux-2.4.0/include/net/neighbour.h */
36
37 #define NUD_INCOMPLETE  0x01
38 #define NUD_REACHABLE   0x02
39 #define NUD_STALE       0x04
40 #define NUD_DELAY       0x08
41 #define NUD_PROBE       0x10
42 #define NUD_FAILED      0x20
43
44 #define NUD_NOARP       0x40
45 #define NUD_PERMANENT   0x80
46 #define NUD_NONE        0x00
47
48 #define NTF_PROXY       0x08    /* == ATF_PUBL */
49 #define NTF_ROUTER      0x80
50 #define NTF_02          0x02  /* waiting for answer of Alexey -eckes */
51 #define NTF_04          0x04  /* waiting for answer of Alexey -eckes */
52
53 /* */
54
55
56 extern struct aftype inet6_aftype;
57
58
59 int rprint_fib6(int ext, int numeric)
60 {
61     char buff[4096], iface[16], flags[16];
62     char addr6[128], naddr6[128];
63     struct sockaddr_in6 saddr6, snaddr6;
64     int num, iflags, metric, refcnt, use, prefix_len, slen;
65     FILE *fp = fopen(_PATH_PROCNET_ROUTE6, "r");
66     
67     char addr6p[8][5], saddr6p[8][5], naddr6p[8][5];
68
69     if (!fp) {
70         perror(_PATH_PROCNET_ROUTE6);
71         printf(_("INET6 (IPv6) not configured in this system.\n"));
72         return 1;
73     }
74
75     if (numeric & RTF_CACHE)
76         printf(_("Kernel IPv6 routing cache\n"));
77     else
78         printf(_("Kernel IPv6 routing table\n"));
79
80     printf(_("Destination                    "
81              "Next Hop                   "
82              "Flag Met Ref Use If\n"));
83
84     while (fgets(buff, 1023, fp)) {
85         num = sscanf(buff, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %4s%4s%4s%4s%4s%4s%4s%4s %02x %4s%4s%4s%4s%4s%4s%4s%4s %08x %08x %08x %08x %s\n",
86                      addr6p[0], addr6p[1], addr6p[2], addr6p[3],
87                      addr6p[4], addr6p[5], addr6p[6], addr6p[7],
88                      &prefix_len,
89                      saddr6p[0], saddr6p[1], saddr6p[2], saddr6p[3],
90                      saddr6p[4], saddr6p[5], saddr6p[6], saddr6p[7],
91                      &slen,
92                      naddr6p[0], naddr6p[1], naddr6p[2], naddr6p[3],
93                      naddr6p[4], naddr6p[5], naddr6p[6], naddr6p[7],
94                      &metric, &refcnt, &use, &iflags, iface);
95 #if 0
96         if (num < 23)
97             continue;
98 #endif
99         if (iflags & RTF_CACHE) {
100                 if (!(numeric & RTF_CACHE))
101                         continue;
102         } else {
103                 if (numeric & RTF_CACHE)
104                         continue;
105         }
106                         
107         /* Fetch and resolve the target address. */
108         snprintf(addr6, sizeof(addr6), "%s:%s:%s:%s:%s:%s:%s:%s",
109                  addr6p[0], addr6p[1], addr6p[2], addr6p[3],
110                  addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
111         inet6_aftype.input(1, addr6, (struct sockaddr *) &saddr6);
112         snprintf(addr6, sizeof(addr6), "%s/%d",
113                  inet6_aftype.sprint((struct sockaddr *) &saddr6, 1),
114                  prefix_len);
115
116         /* Fetch and resolve the nexthop address. */
117         snprintf(naddr6, sizeof(naddr6), "%s:%s:%s:%s:%s:%s:%s:%s",
118                  naddr6p[0], naddr6p[1], naddr6p[2], naddr6p[3],
119                  naddr6p[4], naddr6p[5], naddr6p[6], naddr6p[7]);
120         inet6_aftype.input(1, naddr6, (struct sockaddr *) &snaddr6);
121         snprintf(naddr6, sizeof(naddr6), "%s",
122                  inet6_aftype.sprint((struct sockaddr *) &snaddr6, 1));
123
124         /* Decode the flags. */
125
126         flags[0]=0;
127         if (iflags & RTF_UP)
128             strcat(flags, "U");
129         if (iflags & RTF_REJECT)
130             strcat(flags, "!");
131         if (iflags & RTF_GATEWAY)
132             strcat(flags, "G");
133         if (iflags & RTF_HOST)
134             strcat(flags, "H");
135         if (iflags & RTF_DEFAULT)
136             strcat(flags, "D");
137         if (iflags & RTF_ADDRCONF)
138             strcat(flags, "A");
139         if (iflags & RTF_CACHE)
140             strcat(flags, "C");
141         if (iflags & RTF_ALLONLINK)
142             strcat(flags, "a");
143         if (iflags & RTF_EXPIRES)
144             strcat(flags, "e");
145         if (iflags & RTF_MODIFIED)
146             strcat(flags, "m");
147         if (iflags & RTF_NONEXTHOP)
148             strcat(flags, "n");
149         if (iflags & RTF_FLOW)
150             strcat(flags, "f");
151
152         /* Print the info. */
153         printf("%-30s %-26s %-4s %-3d %-1d%6d %s\n",
154                addr6, naddr6, flags, metric, refcnt, use, iface);
155     }
156
157     (void) fclose(fp);
158     return (0);
159 }
160
161 int rprint_cache6(int ext, int numeric)
162 {
163     char buff[4096], iface[16], flags[16];
164     char addr6[128], haddr[20], statestr[20];
165     struct sockaddr_in6 saddr6;
166     int type, num, refcnt, prefix_len, location, state, gc;
167     long tstamp, expire, ndflags, reachable, stale, delete;
168     FILE *fp = fopen(_PATH_PROCNET_NDISC, "r");
169     char addr6p[8][5], haddrp[6][3];
170
171     if (!fp) {
172         return rprint_fib6(ext, numeric | RTF_CACHE);
173     }
174     printf(_("Kernel IPv6 Neighbour Cache\n"));
175
176     if (ext == 2)
177         printf(_("Neighbour                                   "
178                  "HW Address        "
179                  "Iface    Flags Ref State\n"));
180     else
181         printf(_("Neighbour                                   "
182                  "HW Address        "
183         "Iface    Flags Ref State            Stale(sec) Delete(sec)\n"));
184
185
186     while (fgets(buff, 1023, fp)) {
187         num = sscanf(buff, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %08lx %08lx %08lx %04x %04x %04lx %8s %2s%2s%2s%2s%2s%2s\n",
188                      addr6p[0], addr6p[1], addr6p[2], addr6p[3],
189                      addr6p[4], addr6p[5], addr6p[6], addr6p[7],
190                      &location, &prefix_len, &type, &state, &expire, &tstamp, &reachable, &gc, &refcnt,
191                      &ndflags, iface,
192         haddrp[0], haddrp[1], haddrp[2], haddrp[3], haddrp[4], haddrp[5]);
193
194         /* Fetch and resolve the nexthop address. */
195         snprintf(addr6, sizeof(addr6), "%s:%s:%s:%s:%s:%s:%s:%s",
196                  addr6p[0], addr6p[1], addr6p[2], addr6p[3],
197                  addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
198         inet6_aftype.input(1, addr6, (struct sockaddr *) &saddr6);
199         snprintf(addr6, sizeof(addr6), "%s/%d",
200                inet6_aftype.sprint((struct sockaddr *) &saddr6, numeric),
201                  prefix_len);
202
203         /* Fetch the  hardware address. */
204         snprintf(haddr, sizeof(haddr), "%s:%s:%s:%s:%s:%s",
205         haddrp[0], haddrp[1], haddrp[2], haddrp[3], haddrp[4], haddrp[5]);
206
207         /* Decode the flags. */
208         flags[0] = '\0';
209         if (ndflags & NTF_ROUTER)
210             strcat(flags, "R");
211         if (ndflags & NTF_04)
212             strcat(flags, "x");
213         if (ndflags & NTF_02)
214             strcat(flags, "h");
215         if (ndflags & NTF_PROXY)
216             strcat(flags, "P");
217
218         /* Decode the state */
219         switch (state) {
220         case NUD_NONE:
221             strcpy(statestr, "NONE");
222             break;
223         case NUD_INCOMPLETE:
224             strcpy(statestr, "INCOMPLETE");
225             break;
226         case NUD_REACHABLE:
227             strcpy(statestr, "REACHABLE");
228             break;
229         case NUD_STALE:
230             strcpy(statestr, "STALE");
231             break;
232         case NUD_DELAY:
233             strcpy(statestr, "DELAY");
234             break;
235         case NUD_PROBE:
236             strcpy(statestr, "PROBE");
237             break;
238         case NUD_FAILED:
239             strcpy(statestr, "FAILED");
240             break;
241         case NUD_NOARP:
242             strcpy(statestr, "NOARP");
243             break;
244         case NUD_PERMANENT:
245             strcpy(statestr, "PERM");
246             break;
247         default:
248             snprintf(statestr, sizeof(statestr), "UNKNOWN(%02x)", state);
249             break;
250         }
251
252         /* Print the info. */
253         printf("%-43s %-17s %-8s %-5s %-3d %-16s",
254                addr6, haddr, iface, flags, refcnt, statestr);
255
256         stale = 0;
257         if (state == NUD_REACHABLE)
258             stale = reachable > tstamp ? reachable - tstamp : 0;
259         delete = gc > tstamp ? gc - tstamp : 0;
260         if (ext != 2) {
261             printf(" %-9ld ", stale / HZ);
262             if (refcnt)
263                 printf(" * ");
264             else
265                 printf(" %-7ld ", delete / HZ);
266         }
267         printf("\n");
268     }
269
270     (void) fclose(fp);
271     return (0);
272 }
273
274 int INET6_rprint(int options)
275 {
276     int ext = options & FLAG_EXT;
277     int numeric = options & (FLAG_NUM_HOST | FLAG_SYM);
278     int rc = E_INTERN;
279
280     if (options & FLAG_FIB)
281         if ((rc = rprint_fib6(ext, numeric)))
282             return (rc);
283
284     if (options & FLAG_CACHE)
285         if ((rc = rprint_cache6(ext, numeric)))
286             return (rc);
287     return (rc);
288 }
289
290 #endif                          /* HAVE_AFINET6 */