summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2011-07-19 13:02:51 +0300
committerTimo Teräs <timo.teras@iki.fi>2011-07-19 13:02:51 +0300
commit604378a88fc348718b01e5ce8a3a77cf976a7065 (patch)
tree3f755bc28ec8feebf1f7fa505a80b1ce109c4941 /src
parent8cfce755734a35f725603aa414b6e9d8e6f0f89c (diff)
downloadsquark-604378a88fc348718b01e5ce8a3a77cf976a7065.tar.bz2
squark-604378a88fc348718b01e5ce8a3a77cf976a7065.tar.xz
auth-snmp: implement Q-BRIDGE-MIB FIB queries
Certain switches seem to export FIB of tagged VLANs only in the Q-BRIDGE-MIB only. Detect if switch support Q-BRIDGE-MIB during information discovery, and prefer it over the older BRIDGE-MIB. Q-BRIDGE-MIB should be used anyway, since it's the only reliable way to trace MAC properly when it appears in multiple VLANs.
Diffstat (limited to 'src')
-rw-r--r--src/squark-auth-snmp.c75
1 files changed, 49 insertions, 26 deletions
diff --git a/src/squark-auth-snmp.c b/src/squark-auth-snmp.c
index f6e8d5b..d9631a0 100644
--- a/src/squark-auth-snmp.c
+++ b/src/squark-auth-snmp.c
@@ -2,7 +2,7 @@
* An external acl helper for Squid which collects authentication
* information about an IP-address from switches via SNMP.
*
- * Copyright (C) 2010 Timo Teräs <timo.teras@iki.fi>
+ * Copyright (C) 2010-2011 Timo Teräs <timo.teras@iki.fi>
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
@@ -11,7 +11,6 @@
*/
/* TODO:
- * - implement Q-BRIDGE-MIB query
* - map vlan names to vlan index
* - print some usage information
* - poll lldpStatsRemTablesLastChangeTime when doing switch update
@@ -33,6 +32,12 @@
#include "authdb.h"
#include "filterdb.h"
+#if 0
+#define dbg_printf(args...) printf(args)
+#else
+#define dbg_printf(args...)
+#endif
+
/* Compile time configurables */
#define SWITCH_HASH_SIZE 128
#define PORT_HASH_SIZE 128
@@ -56,8 +61,9 @@
#define FORMAT_PORT_WEBAUTH 0x80 /* %w */
/* Some info about the switch which we need */
-#define SWITCHF_NO_LLDP 0x01
-#define SWITCHF_BRIDGE_MIB_HAS_VLAN 0x02
+#define SWITCHF_NO_LLDP_MIB 0x01
+#define SWITCHF_NO_Q_BRIDGE_MIB 0x02
+#define SWITCHF_BRIDGE_MIB_HAS_VLAN 0x04
/* IANA-AddressFamilyNumbers */
#define IANA_AFN_OTHER 0
@@ -81,6 +87,10 @@ static const oid IP_MIB_ipNetToPhysicalPhysAddress[] =
{ SNMP_OID_MIB2, 4, 35, 1, 4 };
static const oid BRIDGE_MIB_dot1dTpFdbPort[] =
{ SNMP_OID_MIB2, 17, 4, 3, 1, 2 };
+static const oid Q_BRIDGE_MIB_dot1qVlanVersionNumber_0[] =
+ { SNMP_OID_MIB2, 17, 7, 1, 1, 1, 0 };
+static const oid Q_BRIDGE_MIB_dot1qTpFdbPort[] =
+ { SNMP_OID_MIB2, 17, 7, 1, 2, 2, 1, 2 };
static const oid LLDP_lldpLocSysName[] =
{ 1, 0, 8802, 1, 1, 2, 1, 3, 3, 0 };
static const oid LLDP_lldpRemManAddrIfSubtype[] =
@@ -631,6 +641,9 @@ static blob_t var_parse_type(netsnmp_variable_list **varptr, int asn_tag)
if (var->type != asn_tag)
return BLOB_NULL;
+ if (asn_tag == ASN_INTEGER)
+ return BLOB_PTR_LEN(var->val.integer, sizeof(*var->val.integer));
+
return BLOB_PTR_LEN(var->val.string, var->val_len);
}
@@ -794,9 +807,7 @@ static void auth_query_lldp(struct auth_context *auth, int root_query)
blob_t query;
int i;
- /* printf("Query LLDP info for %s:%d\n", addr_print(&si->addr), spi->port); */
-
- if (si->flags & SWITCHF_NO_LLDP) {
+ if (si->flags & SWITCHF_NO_LLDP_MIB) {
memset(&spi->link_partner, 0, sizeof(spi->link_partner));
cache_update(&spi->cache_control);
return;
@@ -833,8 +844,11 @@ static void auth_query_lldp(struct auth_context *auth, int root_query)
}
snprintf(auth->status_msg, sizeof(auth->status_msg)-1,
- "%s: query LLDP tables (%s)",
- si->session->peername, root_query ? "link" : "lacp slaves");
+ "%s: query LLDP tables (%s, base port %d)",
+ si->session->peername, root_query ? "link" : "lacp slaves",
+ auth->lldp_port[0]);
+ dbg_printf("%s\n", auth->status_msg);
+
cache_talk_snmp(&spi->cache_control, si->session, pdu, auth_handle_lldp_reply, auth);
}
@@ -888,24 +902,30 @@ static void auth_query_fib(struct auth_context *auth)
auth->info_available |= si->info_available;
- /* printf("Probing switch %s\n", addr_print(&si->addr)); */
-
pdu = snmp_pdu_create(SNMP_MSG_GET);
-
- /* FIXME: Implement Q-BRIDGE-MIB query too. */
-
- /* BRIDGE-MIB::dot1dTpFdbPort.<MAC> = INTEGER: port */
- query = BLOB_OID(query_oids);
- blob_push(&query, BLOB_OID(BRIDGE_MIB_dot1dTpFdbPort));
- if (si->flags & SWITCHF_BRIDGE_MIB_HAS_VLAN)
+ if (si->flags & SWITCHF_NO_Q_BRIDGE_MIB) {
+ /* BRIDGE-MIB::dot1dTpFdbPort.<MAC> = INTEGER: port */
+ query = BLOB_OID(query_oids);
+ blob_push(&query, BLOB_OID(BRIDGE_MIB_dot1dTpFdbPort));
+ if (si->flags & SWITCHF_BRIDGE_MIB_HAS_VLAN)
+ blob_push_oid(&query, l2_vlan_ndx);
+ blob_push_oid_dump(&query, BLOB_BUF(auth->mac));
+ query = blob_pushed(BLOB_OID(query_oids), query);
+ snmp_add_null_var(pdu, oid_blob(query));
+ } else {
+ /* Q-BRIDGE-MIB::dot1qTpFdbPort.<VLAN>.<MAC> = INTEGER: port */
+ query = BLOB_OID(query_oids);
+ blob_push(&query, BLOB_OID(Q_BRIDGE_MIB_dot1qTpFdbPort));
blob_push_oid(&query, l2_vlan_ndx);
- blob_push_oid_dump(&query, BLOB_BUF(auth->mac));
- query = blob_pushed(BLOB_OID(query_oids), query);
- snmp_add_null_var(pdu, oid_blob(query));
-
+ blob_push_oid_dump(&query, BLOB_BUF(auth->mac));
+ query = blob_pushed(BLOB_OID(query_oids), query);
+ snmp_add_null_var(pdu, oid_blob(query));
+ }
snprintf(auth->status_msg, sizeof(auth->status_msg)-1,
- "%s: probe FIB",
- si->session->peername);
+ "%s: probe FIB (%sBRIDGE-MIB)",
+ si->session->peername,
+ (si->flags & SWITCHF_NO_Q_BRIDGE_MIB) ? "" : "Q-");
+ dbg_printf("%s\n", auth->status_msg);
auth_talk_snmp(auth, si->session, pdu, auth_handle_fib_reply);
}
@@ -925,7 +945,9 @@ static int auth_handle_switch_info_reply(int oper, netsnmp_session *s, int reqid
si->system_oid = blob_dup(var_parse_type(&var, ASN_OBJECT_ID));
si->system_version = blob_cstr_dup(var_parse_type(&var, ASN_OCTET_STR));
if (blob_is_null(var_parse_type(&var, ASN_OCTET_STR)))
- si->flags |= SWITCHF_NO_LLDP;
+ si->flags |= SWITCHF_NO_LLDP_MIB;
+ if (blob_is_null(var_parse_type(&var, ASN_INTEGER)))
+ si->flags |= SWITCHF_NO_Q_BRIDGE_MIB;
if (si->system_name)
si->info_available |= FORMAT_SWITCH_NAME;
if (si->system_location)
@@ -975,6 +997,7 @@ static void auth_query_switch_info(struct auth_context *auth)
snmp_add_null_var(pdu, oid_const(SNMPv2_MIB_sysObjectID));
snmp_add_null_var(pdu, oid_const(SEMI_MIB_hpHttpMgVersion));
snmp_add_null_var(pdu, oid_const(LLDP_lldpLocSysName));
+ snmp_add_null_var(pdu, oid_const(Q_BRIDGE_MIB_dot1qVlanVersionNumber_0));
cache_talk_snmp(&si->cache_control, si->session, pdu, auth_handle_switch_info_reply, auth);
}
@@ -1151,7 +1174,7 @@ int main(int argc, char **argv)
argv += optind;
if (l3_root == NULL || l3_ifname == NULL || l2_vlan == NULL) {
- printf("Mandatory information missing\n");
+ fprintf(stderr, "Mandatory information missing\n");
return 1;
}