dongwei7913 2016-11-10 07:23
浏览 55

反向转换整数以反向生成IP

I wanted to generate IP in reverse order.

Functionality which generate IP address is as follow:

val := 1<<(32-prefixLen) // let take prefixLen as 24
IP4(val) = IP4(256) = 0.0.1.0

I wanted the IP in reverse order i.e., 0.1.0.0, so convert the val in reverse order bytes and send it to IP4() function.

Functionality which I have tried resulted in integer overflow:

temp1:=byte(val*0xff<<24)    
temp2:=byte(val*0xff00<<16)   
temp3:=byte(val*0xff0000<<8)
temp4:=byte(val*0xff000000)  
valReverse := uint32(temp4)|uint32(temp3)|uint32(temp2)|uint32(temp1)
IP4(valReverse)=0.1.0.0 //expected
  • 写回答

1条回答 默认 最新

  • donglu5047 2016-11-10 07:44
    关注

    Reversing bytes

    First, you have to use uint32 type instead of byte as a byte value only has 8 bits (bit positions above 8 don't exist).

    Next, you have to use bitwise AND which is & and not the multiplication *.

    Third, the shift values are incorrect. See this working example:

    prefixLen := uint32(24)
    
    var val uint32
    val = 1 << (32 - prefixLen)
    fmt.Printf("%08x
    ", val)
    
    temp1 := uint32(val & 0xff << 24)
    temp2 := uint32(val & 0xff00 << 8)
    temp3 := uint32(val & 0xff0000 >> 8)
    temp4 := uint32(val & 0xff000000 >> 24)
    valReverse := uint32(temp4) | uint32(temp3) | uint32(temp2) | uint32(temp1)
    
    fmt.Printf("%08x
    ", valReverse)
    

    Output (try it on the Go Playground):

    00000100
    00010000
    

    But personally I would just use the net.IP type which models an IP address with a byte slice, and using that you can simply reverse the bytes with a slice-reversing algorithm.

    This is how it would look like:

    ip := net.IPv4(0, 0, 1, 0).To4()
    fmt.Println(ip)
    
    // Reverse:
    for i, j := 0, len(ip)-1; i < j; i, j = i+1, j-1 {
        ip[i], ip[j] = ip[j], ip[i]
    }
    fmt.Println(ip)
    

    Output (try it on the Go Playground):

    0.0.1.0
    0.1.0.0
    

    Note: if you have the IP as a value of uint32, you can still use the net.IP type, creating the net.IP value like this:

    ip := net.IPv4(byte(val>>24), byte(val>>16), byte(val>>8), byte(val)).To4()
    

    Reversing bits

    If you want to reverse bits, you have to do that bit-by-bit. One possible solution is this:

    prefixLen := uint32(24)
    
    var val uint32
    val = 1 << (32 - prefixLen)
    fmt.Printf("%08x
    ", val)
    
    var valReverse uint32
    for i := 0; i < 32; i, val = i+1, val>>1 {
        valReverse = valReverse<<1 | val&0x01
    }
    fmt.Printf("%08x
    ", valReverse)
    

    Output (try it on the Go Playground):

    00000100
    00800000
    

    An alternative, maybe more complex way to reverse the bits:

    var valReverse uint32
    for mask1, mask2 := uint32(0x01), uint32(0x80000000); mask2 != 0; mask1, mask2 = mask1<<1, mask2>>1 {
        if val&mask1 != 0 {
            valReverse |= mask2
        }
    }
    

    Output is the same, try this variant on the Go Playground.

    评论

报告相同问题?