LCOV - code coverage report
Current view: top level - src/ap - vlan_init.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1475438200 Lines: 84 111 75.7 %
Date: 2016-10-02 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /*
       2             :  * hostapd / VLAN initialization
       3             :  * Copyright 2003, Instant802 Networks, Inc.
       4             :  * Copyright 2005-2006, Devicescape Software, Inc.
       5             :  * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
       6             :  *
       7             :  * This software may be distributed under the terms of the BSD license.
       8             :  * See README for more details.
       9             :  */
      10             : 
      11             : #include "utils/includes.h"
      12             : 
      13             : #include "utils/common.h"
      14             : #include "hostapd.h"
      15             : #include "ap_config.h"
      16             : #include "ap_drv_ops.h"
      17             : #include "wpa_auth.h"
      18             : #include "vlan_init.h"
      19             : #include "vlan_util.h"
      20             : 
      21             : 
      22          51 : static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
      23             :                        int existsok)
      24             : {
      25             :         int ret, i;
      26             : 
      27         510 :         for (i = 0; i < NUM_WEP_KEYS; i++) {
      28         204 :                 if (!hapd->conf->ssid.wep.key[i])
      29         204 :                         continue;
      30           0 :                 wpa_printf(MSG_ERROR,
      31             :                            "VLAN: Refusing to set up VLAN iface %s with WEP",
      32           0 :                            vlan->ifname);
      33           0 :                 return -1;
      34             :         }
      35             : 
      36          51 :         if (!iface_exists(vlan->ifname))
      37          51 :                 ret = hostapd_vlan_if_add(hapd, vlan->ifname);
      38           0 :         else if (!existsok)
      39           0 :                 return -1;
      40             :         else
      41           0 :                 ret = 0;
      42             : 
      43          51 :         if (ret)
      44           0 :                 return ret;
      45             : 
      46          51 :         ifconfig_up(vlan->ifname); /* else wpa group will fail fatal */
      47             : 
      48          51 :         if (hapd->wpa_auth)
      49          43 :                 ret = wpa_auth_ensure_group(hapd->wpa_auth, vlan->vlan_id);
      50             : 
      51          51 :         if (ret == 0)
      52          51 :                 return ret;
      53             : 
      54           0 :         wpa_printf(MSG_ERROR, "WPA initialization for VLAN %d failed (%d)",
      55             :                    vlan->vlan_id, ret);
      56           0 :         if (wpa_auth_release_group(hapd->wpa_auth, vlan->vlan_id))
      57           0 :                 wpa_printf(MSG_ERROR, "WPA deinit of %s failed", vlan->ifname);
      58             : 
      59             :         /* group state machine setup failed */
      60           0 :         if (hostapd_vlan_if_remove(hapd, vlan->ifname))
      61           0 :                 wpa_printf(MSG_ERROR, "Removal of %s failed", vlan->ifname);
      62             : 
      63           0 :         return ret;
      64             : }
      65             : 
      66             : 
      67          51 : int vlan_if_remove(struct hostapd_data *hapd, struct hostapd_vlan *vlan)
      68             : {
      69             :         int ret;
      70             : 
      71          51 :         ret = wpa_auth_release_group(hapd->wpa_auth, vlan->vlan_id);
      72          51 :         if (ret)
      73           0 :                 wpa_printf(MSG_ERROR,
      74             :                            "WPA deinitialization for VLAN %d failed (%d)",
      75             :                            vlan->vlan_id, ret);
      76             : 
      77          51 :         return hostapd_vlan_if_remove(hapd, vlan->ifname);
      78             : }
      79             : 
      80             : 
      81        2024 : static int vlan_dynamic_add(struct hostapd_data *hapd,
      82             :                             struct hostapd_vlan *vlan)
      83             : {
      84        4084 :         while (vlan) {
      85          36 :                 if (vlan->vlan_id != VLAN_ID_WILDCARD) {
      86           6 :                         if (vlan_if_add(hapd, vlan, 1)) {
      87           0 :                                 wpa_printf(MSG_ERROR,
      88             :                                            "VLAN: Could not add VLAN %s: %s",
      89           0 :                                            vlan->ifname, strerror(errno));
      90           0 :                                 return -1;
      91             :                         }
      92             : #ifdef CONFIG_FULL_DYNAMIC_VLAN
      93           6 :                         vlan_newlink(vlan->ifname, hapd);
      94             : #endif /* CONFIG_FULL_DYNAMIC_VLAN */
      95             :                 }
      96             : 
      97          36 :                 vlan = vlan->next;
      98             :         }
      99             : 
     100        2024 :         return 0;
     101             : }
     102             : 
     103             : 
     104        2046 : static void vlan_dynamic_remove(struct hostapd_data *hapd,
     105             :                                 struct hostapd_vlan *vlan)
     106             : {
     107             :         struct hostapd_vlan *next;
     108             : 
     109        4128 :         while (vlan) {
     110          36 :                 next = vlan->next;
     111             : 
     112             : #ifdef CONFIG_FULL_DYNAMIC_VLAN
     113             :                 /* vlan_dellink() takes care of cleanup and interface removal */
     114          36 :                 if (vlan->vlan_id != VLAN_ID_WILDCARD)
     115           6 :                         vlan_dellink(vlan->ifname, hapd);
     116             : #else /* CONFIG_FULL_DYNAMIC_VLAN */
     117             :                 if (vlan->vlan_id != VLAN_ID_WILDCARD &&
     118             :                     vlan_if_remove(hapd, vlan)) {
     119             :                         wpa_printf(MSG_ERROR, "VLAN: Could not remove VLAN "
     120             :                                    "iface: %s: %s",
     121             :                                    vlan->ifname, strerror(errno));
     122             :                 }
     123             : #endif /* CONFIG_FULL_DYNAMIC_VLAN */
     124             : 
     125          36 :                 vlan = next;
     126             :         }
     127        2046 : }
     128             : 
     129             : 
     130        2024 : int vlan_init(struct hostapd_data *hapd)
     131             : {
     132             : #ifdef CONFIG_FULL_DYNAMIC_VLAN
     133        2024 :         hapd->full_dynamic_vlan = full_dynamic_vlan_init(hapd);
     134             : #endif /* CONFIG_FULL_DYNAMIC_VLAN */
     135             : 
     136        4021 :         if ((hapd->conf->ssid.dynamic_vlan != DYNAMIC_VLAN_DISABLED ||
     137        2027 :              hapd->conf->ssid.per_sta_vif) &&
     138          30 :             !hapd->conf->vlan) {
     139             :                 /* dynamic vlans enabled but no (or empty) vlan_file given */
     140             :                 struct hostapd_vlan *vlan;
     141          24 :                 vlan = os_zalloc(sizeof(*vlan));
     142          24 :                 if (vlan == NULL) {
     143           0 :                         wpa_printf(MSG_ERROR, "Out of memory while assigning "
     144             :                                    "VLAN interfaces");
     145           0 :                         return -1;
     146             :                 }
     147             : 
     148          24 :                 vlan->vlan_id = VLAN_ID_WILDCARD;
     149          24 :                 os_snprintf(vlan->ifname, sizeof(vlan->ifname), "%s.#",
     150          24 :                             hapd->conf->iface);
     151          24 :                 vlan->next = hapd->conf->vlan;
     152          24 :                 hapd->conf->vlan = vlan;
     153             :         }
     154             : 
     155        2024 :         if (vlan_dynamic_add(hapd, hapd->conf->vlan))
     156           0 :                 return -1;
     157             : 
     158        2024 :         return 0;
     159             : }
     160             : 
     161             : 
     162        2046 : void vlan_deinit(struct hostapd_data *hapd)
     163             : {
     164        2046 :         vlan_dynamic_remove(hapd, hapd->conf->vlan);
     165             : 
     166             : #ifdef CONFIG_FULL_DYNAMIC_VLAN
     167        2046 :         full_dynamic_vlan_deinit(hapd->full_dynamic_vlan);
     168        2046 :         hapd->full_dynamic_vlan = NULL;
     169             : #endif /* CONFIG_FULL_DYNAMIC_VLAN */
     170        2046 : }
     171             : 
     172             : 
     173          45 : struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
     174             :                                        struct hostapd_vlan *vlan,
     175             :                                        int vlan_id,
     176             :                                        struct vlan_description *vlan_desc)
     177             : {
     178             :         struct hostapd_vlan *n;
     179             :         char ifname[IFNAMSIZ + 1], *pos;
     180             : 
     181          45 :         if (vlan == NULL || vlan->vlan_id != VLAN_ID_WILDCARD)
     182           0 :                 return NULL;
     183             : 
     184          45 :         wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d ifname=%s)",
     185          45 :                    __func__, vlan_id, vlan->ifname);
     186          45 :         os_strlcpy(ifname, vlan->ifname, sizeof(ifname));
     187          45 :         pos = os_strchr(ifname, '#');
     188          45 :         if (pos == NULL)
     189           0 :                 return NULL;
     190          45 :         *pos++ = '\0';
     191             : 
     192          45 :         n = os_zalloc(sizeof(*n));
     193          45 :         if (n == NULL)
     194           0 :                 return NULL;
     195             : 
     196          45 :         n->vlan_id = vlan_id;
     197          45 :         if (vlan_desc)
     198          41 :                 n->vlan_desc = *vlan_desc;
     199          45 :         n->dynamic_vlan = 1;
     200             : 
     201          45 :         os_snprintf(n->ifname, sizeof(n->ifname), "%s%d%s", ifname, vlan_id,
     202             :                     pos);
     203             : 
     204          45 :         n->next = hapd->conf->vlan;
     205          45 :         hapd->conf->vlan = n;
     206             : 
     207             :         /* hapd->conf->vlan needs this new VLAN here for WPA setup */
     208          45 :         if (vlan_if_add(hapd, n, 0)) {
     209           0 :                 hapd->conf->vlan = n->next;
     210           0 :                 os_free(n);
     211           0 :                 n = NULL;
     212             :         }
     213             : 
     214          45 :         return n;
     215             : }
     216             : 
     217             : 
     218          96 : int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id)
     219             : {
     220             :         struct hostapd_vlan *vlan;
     221             : 
     222          96 :         if (vlan_id <= 0)
     223           0 :                 return 1;
     224             : 
     225          96 :         wpa_printf(MSG_DEBUG, "VLAN: %s(ifname=%s vlan_id=%d)",
     226          96 :                    __func__, hapd->conf->iface, vlan_id);
     227             : 
     228          96 :         vlan = hapd->conf->vlan;
     229         244 :         while (vlan) {
     230         139 :                 if (vlan->vlan_id == vlan_id && vlan->dynamic_vlan > 0) {
     231          87 :                         vlan->dynamic_vlan--;
     232          87 :                         break;
     233             :                 }
     234          52 :                 vlan = vlan->next;
     235             :         }
     236             : 
     237          96 :         if (vlan == NULL)
     238           9 :                 return 1;
     239             : 
     240          87 :         if (vlan->dynamic_vlan == 0) {
     241          45 :                 vlan_if_remove(hapd, vlan);
     242             : #ifdef CONFIG_FULL_DYNAMIC_VLAN
     243          45 :                 vlan_dellink(vlan->ifname, hapd);
     244             : #endif /* CONFIG_FULL_DYNAMIC_VLAN */
     245             :         }
     246             : 
     247          87 :         return 0;
     248             : }

Generated by: LCOV version 1.10