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