1/*
2 * Copyright (c) 2009-2011 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29/*	$KAME: dump.c,v 1.32 2003/05/19 09:46:50 keiichi Exp $	*/
30
31/*
32 * Copyright (C) 2000 WIDE Project.
33 * All rights reserved.
34 *
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
37 * are met:
38 * 1. Redistributions of source code must retain the above copyright
39 *    notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 *    notice, this list of conditions and the following disclaimer in the
42 *    documentation and/or other materials provided with the distribution.
43 * 3. Neither the name of the project nor the names of its contributors
44 *    may be used to endorse or promote products derived from this software
45 *    without specific prior written permission.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 * SUCH DAMAGE.
58 */
59#include <sys/types.h>
60#include <sys/socket.h>
61#include <sys/queue.h>
62
63#include <net/if.h>
64#include <net/if_var.h>
65#include <net/if_dl.h>
66
67#include <netinet/in.h>
68
69/* XXX: the following two are non-standard include files */
70#include <netinet6/in6_var.h>
71#include <netinet6/nd6.h>
72
73#include <arpa/inet.h>
74
75#include <time.h>
76#include <stdio.h>
77#include <stdarg.h>
78#include <syslog.h>
79#include <string.h>
80#include <errno.h>
81
82#include "rtadvd.h"
83#include "timer.h"
84#include "if.h"
85#include "dump.h"
86
87static FILE *fp;
88
89extern struct rainfo *ralist;
90
91static char *ether_str(struct sockaddr_dl *);
92static void if_dump(void);
93
94static char *rtpref_str[] = {
95	"medium",		/* 00 */
96	"high",			/* 01 */
97	"rsv",			/* 10 */
98	"low"			/* 11 */
99};
100
101static char *
102ether_str(sdl)
103	struct sockaddr_dl *sdl;
104{
105	static char hbuf[32];
106	u_char *cp;
107
108	if (sdl->sdl_alen && sdl->sdl_alen > 5) {
109		cp = (u_char *)LLADDR(sdl);
110		snprintf(hbuf, sizeof(hbuf), "%x:%x:%x:%x:%x:%x",
111			cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
112	} else
113		snprintf(hbuf, sizeof(hbuf), "NONE");
114
115	return(hbuf);
116}
117
118static void
119if_dump()
120{
121	struct rainfo *rai;
122	struct prefix *pfx;
123#ifdef ROUTEINFO
124	struct rtinfo *rti;
125#endif
126	char prefixbuf[INET6_ADDRSTRLEN];
127	int first;
128	struct timeval now;
129
130	gettimeofday(&now, NULL); /* XXX: unused in most cases */
131	for (rai = ralist; rai; rai = rai->next) {
132		fprintf(fp, "%s:\n", rai->ifname);
133
134		fprintf(fp, "  Status: %s\n",
135			(iflist[rai->ifindex]->ifm_flags & IFF_UP) ? "UP" :
136			"DOWN");
137
138		/* control information */
139		if (rai->lastsent.tv_sec) {
140			/* note that ctime() appends CR by itself */
141			fprintf(fp, "  Last RA sent: %s",
142			    ctime((time_t *)&rai->lastsent.tv_sec));
143		}
144		if (rai->timer) {
145			fprintf(fp, "  Next RA will be sent: %s",
146			    ctime((time_t *)&rai->timer->tm.tv_sec));
147		}
148		else
149			fprintf(fp, "  RA timer is stopped");
150		fprintf(fp, "  waits: %d, initcount: %d\n",
151			rai->waiting, rai->initcounter);
152
153		/* statistics */
154		fprintf(fp, "  statistics: RA(out/in/inconsistent): "
155		    "%llu/%llu/%llu, ",
156		    (unsigned long long)rai->raoutput,
157		    (unsigned long long)rai->rainput,
158		    (unsigned long long)rai->rainconsistent);
159		fprintf(fp, "RS(input): %llu\n",
160		    (unsigned long long)rai->rsinput);
161
162		/* interface information */
163		if (rai->advlinkopt)
164			fprintf(fp, "  Link-layer address: %s\n",
165			    ether_str(rai->sdl));
166		fprintf(fp, "  MTU: %d\n", rai->phymtu);
167
168		/* Router configuration variables */
169		fprintf(fp, "  DefaultLifetime: %d, MaxAdvInterval: %d, "
170		    "MinAdvInterval: %d\n", rai->lifetime, rai->maxinterval,
171		    rai->mininterval);
172		fprintf(fp, "  Flags: %s%s%s, ",
173		    rai->managedflg ? "M" : "", rai->otherflg ? "O" : "", "");
174		fprintf(fp, "Preference: %s, ",
175			rtpref_str[(rai->rtpref >> 3) & 0xff]);
176		fprintf(fp, "MTU: %d\n", rai->linkmtu);
177		fprintf(fp, "  ReachableTime: %d, RetransTimer: %d, "
178			"CurHopLimit: %d\n", rai->reachabletime,
179			rai->retranstimer, rai->hoplimit);
180		if (rai->clockskew)
181			fprintf(fp, "  Clock skew: %ldsec\n",
182			    rai->clockskew);
183		for (first = 1, pfx = rai->prefix.next; pfx != &rai->prefix;
184		     pfx = pfx->next) {
185			if (first) {
186				fprintf(fp, "  Prefixes:\n");
187				first = 0;
188			}
189			fprintf(fp, "    %s/%d(",
190			    inet_ntop(AF_INET6, &pfx->prefix, prefixbuf,
191			    sizeof(prefixbuf)), pfx->prefixlen);
192			switch (pfx->origin) {
193			case PREFIX_FROM_KERNEL:
194				fprintf(fp, "KERNEL, ");
195				break;
196			case PREFIX_FROM_CONFIG:
197				fprintf(fp, "CONFIG, ");
198				break;
199			case PREFIX_FROM_DYNAMIC:
200				fprintf(fp, "DYNAMIC, ");
201				break;
202			}
203			if (pfx->validlifetime == ND6_INFINITE_LIFETIME)
204				fprintf(fp, "vltime: infinity");
205			else
206				fprintf(fp, "vltime: %ld",
207					(long)pfx->validlifetime);
208			if (pfx->vltimeexpire != 0)
209				fprintf(fp, "(decr,expire %ld), ", (long)
210					pfx->vltimeexpire > now.tv_sec ?
211					pfx->vltimeexpire - now.tv_sec : 0);
212			else
213				fprintf(fp, ", ");
214			if (pfx->preflifetime ==  ND6_INFINITE_LIFETIME)
215				fprintf(fp, "pltime: infinity");
216			else
217				fprintf(fp, "pltime: %ld",
218					(long)pfx->preflifetime);
219			if (pfx->pltimeexpire != 0)
220				fprintf(fp, "(decr,expire %ld), ", (long)
221					pfx->pltimeexpire > now.tv_sec ?
222					pfx->pltimeexpire - now.tv_sec : 0);
223			else
224				fprintf(fp, ", ");
225			fprintf(fp, "flags: %s%s%s",
226				pfx->onlinkflg ? "L" : "",
227				pfx->autoconfflg ? "A" : "",
228				"");
229			if (pfx->timer) {
230				struct timeval *rest;
231
232				rest = rtadvd_timer_rest(pfx->timer);
233				if (rest) { /* XXX: what if not? */
234					fprintf(fp, ", expire in: %ld",
235					    (long)rest->tv_sec);
236				}
237			}
238			fprintf(fp, ")\n");
239		}
240#ifdef ROUTEINFO
241		for (first = 1, rti = rai->route.next; rti != &rai->route;
242		     rti = rti->next) {
243			if (first) {
244				fprintf(fp, "  Route Information:\n");
245				first = 0;
246			}
247			fprintf(fp, "    %s/%d (",
248				inet_ntop(AF_INET6, &rti->prefix,
249					  prefixbuf, sizeof(prefixbuf)),
250				rti->prefixlen);
251			fprintf(fp, "preference: %s, ",
252				rtpref_str[0xff & (rti->rtpref >> 3)]);
253			if (rti->ltime == ND6_INFINITE_LIFETIME)
254				fprintf(fp, "lifetime: infinity");
255			else
256				fprintf(fp, "lifetime: %ld", (long)rti->ltime);
257			fprintf(fp, ")\n");
258		}
259#endif
260	}
261}
262
263void
264rtadvd_dump_file(dumpfile)
265	char *dumpfile;
266{
267	syslog(LOG_DEBUG, "<%s> dump current status to %s", __func__,
268	    dumpfile);
269
270	if ((fp = fopen(dumpfile, "w")) == NULL) {
271		syslog(LOG_WARNING, "<%s> open a dump file(%s)",
272		    __func__, dumpfile);
273		return;
274	}
275
276	if_dump();
277
278	fclose(fp);
279}
280