mirror of
https://github.com/Team254/cheesy-arena-lite.git
synced 2026-03-09 21:56:50 -04:00
150 lines
4.1 KiB
Go
150 lines
4.1 KiB
Go
// Copyright 2014 Team 254. All Rights Reserved.
|
|
// Author: pat@patfairbank.com (Patrick Fairbank)
|
|
//
|
|
// Methods for configuring a Cisco Aironet AP1252AG access point for team SSIDs and VLANs.
|
|
|
|
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"fmt"
|
|
"net"
|
|
"regexp"
|
|
"strconv"
|
|
"sync"
|
|
)
|
|
|
|
const aironetTelnetPort = 23
|
|
const (
|
|
red1Vlan = 11
|
|
red2Vlan = 12
|
|
red3Vlan = 13
|
|
blue1Vlan = 14
|
|
blue2Vlan = 15
|
|
blue3Vlan = 16
|
|
)
|
|
|
|
var aironetMutex sync.Mutex
|
|
|
|
// Sets up wireless networks for the given set of teams.
|
|
func ConfigureTeamWifi(red1, red2, red3, blue1, blue2, blue3 *Team) error {
|
|
for _, team := range []*Team{red1, red2, red3, blue1, blue2, blue3} {
|
|
if team != nil && (len(team.WpaKey) < 8 || len(team.WpaKey) > 63) {
|
|
return fmt.Errorf("Invalid WPA key '%s' configured for team %d.", team.WpaKey, team.Id)
|
|
}
|
|
}
|
|
|
|
// Determine what new SSIDs are needed and build the commands to set them up.
|
|
oldSsids, err := getSsids()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
addSsidsCommand := ""
|
|
associateSsidsCommand := ""
|
|
replaceSsid := func(team *Team, vlan int) {
|
|
if team == nil {
|
|
return
|
|
}
|
|
if oldSsids[strconv.Itoa(team.Id)] == vlan {
|
|
delete(oldSsids, strconv.Itoa(team.Id))
|
|
} else {
|
|
addSsidsCommand += fmt.Sprintf("dot11 ssid %d\nvlan %d\nauthentication open\nauthentication "+
|
|
"key-management wpa version 2\nmbssid guest-mode\nwpa-psk ascii %s\n", team.Id, vlan, team.WpaKey)
|
|
associateSsidsCommand += fmt.Sprintf("ssid %d\n", team.Id)
|
|
}
|
|
}
|
|
replaceSsid(red1, red1Vlan)
|
|
replaceSsid(red2, red2Vlan)
|
|
replaceSsid(red3, red3Vlan)
|
|
replaceSsid(blue1, blue1Vlan)
|
|
replaceSsid(blue2, blue2Vlan)
|
|
replaceSsid(blue3, blue3Vlan)
|
|
if len(addSsidsCommand) != 0 {
|
|
associateSsidsCommand = "interface Dot11Radio1\n" + associateSsidsCommand
|
|
}
|
|
|
|
// Build the command to remove the SSIDs that are no longer needed.
|
|
removeSsidsCommand := ""
|
|
for ssid, _ := range oldSsids {
|
|
removeSsidsCommand += fmt.Sprintf("no dot11 ssid %s\n", ssid)
|
|
}
|
|
|
|
command := removeSsidsCommand + addSsidsCommand + associateSsidsCommand
|
|
if len(command) > 0 {
|
|
_, err = runAironetConfigCommand(removeSsidsCommand + addSsidsCommand + associateSsidsCommand)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Returns a map of currently-configured SSIDs to VLANs.
|
|
func getSsids() (map[string]int, error) {
|
|
// Get the entire config dump.
|
|
config, err := runAironetCommand("show running-config\n")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Parse out the SSIDs and VLANs from the config dump.
|
|
re := regexp.MustCompile("(?s)dot11 ssid (\\w+)\\s+vlan (\\d+)")
|
|
ssidMatches := re.FindAllStringSubmatch(config, -1)
|
|
if ssidMatches == nil {
|
|
// There are probably no SSIDs currently configured.
|
|
return nil, nil
|
|
}
|
|
|
|
// Build the map of SSID to VLAN.
|
|
ssids := make(map[string]int)
|
|
for _, match := range ssidMatches {
|
|
vlan, _ := strconv.Atoi(match[2])
|
|
ssids[match[1]] = vlan
|
|
}
|
|
return ssids, nil
|
|
}
|
|
|
|
// Logs into the Aironet via Telnet and runs the given command in user exec mode. Reads the output and returns
|
|
// it as a string.
|
|
func runAironetCommand(command string) (string, error) {
|
|
// Make sure multiple commands aren't being run at the same time.
|
|
aironetMutex.Lock()
|
|
defer aironetMutex.Unlock()
|
|
|
|
// Open a Telnet connection to the AP.
|
|
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", eventSettings.ApAddress, aironetTelnetPort))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer conn.Close()
|
|
|
|
// Login to the AP, send the command, and log out all at once.
|
|
writer := bufio.NewWriter(conn)
|
|
_, err = writer.WriteString(fmt.Sprintf("%s\n%s\nterminal length 0\n%sexit\n", eventSettings.ApUsername,
|
|
eventSettings.ApPassword, command))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
err = writer.Flush()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// Read the response.
|
|
var reader bytes.Buffer
|
|
_, err = reader.ReadFrom(conn)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return reader.String(), nil
|
|
}
|
|
|
|
// Logs into the Aironet via Telnet and runs the given command in global configuration mode. Reads the output
|
|
// and returns it as a string.
|
|
func runAironetConfigCommand(command string) (string, error) {
|
|
return runAironetCommand(fmt.Sprintf("config terminal\n%send\ncopy running-config startup-config\n\n",
|
|
command))
|
|
}
|