LCOV - code coverage report
Current view: top level - src/common - gas.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1443382998 Lines: 93 93 100.0 %
Date: 2015-09-27 Functions: 15 15 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Generic advertisement service (GAS) (IEEE 802.11u)
       3             :  * Copyright (c) 2009, Atheros Communications
       4             :  * Copyright (c) 2011-2012, Qualcomm Atheros
       5             :  *
       6             :  * This software may be distributed under the terms of the BSD license.
       7             :  * See README for more details.
       8             :  */
       9             : 
      10             : #include "includes.h"
      11             : 
      12             : #include "common.h"
      13             : #include "ieee802_11_defs.h"
      14             : #include "gas.h"
      15             : 
      16             : 
      17             : static struct wpabuf *
      18         670 : gas_build_req(u8 action, u8 dialog_token, size_t size)
      19             : {
      20             :         struct wpabuf *buf;
      21             : 
      22         670 :         buf = wpabuf_alloc(100 + size);
      23         670 :         if (buf == NULL)
      24           1 :                 return NULL;
      25             : 
      26         669 :         wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
      27         669 :         wpabuf_put_u8(buf, action);
      28         669 :         wpabuf_put_u8(buf, dialog_token);
      29             : 
      30         669 :         return buf;
      31             : }
      32             : 
      33             : 
      34         474 : struct wpabuf * gas_build_initial_req(u8 dialog_token, size_t size)
      35             : {
      36         474 :         return gas_build_req(WLAN_PA_GAS_INITIAL_REQ, dialog_token,
      37             :                              size);
      38             : }
      39             : 
      40             : 
      41         196 : struct wpabuf * gas_build_comeback_req(u8 dialog_token)
      42             : {
      43         196 :         return gas_build_req(WLAN_PA_GAS_COMEBACK_REQ, dialog_token, 0);
      44             : }
      45             : 
      46             : 
      47             : static struct wpabuf *
      48         332 : gas_build_resp(u8 action, u8 dialog_token, u16 status_code, u8 frag_id,
      49             :                u8 more, u16 comeback_delay, size_t size)
      50             : {
      51             :         struct wpabuf *buf;
      52             : 
      53         332 :         buf = wpabuf_alloc(100 + size);
      54         332 :         if (buf == NULL)
      55           2 :                 return NULL;
      56             : 
      57         330 :         wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
      58         330 :         wpabuf_put_u8(buf, action);
      59         330 :         wpabuf_put_u8(buf, dialog_token);
      60         330 :         wpabuf_put_le16(buf, status_code);
      61         330 :         if (action == WLAN_PA_GAS_COMEBACK_RESP)
      62          55 :                 wpabuf_put_u8(buf, frag_id | (more ? 0x80 : 0));
      63         330 :         wpabuf_put_le16(buf, comeback_delay);
      64             : 
      65         330 :         return buf;
      66             : }
      67             : 
      68             : 
      69             : struct wpabuf *
      70         276 : gas_build_initial_resp(u8 dialog_token, u16 status_code, u16 comeback_delay,
      71             :                        size_t size)
      72             : {
      73         276 :         return gas_build_resp(WLAN_PA_GAS_INITIAL_RESP, dialog_token,
      74             :                               status_code, 0, 0, comeback_delay, size);
      75             : }
      76             : 
      77             : 
      78             : static struct wpabuf *
      79          56 : gas_build_comeback_resp(u8 dialog_token, u16 status_code, u8 frag_id, u8 more,
      80             :                         u16 comeback_delay, size_t size)
      81             : {
      82          56 :         return gas_build_resp(WLAN_PA_GAS_COMEBACK_RESP, dialog_token,
      83             :                               status_code, frag_id, more, comeback_delay,
      84             :                               size);
      85             : }
      86             : 
      87             : 
      88             : /**
      89             :  * gas_add_adv_proto_anqp - Add an Advertisement Protocol element
      90             :  * @buf: Buffer to which the element is added
      91             :  * @query_resp_len_limit: Query Response Length Limit in units of 256 octets
      92             :  * @pame_bi: Pre-Association Message Exchange BSSID Independent (0/1)
      93             :  *
      94             :  *
      95             :  * @query_resp_len_limit is 0 for request and 1-0x7f for response. 0x7f means
      96             :  * that the maximum limit is determined by the maximum allowable number of
      97             :  * fragments in the GAS Query Response Fragment ID.
      98             :  */
      99         794 : static void gas_add_adv_proto_anqp(struct wpabuf *buf, u8 query_resp_len_limit,
     100             :                                    u8 pame_bi)
     101             : {
     102             :         /* Advertisement Protocol IE */
     103         794 :         wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO);
     104         794 :         wpabuf_put_u8(buf, 2); /* Length */
     105         794 :         wpabuf_put_u8(buf, (query_resp_len_limit & 0x7f) |
     106             :                       (pame_bi ? 0x80 : 0));
     107             :         /* Advertisement Protocol */
     108         794 :         wpabuf_put_u8(buf, ACCESS_NETWORK_QUERY_PROTOCOL);
     109         794 : }
     110             : 
     111             : 
     112         466 : struct wpabuf * gas_anqp_build_initial_req(u8 dialog_token, size_t size)
     113             : {
     114             :         struct wpabuf *buf;
     115             : 
     116         466 :         buf = gas_build_initial_req(dialog_token, 4 + size);
     117         466 :         if (buf == NULL)
     118           1 :                 return NULL;
     119             : 
     120         465 :         gas_add_adv_proto_anqp(buf, 0, 0);
     121             : 
     122         465 :         wpabuf_put(buf, 2); /* Query Request Length to be filled */
     123             : 
     124         465 :         return buf;
     125             : }
     126             : 
     127             : 
     128         275 : struct wpabuf * gas_anqp_build_initial_resp(u8 dialog_token, u16 status_code,
     129             :                                             u16 comeback_delay, size_t size)
     130             : {
     131             :         struct wpabuf *buf;
     132             : 
     133         275 :         buf = gas_build_initial_resp(dialog_token, status_code, comeback_delay,
     134             :                                      4 + size);
     135         275 :         if (buf == NULL)
     136           1 :                 return NULL;
     137             : 
     138         274 :         gas_add_adv_proto_anqp(buf, 0x7f, 0);
     139             : 
     140         274 :         wpabuf_put(buf, 2); /* Query Response Length to be filled */
     141             : 
     142         274 :         return buf;
     143             : }
     144             : 
     145             : 
     146         206 : struct wpabuf * gas_anqp_build_initial_resp_buf(u8 dialog_token,
     147             :                                                 u16 status_code,
     148             :                                                 u16 comeback_delay,
     149             :                                                 struct wpabuf *payload)
     150             : {
     151             :         struct wpabuf *buf;
     152             : 
     153         206 :         buf = gas_anqp_build_initial_resp(dialog_token, status_code,
     154             :                                           comeback_delay,
     155             :                                           payload ? wpabuf_len(payload) : 0);
     156         206 :         if (buf == NULL)
     157           1 :                 return NULL;
     158             : 
     159         205 :         if (payload)
     160         188 :                 wpabuf_put_buf(buf, payload);
     161             : 
     162         205 :         gas_anqp_set_len(buf);
     163             : 
     164         205 :         return buf;
     165             : }
     166             : 
     167             : 
     168          56 : struct wpabuf * gas_anqp_build_comeback_resp(u8 dialog_token, u16 status_code,
     169             :                                              u8 frag_id, u8 more,
     170             :                                              u16 comeback_delay, size_t size)
     171             : {
     172             :         struct wpabuf *buf;
     173             : 
     174          56 :         buf = gas_build_comeback_resp(dialog_token, status_code,
     175             :                                       frag_id, more, comeback_delay, 4 + size);
     176          56 :         if (buf == NULL)
     177           1 :                 return NULL;
     178             : 
     179          55 :         gas_add_adv_proto_anqp(buf, 0x7f, 0);
     180             : 
     181          55 :         wpabuf_put(buf, 2); /* Query Response Length to be filled */
     182             : 
     183          55 :         return buf;
     184             : }
     185             : 
     186             : 
     187          38 : struct wpabuf * gas_anqp_build_comeback_resp_buf(u8 dialog_token,
     188             :                                                  u16 status_code,
     189             :                                                  u8 frag_id, u8 more,
     190             :                                                  u16 comeback_delay,
     191             :                                                  struct wpabuf *payload)
     192             : {
     193             :         struct wpabuf *buf;
     194             : 
     195          38 :         buf = gas_anqp_build_comeback_resp(dialog_token, status_code, frag_id,
     196             :                                            more, comeback_delay,
     197             :                                            payload ? wpabuf_len(payload) : 0);
     198          38 :         if (buf == NULL)
     199           1 :                 return NULL;
     200             : 
     201          37 :         if (payload)
     202          36 :                 wpabuf_put_buf(buf, payload);
     203             : 
     204          37 :         gas_anqp_set_len(buf);
     205             : 
     206          37 :         return buf;
     207             : }
     208             : 
     209             : 
     210             : /**
     211             :  * gas_anqp_set_len - Set Query Request/Response Length
     212             :  * @buf: GAS message
     213             :  *
     214             :  * This function is used to update the Query Request/Response Length field once
     215             :  * the payload has been filled.
     216             :  */
     217         798 : void gas_anqp_set_len(struct wpabuf *buf)
     218             : {
     219             :         u8 action;
     220             :         size_t offset;
     221             :         u8 *len;
     222             : 
     223         798 :         if (buf == NULL || wpabuf_len(buf) < 2)
     224           2 :                 return;
     225             : 
     226         796 :         action = *(wpabuf_head_u8(buf) + 1);
     227         796 :         switch (action) {
     228             :         case WLAN_PA_GAS_INITIAL_REQ:
     229         466 :                 offset = 3 + 4;
     230         466 :                 break;
     231             :         case WLAN_PA_GAS_INITIAL_RESP:
     232         274 :                 offset = 7 + 4;
     233         274 :                 break;
     234             :         case WLAN_PA_GAS_COMEBACK_RESP:
     235          55 :                 offset = 8 + 4;
     236          55 :                 break;
     237             :         default:
     238           1 :                 return;
     239             :         }
     240             : 
     241         795 :         if (wpabuf_len(buf) < offset + 2)
     242           1 :                 return;
     243             : 
     244         794 :         len = wpabuf_mhead_u8(buf) + offset;
     245         794 :         WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
     246             : }
     247             : 
     248             : 
     249             : /**
     250             :  * gas_anqp_add_element - Add ANQP element header
     251             :  * @buf: GAS message
     252             :  * @info_id: ANQP Info ID
     253             :  * Returns: Pointer to the Length field for gas_anqp_set_element_len()
     254             :  */
     255        1565 : u8 * gas_anqp_add_element(struct wpabuf *buf, u16 info_id)
     256             : {
     257        1565 :         wpabuf_put_le16(buf, info_id);
     258        1565 :         return wpabuf_put(buf, 2); /* Length to be filled */
     259             : }
     260             : 
     261             : 
     262             : /**
     263             :  * gas_anqp_set_element_len - Update ANQP element Length field
     264             :  * @buf: GAS message
     265             :  * @len_pos: Length field position from gas_anqp_add_element()
     266             :  *
     267             :  * This function is called after the ANQP element payload has been added to the
     268             :  * buffer.
     269             :  */
     270        1872 : void gas_anqp_set_element_len(struct wpabuf *buf, u8 *len_pos)
     271             : {
     272        1872 :         WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(buf, 0) - len_pos - 2);
     273        1872 : }

Generated by: LCOV version 1.10