calculando rede e broadcast com python

Talvez você esteja se perguntando: por que em C é tão simples e com python o inet_aton() não retorna nada útil para ser usado com & (and)? hehe. É que o inet_aton() do python retorna uma string, e com o módulo struct você poderá obter o long int que tanto deseja.

Imagino que seja isso que você procura:

$ ./netcalc.py
use: netcalc.py ip/[mask|cidr]  

$ ./netcalc.py 192.168.0.200/25
cidr=25, effective networks=2, effective hosts=126

address   :    192.168.0.200 (11000000.10101000.00000000.11001000)
netmask   :  255.255.255.128 (11111111.11111111.11111111.10000000)
network   :    192.168.0.128 (11000000.10101000.00000000.10000000)
broadcast :    192.168.0.255 (11000000.10101000.00000000.11111111)  

$ ./netcalc.py 192.168.0.100/255.255.255.240
cidr=28, effective networks=16, effective hosts=14

address   :    192.168.0.100 (11000000.10101000.00000000.01100100)
netmask   :  255.255.255.240 (11111111.11111111.11111111.11110000)
network   :     192.168.0.96 (11000000.10101000.00000000.01100000)
broadcast :    192.168.0.111 (11000000.10101000.00000000.01101111)

Bom, pra facilitar sua vida, já escrevi o código. Ele é bem simples – chega a ser tosco – e não faz nenhum tipo de validação nos endereços IP. na verdade, ele usa que o inet_aton() retorna – isso significa que se você usar o IP 100.200.300 e o inet_aton() permitir, o programa vai retornar algo inesperado.

Este programa usa o módulo bitprint que já postei aqui, pra imprimir o conteúdo binário dos endereços. O cálculo do endereço de rede e broadcast é simples e genérico:

network = ip & netmask
broadcast = ~network ^ netmask

Enfim, segue aí o código:

#!/usr/bin/env python
# coding: utf-8
# netcalc.py 20080318 AF

import sys, bitprint
from struct import pack, unpack
from socket import inet_ntoa, inet_aton

mask = 1L<<31
xnet = (1L<<32)-1
cidr_range = range(9, 32)

def bp(addr):
    buff = []
    bits = str(bitprint.XBits(addr))
    for n in range(4):
        pos = n*8
        buff.append(bits[pos:pos+8])

    return '.'.join(buff)

def cidr_to_netmask(cidr):
    return ((1L<<cidr)-1)<<(32-cidr)

def netmask_to_cidr(netmask):
    cidr = 0
    mm = mask
    for n in range(32):
        if netmask & mm: cidr+=1
        mm>>=1

    return cidr

if __name__ == '__main__':
    try:
        ip_s, temp = sys.argv[1].split('/')
    except:
        print 'use: %s ip/[mask|cidr]' % sys.argv[0]
        sys.exit(1)

    if temp.isdigit():
        cidr = long(temp)
        if cidr not in cidr_range:
            print 'cidr inválido: %d' % cidr
            sys.exit(1)
        nm = cidr_to_netmask(cidr)
    else:
        nm = unpack('>L', inet_aton(temp))[0]
        cidr = netmask_to_cidr(nm)

    ip = unpack('>L', inet_aton(ip_s))[0]
    nw = ip & nm
    bc = (~nw ^ nm) & xnet

    nets = pow(2, cidr%8)
    hosts = pow(2, 32-cidr)-2

    print 'cidr=%d, effective networks=%d, effective hosts=%d\n' % (cidr, nets, hosts)

    print 'address   : % 16s (%s)' % (ip_s, bp(ip))
    print 'netmask   : % 16s (%s)' % (inet_ntoa(pack('>L', nm)), bp(nm))
    print 'network   : % 16s (%s)' % (inet_ntoa(pack('>L', nw)), bp(nw))
    print 'broadcast : % 16s (%s)' % (inet_ntoa(pack('>L', bc)), bp(bc))

Divirta-se!

Anúncios

One Comment on “calculando rede e broadcast com python”

  1. Lucas disse:

    Olá,

    saberia me dizer como eu faria para saber se um IP pertence a uma rede ou não?

    preciso de um programinha em python que veja o IP da máquina local(DHCP) e verifique com um IP que eu vou definir se esse IP que eu definir pertence a sub-rede do DHCP. Finalidade evitar conflitos de IP de rede local com IP de VPN.

    Obrigado,

    Lucas.


Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s