[PATCHv2 13/21] radius: parse tagged vlan information
Michael Braun
michael-dev
Thu Jun 6 03:09:39 PDT 2013
Signed-hostap: Michael Braun <michael-dev at fami-braun.de>
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);
More information about the Hostap
mailing list