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