mirror of
https://github.com/ncruces/go-sqlite3.git
synced 2026-01-12 22:19:14 +00:00
114 lines
2.6 KiB
Go
114 lines
2.6 KiB
Go
// Package ipaddr provides functions to manipulate IPs and CIDRs.
|
|
//
|
|
// It provides the following functions:
|
|
// - ipcontains(prefix, ip)
|
|
// - ipoverlaps(prefix1, prefix2)
|
|
// - ipfamily(ip/prefix)
|
|
// - iphost(ip/prefix)
|
|
// - ipmasklen(prefix)
|
|
// - ipnetwork(prefix)
|
|
package ipaddr
|
|
|
|
import (
|
|
"errors"
|
|
"net/netip"
|
|
|
|
"github.com/ncruces/go-sqlite3"
|
|
)
|
|
|
|
// Register IP/CIDR functions for a database connection.
|
|
func Register(db *sqlite3.Conn) error {
|
|
const flags = sqlite3.DETERMINISTIC | sqlite3.INNOCUOUS
|
|
return errors.Join(
|
|
db.CreateFunction("ipcontains", 2, flags, contains),
|
|
db.CreateFunction("ipoverlaps", 2, flags, overlaps),
|
|
db.CreateFunction("ipfamily", 1, flags, family),
|
|
db.CreateFunction("iphost", 1, flags, host),
|
|
db.CreateFunction("ipmasklen", 1, flags, masklen),
|
|
db.CreateFunction("ipnetwork", 1, flags, network))
|
|
}
|
|
|
|
func contains(ctx sqlite3.Context, arg ...sqlite3.Value) {
|
|
prefix, err := netip.ParsePrefix(arg[0].Text())
|
|
if err != nil {
|
|
ctx.ResultError(err)
|
|
return // notest
|
|
}
|
|
addr, err := netip.ParseAddr(arg[1].Text())
|
|
if err != nil {
|
|
ctx.ResultError(err)
|
|
return // notest
|
|
}
|
|
ctx.ResultBool(prefix.Contains(addr))
|
|
}
|
|
|
|
func overlaps(ctx sqlite3.Context, arg ...sqlite3.Value) {
|
|
prefix1, err := netip.ParsePrefix(arg[0].Text())
|
|
if err != nil {
|
|
ctx.ResultError(err)
|
|
return // notest
|
|
}
|
|
prefix2, err := netip.ParsePrefix(arg[0].Text())
|
|
if err != nil {
|
|
ctx.ResultError(err)
|
|
return // notest
|
|
}
|
|
ctx.ResultBool(prefix1.Overlaps(prefix2))
|
|
}
|
|
|
|
func family(ctx sqlite3.Context, arg ...sqlite3.Value) {
|
|
addr, err := addr(arg[0].Text())
|
|
if err != nil {
|
|
ctx.ResultError(err)
|
|
return // notest
|
|
}
|
|
switch {
|
|
case addr.Is4():
|
|
ctx.ResultInt(4)
|
|
case addr.Is6():
|
|
ctx.ResultInt(6)
|
|
}
|
|
}
|
|
|
|
func host(ctx sqlite3.Context, arg ...sqlite3.Value) {
|
|
addr, err := addr(arg[0].Text())
|
|
if err != nil {
|
|
ctx.ResultError(err)
|
|
return // notest
|
|
}
|
|
buf, _ := addr.MarshalText()
|
|
ctx.ResultRawText(buf)
|
|
}
|
|
|
|
func masklen(ctx sqlite3.Context, arg ...sqlite3.Value) {
|
|
prefix, err := netip.ParsePrefix(arg[0].Text())
|
|
if err != nil {
|
|
ctx.ResultError(err)
|
|
return // notest
|
|
}
|
|
ctx.ResultInt(prefix.Bits())
|
|
}
|
|
|
|
func network(ctx sqlite3.Context, arg ...sqlite3.Value) {
|
|
prefix, err := netip.ParsePrefix(arg[0].Text())
|
|
if err != nil {
|
|
ctx.ResultError(err)
|
|
return // notest
|
|
}
|
|
buf, _ := prefix.Masked().MarshalText()
|
|
ctx.ResultRawText(buf)
|
|
}
|
|
|
|
func addr(text string) (netip.Addr, error) {
|
|
addr, err := netip.ParseAddr(text)
|
|
if err != nil {
|
|
if prefix, err := netip.ParsePrefix(text); err == nil {
|
|
return prefix.Addr(), nil
|
|
}
|
|
if addrpt, err := netip.ParseAddrPort(text); err == nil {
|
|
return addrpt.Addr(), nil
|
|
}
|
|
}
|
|
return addr, err
|
|
}
|