aten-ipmi-tools/main.go
Davíð Steinn Geirsson facd13cb38 fix: address code review findings
- Guard uint32 underflow in CSW residue calculation
- Use net.JoinHostPort for IPv6 compatibility
- Add LBA bounds checking in Read10/Read12
- Clean up redundant byte writes in ReadFormatCapacities

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 00:53:51 +00:00

102 lines
2.4 KiB
Go

package main
import (
"flag"
"fmt"
"log"
"net"
"os"
"os/signal"
"syscall"
"time"
)
func main() {
user := flag.String("u", "admin", "BMC username")
pass := flag.String("p", "admin", "BMC password")
port := flag.Int("port", 623, "BMC virtual media TCP port")
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage: %s [flags] <bmc-host> <image.iso>\n\nFlags:\n", os.Args[0])
flag.PrintDefaults()
}
flag.Parse()
if flag.NArg() != 2 {
flag.Usage()
os.Exit(1)
}
host := flag.Arg(0)
isoPath := flag.Arg(1)
// Open and validate ISO file
isoFile, err := os.Open(isoPath)
if err != nil {
log.Fatalf("open ISO: %v", err)
}
defer isoFile.Close()
isoInfo, err := isoFile.Stat()
if err != nil {
log.Fatalf("stat ISO: %v", err)
}
isoSize := isoInfo.Size()
if isoSize < 0x8054 {
log.Fatalf("ISO file too small (%d bytes)", isoSize)
}
totalSectors := uint32(isoSize / 2048)
log.Printf("ISO: %s (%d bytes, %d sectors)", isoPath, isoSize, totalSectors)
// TCP connect
addr := net.JoinHostPort(host, fmt.Sprintf("%d", *port))
log.Printf("Connecting to %s...", addr)
conn, err := net.DialTimeout("tcp", addr, 10*time.Second)
if err != nil {
log.Fatalf("connect: %v", err)
}
defer conn.Close()
log.Printf("Connected")
// Send PlugIn packet
pluginPkt := buildPlugInPacket(*user, *pass)
if _, err := conn.Write(pluginPkt); err != nil {
log.Fatalf("send plugin: %v", err)
}
log.Printf("Sent PlugIn packet (%d bytes)", len(pluginPkt))
// Read mount status
status, err := readMountStatus(conn)
if err != nil {
log.Fatalf("mount status: %v", err)
}
if status != 0x00 {
log.Fatalf("mount failed: %s", mountStatusString(status))
}
log.Printf("Mount OK")
// Send SetEP command
if _, err := conn.Write(buildSetEPPacket()); err != nil {
log.Fatalf("send setep: %v", err)
}
log.Printf("Sent SetEP, entering SCSI command loop")
// Signal handling for clean unmount
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
// SCSI command loop
dev := &SCSIDevice{
file: isoFile,
totalSectors: totalSectors,
sense: initialSenseData(),
}
err = commandLoop(conn, dev, sigCh)
// Clean unmount
log.Printf("Sending unmount...")
conn.Write(buildUnmountPacket())
if err != nil {
log.Fatalf("command loop: %v", err)
}
log.Printf("Unmounted cleanly")
}