I have this form:
class NetworkInput(forms.Form):
IP = forms.GenericIPAddressField()
Netmask = forms.IntegerField()
The users should be able to enter an IPv4 or an IPv6 address.
Depending of the IP version the validation of Netmask should look like this:
import ipcalc
IP = ipcalc.IP(IP)
if IP.version() == 4:
if Netmask > 29:
raise ValidationError(u'%s is not big enough' % value)
else:
if Netmask > 125:
raise ValidationError(u'%s is not big enough' % value)
But I don't know how to access the variable IP when validating the Netmask.
As explained in the django docs at https://docs.djangoproject.com/en/1.5/ref/forms/validation/#cleaning-and-validating-fields-that-depend-on-each-other
create a clean() method that does the combined validation, e.g
def clean(self):
IP = self.cleaned_data['IP']
Netmask = self.cleaned_data['Netmask']
IP = ipcalc.IP(IP)
if IP.version() == 4:
if Netmask > 29:
raise ValidationError(u'%s is not big enough' % value)
else:
if Netmask > 125:
raise ValidationError(u'%s is not big enough' % value)
Related
I have the following MicroPython code running on an ESP32:
import network
wlan_sta = network.WLAN(network.STA_IF)
wlan_sta.active(True)
wlan_mac = wlan_sta.config('mac')
print("MAC Address:", wlan_mac) # Show MAC for peering
The output looks like this:
MAC Address: b'0\xae\xa4z\xa7$'
I would like to display it in the more familiar format of six pairs of hex digits, like this:
MAC Address: AABBCC112233
After searching for a solution on the internet, I've tried:
print("MAC Address:", str(wlan_mac)) but it displays the same as when not using str()
print("MAC Address:", hex(wlan_mac)) but it results in TypeError: can't convert bytes to int
print("MAC Address:", wlan_mac.hex()) but it says AttributeError: 'bytes' object has no attribute 'hex'
I am also a little suspicious of the bytes retrieved from wlan_sta.config('mac'). I would have expected something that looked more like b'\xaa\xbb\xcc\x11\x22\x33' instead of b'0\xae\xa4z\xa7$'. The z and the $ seem very out of place for something that should be hexadecimal and it seems too short for what should be six pairs of digits.
So my question is two-fold:
Am I using the correct method to get the MAC address?
If it is correct, how can I format it as six pairs of hex digits?
I am also a little suspicious of the bytes retrieved from wlan_sta.config('mac'). I would have expected something that looked more like b'\xaa\xbb\xcc\x11\x22\x33' instead of b'0\xae\xa4z\xa7$'. The z and the $ seem very out of place for something that should be hexadecimal and it seems too short for what should be six pairs of digits.
You're not getting back a hexadecimal string, you're getting a byte string. So if the MAC address contains the value 7A, then the byte string will contain z (which has ASCII value 122 (hex 7A)).
Am I using the correct method to get the MAC address?
You are!
If it is correct, how can I format it as six pairs of hex digits?
If you want to print the MAC address as a hex string, you can use the
ubinascii.hexlify method:
>>> import ubinascii
>>> import network
>>> wlan_sta = network.WLAN(network.STA_IF)
>>> wlan_sta.active(True)
>>> wlan_mac = wlan_sta.config('mac')
>>> print(ubinascii.hexlify(wlan_mac).decode())
30aea47aa724
Or maybe:
>>> print(ubinascii.hexlify(wlan_mac).decode().upper())
30AEA47AA724
You can use:
def wifi_connect(ssid, pwd):
sta_if = None
import network
sta_if = network.WLAN(network.STA_IF)
if not sta_if.isconnected():
print("connecting to network...")
sta_if.active(True)
sta_if.connect(ssid, pwd)
while not sta_if.isconnected():
pass
print("----------------------------------------")
print("network config:", sta_if.ifconfig())
print("----------------------------------------")
get_my_mac_addr(sta_if)
Then:
def get_my_mac_addr(sta_if):
import ubinascii
import network
wlan_mac = sta_if.config('mac')
my_mac_addr = ubinascii.hexlify(wlan_mac).decode()
my_mac_addr = format_mac_addr(my_mac_addr)
Then:
def format_mac_addr(addr):
mac_addr = addr
mac_addr = mac_addr.upper()
new_mac = ""
for i in range(0, len(mac_addr),2):
#print(mac_addr[i] + mac_addr[i+1])
if (i == len(mac_addr) - 2):
new_mac = new_mac + mac_addr[i] + mac_addr[i+1]
else:
new_mac = new_mac + mac_addr[i] + mac_addr[i+1] + ":"
print("----------------------------------------")
print("My MAC Address:" + new_mac)
print("----------------------------------------")
return new_mac
Return:
----------------------------------------
My MAC Address:xx:xx:xx:xx:xx:xx
----------------------------------------
Does Ruby have a simple way to convert a range of IP addresses to CIDR?
I know in Python we can do it like this:
cidr = netaddr.iprange_to_cidrs(startip, endip)
I've looked to other questions here at StackOverflow and none of them are about converting a range of IP addresses to a single CIDR, like:
startip = '250.154.64.0'
endip = '250.154.64.255'
output: '250.154.64.0/24'
Found it!
require 'netaddr'
startip = '250.154.64.0'
endip = '250.154.64.255'
ip_net_range = NetAddr.range(startip, endip, :Inclusive => true, :Objectify => true)
cidrs = NetAddr.merge(ip_net_range, :Objectify => true)
puts cidrs
output: 250.154.64.0/24
I am working on code, and trying to add ipv6 support. The following code is in the current code base for ipv4 support. The code takes a ipv4 ip address and gets the subnet mask for the address on a /32.
// string of ip address
networkInterface["ip_address"] = v.IpAddress[0]
m := net.CIDRMask(v.IpConfig.IpAddress[0].PrefixLength, 32)
subnetMask := net.IPv4(m[0], m[1], m[2], m[3])
networkInterface["subnet_mask"] = subnetMask.String()
I know that net.CIDRMask works with ipv6, I am uncertain how to use it with an ipv6 address.
I am now testing the ip address to determine if the address is ipv4 or ipv6:
testInput := net.ParseIP(v.IpAddress[0])
if testInput.To4() != nil {
// find ipv4 subnet mask
}
if testInput.To16() != nil {
// do ipv6 subnet mask
}
The unit tests for net.CIDRMask have examples working with ipv6 located here: https://golang.org/src/net/ip_test.go
But it is beyond both my golang experience and ipv6 knowledge.
While RTFM'ing the docs https://golang.org/pkg/net/#CIDRMask mention:
func CIDRMask(ones, bits int) IPMask
CIDRMask returns an IPMask consisting of `ones' 1 bits followed by 0s
up to a total length of `bits' bits. For a mask of this form, CIDRMask
is the inverse of IPMask.Size.
So what values do I use for ones and bits?
This is what is comming back from the api:
$ govc vm.info -json vcsa | jq .VirtualMachines[0].Guest.Net[0].IpConfig.IpAddress [ {
"IpAddress": "10.20.128.218",
"PrefixLength": 22,
"Origin": "",
"State": "preferred",
"Lifetime": null } ]
Thanks in advance!
I'm not sure what PrefixLength is, it may be some field defined in one of your structs, but it doesn't appear to be a field on anything in the net package, or in fact anywhere in the standard library: https://golang.org/search?q=PrefixLength.
So I'm not sure what PrefixLength is expected to give, but, I can tell you:
IPv4 addresses consist of 32 bits of data (256 x 256 x 256 x 256 total IPs), so when dealing with IPv4, the value for the bits argument to net.CIDRMask should be 32.
IPv4 addresses have 128 bits of data, so the bits argument is 128.
The subnet mask for a CIDR range corresponding to a single IP will have the maximum number of ones, so the ones value is 32 or 128, depending on whether you're talking IPv4 or IPv6.
Therefore, for IPv4, you should call net.CIDRMask(32, 32), and for IPv6, net.CIDRMask(128, 128). Since these will be the exact same calculations every time, you have the option to simply set the values up front as constants in your code. The correct values are:
For IPv4: https://golang.org/src/net/ip_test.go#L307
For IPv6: https://golang.org/src/net/ip_test.go#L311
What i am wanting to do is to ssh into a ubiquiti device, run brctl showmacs br0 and only retrieve the mac addresses on the local port (1) for instance:
1 d4:ca:6d:ec:aa:fe no 0.05
would be printed/put/written-to-file because it begins with a 1 while:
2 4c:5e:0c:d5:ba:95 no 38.62
will not.
Strings respond to []; so you could take your collection #collection and :select where x[0] == '1'.
only_ones = #collection.select{|x| x[0] == '1' }
You can use SSHKit to run a remote command:
on 'ubiquiti.yourdomain.com' do
output = capture(:brctl, 'showmacs br0')
puts output.lines.select{|line| line.start_with? "1"}
end
I am new with LUA so take it easy to me.
I have the following code that should be ran into mikrotik router.
Could you possibly tell me what it does?
:local content
:local i
#For each mangle in the list
:foreach i in=[/ip firewall mangle find comment !=""] do={
#Pull comment out of queue and divide up accordingly
:set content [/ip firewall mangle get $i comment]
:if ([:find $content "!"] != "") do={
:local pos1 [:find $content "!"]
:local pos4 [:len $content]
:local pos2 ([:find [:pick $content ($pos1+1) $pos4] "!"]+($pos1+1))
:local pos3 ([:find [:pick $content ($pos2+1) $pos4] "!"]+($pos2+1))
This is a Mikrotik script which search for rules with comments in the firewall mangle rules, and find the comments with exclamation points "!".
The variables pos1 pos2 pos3 are first, second and third location of ! in the comments.
For instance:
If there is a comment like this: a!b!cde!fg
Variables would be:
pos1=1 pos2=3 pos3=7
The location starts from zero, so first location is 0 and second is 1!