1/* 2 * Decode functions which provides decoding of GAS packets as defined in 802.11u. 3 * 4 * Copyright (C) 2015, Broadcom Corporation 5 * All Rights Reserved. 6 * 7 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; 8 * the contents of this file may not be disclosed to third parties, copied 9 * or duplicated in any form, in whole or in part, without the prior 10 * written permission of Broadcom Corporation. 11 * 12 * $Id:$ 13 */ 14 15#include <stdio.h> 16#include <stdlib.h> 17#include <string.h> 18#include "proto/802.11.h" 19#include "trace.h" 20#include "bcm_decode_ie.h" 21#include "bcm_decode_gas.h" 22 23static void printGasFrame(bcm_decode_gas_t *gasDecode) 24{ 25 WL_P2PO(("decoded GAS frame:\n")); 26 WL_P2PO((" category = %d\n", gasDecode->category)); 27 WL_P2PO((" action = %d (%s)\n", gasDecode->action, 28 gasDecode->action == GAS_REQUEST_ACTION_FRAME ? "GAS REQUEST" : 29 gasDecode->action == GAS_RESPONSE_ACTION_FRAME ? "GAS RESPONSE" : 30 gasDecode->action == GAS_COMEBACK_REQUEST_ACTION_FRAME ? 31 "GAS COMEBACK REQUEST" : 32 gasDecode->action == GAS_COMEBACK_RESPONSE_ACTION_FRAME ? 33 "GAS COMEBACK RESPONSE" : 34 "?")); 35 WL_P2PO((" dialog token = %d\n", gasDecode->dialogToken)); 36 switch (gasDecode->action) 37 { 38 case GAS_REQUEST_ACTION_FRAME: 39 WL_P2PO((" advertisement protocol ID = %d\n", 40 gasDecode->request.apie.protocolId)); 41 WL_PRPKT(" request", 42 gasDecode->request.req, gasDecode->request.reqLen); 43 break; 44 case GAS_RESPONSE_ACTION_FRAME: 45 WL_P2PO((" status code = %d\n", 46 gasDecode->response.statusCode)); 47 WL_P2PO((" comeback delay = 0x%04x\n", 48 gasDecode->response.comebackDelay)); 49 WL_P2PO((" advertisement protocol ID = %d\n", 50 gasDecode->response.apie.protocolId)); 51 WL_PRPKT(" response", 52 gasDecode->response.rsp, gasDecode->response.rspLen); 53 break; 54 case GAS_COMEBACK_REQUEST_ACTION_FRAME: 55 /* nothing */ 56 break; 57 case GAS_COMEBACK_RESPONSE_ACTION_FRAME: 58 WL_P2PO((" status code = %d\n", 59 gasDecode->comebackResponse.statusCode)); 60 WL_P2PO((" fragment ID = 0x%02x\n", 61 gasDecode->comebackResponse.fragmentId)); 62 WL_P2PO((" comeback delay = 0x%04x\n", 63 gasDecode->comebackResponse.comebackDelay)); 64 WL_P2PO((" advertisement protocol ID = %d\n", 65 gasDecode->comebackResponse.apie.protocolId)); 66 WL_PRPKT(" response", 67 gasDecode->comebackResponse.rsp, gasDecode->comebackResponse.rspLen); 68 break; 69 default: 70 break; 71 } 72} 73 74static int decodeAdvertisementProtocol(bcm_decode_t *pkt, 75 bcm_decode_ie_adv_proto_tuple_t *ap) 76{ 77 uint8 ie, len; 78 79 if (!bcm_decode_byte(pkt, &ie) || ie != DOT11_MNG_ADVERTISEMENT_ID) { 80 WL_ERROR(("decode error\n")); 81 return FALSE; 82 } 83 84 if (!bcm_decode_byte(pkt, &len) || len != 2) { 85 WL_ERROR(("decode error\n")); 86 return FALSE; 87 } 88 89 if (!bcm_decode_ie_advertisement_protocol_tuple(pkt, ap)) { 90 WL_ERROR(("decode error\n")); 91 return FALSE; 92 } 93 94 return TRUE; 95} 96 97static int decodeReqRsp(bcm_decode_t *pkt, uint16 *rLen, uint8 **r) 98{ 99 if (!bcm_decode_le16(pkt, rLen)) { 100 WL_ERROR(("decode error\n")); 101 return FALSE; 102 } 103 104 if (bcm_decode_remaining(pkt) < *rLen) { 105 WL_ERROR(("decode error\n")); 106 return FALSE; 107 } 108 109 *r = bcm_decode_current_ptr(pkt); 110 bcm_decode_offset_set(pkt, bcm_decode_offset(pkt) + *rLen); 111 112 return TRUE; 113} 114 115int bcm_decode_gas(bcm_decode_t *pkt, bcm_decode_gas_t *gasDecode) 116{ 117 118 memset(gasDecode, 0, sizeof(*gasDecode)); 119 120 if (bcm_decode_remaining(pkt) < 3) { 121 WL_ERROR(("decode error\n")); 122 return FALSE; 123 } 124 125 (void)bcm_decode_byte(pkt, &gasDecode->category); 126 (void)bcm_decode_byte(pkt, &gasDecode->action); 127 (void)bcm_decode_byte(pkt, &gasDecode->dialogToken); 128 129 if (gasDecode->category != DOT11_ACTION_CAT_PUBLIC) { 130 WL_P2PO(("invalid category %d\n", gasDecode->category)); 131 return FALSE; 132 } 133 134 switch (gasDecode->action) 135 { 136 case GAS_REQUEST_ACTION_FRAME: 137 if (!decodeAdvertisementProtocol(pkt, &gasDecode->request.apie)) { 138 WL_ERROR(("decode error\n")); 139 return FALSE; 140 } 141 if (!decodeReqRsp(pkt, &gasDecode->request.reqLen, &gasDecode->request.req)) { 142 WL_ERROR(("decode error\n")); 143 return FALSE; 144 } 145 break; 146 case GAS_RESPONSE_ACTION_FRAME: 147 if (!bcm_decode_le16(pkt, &gasDecode->response.statusCode)) { 148 WL_ERROR(("decode error\n")); 149 return FALSE; 150 } 151 if (!bcm_decode_le16(pkt, &gasDecode->response.comebackDelay)) { 152 WL_ERROR(("decode error\n")); 153 return FALSE; 154 } 155 if (!decodeAdvertisementProtocol(pkt, &gasDecode->response.apie)) { 156 WL_ERROR(("decode error\n")); 157 return FALSE; 158 } 159 if (!decodeReqRsp(pkt, &gasDecode->response.rspLen, &gasDecode->response.rsp)) { 160 WL_ERROR(("decode error\n")); 161 return FALSE; 162 } 163 break; 164 case GAS_COMEBACK_REQUEST_ACTION_FRAME: 165 /* nothing */ 166 break; 167 case GAS_COMEBACK_RESPONSE_ACTION_FRAME: 168 if (!bcm_decode_le16(pkt, &gasDecode->comebackResponse.statusCode)) { 169 WL_ERROR(("decode error\n")); 170 return FALSE; 171 } 172 if (!bcm_decode_byte(pkt, &gasDecode->comebackResponse.fragmentId)) { 173 WL_ERROR(("decode error\n")); 174 return FALSE; 175 } 176 if (!bcm_decode_le16(pkt, &gasDecode->comebackResponse.comebackDelay)) { 177 WL_ERROR(("decode error\n")); 178 return FALSE; 179 } 180 if (!decodeAdvertisementProtocol(pkt, &gasDecode->comebackResponse.apie)) { 181 WL_ERROR(("decode error\n")); 182 return FALSE; 183 } 184 if (!decodeReqRsp(pkt, &gasDecode->comebackResponse.rspLen, 185 &gasDecode->comebackResponse.rsp)) { 186 WL_ERROR(("decode error\n")); 187 return FALSE; 188 } 189 break; 190 default: 191 WL_P2PO(("invalid action %d\n", gasDecode->action)); 192 return FALSE; 193 break; 194 } 195 196 printGasFrame(gasDecode); 197 return TRUE; 198} 199