feat: add registry config, image upload/download, and OCI format support
Backend: - Add registry_address configuration API (GET/POST) - Add tar image upload with OCI and Docker format support - Add image download with streaming optimization - Fix blob download using c.Send (Fiber v3 SendStream bug) - Add registry_address prefix stripping for all OCI v2 endpoints - Add AGENTS.md for project documentation Frontend: - Add settings store with Snackbar notifications - Add image upload dialog with progress bar - Add download state tracking with multi-stage feedback - Replace alert() with MUI Snackbar messages - Display image names without registry_address prefix 🤖 Generated with [Qoder](https://qoder.com)
This commit is contained in:
229
pkg/tool/ip.go
Normal file
229
pkg/tool/ip.go
Normal file
@@ -0,0 +1,229 @@
|
||||
package tool
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
)
|
||||
|
||||
var (
|
||||
privateIPv4Blocks []*net.IPNet
|
||||
privateIPv6Blocks []*net.IPNet
|
||||
)
|
||||
|
||||
func init() {
|
||||
// IPv4私有地址段
|
||||
for _, cidr := range []string{
|
||||
"10.0.0.0/8", // A类私有地址
|
||||
"172.16.0.0/12", // B类私有地址
|
||||
"192.168.0.0/16", // C类私有地址
|
||||
"169.254.0.0/16", // 链路本地地址
|
||||
"127.0.0.0/8", // 环回地址
|
||||
} {
|
||||
_, block, _ := net.ParseCIDR(cidr)
|
||||
privateIPv4Blocks = append(privateIPv4Blocks, block)
|
||||
}
|
||||
|
||||
// IPv6私有地址段
|
||||
for _, cidr := range []string{
|
||||
"fc00::/7", // 唯一本地地址
|
||||
"fe80::/10", // 链路本地地址
|
||||
"::1/128", // 环回地址
|
||||
} {
|
||||
_, block, _ := net.ParseCIDR(cidr)
|
||||
privateIPv6Blocks = append(privateIPv6Blocks, block)
|
||||
}
|
||||
}
|
||||
|
||||
func IsPrivateIP(ipStr string) bool {
|
||||
ip := net.ParseIP(ipStr)
|
||||
if ip == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// 处理IPv4和IPv4映射的IPv6地址
|
||||
if ip4 := ip.To4(); ip4 != nil {
|
||||
for _, block := range privateIPv4Blocks {
|
||||
if block.Contains(ip4) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 处理IPv6地址
|
||||
for _, block := range privateIPv6Blocks {
|
||||
if block.Contains(ip) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func IP2Int(ip net.IP) uint32 {
|
||||
if ip == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
ip = ip.To4()
|
||||
if ip == nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return binary.BigEndian.Uint32(ip)
|
||||
}
|
||||
|
||||
func Int2IP(ip uint32) net.IP {
|
||||
data := make(net.IP, 4)
|
||||
binary.BigEndian.PutUint32(data, ip)
|
||||
return data
|
||||
}
|
||||
|
||||
func IPStr2Int(ipStr string) *uint32 {
|
||||
ip := IP2Int(net.ParseIP(ipStr))
|
||||
if ip == 0 {
|
||||
return nil
|
||||
}
|
||||
return &ip
|
||||
}
|
||||
|
||||
func Int2IPStr(ip uint32) string {
|
||||
return Int2IP(ip).String()
|
||||
}
|
||||
|
||||
func GetLastIP4(cidr string) (lastIP4 uint32, err error) {
|
||||
ip, ipNet, err := net.ParseCIDR(cidr)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
firstIP4 := IP2Int(ip.Mask(ipNet.Mask))
|
||||
ipNetMaskInt := binary.BigEndian.Uint32(ipNet.Mask)
|
||||
lastIP4 = firstIP4 | ^ipNetMaskInt
|
||||
return
|
||||
}
|
||||
|
||||
func IsCIDRConflict(cidr1, cidr2 string) (conflict bool, err error) {
|
||||
_, ipNet1, err := net.ParseCIDR(cidr1)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_, ipNet2, err := net.ParseCIDR(cidr2)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if ipNet2.Contains(ipNet1.IP) || ipNet1.Contains(ipNet2.IP) {
|
||||
conflict = true
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func GetCIDRs(startCIDR, endCIDR string, mask uint8) (cidrs []string, err error) {
|
||||
cidrs = append(cidrs, startCIDR)
|
||||
|
||||
currentCIDR := startCIDR
|
||||
for {
|
||||
lastIP4, err := GetLastIP4(currentCIDR)
|
||||
if err != nil {
|
||||
return cidrs, err
|
||||
}
|
||||
|
||||
nextCIDR := Int2IPStr(lastIP4+1) + fmt.Sprintf("/%d", mask)
|
||||
cidrs = append(cidrs, nextCIDR)
|
||||
|
||||
conflict, err := IsCIDRConflict(nextCIDR, endCIDR)
|
||||
if err != nil {
|
||||
return cidrs, err
|
||||
}
|
||||
if conflict {
|
||||
break
|
||||
}
|
||||
|
||||
currentCIDR = nextCIDR
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func GetLocalIP() (ip string, err error) {
|
||||
ifaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, iface := range ifaces {
|
||||
if iface.Name != "eth0" {
|
||||
continue
|
||||
}
|
||||
|
||||
addrs, err := iface.Addrs()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, addr := range addrs {
|
||||
switch v := addr.(type) {
|
||||
case *net.IPNet:
|
||||
ip = v.IP.String()
|
||||
if ip == "192.168.88.88" {
|
||||
continue
|
||||
}
|
||||
return ip, err
|
||||
case *net.IPAddr:
|
||||
ip = v.IP.String()
|
||||
if ip == "192.168.88.88" {
|
||||
continue
|
||||
}
|
||||
return ip, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ip = "127.0.0.1"
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func LookupIP(host string) (ip string, err error) {
|
||||
ips, err := net.LookupIP(host)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, i := range ips {
|
||||
if ipv4 := i.To4(); ipv4 != nil {
|
||||
ip = ipv4.String()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
func LookupIPv4(host string) (uint32, error) {
|
||||
ips, err := net.LookupIP(host)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
for _, i := range ips {
|
||||
if ipv4 := i.To4(); ipv4 != nil {
|
||||
return binary.BigEndian.Uint32(ipv4), nil
|
||||
}
|
||||
}
|
||||
|
||||
return 0, errors.New("host not found " + host)
|
||||
}
|
||||
|
||||
func ResolveIPv4(host string) (uint32, error) {
|
||||
addr, err := net.ResolveIPAddr("ip4", host)
|
||||
if err == nil && addr != nil {
|
||||
addrV4 := binary.BigEndian.Uint32(addr.IP.To4())
|
||||
|
||||
return addrV4, err
|
||||
}
|
||||
|
||||
return 0, err
|
||||
}
|
||||
Reference in New Issue
Block a user