Interworking: Add advertising of 3GPP Cellular Network info
authorJay Katabathuni <jkatabat@qca.qualcomm.com>
Mon, 30 Jul 2012 19:07:35 +0000 (22:07 +0300)
committerJouni Malinen <j@w1.fi>
Sat, 25 Aug 2012 15:26:28 +0000 (18:26 +0300)
The anqp_3gpp_cell_net parameter can be used to configure hostapd
to advertise 3GPP Cellular Network ANQP information.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>

hostapd/config_file.c
hostapd/hostapd.conf
src/ap/ap_config.c
src/ap/ap_config.h
src/ap/gas_serv.c
src/ap/gas_serv.h

index c2804b9..fceb33f 100644 (file)
@@ -1329,6 +1329,82 @@ fail:
                   line, pos);
        return -1;
 }
+
+
+static int parse_3gpp_cell_net(struct hostapd_bss_config *bss, char *buf,
+                              int line)
+{
+       size_t count;
+       char *pos;
+       u8 *info = NULL, *ipos;
+
+       /* format: <MCC1,MNC1>[;<MCC2,MNC2>][;...] */
+
+       count = 1;
+       for (pos = buf; *pos; pos++) {
+               if ((*pos < '0' && *pos > '9') && *pos != ';' && *pos != ',')
+                       goto fail;
+               if (*pos == ';')
+                       count++;
+       }
+       if (1 + count * 3 > 0x7f)
+               goto fail;
+
+       info = os_zalloc(2 + 3 + count * 3);
+       if (info == NULL)
+               return -1;
+
+       ipos = info;
+       *ipos++ = 0; /* GUD - Version 1 */
+       *ipos++ = 3 + count * 3; /* User Data Header Length (UDHL) */
+       *ipos++ = 0; /* PLMN List IEI */
+       /* ext(b8) | Length of PLMN List value contents(b7..1) */
+       *ipos++ = 1 + count * 3;
+       *ipos++ = count; /* Number of PLMNs */
+
+       pos = buf;
+       while (pos && *pos) {
+               char *mcc, *mnc;
+               size_t mnc_len;
+
+               mcc = pos;
+               mnc = os_strchr(pos, ',');
+               if (mnc == NULL)
+                       goto fail;
+               *mnc++ = '\0';
+               pos = os_strchr(mnc, ';');
+               if (pos)
+                       *pos++ = '\0';
+
+               mnc_len = os_strlen(mnc);
+               if (os_strlen(mcc) != 3 || (mnc_len != 2 && mnc_len != 3))
+                       goto fail;
+
+               /* BC coded MCC,MNC */
+               /* MCC digit 2 | MCC digit 1 */
+               *ipos++ = ((mcc[1] - '0') << 4) | (mcc[0] - '0');
+               /* MNC digit 3 | MCC digit 3 */
+               *ipos++ = (((mnc_len == 2) ? 0xf0 : ((mnc[2] - '0') << 4))) |
+                       (mcc[2] - '0');
+               /* MNC digit 2 | MNC digit 1 */
+               *ipos++ = ((mnc[1] - '0') << 4) | (mnc[0] - '0');
+       }
+
+       os_free(bss->anqp_3gpp_cell_net);
+       bss->anqp_3gpp_cell_net = info;
+       bss->anqp_3gpp_cell_net_len = 2 + 3 + 3 * count;
+       wpa_hexdump(MSG_MSGDUMP, "3GPP Cellular Network information",
+                   bss->anqp_3gpp_cell_net, bss->anqp_3gpp_cell_net_len);
+
+       return 0;
+
+fail:
+       wpa_printf(MSG_ERROR, "Line %d: Invalid anqp_3gpp_cell_net: %s",
+                  line, buf);
+       os_free(info);
+       return -1;
+}
+
 #endif /* CONFIG_INTERWORKING */
 
 
@@ -2479,6 +2555,9 @@ static int hostapd_config_fill(struct hostapd_config *conf,
                        os_free(bss->domain_name);
                        bss->domain_name = domain_list;
                        bss->domain_name_len = domain_list_len;
+               } else if (os_strcmp(buf, "anqp_3gpp_cell_net") == 0) {
+                       if (parse_3gpp_cell_net(bss, pos, line) < 0)
+                               errors++;
                } else if (os_strcmp(buf, "gas_frag_limit") == 0) {
                        bss->gas_frag_limit = atoi(pos);
                } else if (os_strcmp(buf, "gas_comeback_delay") == 0) {
index 1740b49..f02c3cd 100644 (file)
@@ -1384,6 +1384,10 @@ own_ip_addr=127.0.0.1
 # format: <variable-octet str>[,<variable-octet str>]
 #domain_name=example.com,another.example.com,yet-another.example.com
 
+# 3GPP Cellular Network information
+# format: <MCC1,MNC1>[;<MCC2,MNC2>][;...]
+#anqp_3gpp_cell_net=244,91;310,026;234,56
+
 ##### Hotspot 2.0 #############################################################
 
 # Enable Hotspot 2.0 support
index 4fa1114..c804ec5 100644 (file)
@@ -499,6 +499,7 @@ static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
        os_free(conf->roaming_consortium);
        os_free(conf->venue_name);
        os_free(conf->network_auth_type);
+       os_free(conf->anqp_3gpp_cell_net);
        os_free(conf->domain_name);
 
 #ifdef CONFIG_RADIUS_TEST
index 6a8174d..80f65c5 100644 (file)
@@ -396,6 +396,10 @@ struct hostapd_bss_config {
        u8 ipaddr_type_availability;
        u8 ipaddr_type_configured;
 
+       /* IEEE 802.11u - 3GPP Cellular Network */
+       u8 *anqp_3gpp_cell_net;
+       size_t anqp_3gpp_cell_net_len;
+
        /* IEEE 802.11u - Domain Name */
        u8 *domain_name;
        size_t domain_name_len;
index 249cf46..dfbed39 100644 (file)
@@ -158,6 +158,8 @@ static void anqp_add_capab_list(struct hostapd_data *hapd,
                wpabuf_put_le16(buf, ANQP_ROAMING_CONSORTIUM);
        if (hapd->conf->ipaddr_type_configured)
                wpabuf_put_le16(buf, ANQP_IP_ADDR_TYPE_AVAILABILITY);
+       if (hapd->conf->anqp_3gpp_cell_net)
+               wpabuf_put_le16(buf, ANQP_3GPP_CELLULAR_NETWORK);
        if (hapd->conf->domain_name)
                wpabuf_put_le16(buf, ANQP_DOMAIN_NAME);
        anqp_add_hs_capab_list(hapd, buf);
@@ -225,6 +227,19 @@ static void anqp_add_ip_addr_type_availability(struct hostapd_data *hapd,
 }
 
 
+static void anqp_add_3gpp_cellular_network(struct hostapd_data *hapd,
+                                          struct wpabuf *buf)
+{
+       if (hapd->conf->anqp_3gpp_cell_net) {
+               wpabuf_put_le16(buf, ANQP_3GPP_CELLULAR_NETWORK);
+               wpabuf_put_le16(buf,
+                               hapd->conf->anqp_3gpp_cell_net_len);
+               wpabuf_put_data(buf, hapd->conf->anqp_3gpp_cell_net,
+                               hapd->conf->anqp_3gpp_cell_net_len);
+       }
+}
+
+
 static void anqp_add_domain_name(struct hostapd_data *hapd, struct wpabuf *buf)
 {
        if (hapd->conf->domain_name) {
@@ -257,6 +272,8 @@ gas_serv_build_gas_resp_payload(struct hostapd_data *hapd,
                anqp_add_roaming_consortium(hapd, buf);
        if (request & ANQP_REQ_IP_ADDR_TYPE_AVAILABILITY)
                anqp_add_ip_addr_type_availability(hapd, buf);
+       if (request & ANQP_REQ_3GPP_CELLULAR_NETWORK)
+               anqp_add_3gpp_cellular_network(hapd, buf);
        if (request & ANQP_REQ_DOMAIN_NAME)
                anqp_add_domain_name(hapd, buf);
 
@@ -332,6 +349,12 @@ static void rx_anqp_query_list_id(struct hostapd_data *hapd, u16 info_id,
                             hapd->conf->ipaddr_type_configured,
                             0, 0, qi);
                break;
+       case ANQP_3GPP_CELLULAR_NETWORK:
+               set_anqp_req(ANQP_REQ_3GPP_CELLULAR_NETWORK,
+                            "3GPP Cellular Network",
+                            hapd->conf->anqp_3gpp_cell_net != NULL,
+                            0, 0, qi);
+               break;
        case ANQP_DOMAIN_NAME:
                set_anqp_req(ANQP_REQ_DOMAIN_NAME, "Domain Name",
                             hapd->conf->domain_name != NULL,
index ef71c2d..dc4bf05 100644 (file)
@@ -19,6 +19,8 @@
        (1 << (ANQP_ROAMING_CONSORTIUM - ANQP_QUERY_LIST))
 #define ANQP_REQ_IP_ADDR_TYPE_AVAILABILITY \
        (1 << (ANQP_IP_ADDR_TYPE_AVAILABILITY - ANQP_QUERY_LIST))
+#define ANQP_REQ_3GPP_CELLULAR_NETWORK \
+       (1 << (ANQP_3GPP_CELLULAR_NETWORK - ANQP_QUERY_LIST))
 #define ANQP_REQ_DOMAIN_NAME \
        (1 << (ANQP_DOMAIN_NAME - ANQP_QUERY_LIST))
 #define ANQP_REQ_HS_CAPABILITY_LIST \