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
dhcp6opt_print(const u_char * cp,u_int length)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
dhcp6_relay_print(const u_char * cp,u_int length)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
dhcp6_print(const u_char * cp,u_int length)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