subnet masks etc....... 
Author Message
 subnet masks etc.......

logic:                                                                  
   1. given a subnet address and a mask [192.9.111.0 and 255.255.255.224]
   2. and an address [(a) 192.9.111.1 OR (b) 192.9.111.50]              
   3. determine if (a) belongs to a subnet specified in 1. [whereas (b)  
          does NOT]                                                      

Say if I have a file subnets.txt                                        
#subnet | mask                                                          
192.9.111.0|255.255.255.224                                              
192.9.111.0|255.255.255.192                                              

(a) will be validated by the FIRST record/row                            
(b) will be validated by the SECOND record/row                          

Anyone have any leads/tips or snippets I could elaborate on?!



Sat, 07 May 2005 20:51:33 GMT  
 subnet masks etc.......

Quote:
> logic:
>    1. given a subnet address and a mask [192.9.111.0 and 255.255.255.224]
>    2. and an address [(a) 192.9.111.1 OR (b) 192.9.111.50]
>    3. determine if (a) belongs to a subnet specified in 1. [whereas (b)
>           does NOT]

> Say if I have a file subnets.txt
> #subnet | mask
> 192.9.111.0|255.255.255.224
> 192.9.111.0|255.255.255.192

> (a) will be validated by the FIRST record/row
> (b) will be validated by the SECOND record/row

> Anyone have any leads/tips or snippets I could elaborate on?!

Life is easier with gawk and bitwise boolean operators.  Do you have gawk?
Otherwise, seach Google groups for comp.lang.awk "bitwise" for some
solutions to that sub-problem.

You could use FS = "|" and split(ip,ipQuads,".") to break your data lines.

You could use
    /^[ \t]*#/ {next}
to skip your "#" comment lines.

    - Dan



Sat, 07 May 2005 21:36:28 GMT  
 subnet masks etc.......

Quote:

>logic:
>   1. given a subnet address and a mask [192.9.111.0 and 255.255.255.224]
>   2. and an address [(a) 192.9.111.1 OR (b) 192.9.111.50]              
>   3. determine if (a) belongs to a subnet specified in 1. [whereas (b)  
>          does NOT]                                                      

>Say if I have a file subnets.txt                                        
>#subnet | mask                                                          
>192.9.111.0|255.255.255.224                                              
>192.9.111.0|255.255.255.192                                              

>(a) will be validated by the FIRST record/row
>(b) will be validated by the SECOND record/row

>Anyone have any leads/tips or snippets I could elaborate on?!

I usually do this by converting addresses to numbers:

        function iptonum(ip,
                        ipn, n, i) {
                split(ip, ipn, ".")
                n = 0
                for(i = 1; i <= 4; i++) n = n * 256 + ipn[i]
                return n
        }

The converse (although not needed for this job) is:

        function numtoip(n,
                        ip, i) {
                ip = ""
                for(i = 4; i >= 1; i--) {
                        ip = n % 256 "." ip
                        n = int(n / 256)
                }
                return substr(ip, 1, length(ip) - 1)
        }

The next trick is that the number of hosts specified by as given mask is
2^32 - mask value, so the number of hosts specified by 255.255.255.224 is:

        2^32 - iptonum("255.255.255.224")

From there it's a simple matter to implement what you want:

        BEGIN {
                ips = 0
                oldFS = FS
                FS="|"                                # Field sep id |
                while((getline < "subnets.txt") > 0) {
                        gsub(/#.*/, "")               # remove comments
                        if(!NF) continue        # ignore blank lines
                        ips++
                        iplo[ips] = iptonum($1)
                        iphi[ips] = iplo[ips] + (2^32 = iptonum($2))
                }
                close("subnets.txt")
                FS = oldFS
        }

        {
                n = iptonum($1)
                for(i = 1; i <= ips; i++) {
                        if(n >= iplo[i] && n < iphi[i]) {
                                print $1, "valid"
                                break
                        }
                }
                if(i > ips) print $1, "invalid"
        }

Who the heck needs bitwise ops?

-- don



Sun, 08 May 2005 15:32:04 GMT  
 subnet masks etc.......

Quote:


> >logic:
> >   1. given a subnet address and a mask [192.9.111.0 and 255.255.255.224]
> >   2. and an address [(a) 192.9.111.1 OR (b) 192.9.111.50]
> >   3. determine if (a) belongs to a subnet specified in 1. [whereas (b)
> >          does NOT]

> >Say if I have a file subnets.txt
> >#subnet | mask
> >192.9.111.0|255.255.255.224
> >192.9.111.0|255.255.255.192

> >(a) will be validated by the FIRST record/row
> >(b) will be validated by the SECOND record/row

> >Anyone have any leads/tips or snippets I could elaborate on?!

> I usually do this by converting addresses to numbers:

> function iptonum(ip,
> ipn, n, i) {
> split(ip, ipn, ".")
> n = 0
> for(i = 1; i <= 4; i++) n = n * 256 + ipn[i]
> return n
> }

> The converse (although not needed for this job) is:

> function numtoip(n,
> ip, i) {
> ip = ""
> for(i = 4; i >= 1; i--) {
> ip = n % 256 "." ip
> n = int(n / 256)
> }
> return substr(ip, 1, length(ip) - 1)
> }

> The next trick is that the number of hosts specified by as given mask is
> 2^32 - mask value, so the number of hosts specified by 255.255.255.224 is:

> 2^32 - iptonum("255.255.255.224")

> From there it's a simple matter to implement what you want:

> BEGIN {
> ips = 0
> oldFS = FS
> FS="|" # Field sep id |
> while((getline < "subnets.txt") > 0) {
> gsub(/#.*/, "") # remove comments
> if(!NF) continue # ignore blank lines
> ips++
> iplo[ips] = iptonum($1)
> iphi[ips] = iplo[ips] + (2^32 = iptonum($2))
> }
> close("subnets.txt")
> FS = oldFS
> }

> {
> n = iptonum($1)
> for(i = 1; i <= ips; i++) {
> if(n >= iplo[i] && n < iphi[i]) {
> print $1, "valid"
> break
> }
> }
> if(i > ips) print $1, "invalid"
> }

> Who the heck needs bitwise ops?

> -- don

Hi, Don -

I was wondering if you tested your code.  In particular, I'm wondering about
the clause
    (2^32 = iptonum($2))
which looks like an assignment into an expression to me.  (And I sure hate
it when news clients strip code indentation!)

Quote:
> Who the heck needs bitwise ops?

Well, as you've illustrated, not many people NEED bitwise ops.  But here is
an example of how you could use them to your advantage.  Like you, I convert
the dotted-quads to a four-byte integer.

(BTW, your code and mine both fail to duplicate a common "bug" in most IP
code:  that is, we both convert ".010." to 10.  Microsoft's Win2K IP code
(which undoubtedly traces its heritage to Berkely or before) uses a C
library function that sees the leading zero as an indicator that the rest of
the string is to be interpretted as octal.  So the machine at 192.168.1.8
replies to 'ping 192.168.001.010'.)

The CIDR conversion uses the lshift() operation, and the IP comparison
relies on a simple validation for IP-on-subnet, basically
    v = I & M == N
(v: valid; I: IP addr; M: netmask; N: network addr)

Finally, vgersh99 (the OP) seemed to imply that the validation was all that
was required.  Your 'break' does this.  I opted to list all of the subnets a
particular IP could belong to, because it occurred to me that vgersh99's
sample, 192.9.111.1, is valid on both the subnets he presented, and if I
were scanning a network, I might want to know about multiple subnet
membership.

    - Dan

validate.awk
----------
    BEGIN {
        FS = "[.|]"
        while (getline < "subnets.txt" > 0) {
            if (/^[ \t]*#/) continue
            net[++c] = $4+256*($3+256*($2+256*$1))
            m = mask[c] = $8+256*($7+256*($6+256*$5))
            for (cidr = 0; m > 0; m = lshift(m,1)) cidr++
            subnet[c] = gensub(/\|.*$/,"/" cidr,1)
        }
    }
    {
        err = " invalid"
        printf "%s:", $0
        for (i = 1; i <= c; i++)
            if (and($4+256*($3+256*($2+256*$1)),mask[i]) == net[i]) {
                printf " " subnet[i]
                err = ""
            }
        print err
    }

subnets.txt
----------
    #subnet | mask
    192.9.111.0|255.255.255.224
    192.9.111.0|255.255.255.192
    172.16.0.0|255.240.0.0
    172.22.0.0|255.255.0.0

addresses.txt
----------
    192.9.111.1
    192.9.111.50
    192.12.111.50
    192.8.121.12
    172.16.4.2
    172.18.0.1
    172.48.4.4
    172.22.75.251
    172.23.75.251

(output) (gawk 3.1.0/Win98)
----------
    >awk -f validate.awk addresses.txt
    192.9.111.1: 192.9.111.0/27 192.9.111.0/26
    192.9.111.50: 192.9.111.0/26
    192.12.111.50: invalid
    192.8.121.12: invalid
    172.16.4.2: 172.16.0.0/12
    172.18.0.1: 172.16.0.0/12
    172.48.4.4: invalid
    172.22.75.251: 172.16.0.0/12 172.22.0.0/16
    172.23.75.251: 172.16.0.0/12



Mon, 09 May 2005 14:20:55 GMT  
 subnet masks etc.......

Quote:

>I was wondering if you tested your code.  In particular, I'm wondering about
>the clause
>    (2^32 = iptonum($2))
>which looks like an assignment into an expression to me.  (And I sure hate
>it when news clients strip code indentation!)

Whaddaya want for $0?  Tested code?

(I tested the bits, the final edit probably skipped a bit.)

Quote:
>Well, as you've illustrated, not many people NEED bitwise ops.  But here is
>an example of how you could use them to your advantage.  Like you, I convert
>the dotted-quads to a four-byte integer.

I guess I was demonstrating a more general approach; the 2^32 - mask
technique allows you to do things like:

        # ping all addresses in a subnet
        addr = iptonum(address)
        size = 2^32 - iptonum(mask)
        for(ip = addr + 1; ip < addr + size - 1; ip++) # skip net & broadcast
                system("ping -c 1 " numtoip(ip))

Quote:
>(BTW, your code and mine both fail to duplicate a common "bug" in most IP
>code:  that is, we both convert ".010." to 10.  Microsoft's Win2K IP code
>(which undoubtedly traces its heritage to Berkely or before) uses a C
>library function that sees the leading zero as an indicator that the rest of
>the string is to be interpretted as octal.  So the machine at 192.168.1.8
>replies to 'ping 192.168.001.010'.)

Yeah.  The Unix inet_addr() function suffers this flaw, which means
basically everything that can take an IP address.  It's easy enough to
duplicate using the strtonum() function in GAWK 3.1:

        function iptonum(ip,
                        ipn, n, i) {
                split(ip, ipn, ".")
                n = 0
                for(i = 1; i <= 4; i++)
                        n = n * 256 + strtonum(ipn[i])
                return n
        }

In fact there are a few subtleties in inet_addr(), e.g:

        1               -> 0.0.0.1
        1.2             -> 1.0.0.2
        1.2.3           -> 1.2.0.3
        1000000         -> 0.15.66.64
        0xa.013.12.13   -> 10.11.12.13

I think this is horrible unnecessary bug food, but who am I to argue
against 20 years of IP development on Unix boxen?  Again, it's not that
hard to implement using strtonum(), but I don't feel like it right now.

-- don



Mon, 09 May 2005 17:30:19 GMT  
 subnet masks etc.......
Hi,

Quote:

> Whaddaya want for $0?  Tested code?

the whole record, of course.

Stepan



Mon, 09 May 2005 19:31:45 GMT  
 
 [ 6 post ] 

 Relevant Pages 

1. subnet mask of machine running the tcl script

2. maxval,product, etc with mask all false

3. Calculator cgi/Subnet calculator

4. Scanning a Subnet with python?

5. Algorithm etc etc

6. Overloading and / or / = / etc etc

7. Demos, PMode, Graphics, Docs, Tutorials, etc, etc

8. Demos, PMode, Graphics, Docs, Tutorials, etc, etc

9. Embedding Python, PyImport_* etc etc...

10. Is there a standard module library function to access /etc/passwd or /etc/group

11. TOUPPER etc on DEC/VAXstation etc

12. Complicated problems with interpreters, forking, etc. etc. etc...

 

 
Powered by phpBB® Forum Software