1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include "defs.h"
30 #include "tables.h"
31 
32 static void	print_opt(struct nd_opt_hdr *opt, int len);
33 
34 void
35 print_route_sol(char *str, struct phyint *pi,
36     struct nd_router_solicit *rs, int len, struct sockaddr_in6 *addr)
37 {
38 	struct nd_opt_hdr *opt;
39 	char abuf[INET6_ADDRSTRLEN];
40 
41 	logmsg(LOG_DEBUG, "%s %s (%d bytes) on %s\n", str,
42 	    inet_ntop(addr->sin6_family, (void *)&addr->sin6_addr,
43 	    abuf, sizeof (abuf)),
44 	    len, pi->pi_name);
45 
46 	len -= sizeof (*rs);
47 	opt = (struct nd_opt_hdr *)&rs[1];
48 	print_opt(opt, len);
49 }
50 
51 void
52 print_route_adv(char *str, struct phyint *pi,
53     struct nd_router_advert *ra, int len, struct sockaddr_in6 *addr)
54 {
55 	struct nd_opt_hdr *opt;
56 	char abuf[INET6_ADDRSTRLEN];
57 
58 	logmsg(LOG_DEBUG, "%s %s (%d bytes) on %s\n", str,
59 	    inet_ntop(addr->sin6_family, (void *)&addr->sin6_addr,
60 	    abuf, sizeof (abuf)),
61 	    len, pi->pi_name);
62 	logmsg(LOG_DEBUG, "\tMax hop limit: %u\n", ra->nd_ra_curhoplimit);
63 	logmsg(LOG_DEBUG, "\tManaged address configuration: %s\n",
64 	    (ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) ?
65 	    "Set" : "Not set");
66 	logmsg(LOG_DEBUG, "\tOther configuration flag: %s\n",
67 	    (ra->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) ?
68 	    "Set" : "Not set");
69 	logmsg(LOG_DEBUG, "\tRouter lifetime: %u\n",
70 	    ntohs(ra->nd_ra_router_lifetime));
71 	logmsg(LOG_DEBUG, "\tReachable timer: %u\n",
72 	    ntohl(ra->nd_ra_reachable));
73 	logmsg(LOG_DEBUG, "\tReachable retrans timer: %u\n",
74 	    ntohl(ra->nd_ra_retransmit));
75 
76 	len -= sizeof (*ra);
77 	opt = (struct nd_opt_hdr *)&ra[1];
78 	print_opt(opt, len);
79 }
80 
81 static void
82 print_opt(struct nd_opt_hdr *opt, int len)
83 {
84 	struct nd_opt_prefix_info *po;
85 	struct nd_opt_mtu *mo;
86 	struct nd_opt_lla *lo;
87 	int optlen;
88 	char abuf[INET6_ADDRSTRLEN];
89 	char llabuf[BUFSIZ];
90 
91 	while (len >= sizeof (struct nd_opt_hdr)) {
92 		optlen = opt->nd_opt_len * 8;
93 		if (optlen == 0) {
94 			logmsg(LOG_DEBUG, "Zero length option!\n");
95 			break;
96 		}
97 		switch (opt->nd_opt_type) {
98 		case ND_OPT_PREFIX_INFORMATION:
99 			po = (struct nd_opt_prefix_info *)opt;
100 			if (optlen != sizeof (*po) ||
101 			    optlen > len)
102 				break;
103 
104 			logmsg(LOG_DEBUG, "\tPrefix: %s/%u\n",
105 			    inet_ntop(AF_INET6, (void *)&po->nd_opt_pi_prefix,
106 			    abuf, sizeof (abuf)),
107 			    po->nd_opt_pi_prefix_len);
108 			logmsg(LOG_DEBUG, "\t\tOn link flag:%s\n",
109 			    (po->nd_opt_pi_flags_reserved &
110 			    ND_OPT_PI_FLAG_ONLINK) ?
111 			    "Set" : "Not set");
112 			logmsg(LOG_DEBUG, "\t\tAuto addrconf flag:%s\n",
113 			    (po->nd_opt_pi_flags_reserved &
114 			    ND_OPT_PI_FLAG_AUTO) ?
115 			    "Set" : "Not set");
116 			logmsg(LOG_DEBUG, "\t\tValid time: %u\n",
117 			    ntohl(po->nd_opt_pi_valid_time));
118 			logmsg(LOG_DEBUG, "\t\tPreferred time: %u\n",
119 			    ntohl(po->nd_opt_pi_preferred_time));
120 			break;
121 		case ND_OPT_MTU:
122 			mo = (struct nd_opt_mtu *)opt;
123 			if (optlen != sizeof (*mo) ||
124 			    optlen > len)
125 				break;
126 			logmsg(LOG_DEBUG, "\tMTU: %d\n",
127 			    ntohl(mo->nd_opt_mtu_mtu));
128 			break;
129 		case ND_OPT_SOURCE_LINKADDR:
130 			lo = (struct nd_opt_lla *)opt;
131 			if (optlen < 8 ||
132 			    optlen > len)
133 				break;
134 			(void) fmt_lla(llabuf, sizeof (llabuf),
135 			    lo->nd_opt_lla_hdw_addr,
136 			    optlen - sizeof (nd_opt_hdr_t));
137 			logmsg(LOG_DEBUG, "\tSource LLA: len %d <%s>\n",
138 			    optlen - sizeof (nd_opt_hdr_t),
139 			    llabuf);
140 			break;
141 		case ND_OPT_TARGET_LINKADDR:
142 			lo = (struct nd_opt_lla *)opt;
143 			if (optlen < 8||
144 			    optlen > len)
145 				break;
146 			(void) fmt_lla(llabuf, sizeof (llabuf),
147 			    lo->nd_opt_lla_hdw_addr,
148 			    optlen - sizeof (nd_opt_hdr_t));
149 			logmsg(LOG_DEBUG, "\tTarget LLA: len %d <%s>\n",
150 			    optlen - sizeof (nd_opt_hdr_t),
151 			    llabuf);
152 			break;
153 		case ND_OPT_REDIRECTED_HEADER:
154 			logmsg(LOG_DEBUG, "\tRedirected header option!\n");
155 			break;
156 		default:
157 			logmsg(LOG_DEBUG, "Unknown option %d (0x%x)\n",
158 			    opt->nd_opt_type, opt->nd_opt_type);
159 			break;
160 		}
161 		opt = (struct nd_opt_hdr *)((char *)opt + optlen);
162 		len -= optlen;
163 	}
164 }
165 
166 char *
167 fmt_lla(char *llabuf, int bufsize, uchar_t *lla, int llalen)
168 {
169 	int i;
170 	char *cp = llabuf;
171 
172 	for (i = 0; i < llalen; i++) {
173 		if (i == llalen - 1) /* Last byte? */
174 			(void) snprintf(cp, bufsize, "%02x", lla[i] & 0xFF);
175 		else
176 			(void) snprintf(cp, bufsize, "%02x:", lla[i] & 0xFF);
177 		bufsize -= strlen(cp);
178 		cp += strlen(cp);
179 	}
180 	return (llabuf);
181 }
182