route.8: Remove NS remains.
[dragonfly.git] / usr.sbin / IPXrouted / trace.c
1 /*
2  * Copyright (c) 1985, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Copyright (c) 1995 John Hay.  All rights reserved.
6  *
7  * This file includes significant work done at Cornell University by
8  * Bill Nesheim.  That work included by permission.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  * $FreeBSD: src/usr.sbin/IPXrouted/trace.c,v 1.6.2.1 2000/07/20 10:35:22 kris Exp $
35  * $DragonFly: src/usr.sbin/IPXrouted/trace.c,v 1.6 2006/01/22 03:43:38 swildner Exp $
36  *
37  * @(#)trace.c  8.1 (Berkeley) 6/5/93
38  */
39
40 /*
41  * Routing Table Management Daemon
42  */
43 #define RIPCMDS
44 #define SAPCMDS
45 #include <stdlib.h>
46 #include <unistd.h>
47 #include <sys/types.h>
48 #include <time.h>
49 #include "defs.h"
50
51 #define NRECORDS        50              /* size of circular trace buffer */
52 #ifdef DEBUG
53 FILE    *ftrace = stdout;
54 int     tracing = 1;
55 #else /* DEBUG */
56 FILE    *ftrace = NULL;
57 int     tracing = 0;
58 #endif
59
60 void dumpif(FILE *fd, struct interface *ifp);
61 void dumptrace(FILE *fd, char *dir, struct ifdebug *ifd);
62
63 static int iftraceinit(struct interface *, struct ifdebug *);
64
65 void
66 traceinit(struct interface *ifp)
67 {
68         if (iftraceinit(ifp, &ifp->int_input) &&
69             iftraceinit(ifp, &ifp->int_output))
70                 return;
71         tracing = 0;
72         syslog(LOG_ERR, "traceinit: can't init %s\n", ifp->int_name);
73 }
74
75 static int
76 iftraceinit(struct interface *ifp, struct ifdebug *ifd)
77 {
78         struct iftrace *t;
79
80         ifd->ifd_records =
81           (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace));
82         if (ifd->ifd_records == 0)
83                 return (0);
84         ifd->ifd_front = ifd->ifd_records;
85         ifd->ifd_count = 0;
86         for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) {
87                 t->ift_size = 0;
88                 t->ift_packet = 0;
89         }
90         ifd->ifd_if = ifp;
91         return (1);
92 }
93
94 void
95 traceon(char *file)
96 {
97
98         if (ftrace != NULL)
99                 return;
100         ftrace = fopen(file, "a");
101         if (ftrace == NULL)
102                 return;
103         dup2(fileno(ftrace), 1);
104         dup2(fileno(ftrace), 2);
105         tracing = 1;
106 }
107
108 void
109 traceoff(void)
110 {
111         if (!tracing)
112                 return;
113         if (ftrace != NULL)
114                 fclose(ftrace);
115         ftrace = NULL;
116         tracing = 0;
117 }
118
119 void
120 trace(struct ifdebug *ifd, struct sockaddr *who, char *p, int len, int m)
121 {
122         struct iftrace *t;
123
124         if (ifd->ifd_records == 0)
125                 return;
126         t = ifd->ifd_front++;
127         if (ifd->ifd_front >= ifd->ifd_records + NRECORDS)
128                 ifd->ifd_front = ifd->ifd_records;
129         if (ifd->ifd_count < NRECORDS)
130                 ifd->ifd_count++;
131         if (t->ift_size > 0 && t->ift_packet)
132                 free(t->ift_packet);
133         t->ift_packet = 0;
134         t->ift_stamp = time(0);
135         t->ift_who = *who;
136         if (len > 0) {
137                 t->ift_packet = malloc(len);
138                 if (t->ift_packet)
139                         bcopy(p, t->ift_packet, len);
140                 else
141                         len = 0;
142         }
143         t->ift_size = len;
144         t->ift_metric = m;
145 }
146
147 void
148 traceaction(FILE *fd, char *action, struct rt_entry *rt)
149 {
150         struct sockaddr_ipx *dst, *gate;
151         static struct bits {
152                 int     t_bits;
153                 char    *t_name;
154         } flagbits[] = {
155                 { RTF_UP,       "UP" },
156                 { RTF_GATEWAY,  "GATEWAY" },
157                 { RTF_HOST,     "HOST" },
158                 { 0 }
159         }, statebits[] = {
160                 { RTS_PASSIVE,  "PASSIVE" },
161                 { RTS_REMOTE,   "REMOTE" },
162                 { RTS_INTERFACE,"INTERFACE" },
163                 { RTS_CHANGED,  "CHANGED" },
164                 { 0 }
165         };
166         struct bits *p;
167         int first;
168         char *cp;
169
170         if (fd == NULL)
171                 return;
172         fprintf(fd, "%s ", action);
173         dst = (struct sockaddr_ipx *)&rt->rt_dst;
174         gate = (struct sockaddr_ipx *)&rt->rt_router;
175         fprintf(fd, "dst %s, ", ipxdp_ntoa(&dst->sipx_addr));
176         fprintf(fd, "router %s, metric %d, ticks %d, flags",
177              ipxdp_ntoa(&gate->sipx_addr), rt->rt_metric, rt->rt_ticks);
178         cp = " %s";
179         for (first = 1, p = flagbits; p->t_bits > 0; p++) {
180                 if ((rt->rt_flags & p->t_bits) == 0)
181                         continue;
182                 fprintf(fd, cp, p->t_name);
183                 if (first) {
184                         cp = "|%s";
185                         first = 0;
186                 }
187         }
188         fprintf(fd, " state");
189         cp = " %s";
190         for (first = 1, p = statebits; p->t_bits > 0; p++) {
191                 if ((rt->rt_state & p->t_bits) == 0)
192                         continue;
193                 fprintf(fd, cp, p->t_name);
194                 if (first) {
195                         cp = "|%s";
196                         first = 0;
197                 }
198         }
199         putc('\n', fd);
200         if (!tracepackets && (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp)
201                 dumpif(fd, rt->rt_ifp);
202         fflush(fd);
203 }
204
205 void
206 traceactionlog(char *action, struct rt_entry *rt)
207 {
208         struct sockaddr_ipx *dst, *gate;
209         static struct bits {
210                 int     t_bits;
211                 char    *t_name;
212         } flagbits[] = {
213                 { RTF_UP,       "UP" },
214                 { RTF_GATEWAY,  "GATEWAY" },
215                 { RTF_HOST,     "HOST" },
216                 { 0 }
217         }, statebits[] = {
218                 { RTS_PASSIVE,  "PASSIVE" },
219                 { RTS_REMOTE,   "REMOTE" },
220                 { RTS_INTERFACE,"INTERFACE" },
221                 { RTS_CHANGED,  "CHANGED" },
222                 { 0 }
223         };
224         struct bits *p;
225         int first;
226         char *cp;
227         char *lstr, *olstr;
228
229         dst = (struct sockaddr_ipx *)&rt->rt_dst;
230         gate = (struct sockaddr_ipx *)&rt->rt_router;
231         asprintf(&lstr, "%s dst %s,", action, ipxdp_ntoa(&dst->sipx_addr));
232         olstr = lstr;
233         asprintf(&lstr, "%s router %s, metric %d, ticks %d, flags",
234              olstr, ipxdp_ntoa(&gate->sipx_addr), rt->rt_metric, rt->rt_ticks);
235         free(olstr);
236         olstr = lstr;
237         cp = "%s %s";
238         for (first = 1, p = flagbits; p->t_bits > 0; p++) {
239                 if ((rt->rt_flags & p->t_bits) == 0)
240                         continue;
241                 asprintf(&lstr, cp, olstr, p->t_name);
242                 free(olstr);
243                 olstr = lstr;
244                 if (first) {
245                         cp = "%s|%s";
246                         first = 0;
247                 }
248         }
249         asprintf(&lstr, "%s state", olstr);
250         free(olstr);
251         olstr = lstr;
252         cp = "%s %s";
253         for (first = 1, p = statebits; p->t_bits > 0; p++) {
254                 if ((rt->rt_state & p->t_bits) == 0)
255                         continue;
256                 asprintf(&lstr, cp, olstr, p->t_name);
257                 free(olstr);
258                 olstr = lstr;
259                 if (first) {
260                         cp = "%s|%s";
261                         first = 0;
262                 }
263         }
264         syslog(LOG_DEBUG, "%s", lstr);
265         free(lstr);
266 }
267
268 void
269 tracesapactionlog(char *action, struct sap_entry *sap)
270 {
271         syslog(LOG_DEBUG, "%-12.12s  service %04X %-20.20s "
272                     "addr %s.%04X %c metric %d\n",
273                      action,
274                      ntohs(sap->sap.ServType),
275                      sap->sap.ServName,
276                      ipxdp_ntoa(&sap->sap.ipx),
277                      ntohs(sap->sap.ipx.x_port),
278                      (sap->clone ? 'C' : ' '),
279                      ntohs(sap->sap.hops));
280 }
281
282 void
283 dumpif(FILE *fd, struct interface *ifp)
284 {
285         if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) {
286                 fprintf(fd, "*** Packet history for interface %s ***\n",
287                         ifp->int_name);
288                 dumptrace(fd, "to", &ifp->int_output);
289                 dumptrace(fd, "from", &ifp->int_input);
290                 fprintf(fd, "*** end packet history ***\n");
291         }
292 }
293
294 void
295 dumptrace(FILE *fd, char *dir, struct ifdebug *ifd)
296 {
297         struct iftrace *t;
298         char *cp;
299
300         cp = !strcmp(dir, "to") ? "Output" : "Input";
301         if (ifd->ifd_front == ifd->ifd_records &&
302             ifd->ifd_front->ift_size == 0) {
303                 fprintf(fd, "%s: no packets.\n", cp);
304                 return;
305         }
306         fprintf(fd, "%s trace:\n", cp);
307         t = ifd->ifd_front - ifd->ifd_count;
308         if (t < ifd->ifd_records)
309                 t += NRECORDS;
310         for ( ; ifd->ifd_count; ifd->ifd_count--, t++) {
311                 if (t >= ifd->ifd_records + NRECORDS)
312                         t = ifd->ifd_records;
313                 if (t->ift_size == 0)
314                         continue;
315                 fprintf(fd, "%.24s: metric=%d\n", ctime(&t->ift_stamp),
316                         t->ift_metric);
317                 dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size);
318         }
319 }
320
321 void
322 dumppacket(FILE *fd, char *dir, struct sockaddr *source, char *cp, int size)
323 {
324         struct rip *msg = (struct rip *)cp;
325         struct netinfo *n;
326         struct sockaddr_ipx *who = (struct sockaddr_ipx *)source;
327
328         if (msg->rip_cmd && ntohs(msg->rip_cmd) < RIPCMD_MAX)
329                 fprintf(fd, "%s %s %s#%x", ripcmds[ntohs(msg->rip_cmd)],
330                     dir, ipxdp_ntoa(&who->sipx_addr), 
331                     ntohs(who->sipx_addr.x_port));
332         else {
333                 fprintf(fd, "Bad cmd 0x%x %s %s#%x\n", ntohs(msg->rip_cmd),
334                     dir, ipxdp_ntoa(&who->sipx_addr), 
335                     ntohs(who->sipx_addr.x_port));
336                 fprintf(fd, "size=%d cp=%p packet=%p\n", size, cp, packet);
337                 return;
338         }
339         switch (ntohs(msg->rip_cmd)) {
340
341         case RIPCMD_REQUEST:
342         case RIPCMD_RESPONSE:
343                 fprintf(fd, ":\n");
344                 size -= sizeof (u_short);
345                 n = msg->rip_nets;
346                 for (; size > 0; n++, size -= sizeof (struct netinfo)) {
347                         if (size < sizeof (struct netinfo))
348                                 break;
349                         fprintf(fd, "\tnet %s metric %d ticks %d\n",
350                              ipxdp_nettoa(n->rip_dst),
351                              ntohs(n->rip_metric),
352                              ntohs(n->rip_ticks));
353                 }
354                 break;
355
356         }
357 }
358
359 void
360 dumpsappacket(FILE *fd, char *dir, struct sockaddr *source, char *cp, int size)
361 {
362         struct sap_packet *msg = (struct sap_packet *)cp;
363         struct sap_info *n;
364         struct sockaddr_ipx *who = (struct sockaddr_ipx *)source;
365
366         if (msg->sap_cmd && ntohs(msg->sap_cmd) < SAPCMD_MAX)
367                 fprintf(fd, "%s %s %s#%x", sapcmds[ntohs(msg->sap_cmd)],
368                     dir, ipxdp_ntoa(&who->sipx_addr), 
369                     ntohs(who->sipx_addr.x_port));
370         else {
371                 fprintf(fd, "Bad cmd 0x%x %s %s#%x\n", ntohs(msg->sap_cmd),
372                     dir, ipxdp_ntoa(&who->sipx_addr), 
373                     ntohs(who->sipx_addr.x_port));
374                 fprintf(fd, "size=%d cp=%p packet=%p\n", size, cp, packet);
375                 return;
376         }
377         switch (ntohs(msg->sap_cmd)) {
378
379         case SAP_REQ:
380         case SAP_RESP:
381         case SAP_REQ_NEAR:
382         case SAP_RESP_NEAR:
383                 fprintf(fd, ":\n");
384                 size -= sizeof (u_short);
385                 n = msg->sap;
386                 for (; size > 0; n++, size -= sizeof (struct sap_info)) {
387                         if (size < sizeof (struct sap_info))
388                                 break;
389                         fprintf(fd, "  service %04X %-20.20s "
390                                     "addr %s.%04X metric %d\n",
391                              ntohs(n->ServType),
392                              n->ServName,
393                              ipxdp_ntoa(&n->ipx),
394                              ntohs(n->ipx.x_port),
395                              ntohs(n->hops));
396                 }
397                 break;
398
399         }
400 }
401
402 void
403 dumpsaptable(FILE *fd, struct sap_hash *sh)
404 {
405         struct sap_entry *sap;
406         struct sap_hash *hash;
407         int x = 0;
408
409         fprintf(fd, "------- SAP table dump. -------\n");
410         for (hash = sh; hash < &sh[SAPHASHSIZ]; hash++, x++) {
411                 fprintf(fd, "HASH %d\n", x);
412                 sap = hash->forw;
413                 for (; sap != (struct sap_entry *)hash; sap = sap->forw) {
414                         fprintf(fd, "  service %04X %-20.20s "
415                                     "addr %s.%04X %c metric %d\n",
416                                      ntohs(sap->sap.ServType),
417                                      sap->sap.ServName,
418                                      ipxdp_ntoa(&sap->sap.ipx),
419                                      ntohs(sap->sap.ipx.x_port),
420                                      (sap->clone ? 'C' : ' '),
421                                      ntohs(sap->sap.hops));
422                 }
423         }
424         fprintf(fd, "\n");
425 }
426
427 void
428 dumpriptable(FILE *fd)
429 {
430         struct rt_entry *rip;
431         struct rthash *hash;
432         int x;
433         struct rthash *rh = nethash;
434
435         fprintf(fd, "------- RIP table dump. -------\n");
436         x = 0;
437         fprintf(fd, "Network table.\n");
438
439         for (hash = rh; hash < &rh[ROUTEHASHSIZ]; hash++, x++) {
440                 fprintf(fd, "HASH %d\n", x);
441                 rip = hash->rt_forw;
442                 for (; rip != (struct rt_entry *)hash; rip = rip->rt_forw) {
443                         fprintf(fd, "  dest %s\t", 
444                                 ipxdp_ntoa(&satoipx_addr(rip->rt_dst)));
445                         fprintf(fd, "%s metric %d, ticks %d\n",
446                                 ipxdp_ntoa(&satoipx_addr(rip->rt_router)),
447                                 rip->rt_metric,
448                                 rip->rt_ticks);
449                 }
450         }
451         fprintf(fd, "\n");
452 }
453
454 union ipx_net_u net;
455
456 char *
457 ipxdp_nettoa(union ipx_net val)
458 {
459         static char buf[100];
460         
461         net.net_e = val;
462         sprintf(buf, "%u", ntohl(net.long_e));
463         return (buf);
464 }
465
466
467 char *
468 ipxdp_ntoa(struct ipx_addr *addr)
469 {
470     static char buf[100];
471
472     sprintf(buf, "%s#%x:%x:%x:%x:%x:%x",
473         ipxdp_nettoa(addr->x_net),
474         addr->x_host.c_host[0], addr->x_host.c_host[1], 
475         addr->x_host.c_host[2], addr->x_host.c_host[3], 
476         addr->x_host.c_host[4], addr->x_host.c_host[5]);
477         
478     return(buf);
479 }