1 /* $OpenBSD: print-dhcp6.c,v 1.13 2021/12/01 18:28:45 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 2019 David Gwynne <dlg@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/time.h> 20 #include <sys/socket.h> 21 22 #include <net/if.h> 23 24 #include <netinet/in.h> 25 26 #include <ctype.h> 27 #include <stdio.h> 28 #include <string.h> 29 #include <arpa/inet.h> 30 31 #include "interface.h" 32 #include "extract.h" 33 #include "addrtoname.h" 34 35 /* Message type */ 36 #define DH6_SOLICIT 1 37 #define DH6_ADVERTISE 2 38 #define DH6_REQUEST 3 39 #define DH6_CONFIRM 4 40 #define DH6_RENEW 5 41 #define DH6_REBIND 6 42 #define DH6_REPLY 7 43 #define DH6_RELEASE 8 44 #define DH6_DECLINE 9 45 #define DH6_RECONFIGURE 10 46 #define DH6_INFORMATION_REQUEST 11 47 #define DH6_RELAY_FORW 12 48 #define DH6_RELAY_REPL 13 49 50 static void 51 dhcp6opt_print(const u_char *cp, u_int length) 52 { 53 uint16_t code, len; 54 u_int i; 55 int l = snapend - cp; 56 57 while (length > 0) { 58 if (l < sizeof(code)) 59 goto trunc; 60 if (length < sizeof(code)) 61 goto iptrunc; 62 63 code = EXTRACT_16BITS(cp); 64 cp += sizeof(code); 65 length -= sizeof(code); 66 l -= sizeof(code); 67 68 if (l < sizeof(len)) 69 goto trunc; 70 if (length < sizeof(len)) 71 goto iptrunc; 72 73 len = EXTRACT_16BITS(cp); 74 cp += sizeof(len); 75 length -= sizeof(len); 76 l -= sizeof(len); 77 78 printf("\n\toption %u len %u", code, len); 79 80 if (len > 0) { 81 if (l < len) 82 goto trunc; 83 if (length < len) 84 goto iptrunc; 85 86 printf(" "); 87 for (i = 0; i < len; i++) 88 printf("%02x", cp[4 + i] & 0xff); 89 90 cp += len; 91 length -= len; 92 l -= len; 93 } 94 } 95 return; 96 97 trunc: 98 printf(" [|dhcp6opt]"); 99 return; 100 iptrunc: 101 printf(" ip truncated"); 102 } 103 104 static void 105 dhcp6_relay_print(const u_char *cp, u_int length) 106 { 107 uint8_t msgtype; 108 const char *msgname = NULL; 109 110 msgtype = *cp; 111 112 switch (msgtype) { 113 case DH6_RELAY_FORW: 114 msgname = "Relay-forward"; 115 break; 116 case DH6_RELAY_REPL: 117 msgname = "Relay-reply"; 118 break; 119 } 120 121 printf(" %s", msgname); 122 } 123 124 void 125 dhcp6_print(const u_char *cp, u_int length) 126 { 127 uint8_t msgtype; 128 uint32_t hdr; 129 int l = snapend - cp; 130 const char *msgname; 131 132 printf("DHCPv6"); 133 134 if (l < sizeof(msgtype)) 135 goto trunc; 136 if (length < sizeof(msgtype)) 137 goto iptrunc; 138 139 msgtype = *cp; 140 141 switch (msgtype) { 142 case DH6_SOLICIT: 143 msgname = "Solicit"; 144 break; 145 case DH6_ADVERTISE: 146 msgname = "Advertise"; 147 break; 148 case DH6_REQUEST: 149 msgname = "Request"; 150 break; 151 case DH6_CONFIRM: 152 msgname = "Confirm"; 153 break; 154 case DH6_RENEW: 155 msgname = "Renew"; 156 break; 157 case DH6_REBIND: 158 msgname = "Rebind"; 159 break; 160 case DH6_REPLY: 161 msgname = "Reply"; 162 break; 163 case DH6_RELEASE: 164 msgname = "Release"; 165 break; 166 case DH6_DECLINE: 167 msgname = "Decline"; 168 break; 169 case DH6_RECONFIGURE: 170 msgname = "Reconfigure"; 171 break; 172 case DH6_INFORMATION_REQUEST: 173 msgname = "Information-request"; 174 break; 175 case DH6_RELAY_FORW: 176 case DH6_RELAY_REPL: 177 dhcp6_relay_print(cp, length); 178 return; 179 default: 180 printf(" unknown message type %u", msgtype); 181 return; 182 } 183 184 printf(" %s", msgname); 185 186 if (l < sizeof(hdr)) 187 goto trunc; 188 if (length < sizeof(hdr)) 189 goto iptrunc; 190 191 hdr = EXTRACT_32BITS(cp); 192 printf(" xid %x", hdr & 0xffffff); 193 194 if (vflag) { 195 cp += sizeof(hdr); 196 length -= sizeof(hdr); 197 198 dhcp6opt_print(cp, length); 199 } 200 return; 201 202 trunc: 203 printf(" [|dhcp6]"); 204 return; 205 iptrunc: 206 printf(" ip truncated"); 207 } 208