From patchwork Mon Apr 8 12:36:54 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: michael-dev X-Patchwork-Id: 249369 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from maxx.maxx.shmoo.com (maxx.shmoo.com [205.134.188.171]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "maxx.shmoo.com", Issuer "CA Cert Signing Authority" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 362062C0095 for ; Thu, 6 Jun 2013 20:13:07 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 047029D27E; Thu, 6 Jun 2013 06:12:07 -0400 (EDT) X-Virus-Scanned: amavisd-new at maxx.shmoo.com Received: from maxx.maxx.shmoo.com ([127.0.0.1]) by localhost (maxx.shmoo.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 37QMhHK+xVgs; Thu, 6 Jun 2013 06:12:06 -0400 (EDT) Received: from maxx.shmoo.com (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 5C2479C1C1; Thu, 6 Jun 2013 06:09:41 -0400 (EDT) X-Original-To: mailman-post+hostap@maxx.shmoo.com Delivered-To: mailman-post+hostap@maxx.shmoo.com Received: from localhost (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id A22B19C12A for ; Thu, 6 Jun 2013 06:09:39 -0400 (EDT) X-Virus-Scanned: amavisd-new at maxx.shmoo.com Received: from maxx.maxx.shmoo.com ([127.0.0.1]) by localhost (maxx.shmoo.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 31PXxB3D8ju8 for ; Thu, 6 Jun 2013 06:09:34 -0400 (EDT) Received: from mail.fem.tu-ilmenau.de (mail.fem.tu-ilmenau.de [141.24.101.79]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id D70519C12C for ; Thu, 6 Jun 2013 06:09:09 -0400 (EDT) Received: from localhost (localhost [127.0.0.1]) by mail.fem.tu-ilmenau.de (Postfix) with ESMTP id 9FADB6539 for ; Thu, 6 Jun 2013 12:09:09 +0200 (CEST) X-Virus-Scanned: amavisd-new at fem.tu-ilmenau.de Received: from mail.fem.tu-ilmenau.de ([127.0.0.1]) by localhost (mail.fem.tu-ilmenau.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id F41WEThRqXql; Thu, 6 Jun 2013 12:09:08 +0200 (CEST) Received: from a234.fem.tu-ilmenau.de (unknown [10.42.51.234]) by mail.fem.tu-ilmenau.de (Postfix) with ESMTP; Thu, 6 Jun 2013 12:09:07 +0200 (CEST) Received: by a234.fem.tu-ilmenau.de (Postfix, from userid 0) id 28A1720A673; Thu, 6 Jun 2013 12:09:07 +0200 (CEST) Message-Id: <0aa7f1a71a8b1d66d69ae6adea73e1628a308453.1370512966.git.michael-dev@fami-braun.de> In-Reply-To: References: From: Michael Braun Date: Mon, 8 Apr 2013 14:36:54 +0200 Subject: [PATCHv2 13/21] radius: parse tagged vlan information To: hostap@lists.shmoo.com MIME-Version: 1.0 Cc: projekt-wlan@fem.tu-ilmenau.de X-BeenThere: hostap@lists.shmoo.com X-Mailman-Version: 2.1.11 Precedence: list Reply-To: projekt-wlan@fem.tu-ilmenau.de List-Id: HostAP Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: hostap-bounces@lists.shmoo.com Errors-To: hostap-bounces@lists.shmoo.com Signed-hostap: Michael Braun diff --git a/src/ap/ieee802_11_auth.c b/src/ap/ieee802_11_auth.c index 9d077eb..b6829ba 100644 --- a/src/ap/ieee802_11_auth.c +++ b/src/ap/ieee802_11_auth.c @@ -540,8 +540,14 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req, cache->acct_interim_interval = 0; } - vlan_alloc(&cache->vlan_id, radius_msg_get_vlanid(msg), 0, - NULL); + { + int untagged, num_tagged, *tagged; + num_tagged = radius_msg_get_vlanid(msg, &untagged, + &tagged); + vlan_alloc(&cache->vlan_id, untagged, num_tagged, + tagged); + os_free(tagged); + } decode_tunnel_passwords(hapd, shared_secret, shared_secret_len, msg, req, cache); diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c index 1bc5fb2..1492a43 100644 --- a/src/ap/ieee802_1x.c +++ b/src/ap/ieee802_1x.c @@ -1444,8 +1444,11 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, #ifndef CONFIG_NO_VLAN else { vlan_alloc_copy(&old_vlanid, &sta->vlan_id); - vlan_alloc(&sta->vlan_id, radius_msg_get_vlanid(msg), - 0, NULL); + int *tagged, untagged, num_tagged; + num_tagged = radius_msg_get_vlanid(msg, &untagged, + &tagged); + vlan_alloc(&sta->vlan_id, untagged, num_tagged, tagged); + os_free(tagged); } if (vlan_notempty(&sta->vlan_id) && vlan_untagged(&sta->vlan_id) > 0 && diff --git a/src/radius/radius.c b/src/radius/radius.c index d1feec9..dd5ad91 100644 --- a/src/radius/radius.c +++ b/src/radius/radius.c @@ -214,6 +214,8 @@ static struct radius_attr_type radius_attrs[] = RADIUS_ATTR_INT32 }, { RADIUS_ATTR_EVENT_TIMESTAMP, "Event-Timestamp", RADIUS_ATTR_INT32 }, + { RADIUS_ATTR_EGRESS_VLANID, "Egress-VLANID", + RADIUS_ATTR_INT32 }, { RADIUS_ATTR_NAS_PORT_TYPE, "NAS-Port-Type", RADIUS_ATTR_INT32 }, { RADIUS_ATTR_TUNNEL_TYPE, "Tunnel-Type", RADIUS_ATTR_HEXDUMP }, { RADIUS_ATTR_TUNNEL_MEDIUM_TYPE, "Tunnel-Medium-Type", @@ -1331,10 +1333,15 @@ struct radius_tunnel_attrs { /** * radius_msg_get_vlanid - Parse RADIUS attributes for VLAN tunnel information + * * @msg: RADIUS message - * Returns: VLAN ID for the first tunnel configuration of -1 if none is found + * @untagged: pointer to store untagged vlan_id + * @tagged: pointer to store pointer to tagged list + * + * Returns: number of tagged tunnel configurations, -1 if neither tagged nor + * untagged configuration is found */ -int radius_msg_get_vlanid(struct radius_msg *msg) +int radius_msg_get_vlanid(struct radius_msg *msg, int *untagged, int **tagged) { struct radius_tunnel_attrs tunnel[RADIUS_TUNNEL_TAGS], *tun; size_t i; @@ -1342,8 +1349,17 @@ int radius_msg_get_vlanid(struct radius_msg *msg) const u8 *data; char buf[10]; size_t dlen; + int num_tagged = 0; + int vlan_id; +#ifdef CONFIG_VLAN_TAGGED + int tagged_size = 0, new_size, *tmp; +#endif /* CONFIG_VLAN_TAGGED */ os_memset(&tunnel, 0, sizeof(tunnel)); + if (untagged) + *untagged = 0; + if (tagged) + *tagged = NULL; for (i = 0; i < msg->attr_used; i++) { attr = radius_get_attr_hdr(msg, i); @@ -1380,24 +1396,65 @@ int radius_msg_get_vlanid(struct radius_msg *msg) break; os_memcpy(buf, data, dlen); buf[dlen] = '\0'; + vlan_id = atoi(buf); + if (vlan_id <= 0) + break; tun->tag_used++; - tun->vlanid = atoi(buf); + tun->vlanid = vlan_id; + break; + case RADIUS_ATTR_EGRESS_VLANID: /* RFC 4675 */ + if (attr->length != 6) + break; + vlan_id = WPA_GET_BE24(data + 1); + if (vlan_id <= 0) + break; + if (data[0] == 0x31 && tagged) { /* tagged vlan */ + #ifdef CONFIG_VLAN_TAGGED + if (num_tagged >= tagged_size) { + new_size = 2 * tagged_size; + if (new_size < 1) + new_size = 1; + tmp = os_realloc_array(tagged, + new_size, sizeof(*tagged)); + if (!tmp) + break; + if (tagged_size > 0) + os_memcpy(tmp, *tagged, + sizeof(int) * + tagged_size); + tagged_size = new_size; + *tagged = tmp; + } + (*tagged)[num_tagged] = vlan_id; + num_tagged++; + #endif /* CONFIG_VLAN_TAGGED */ + } else if (data[0] == 0x32 && untagged) { + /* untagged vlan */ + *untagged = vlan_id; + } break; } } + /* use tunnel with lowest tag for untagged vlan id */ for (i = 0; i < RADIUS_TUNNEL_TAGS; i++) { tun = &tunnel[i]; if (tun->tag_used && tun->type == RADIUS_TUNNEL_TYPE_VLAN && tun->medium_type == RADIUS_TUNNEL_MEDIUM_TYPE_802 && - tun->vlanid > 0) - return tun->vlanid; + tun->vlanid > 0 && + untagged) + { + *untagged = tun->vlanid; + break; + } } - return -1; -} + if (!(untagged && *untagged) && !num_tagged) + return -1; + return num_tagged; +} /** * radius_msg_get_tunnel_password - Parse RADIUS attribute Tunnel-Password diff --git a/src/radius/radius.h b/src/radius/radius.h index 2031054..562339e 100644 --- a/src/radius/radius.h +++ b/src/radius/radius.h @@ -79,6 +79,7 @@ enum { RADIUS_ATTR_USER_NAME = 1, RADIUS_ATTR_ACCT_INPUT_GIGAWORDS = 52, RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS = 53, RADIUS_ATTR_EVENT_TIMESTAMP = 55, + RADIUS_ATTR_EGRESS_VLANID = 56, RADIUS_ATTR_NAS_PORT_TYPE = 61, RADIUS_ATTR_TUNNEL_TYPE = 64, RADIUS_ATTR_TUNNEL_MEDIUM_TYPE = 65, @@ -239,7 +240,7 @@ radius_msg_add_attr_user_password(struct radius_msg *msg, const u8 *data, size_t data_len, const u8 *secret, size_t secret_len); int radius_msg_get_attr(struct radius_msg *msg, u8 type, u8 *buf, size_t len); -int radius_msg_get_vlanid(struct radius_msg *msg); +int radius_msg_get_vlanid(struct radius_msg *msg, int *untagged, int **tagged); char * radius_msg_get_tunnel_password(struct radius_msg *msg, int *keylen, const u8 *secret, size_t secret_len, struct radius_msg *sent_msg, size_t n);