Files
network-topology-discovery/internal/device/windows.go
T
Your Name d0927cbad5 Initial commit: 网络拓扑发现系统
- 支持Cisco、华为、H3C、ASA、Linux、Windows设备
- SSH远程采集设备信息
- 自动发现网络拓扑(LLDP/CDP)
- Web可视化界面
- 支持旧版SSH加密算法兼容
2026-04-25 22:35:51 +08:00

201 lines
4.9 KiB
Go

package device
import (
"fmt"
"network-topology-discovery/pkg/models"
"strings"
)
// WindowsParser Windows Server解析器
type WindowsParser struct {
BaseParser
}
// GetCommands 获取Windows命令列表
func (p *WindowsParser) GetCommands() []string {
return []string{
"hostname",
"systeminfo | findstr /B /C:\"OS Name\" /C:\"OS Version\"",
"Get-NetAdapter | Select-Object Name, InterfaceDescription, Status, MacAddress, LinkSpeed | Format-List",
"Get-NetIPAddress | Where-Object AddressFamily -eq IPv4 | Select-Object InterfaceAlias, IPAddress, PrefixLength | Format-List",
"systeminfo | findstr /B /C:\"System Boot Time\"",
}
}
// Parse 解析Windows输出
func (p *WindowsParser) Parse(device *models.Device, outputs []string) error {
if len(outputs) < 5 {
return fmt.Errorf("insufficient command outputs")
}
device.Hostname = strings.TrimSpace(outputs[0])
device.OSVersion = p.parseOSVersion(outputs[1])
device.Uptime = p.parseUptime(outputs[4])
device.Interfaces = p.parseInterfaces(outputs[2], outputs[3])
return nil
}
func (p *WindowsParser) parseOSVersion(output string) string {
lines := strings.Split(output, "\n")
var osInfo []string
for _, line := range lines {
if strings.Contains(line, "OS Name") || strings.Contains(line, "OS Version") {
parts := strings.SplitN(line, ":", 2)
if len(parts) == 2 {
osInfo = append(osInfo, strings.TrimSpace(parts[1]))
}
}
}
return strings.Join(osInfo, ", ")
}
func (p *WindowsParser) parseUptime(output string) string {
if strings.Contains(output, "System Boot Time") {
parts := strings.SplitN(output, ":", 2)
if len(parts) == 2 {
return strings.TrimSpace(parts[1])
}
}
return output
}
func (p *WindowsParser) parseInterfaces(adapterOutput, ipOutput string) []models.Interface {
var interfaces []models.Interface
// 解析网卡信息
adapters := p.parseNetAdapters(adapterOutput)
// 解析IP信息
ipMap := p.parseIPAddresses(ipOutput)
// 合并信息
for _, adapter := range adapters {
iface := adapter
if ipInfo, ok := ipMap[adapter.Name]; ok {
iface.IP = ipInfo.IP
iface.Mask = ipInfo.Mask
}
interfaces = append(interfaces, iface)
}
return interfaces
}
func (p *WindowsParser) parseNetAdapters(output string) []models.Interface {
var interfaces []models.Interface
var currentInterface *models.Interface
lines := strings.Split(output, "\n")
for _, line := range lines {
line = strings.TrimSpace(line)
if line == "" {
continue
}
if strings.Contains(line, "Name") && strings.Contains(line, ":") {
if currentInterface != nil {
interfaces = append(interfaces, *currentInterface)
}
parts := strings.SplitN(line, ":", 2)
if len(parts) == 2 {
currentInterface = &models.Interface{
Name: strings.TrimSpace(parts[1]),
}
}
}
if currentInterface != nil {
if strings.Contains(line, "InterfaceDescription") {
parts := strings.SplitN(line, ":", 2)
if len(parts) == 2 {
currentInterface.Description = strings.TrimSpace(parts[1])
}
}
if strings.Contains(line, "Status") {
parts := strings.SplitN(line, ":", 2)
if len(parts) == 2 {
status := strings.TrimSpace(parts[1])
if status == "Up" {
currentInterface.Status = "up"
} else {
currentInterface.Status = "down"
}
}
}
if strings.Contains(line, "MacAddress") {
parts := strings.SplitN(line, ":", 2)
if len(parts) == 2 {
currentInterface.MAC = strings.TrimSpace(parts[1])
}
}
if strings.Contains(line, "LinkSpeed") {
parts := strings.SplitN(line, ":", 2)
if len(parts) == 2 {
currentInterface.Speed = strings.TrimSpace(parts[1])
}
}
}
}
if currentInterface != nil {
interfaces = append(interfaces, *currentInterface)
}
return interfaces
}
type ipInfo struct {
IP string
Mask string
}
func (p *WindowsParser) parseIPAddresses(output string) map[string]ipInfo {
ipMap := make(map[string]ipInfo)
var currentAlias string
lines := strings.Split(output, "\n")
for _, line := range lines {
line = strings.TrimSpace(line)
if line == "" {
continue
}
if strings.Contains(line, "InterfaceAlias") {
parts := strings.SplitN(line, ":", 2)
if len(parts) == 2 {
currentAlias = strings.TrimSpace(parts[1])
}
}
if strings.Contains(line, "IPAddress") && currentAlias != "" {
parts := strings.SplitN(line, ":", 2)
if len(parts) == 2 {
if _, ok := ipMap[currentAlias]; !ok {
ipMap[currentAlias] = ipInfo{}
}
info := ipMap[currentAlias]
info.IP = strings.TrimSpace(parts[1])
ipMap[currentAlias] = info
}
}
if strings.Contains(line, "PrefixLength") && currentAlias != "" {
parts := strings.SplitN(line, ":", 2)
if len(parts) == 2 {
if _, ok := ipMap[currentAlias]; !ok {
ipMap[currentAlias] = ipInfo{}
}
info := ipMap[currentAlias]
info.Mask = strings.TrimSpace(parts[1])
ipMap[currentAlias] = info
}
}
}
return ipMap
}