#Gorm/Postgresql convert ip_addr into 8bit int.

38 messages · Page 1 of 1 (latest)

twin forge
#

Hi.

So i have strings of an ip address, e.g. 192.168.0.1
I need to get that converted into a 8bit int so 192.168.0.1 would turn into 3232235521
You might think, how does he know what that int is? good question, my coworker managed to get it right in perl.

#! /usr/bin/perl -w

use strict;
use Socket;

my $ip=$ARGV[0];
my $n_ip=inet_aton("$ip");
my $u_ip=unpack("N", $n_ip);
print "IP: $ip - U_IP: $u_ip\n";

So i have something to reference.
My postgres database has the datatype int8, this is what i have so far (and i feel i have tried so many things).

type Host struct {
    DhcpIdentifier     []byte
    DhcpIdentifierType int
    Dhcp4SubnetId      int
    Ipv4Address        int `gorm:"type:inet"`
    Hostname           string
}

payload := res.Payload.Results[0]
ipv4 := *(payload.PrimaryIp4.Address)

dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=5432",
    viper.GetString("psql.hostname"),
    viper.GetString("psql.username"),
    viper.GetString("psql.password"),
    viper.GetString("psql.db"))
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
if err != nil {
    log.Error(err)
    os.Exit(0)
}

result := db.Create(&Host{
    DhcpIdentifier:     mac,
    DhcpIdentifierType: 0,
    Dhcp4SubnetId:      subnet,
    Ipv4Address:        ipv4,
    Hostname:           Name,
})

if result.Error != nil {
    log.Error(result.Error)
    os.Exit(0)
}
pale prairie
#

you cant put ip4 in int8. ip4 is 4byte, 32bit. you need atleast int32.

#

int8 is single byte. if you dont want to store it as string, you can store it as raw bytes and it'll take less space. postgre also has inet native type, it handle both ip4 and ip6.

twin forge
#

i can't modify my postgres.
the database is from a software i use.

and the perl i posted, works just fine to be put into the postgres, so it must be possible to do the same in go.
that's why i posted the perl part too

pale prairie
#

what is the datatype in the db?

#

for Ipv4Address ?

twin forge
#

int8

pale prairie
#

try remove gorm:"type:inet"

#

my bad. postgre int8 is int64 in go

twin forge
#

ah

#

so 1. i should change my type from int to int64

pale prairie
#

just int should be fine, in 64bit cpu (who use 32bit cpu now days?)

twin forge
#

true 😛

pale prairie
#

i think the problem is gorm:"type:inet", it hint gorm to use inet type.

twin forge
#

it was a shot from me last night to see if it worked

#

it didn't

#

so i'm basically up for anything that can convert the string

pale prairie
twin forge
#

ya was just about say i could use parse

#

nice, i will test it right now hyperWOW

#

so i added.

func ip2int(ip net.IP) uint32 {
    if len(ip) == 16 {
        panic("no sane way to convert ipv6 into uint32")
    }
    return binary.BigEndian.Uint32(ip)
}

And using it just simply like this for testing:

ipv4Str := *(payload.PrimaryIp4.Address)
log.Info(ipv4Str)
ipv4 := ip2int(net.ParseIP(ipv4Str))
log.Info(ipv4)

but i get.

panic: runtime error: index out of range [3] with length 0

goroutine 1 [running]:
encoding/binary.bigEndian.Uint32(...)
        /usr/local/go/src/encoding/binary/binary.go:157
pale prairie
#

length 0 means net.ParseIP return nil

#

probably, the input is not ip

pale prairie
#

net package has ParseCIDR to handle ip with subnet

twin forge
#

ah, ya.. was doing a strings.split KEK already knew it was ugly and kinda stupid

#

with the split i got to this though:
panic: no sane way to convert ipv6 into uint32

#

so the error message from that function

pale prairie
#

yup, call .To4() it'll make sure that the ip can be represented as ip4.

twin forge
#

so down that github gist you sent, they do link to praserx/ipconv that does.

func IPv4ToInt(ipaddr net.IP) (uint32, error) {
    if ipaddr.To4() == nil {
        return 0, ErrNotIPv4Address
    }
    return binary.BigEndian.Uint32(ipaddr.To4()), nil
}

is that betteR?

#

heck it works!