1 /* $OpenBSD: print-dhcp6.c,v 1.12 2019/12/02 22:07:20 dlg 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 struct mbuf; 23 struct rtentry; 24 #include <net/if.h> 25 26 #include <netinet/in.h> 27 28 #include <ctype.h> 29 #include <stdio.h> 30 #include <string.h> 31 #include <arpa/inet.h> 32 33 #include "interface.h" 34 #include "extract.h" 35 #include "addrtoname.h" 36 37 /* Message type */ 38 #define DH6_SOLICIT 1 39 #define DH6_ADVERTISE 2 40 #define DH6_REQUEST 3 41 #define DH6_CONFIRM 4 42 #define DH6_RENEW 5 43 #define DH6_REBIND 6 44 #define DH6_REPLY 7 45 #define DH6_RELEASE 8 46 #define DH6_DECLINE 9 47 #define DH6_RECONFIGURE 10 48 #define DH6_INFORMATION_REQUEST 11 49 #define DH6_RELAY_FORW 12 50 #define DH6_RELAY_REPL 13 51 52 static void 53 dhcp6opt_print(const u_char *cp, u_int length) 54 { 55 uint16_t code, len; 56 u_int i; 57 int l = snapend - cp; 58 59 while (length > 0) { 60 if (l < sizeof(code)) 61 goto trunc; 62 if (length < sizeof(code)) 63 goto iptrunc; 64 65 code = EXTRACT_16BITS(cp); 66 cp += sizeof(code); 67 length -= sizeof(code); 68 l -= sizeof(code); 69 70 if (l < sizeof(len)) 71 goto trunc; 72 if (length < sizeof(len)) 73 goto iptrunc; 74 75 len = EXTRACT_16BITS(cp); 76 cp += sizeof(len); 77 length -= sizeof(len); 78 l -= sizeof(len); 79 80 printf("\n\toption %u len %u", code, len); 81 82 if (len > 0) { 83 if (l < len) 84 goto trunc; 85 if (length < len) 86 goto iptrunc; 87 88 printf(" "); 89 for (i = 0; i < len; i++) 90 printf("%02x", cp[4 + i] & 0xff); 91 92 cp += len; 93 length -= len; 94 l -= len; 95 } 96 } 97 return; 98 99 trunc: 100 printf(" [|dhcp6opt]"); 101 return; 102 iptrunc: 103 printf(" ip truncated"); 104 } 105 106 static void 107 dhcp6_relay_print(const u_char *cp, u_int length) 108 { 109 uint8_t msgtype; 110 const char *msgname = NULL; 111 112 msgtype = *cp; 113 114 switch (msgtype) { 115 case DH6_RELAY_FORW: 116 msgname = "Relay-forward"; 117 break; 118 case DH6_RELAY_REPL: 119 msgname = "Relay-reply"; 120 break; 121 } 122 123 printf(" %s", msgname); 124 } 125 126 void 127 dhcp6_print(const u_char *cp, u_int length) 128 { 129 uint8_t msgtype; 130 uint32_t hdr; 131 int l = snapend - cp; 132 const char *msgname; 133 134 printf("DHCPv6"); 135 136 if (l < sizeof(msgtype)) 137 goto trunc; 138 if (length < sizeof(msgtype)) 139 goto iptrunc; 140 141 msgtype = *cp; 142 143 switch (msgtype) { 144 case DH6_SOLICIT: 145 msgname = "Solicit"; 146 break; 147 case DH6_ADVERTISE: 148 msgname = "Advertise"; 149 break; 150 case DH6_REQUEST: 151 msgname = "Request"; 152 break; 153 case DH6_CONFIRM: 154 msgname = "Confirm"; 155 break; 156 case DH6_RENEW: 157 msgname = "Renew"; 158 break; 159 case DH6_REBIND: 160 msgname = "Rebind"; 161 break; 162 case DH6_REPLY: 163 msgname = "Reply"; 164 break; 165 case DH6_RELEASE: 166 msgname = "Release"; 167 break; 168 case DH6_DECLINE: 169 msgname = "Decline"; 170 break; 171 case DH6_RECONFIGURE: 172 msgname = "Reconfigure"; 173 break; 174 case DH6_INFORMATION_REQUEST: 175 msgname = "Information-request"; 176 break; 177 case DH6_RELAY_FORW: 178 case DH6_RELAY_REPL: 179 dhcp6_relay_print(cp, length); 180 return; 181 default: 182 printf(" unknown message type %u", msgtype); 183 return; 184 } 185 186 printf(" %s", msgname); 187 188 if (l < sizeof(hdr)) 189 goto trunc; 190 if (length < sizeof(hdr)) 191 goto iptrunc; 192 193 hdr = EXTRACT_32BITS(cp); 194 printf(" xid %x", hdr & 0xffffff); 195 196 if (vflag) { 197 cp += sizeof(hdr); 198 length -= sizeof(hdr); 199 200 dhcp6opt_print(cp, length); 201 } 202 return; 203 204 trunc: 205 printf(" [|dhcp6]"); 206 return; 207 iptrunc: 208 printf(" ip truncated"); 209 } 210