1 /* $OpenBSD: print-dhcp6.c,v 1.11 2018/10/22 16:12:45 kn 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 #include <sys/time.h> 33 #include <sys/socket.h> 34 35 struct mbuf; 36 struct rtentry; 37 #include <net/if.h> 38 39 #include <netinet/in.h> 40 41 #include <ctype.h> 42 #include <stdio.h> 43 #include <string.h> 44 #include <arpa/inet.h> 45 46 #include "interface.h" 47 #include "addrtoname.h" 48 #include "dhcp6.h" 49 #include "dhcp6opt.h" 50 51 #if 0 52 static void dhcp6opttab_init(void); 53 static struct dhcp6_opt *dhcp6opttab_byname(char *); 54 #endif 55 static struct dhcp6_opt *dhcp6opttab_bycode(u_int); 56 57 static char tstr[] = " [|dhcp6]"; 58 59 static struct dhcp6_opt dh6opttab[] = { 60 /* IP Address Extension */ 61 { 1, OL6_N, "IP Address", OT6_NONE, }, 62 63 /* General Extension */ 64 { 2, 4, "Time Offset", OT6_NUM, }, 65 { 3, OL6_N, "IEEE 1003.1 POSIX Timezone", OT6_STR, }, 66 { 6, OL6_16N, "Domain Name Server", OT6_V6, }, 67 { 10, OL6_N, "Domain Name", OT6_STR, }, 68 69 /* Application and Service Parameters */ 70 { 16, OL6_N, "Directory Agent", OT6_NONE, }, 71 { 17, OL6_N, "Service Scope" , OT6_NONE, }, 72 { 18, OL6_16N, "Network Time Protocol Servers", OT6_V6, }, 73 { 19, OL6_N, "NIS Domain", OT6_STR, }, 74 { 20, OL6_16N, "NIS Servers", OT6_V6, }, 75 { 21, OL6_N, "NIS+ Domain", OT6_STR, }, 76 { 22, OL6_16N, "NIS+ Servers", OT6_V6, }, 77 78 /* TCP Parameters */ 79 { 32, 4, "TCP Keepalive Interval", OT6_NUM, }, 80 81 /* DHCPv6 Extensions */ 82 { 40, 4, "Maximum DHCPv6 Message Size", OT6_NUM, }, 83 { 41, OL6_N, "DHCP Retransmission and Configuration Parameter", 84 OT6_NONE, }, 85 { 48, OL6_N, "Platform Specific Information", OT6_NONE, }, 86 { 49, OL6_N, "Platform Class Identifier", OT6_STR, }, 87 { 64, OL6_N, "Class Identifier", OT6_STR, }, 88 { 66, 16, "Reconfigure Multicast Address", OT6_V6, }, 89 { 67, 16, "Renumber DHCPv6 Server Address", 90 OT6_V6, }, 91 { 68, OL6_N, "DHCP Relay ICMP Error Message", OT6_NONE, }, 92 { 84, OL6_N, "Client-Server Authentication", OT6_NONE, }, 93 { 85, 4, "Client Key Selection", OT6_NUM, }, 94 95 /* End Extension */ 96 { 65536, OL6_Z, "End", OT6_NONE, }, 97 98 { 0 }, 99 }; 100 101 #if 0 102 static struct dhcp6_opt *dh6o_pad; 103 static struct dhcp6_opt *dh6o_end; 104 105 static void 106 dhcp6opttab_init() 107 { 108 dh6o_pad = dhcp6opttab_bycode(0); 109 dh6o_end = dhcp6opttab_bycode(65536); 110 } 111 #endif 112 113 #if 0 114 static struct dhcp6_opt * 115 dhcp6opttab_byname(name) 116 char *name; 117 { 118 struct dhcp6_opt *p; 119 120 for (p = dh6opttab; p->code; p++) 121 if (strcmp(name, p->name) == 0) 122 return p; 123 return NULL; 124 } 125 #endif 126 127 static struct dhcp6_opt * 128 dhcp6opttab_bycode(code) 129 u_int code; 130 { 131 struct dhcp6_opt *p; 132 133 for (p = dh6opttab; p->code; p++) 134 if (p->code == code) 135 return p; 136 return NULL; 137 } 138 139 static void 140 dhcp6ext_print(u_char *cp, u_char *ep) 141 { 142 u_int16_t code, len; 143 struct dhcp6_opt *p; 144 char buf[BUFSIZ]; 145 int i; 146 147 if (cp == ep) 148 return; 149 printf(" "); 150 while (cp < ep) { 151 code = ntohs(*(u_int16_t *)&cp[0]); 152 if (code != 65535) 153 len = ntohs(*(u_int16_t *)&cp[2]); 154 else 155 len = 0; 156 p = dhcp6opttab_bycode(code); 157 if (p == NULL) { 158 printf("(unknown, len=%d)", len); 159 cp += len + 4; 160 continue; 161 } 162 163 /* sanity check on length */ 164 switch (p->len) { 165 case OL6_N: 166 break; 167 case OL6_16N: 168 if (len % 16 != 0) 169 goto trunc; 170 break; 171 case OL6_Z: 172 if (len != 0) 173 goto trunc; 174 break; 175 default: 176 if (len != p->len) 177 goto trunc; 178 break; 179 } 180 if (cp + 4 + len > ep) { 181 printf("[|%s]", p->name); 182 return; 183 } 184 185 printf("(%s, ", p->name); 186 switch (p->type) { 187 case OT6_V6: 188 for (i = 0; i < len; i += 16) { 189 inet_ntop(AF_INET6, &cp[4 + i], buf, 190 sizeof(buf)); 191 if (i != 0) 192 printf(","); 193 printf("%s", buf); 194 } 195 break; 196 case OT6_STR: 197 memset(&buf, 0, sizeof(buf)); 198 strlcpy(buf, &cp[4], len); 199 printf("%s", buf); 200 break; 201 case OT6_NUM: 202 printf("%d", (u_int32_t)ntohl(*(u_int32_t *)&cp[4])); 203 break; 204 default: 205 for (i = 0; i < len; i++) 206 printf("%02x", cp[4 + i] & 0xff); 207 } 208 printf(")"); 209 cp += len + 4; 210 } 211 return; 212 213 trunc: 214 printf("[|dhcp6ext]"); 215 } 216 217 /* 218 * Print dhcp6 requests 219 */ 220 void 221 dhcp6_print(const u_char *cp, u_int length, 222 u_short sport, u_short dport) 223 { 224 union dhcp6 *dh6; 225 u_char *ep; 226 u_char *extp; 227 228 printf("dhcp6"); 229 230 ep = (u_char *)snapend; 231 232 dh6 = (union dhcp6 *)cp; 233 TCHECK(dh6->dh6_msgtype); 234 switch (dh6->dh6_msgtype) { 235 case DH6_SOLICIT: 236 if (vflag && TTEST(dh6->dh6_sol.dh6sol_relayaddr)) { 237 printf(" solicit("); 238 if ((dh6->dh6_sol.dh6sol_flags & DH6SOL_CLOSE) != 0) 239 printf("C"); 240 if (dh6->dh6_sol.dh6sol_flags != 0) 241 printf(" "); 242 printf("cliaddr=%s", 243 ip6addr_string(&dh6->dh6_sol.dh6sol_cliaddr)); 244 printf(" relayaddr=%s", 245 ip6addr_string(&dh6->dh6_sol.dh6sol_relayaddr)); 246 printf(")"); 247 } else 248 printf(" solicit"); 249 break; 250 case DH6_ADVERT: 251 if (!(vflag && TTEST(dh6->dh6_adv.dh6adv_serveraddr))) { 252 printf(" advert"); 253 break; 254 } 255 printf(" advert("); 256 if ((dh6->dh6_adv.dh6adv_flags & DH6ADV_SERVPRESENT) != 0) 257 printf("S"); 258 if (dh6->dh6_adv.dh6adv_flags != 0) 259 printf(" "); 260 printf("pref=%u", dh6->dh6_adv.dh6adv_pref); 261 printf(" cliaddr=%s", 262 ip6addr_string(&dh6->dh6_adv.dh6adv_cliaddr)); 263 printf(" relayaddr=%s", 264 ip6addr_string(&dh6->dh6_adv.dh6adv_relayaddr)); 265 printf(" servaddr=%s", 266 ip6addr_string(&dh6->dh6_adv.dh6adv_serveraddr)); 267 extp = (u_char *)((&dh6->dh6_adv) + 1); 268 dhcp6ext_print(extp, ep); 269 printf(")"); 270 break; 271 case DH6_REQUEST: 272 if (!(vflag && TTEST(dh6->dh6_req.dh6req_relayaddr))) { 273 printf(" request"); 274 break; 275 } 276 printf(" request("); 277 if ((dh6->dh6_req.dh6req_flags & DH6REQ_CLOSE) != 0) 278 printf("C"); 279 if ((dh6->dh6_req.dh6req_flags & DH6REQ_SERVPRESENT) != 0) 280 printf("S"); 281 if ((dh6->dh6_req.dh6req_flags & DH6REQ_REBOOT) != 0) 282 printf("R"); 283 if (dh6->dh6_req.dh6req_flags != 0) 284 printf(" "); 285 printf("xid=0x%04x", dh6->dh6_req.dh6req_xid); 286 printf(" cliaddr=%s", 287 ip6addr_string(&dh6->dh6_req.dh6req_cliaddr)); 288 printf(" relayaddr=%s", 289 ip6addr_string(&dh6->dh6_req.dh6req_relayaddr)); 290 extp = (char *)((&dh6->dh6_req) + 1); 291 if ((dh6->dh6_req.dh6req_flags & DH6REQ_SERVPRESENT) != 0) { 292 printf(" servaddr=%s", ip6addr_string(extp)); 293 extp += 16; 294 } 295 dhcp6ext_print(extp, ep); 296 printf(")"); 297 break; 298 case DH6_REPLY: 299 if (!(vflag && TTEST(dh6->dh6_rep.dh6rep_xid))) { 300 printf(" reply"); 301 break; 302 } 303 printf(" reply("); 304 if ((dh6->dh6_rep.dh6rep_flagandstat & DH6REP_CLIPRESENT) != 0) 305 printf("C"); 306 if (dh6->dh6_rep.dh6rep_flagandstat != 0) 307 printf(" "); 308 printf("stat=0x%02x", 309 dh6->dh6_rep.dh6rep_flagandstat & DH6REP_STATMASK); 310 extp = (u_char *)((&dh6->dh6_rep) + 1); 311 if ((dh6->dh6_rep.dh6rep_flagandstat & DH6REP_CLIPRESENT) != 0) { 312 printf(" cliaddr=%s", ip6addr_string(extp)); 313 extp += 16; 314 } 315 dhcp6ext_print(extp, ep); 316 printf(")"); 317 break; 318 case DH6_RELEASE: 319 printf(" release"); 320 break; 321 case DH6_RECONFIG: 322 printf(" reconfig"); 323 break; 324 } 325 return; 326 327 trunc: 328 printf("%s", tstr); 329 } 330