1 /* $OpenBSD: print-dhcp6.c,v 1.10 2015/11/18 15:36:20 mmcc Exp $ */ 2 3 /* 4 * Copyright (C) 1998 and 1999 WIDE Project. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the project nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #ifdef INET6 33 34 #include <sys/time.h> 35 #include <sys/socket.h> 36 37 struct mbuf; 38 struct rtentry; 39 #include <net/if.h> 40 41 #include <netinet/in.h> 42 43 #include <ctype.h> 44 #include <stdio.h> 45 #include <string.h> 46 #include <arpa/inet.h> 47 48 #include "interface.h" 49 #include "addrtoname.h" 50 #include "dhcp6.h" 51 #include "dhcp6opt.h" 52 53 #if 0 54 static void dhcp6opttab_init(void); 55 static struct dhcp6_opt *dhcp6opttab_byname(char *); 56 #endif 57 static struct dhcp6_opt *dhcp6opttab_bycode(u_int); 58 59 static char tstr[] = " [|dhcp6]"; 60 61 static struct dhcp6_opt dh6opttab[] = { 62 /* IP Address Extension */ 63 { 1, OL6_N, "IP Address", OT6_NONE, }, 64 65 /* General Extension */ 66 { 2, 4, "Time Offset", OT6_NUM, }, 67 { 3, OL6_N, "IEEE 1003.1 POSIX Timezone", OT6_STR, }, 68 { 6, OL6_16N, "Domain Name Server", OT6_V6, }, 69 { 10, OL6_N, "Domain Name", OT6_STR, }, 70 71 /* Application and Service Parameters */ 72 { 16, OL6_N, "Directory Agent", OT6_NONE, }, 73 { 17, OL6_N, "Service Scope" , OT6_NONE, }, 74 { 18, OL6_16N, "Network Time Protocol Servers", OT6_V6, }, 75 { 19, OL6_N, "NIS Domain", OT6_STR, }, 76 { 20, OL6_16N, "NIS Servers", OT6_V6, }, 77 { 21, OL6_N, "NIS+ Domain", OT6_STR, }, 78 { 22, OL6_16N, "NIS+ Servers", OT6_V6, }, 79 80 /* TCP Parameters */ 81 { 32, 4, "TCP Keepalive Interval", OT6_NUM, }, 82 83 /* DHCPv6 Extensions */ 84 { 40, 4, "Maximum DHCPv6 Message Size", OT6_NUM, }, 85 { 41, OL6_N, "DHCP Retransmission and Configuration Parameter", 86 OT6_NONE, }, 87 { 48, OL6_N, "Platform Specific Information", OT6_NONE, }, 88 { 49, OL6_N, "Platform Class Identifier", OT6_STR, }, 89 { 64, OL6_N, "Class Identifier", OT6_STR, }, 90 { 66, 16, "Reconfigure Multicast Address", OT6_V6, }, 91 { 67, 16, "Renumber DHCPv6 Server Address", 92 OT6_V6, }, 93 { 68, OL6_N, "DHCP Relay ICMP Error Message", OT6_NONE, }, 94 { 84, OL6_N, "Client-Server Authentication", OT6_NONE, }, 95 { 85, 4, "Client Key Selection", OT6_NUM, }, 96 97 /* End Extension */ 98 { 65536, OL6_Z, "End", OT6_NONE, }, 99 100 { 0 }, 101 }; 102 103 #if 0 104 static struct dhcp6_opt *dh6o_pad; 105 static struct dhcp6_opt *dh6o_end; 106 107 static void 108 dhcp6opttab_init() 109 { 110 dh6o_pad = dhcp6opttab_bycode(0); 111 dh6o_end = dhcp6opttab_bycode(65536); 112 } 113 #endif 114 115 #if 0 116 static struct dhcp6_opt * 117 dhcp6opttab_byname(name) 118 char *name; 119 { 120 struct dhcp6_opt *p; 121 122 for (p = dh6opttab; p->code; p++) 123 if (strcmp(name, p->name) == 0) 124 return p; 125 return NULL; 126 } 127 #endif 128 129 static struct dhcp6_opt * 130 dhcp6opttab_bycode(code) 131 u_int code; 132 { 133 struct dhcp6_opt *p; 134 135 for (p = dh6opttab; p->code; p++) 136 if (p->code == code) 137 return p; 138 return NULL; 139 } 140 141 static void 142 dhcp6ext_print(u_char *cp, u_char *ep) 143 { 144 u_int16_t code, len; 145 struct dhcp6_opt *p; 146 char buf[BUFSIZ]; 147 int i; 148 149 if (cp == ep) 150 return; 151 printf(" "); 152 while (cp < ep) { 153 code = ntohs(*(u_int16_t *)&cp[0]); 154 if (code != 65535) 155 len = ntohs(*(u_int16_t *)&cp[2]); 156 else 157 len = 0; 158 p = dhcp6opttab_bycode(code); 159 if (p == NULL) { 160 printf("(unknown, len=%d)", len); 161 cp += len + 4; 162 continue; 163 } 164 165 /* sanity check on length */ 166 switch (p->len) { 167 case OL6_N: 168 break; 169 case OL6_16N: 170 if (len % 16 != 0) 171 goto trunc; 172 break; 173 case OL6_Z: 174 if (len != 0) 175 goto trunc; 176 break; 177 default: 178 if (len != p->len) 179 goto trunc; 180 break; 181 } 182 if (cp + 4 + len > ep) { 183 printf("[|%s]", p->name); 184 return; 185 } 186 187 printf("(%s, ", p->name); 188 switch (p->type) { 189 case OT6_V6: 190 for (i = 0; i < len; i += 16) { 191 inet_ntop(AF_INET6, &cp[4 + i], buf, 192 sizeof(buf)); 193 if (i != 0) 194 printf(","); 195 printf("%s", buf); 196 } 197 break; 198 case OT6_STR: 199 memset(&buf, 0, sizeof(buf)); 200 strlcpy(buf, &cp[4], len); 201 printf("%s", buf); 202 break; 203 case OT6_NUM: 204 printf("%d", (u_int32_t)ntohl(*(u_int32_t *)&cp[4])); 205 break; 206 default: 207 for (i = 0; i < len; i++) 208 printf("%02x", cp[4 + i] & 0xff); 209 } 210 printf(")"); 211 cp += len + 4; 212 } 213 return; 214 215 trunc: 216 printf("[|dhcp6ext]"); 217 } 218 219 /* 220 * Print dhcp6 requests 221 */ 222 void 223 dhcp6_print(const u_char *cp, u_int length, 224 u_short sport, u_short dport) 225 { 226 union dhcp6 *dh6; 227 u_char *ep; 228 u_char *extp; 229 230 printf("dhcp6"); 231 232 ep = (u_char *)snapend; 233 234 dh6 = (union dhcp6 *)cp; 235 TCHECK(dh6->dh6_msgtype); 236 switch (dh6->dh6_msgtype) { 237 case DH6_SOLICIT: 238 if (vflag && TTEST(dh6->dh6_sol.dh6sol_relayaddr)) { 239 printf(" solicit("); 240 if ((dh6->dh6_sol.dh6sol_flags & DH6SOL_CLOSE) != 0) 241 printf("C"); 242 if (dh6->dh6_sol.dh6sol_flags != 0) 243 printf(" "); 244 printf("cliaddr=%s", 245 ip6addr_string(&dh6->dh6_sol.dh6sol_cliaddr)); 246 printf(" relayaddr=%s", 247 ip6addr_string(&dh6->dh6_sol.dh6sol_relayaddr)); 248 printf(")"); 249 } else 250 printf(" solicit"); 251 break; 252 case DH6_ADVERT: 253 if (!(vflag && TTEST(dh6->dh6_adv.dh6adv_serveraddr))) { 254 printf(" advert"); 255 break; 256 } 257 printf(" advert("); 258 if ((dh6->dh6_adv.dh6adv_flags & DH6ADV_SERVPRESENT) != 0) 259 printf("S"); 260 if (dh6->dh6_adv.dh6adv_flags != 0) 261 printf(" "); 262 printf("pref=%u", dh6->dh6_adv.dh6adv_pref); 263 printf(" cliaddr=%s", 264 ip6addr_string(&dh6->dh6_adv.dh6adv_cliaddr)); 265 printf(" relayaddr=%s", 266 ip6addr_string(&dh6->dh6_adv.dh6adv_relayaddr)); 267 printf(" servaddr=%s", 268 ip6addr_string(&dh6->dh6_adv.dh6adv_serveraddr)); 269 extp = (u_char *)((&dh6->dh6_adv) + 1); 270 dhcp6ext_print(extp, ep); 271 printf(")"); 272 break; 273 case DH6_REQUEST: 274 if (!(vflag && TTEST(dh6->dh6_req.dh6req_relayaddr))) { 275 printf(" request"); 276 break; 277 } 278 printf(" request("); 279 if ((dh6->dh6_req.dh6req_flags & DH6REQ_CLOSE) != 0) 280 printf("C"); 281 if ((dh6->dh6_req.dh6req_flags & DH6REQ_SERVPRESENT) != 0) 282 printf("S"); 283 if ((dh6->dh6_req.dh6req_flags & DH6REQ_REBOOT) != 0) 284 printf("R"); 285 if (dh6->dh6_req.dh6req_flags != 0) 286 printf(" "); 287 printf("xid=0x%04x", dh6->dh6_req.dh6req_xid); 288 printf(" cliaddr=%s", 289 ip6addr_string(&dh6->dh6_req.dh6req_cliaddr)); 290 printf(" relayaddr=%s", 291 ip6addr_string(&dh6->dh6_req.dh6req_relayaddr)); 292 extp = (char *)((&dh6->dh6_req) + 1); 293 if ((dh6->dh6_req.dh6req_flags & DH6REQ_SERVPRESENT) != 0) { 294 printf(" servaddr=%s", ip6addr_string(extp)); 295 extp += 16; 296 } 297 dhcp6ext_print(extp, ep); 298 printf(")"); 299 break; 300 case DH6_REPLY: 301 if (!(vflag && TTEST(dh6->dh6_rep.dh6rep_xid))) { 302 printf(" reply"); 303 break; 304 } 305 printf(" reply("); 306 if ((dh6->dh6_rep.dh6rep_flagandstat & DH6REP_CLIPRESENT) != 0) 307 printf("C"); 308 if (dh6->dh6_rep.dh6rep_flagandstat != 0) 309 printf(" "); 310 printf("stat=0x%02x", 311 dh6->dh6_rep.dh6rep_flagandstat & DH6REP_STATMASK); 312 extp = (u_char *)((&dh6->dh6_rep) + 1); 313 if ((dh6->dh6_rep.dh6rep_flagandstat & DH6REP_CLIPRESENT) != 0) { 314 printf(" cliaddr=%s", ip6addr_string(extp)); 315 extp += 16; 316 } 317 dhcp6ext_print(extp, ep); 318 printf(")"); 319 break; 320 case DH6_RELEASE: 321 printf(" release"); 322 break; 323 case DH6_RECONFIG: 324 printf(" reconfig"); 325 break; 326 } 327 return; 328 329 trunc: 330 printf("%s", tstr); 331 } 332 333 #endif /* INET6 */ 334