xref: /netbsd/external/bsd/tcpdump/dist/print-lwapp.c (revision c767dfb8)
1 /*
2  * Copyright (c) 1998-2007 The TCPDUMP project
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that: (1) source code
6  * distributions retain the above copyright notice and this paragraph
7  * in its entirety, and (2) distributions including binary code include
8  * the above copyright notice and this paragraph in its entirety in
9  * the documentation or other materials provided with the distribution.
10  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
11  * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
12  * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13  * FOR A PARTICULAR PURPOSE.
14  *
15  * Original code by Carles Kishimoto <carles.kishimoto@gmail.com>
16  */
17 
18 /* \summary: Light Weight Access Point Protocol (LWAPP) printer */
19 
20 /* specification: RFC 5412 */
21 
22 #include <sys/cdefs.h>
23 #ifndef lint
24 __RCSID("$NetBSD: print-lwapp.c,v 1.7 2017/02/05 04:05:05 spz Exp $");
25 #endif
26 
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30 
31 #include <netdissect-stdinc.h>
32 
33 #include "netdissect.h"
34 #include "extract.h"
35 #include "addrtoname.h"
36 
37 /*
38  * LWAPP transport (common) header
39  *      0                   1                   2                   3
40  *     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
41  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
42  *    |VER| RID |C|F|L|    Frag ID    |            Length             |
43  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44  *    |          Status/WLANs         |   Payload...  |
45  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46  *
47  */
48 
49 struct lwapp_transport_header {
50     uint8_t  version;
51     uint8_t  frag_id;
52     uint8_t  length[2];
53     uint16_t status;
54 };
55 
56 /*
57  * LWAPP control header
58  *      0                   1                   2                   3
59  *      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
60  *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
61  *     |  Message Type |    Seq Num    |      Msg Element Length       |
62  *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
63  *     |                           Session ID                          |
64  *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
65  *     |      Msg Element [0..N]       |
66  *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
67  */
68 
69 struct lwapp_control_header {
70     uint8_t  msg_type;
71     uint8_t  seq_num;
72     uint8_t  len[2];
73     uint8_t  session_id[4];
74 };
75 
76 #define LWAPP_VERSION 0
77 #define	LWAPP_EXTRACT_VERSION(x) (((x)&0xC0)>>6)
78 #define	LWAPP_EXTRACT_RID(x) (((x)&0x38)>>3)
79 #define LWAPP_EXTRACT_CONTROL_BIT(x) (((x)&0x04)>>2)
80 
81 static const struct tok lwapp_header_bits_values[] = {
82     { 0x01, "Last Fragment Bit"},
83     { 0x02, "Fragment Bit"},
84     { 0x04, "Control Bit"},
85     { 0, NULL}
86 };
87 
88 #define	LWAPP_MSGTYPE_DISCOVERY_REQUEST			1
89 #define	LWAPP_MSGTYPE_DISCOVERY_RESPONSE		2
90 #define	LWAPP_MSGTYPE_JOIN_REQUEST			3
91 #define LWAPP_MSGTYPE_JOIN_RESPONSE			4
92 #define LWAPP_MSGTYPE_JOIN_ACK				5
93 #define LWAPP_MSGTYPE_JOIN_CONFIRM			6
94 #define LWAPP_MSGTYPE_CONFIGURE_REQUEST			10
95 #define LWAPP_MSGTYPE_CONFIGURE_RESPONSE		11
96 #define LWAPP_MSGTYPE_CONF_UPDATE_REQUEST		12
97 #define LWAPP_MSGTYPE_CONF_UPDATE_RESPONSE		13
98 #define LWAPP_MSGTYPE_WTP_EVENT_REQUEST			14
99 #define LWAPP_MSGTYPE_WTP_EVENT_RESPONSE		15
100 #define LWAPP_MSGTYPE_CHANGE_STATE_EVENT_REQUEST	16
101 #define LWAPP_MSGTYPE_CHANGE_STATE_EVENT_RESPONSE	17
102 #define LWAPP_MSGTYPE_ECHO_REQUEST			22
103 #define LWAPP_MSGTYPE_ECHO_RESPONSE			23
104 #define LWAPP_MSGTYPE_IMAGE_DATA_REQUEST		24
105 #define LWAPP_MSGTYPE_IMAGE_DATA_RESPONSE		25
106 #define LWAPP_MSGTYPE_RESET_REQUEST			26
107 #define LWAPP_MSGTYPE_RESET_RESPONSE			27
108 #define LWAPP_MSGTYPE_KEY_UPDATE_REQUEST		30
109 #define LWAPP_MSGTYPE_KEY_UPDATE_RESPONSE		31
110 #define LWAPP_MSGTYPE_PRIMARY_DISCOVERY_REQUEST		32
111 #define LWAPP_MSGTYPE_PRIMARY_DISCOVERY_RESPONSE	33
112 #define LWAPP_MSGTYPE_DATA_TRANSFER_REQUEST		34
113 #define LWAPP_MSGTYPE_DATA_TRANSFER_RESPONSE		35
114 #define LWAPP_MSGTYPE_CLEAR_CONFIG_INDICATION		36
115 #define LWAPP_MSGTYPE_WLAN_CONFIG_REQUEST		37
116 #define LWAPP_MSGTYPE_WLAN_CONFIG_RESPONSE		38
117 #define LWAPP_MSGTYPE_MOBILE_CONFIG_REQUEST		39
118 #define LWAPP_MSGTYPE_MOBILE_CONFIG_RESPONSE		40
119 
120 static const struct tok lwapp_msg_type_values[] = {
121     { LWAPP_MSGTYPE_DISCOVERY_REQUEST, "Discovery req"},
122     { LWAPP_MSGTYPE_DISCOVERY_RESPONSE, "Discovery resp"},
123     { LWAPP_MSGTYPE_JOIN_REQUEST, "Join req"},
124     { LWAPP_MSGTYPE_JOIN_RESPONSE, "Join resp"},
125     { LWAPP_MSGTYPE_JOIN_ACK, "Join ack"},
126     { LWAPP_MSGTYPE_JOIN_CONFIRM, "Join confirm"},
127     { LWAPP_MSGTYPE_CONFIGURE_REQUEST, "Configure req"},
128     { LWAPP_MSGTYPE_CONFIGURE_RESPONSE, "Configure resp"},
129     { LWAPP_MSGTYPE_CONF_UPDATE_REQUEST, "Update req"},
130     { LWAPP_MSGTYPE_CONF_UPDATE_RESPONSE, "Update resp"},
131     { LWAPP_MSGTYPE_WTP_EVENT_REQUEST, "WTP event req"},
132     { LWAPP_MSGTYPE_WTP_EVENT_RESPONSE, "WTP event resp"},
133     { LWAPP_MSGTYPE_CHANGE_STATE_EVENT_REQUEST, "Change state event req"},
134     { LWAPP_MSGTYPE_CHANGE_STATE_EVENT_RESPONSE, "Change state event resp"},
135     { LWAPP_MSGTYPE_ECHO_REQUEST, "Echo req"},
136     { LWAPP_MSGTYPE_ECHO_RESPONSE, "Echo resp"},
137     { LWAPP_MSGTYPE_IMAGE_DATA_REQUEST, "Image data req"},
138     { LWAPP_MSGTYPE_IMAGE_DATA_RESPONSE, "Image data resp"},
139     { LWAPP_MSGTYPE_RESET_REQUEST, "Channel status req"},
140     { LWAPP_MSGTYPE_RESET_RESPONSE, "Channel status resp"},
141     { LWAPP_MSGTYPE_KEY_UPDATE_REQUEST, "Key update req"},
142     { LWAPP_MSGTYPE_KEY_UPDATE_RESPONSE, "Key update resp"},
143     { LWAPP_MSGTYPE_PRIMARY_DISCOVERY_REQUEST, "Primary discovery req"},
144     { LWAPP_MSGTYPE_PRIMARY_DISCOVERY_RESPONSE, "Primary discovery resp"},
145     { LWAPP_MSGTYPE_DATA_TRANSFER_REQUEST, "Data transfer req"},
146     { LWAPP_MSGTYPE_DATA_TRANSFER_RESPONSE, "Data transfer resp"},
147     { LWAPP_MSGTYPE_CLEAR_CONFIG_INDICATION, "Clear config ind"},
148     { LWAPP_MSGTYPE_WLAN_CONFIG_REQUEST, "Wlan config req"},
149     { LWAPP_MSGTYPE_WLAN_CONFIG_RESPONSE, "Wlan config resp"},
150     { LWAPP_MSGTYPE_MOBILE_CONFIG_REQUEST, "Mobile config req"},
151     { LWAPP_MSGTYPE_MOBILE_CONFIG_RESPONSE, "Mobile config resp"},
152     { 0, NULL}
153 };
154 
155 /*
156  * LWAPP message elements
157  *
158  * 0                   1                   2                   3
159  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
160  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
161  * |      Type     |             Length            |   Value ...   |
162  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
163  */
164 struct lwapp_message_header {
165     uint8_t type;
166     uint8_t length[2];
167 };
168 
169 void
lwapp_control_print(netdissect_options * ndo,const u_char * pptr,u_int len,int has_ap_ident)170 lwapp_control_print(netdissect_options *ndo,
171                     const u_char *pptr, u_int len, int has_ap_ident)
172 {
173     const struct lwapp_transport_header *lwapp_trans_header;
174     const struct lwapp_control_header *lwapp_control_header;
175     const u_char *tptr;
176     int  tlen;
177     int  msg_tlen;
178 
179     tptr=pptr;
180 
181     if (has_ap_ident) {
182         /* check if enough bytes for AP identity */
183         ND_TCHECK2(*tptr, 6);
184         lwapp_trans_header = (const struct lwapp_transport_header *)(pptr+6);
185     } else {
186         lwapp_trans_header = (const struct lwapp_transport_header *)pptr;
187     }
188     ND_TCHECK(*lwapp_trans_header);
189 
190     /*
191      * Sanity checking of the header.
192      */
193     if (LWAPP_EXTRACT_VERSION(lwapp_trans_header->version) != LWAPP_VERSION) {
194 	ND_PRINT((ndo, "LWAPP version %u packet not supported",
195                LWAPP_EXTRACT_VERSION(lwapp_trans_header->version)));
196 	return;
197     }
198 
199     /* non-verbose */
200     if (ndo->ndo_vflag < 1) {
201         ND_PRINT((ndo, "LWAPPv%u, %s frame, Flags [%s], length %u",
202                LWAPP_EXTRACT_VERSION(lwapp_trans_header->version),
203                LWAPP_EXTRACT_CONTROL_BIT(lwapp_trans_header->version) ? "Control" : "Data",
204                bittok2str(lwapp_header_bits_values,"none",(lwapp_trans_header->version)&0x07),
205                len));
206         return;
207     }
208 
209     /* ok they seem to want to know everything - lets fully decode it */
210     tlen=EXTRACT_16BITS(lwapp_trans_header->length);
211 
212     ND_PRINT((ndo, "LWAPPv%u, %s frame, Radio-id %u, Flags [%s], Frag-id %u, length %u",
213            LWAPP_EXTRACT_VERSION(lwapp_trans_header->version),
214            LWAPP_EXTRACT_CONTROL_BIT(lwapp_trans_header->version) ? "Control" : "Data",
215            LWAPP_EXTRACT_RID(lwapp_trans_header->version),
216            bittok2str(lwapp_header_bits_values,"none",(lwapp_trans_header->version)&0x07),
217 	   lwapp_trans_header->frag_id,
218 	   tlen));
219 
220     if (has_ap_ident) {
221         ND_PRINT((ndo, "\n\tAP identity: %s", etheraddr_string(ndo, tptr)));
222         tptr+=sizeof(const struct lwapp_transport_header)+6;
223     } else {
224         tptr+=sizeof(const struct lwapp_transport_header);
225     }
226 
227     while(tlen>0) {
228 
229         /* did we capture enough for fully decoding the object header ? */
230         ND_TCHECK2(*tptr, sizeof(struct lwapp_control_header));
231 
232         lwapp_control_header = (const struct lwapp_control_header *)tptr;
233 	msg_tlen = EXTRACT_16BITS(lwapp_control_header->len);
234 
235 	/* print message header */
236         ND_PRINT((ndo, "\n\t  Msg type: %s (%u), Seqnum: %u, Msg len: %d, Session: 0x%08x",
237                tok2str(lwapp_msg_type_values,"Unknown",lwapp_control_header->msg_type),
238                lwapp_control_header->msg_type,
239                lwapp_control_header->seq_num,
240                msg_tlen,
241                EXTRACT_32BITS(lwapp_control_header->session_id)));
242 
243         /* did we capture enough for fully decoding the message */
244         ND_TCHECK2(*tptr, msg_tlen);
245 
246 	/* XXX - Decode sub messages for each message */
247         switch(lwapp_control_header->msg_type) {
248         case LWAPP_MSGTYPE_DISCOVERY_REQUEST:
249         case LWAPP_MSGTYPE_DISCOVERY_RESPONSE:
250         case LWAPP_MSGTYPE_JOIN_REQUEST:
251         case LWAPP_MSGTYPE_JOIN_RESPONSE:
252         case LWAPP_MSGTYPE_JOIN_ACK:
253         case LWAPP_MSGTYPE_JOIN_CONFIRM:
254         case LWAPP_MSGTYPE_CONFIGURE_REQUEST:
255         case LWAPP_MSGTYPE_CONFIGURE_RESPONSE:
256         case LWAPP_MSGTYPE_CONF_UPDATE_REQUEST:
257         case LWAPP_MSGTYPE_CONF_UPDATE_RESPONSE:
258         case LWAPP_MSGTYPE_WTP_EVENT_REQUEST:
259         case LWAPP_MSGTYPE_WTP_EVENT_RESPONSE:
260         case LWAPP_MSGTYPE_CHANGE_STATE_EVENT_REQUEST:
261         case LWAPP_MSGTYPE_CHANGE_STATE_EVENT_RESPONSE:
262         case LWAPP_MSGTYPE_ECHO_REQUEST:
263         case LWAPP_MSGTYPE_ECHO_RESPONSE:
264         case LWAPP_MSGTYPE_IMAGE_DATA_REQUEST:
265         case LWAPP_MSGTYPE_IMAGE_DATA_RESPONSE:
266         case LWAPP_MSGTYPE_RESET_REQUEST:
267         case LWAPP_MSGTYPE_RESET_RESPONSE:
268         case LWAPP_MSGTYPE_KEY_UPDATE_REQUEST:
269         case LWAPP_MSGTYPE_KEY_UPDATE_RESPONSE:
270         case LWAPP_MSGTYPE_PRIMARY_DISCOVERY_REQUEST:
271         case LWAPP_MSGTYPE_PRIMARY_DISCOVERY_RESPONSE:
272         case LWAPP_MSGTYPE_DATA_TRANSFER_REQUEST:
273         case LWAPP_MSGTYPE_DATA_TRANSFER_RESPONSE:
274         case LWAPP_MSGTYPE_CLEAR_CONFIG_INDICATION:
275         case LWAPP_MSGTYPE_WLAN_CONFIG_REQUEST:
276         case LWAPP_MSGTYPE_WLAN_CONFIG_RESPONSE:
277         case LWAPP_MSGTYPE_MOBILE_CONFIG_REQUEST:
278         case LWAPP_MSGTYPE_MOBILE_CONFIG_RESPONSE:
279         default:
280             break;
281         }
282 
283         tptr += sizeof(struct lwapp_control_header) + msg_tlen;
284         tlen -= sizeof(struct lwapp_control_header) + msg_tlen;
285     }
286     return;
287 
288  trunc:
289     ND_PRINT((ndo, "\n\t\t packet exceeded snapshot"));
290 }
291 
292 void
lwapp_data_print(netdissect_options * ndo,const u_char * pptr,u_int len)293 lwapp_data_print(netdissect_options *ndo,
294                  const u_char *pptr, u_int len)
295 {
296     const struct lwapp_transport_header *lwapp_trans_header;
297     const u_char *tptr;
298     int tlen;
299 
300     tptr=pptr;
301 
302     /* check if enough bytes for AP identity */
303     ND_TCHECK2(*tptr, 6);
304     lwapp_trans_header = (const struct lwapp_transport_header *)pptr;
305     ND_TCHECK(*lwapp_trans_header);
306 
307     /*
308      * Sanity checking of the header.
309      */
310     if (LWAPP_EXTRACT_VERSION(lwapp_trans_header->version) != LWAPP_VERSION) {
311         ND_PRINT((ndo, "LWAPP version %u packet not supported",
312                LWAPP_EXTRACT_VERSION(lwapp_trans_header->version)));
313         return;
314     }
315 
316     /* non-verbose */
317     if (ndo->ndo_vflag < 1) {
318         ND_PRINT((ndo, "LWAPPv%u, %s frame, Flags [%s], length %u",
319                LWAPP_EXTRACT_VERSION(lwapp_trans_header->version),
320                LWAPP_EXTRACT_CONTROL_BIT(lwapp_trans_header->version) ? "Control" : "Data",
321                bittok2str(lwapp_header_bits_values,"none",(lwapp_trans_header->version)&0x07),
322                len));
323         return;
324     }
325 
326     /* ok they seem to want to know everything - lets fully decode it */
327     tlen=EXTRACT_16BITS(lwapp_trans_header->length);
328 
329     ND_PRINT((ndo, "LWAPPv%u, %s frame, Radio-id  %u, Flags [%s], Frag-id  %u, length %u",
330            LWAPP_EXTRACT_VERSION(lwapp_trans_header->version),
331            LWAPP_EXTRACT_CONTROL_BIT(lwapp_trans_header->version) ? "Control" : "Data",
332            LWAPP_EXTRACT_RID(lwapp_trans_header->version),
333            bittok2str(lwapp_header_bits_values,"none",(lwapp_trans_header->version)&0x07),
334            lwapp_trans_header->frag_id,
335            tlen));
336 
337     tptr+=sizeof(const struct lwapp_transport_header);
338     tlen-=sizeof(const struct lwapp_transport_header);
339 
340     /* FIX - An IEEE 802.11 frame follows - hexdump for now */
341     print_unknown_data(ndo, tptr, "\n\t", tlen);
342 
343     return;
344 
345  trunc:
346     ND_PRINT((ndo, "\n\t\t packet exceeded snapshot"));
347 }
348 
349 /*
350  * Local Variables:
351  * c-style: whitesmith
352  * c-basic-offset: 8
353  * End:
354  */
355