From: marko Date: Sat, 17 May 2008 01:57:02 +0000 (+0000) Subject: Introduce support for automated IPv4 address renumbering, and X-Git-Url: https://git.entuzijast.net/?a=commitdiff_plain;h=7e38c5d814025253f85ada6d294d10a2ffd2d192;p=imunes.git Introduce support for automated IPv4 address renumbering, and replace ad-hoc hardcoded 10.0.0.0/8 address pool with user selectable variable-mask IPv4 address pool. Bug found by: Submitted by: Sanja Marjanovic Reviewed by: Approved by: Obtained from: --- diff --git a/editor.tcl b/editor.tcl index 8b16424..330ed2e 100755 --- a/editor.tcl +++ b/editor.tcl @@ -26,7 +26,7 @@ # and Technology through the research contract #IP-2003-143. # -# $Id: editor.tcl,v 1.89 2008/04/28 11:32:34 miljenko Exp $ +# $Id: editor.tcl,v 1.90 2008/05/17 01:57:02 marko Exp $ #****h* imunes/editor.tcl @@ -1142,6 +1142,18 @@ proc button3node { c x y } { } } + # + # IPv4 autorenumber + # + if { $oper_mode != "exec" && [nodeType $node] == "router" || \ + [nodeType $node] == "pc" || [nodeType $node] == "host"} { + .button3menu add command -label "IPv4 autorenumber" \ + -command changeAddressRange + } else { + .button3menu add command -label "IPv4 autorenumber" \ + -command changeAddressRange -state disabled + } + # # Move to another canvas # @@ -3553,3 +3565,36 @@ proc selectZoom { x y } { grab $w } +#****f* editor.tcl/changeAddressRange +# NAME +# changeAddressRange -- change address range for selected nodes +# SYNOPSIS +# changeAddressRange +# FUNCTION +# +# +#**** +proc changeAddressRange {} { + global changed + global changeAddrRange + global control + + set control 0 + set selected_nodes [selectedNodes] + foreach node $selected_nodes { + foreach ifc [ifcList $node] { + set peer [peerByIfc $node $ifc] + if {[lsearch $selected_nodes $peer] != -1} { + if {[string range $node 1 end] < [string range $peer 1 end]} { + set changeAddrRange 1 + } + autoIPv4addr $node $ifc + set changed 1 + set changeAddrRange 0 + } + } + } + redrawAll + updateUndoLog +} + diff --git a/initgui.tcl b/initgui.tcl index 0b0d654..488cd7d 100755 --- a/initgui.tcl +++ b/initgui.tcl @@ -26,7 +26,7 @@ # and Technology through the research contract #IP-2003-143. # -# $Id: initgui.tcl,v 1.48 2008/05/14 13:51:08 miljenko Exp $ +# $Id: initgui.tcl,v 1.49 2008/05/17 01:57:02 marko Exp $ #****h* imunes/initgui.tcl @@ -314,6 +314,31 @@ menu .menubar.tools -tearoff 0 .menubar.tools add command -label "Align to grid" -underline 0 \ -command { align2grid } .menubar.tools add separator +.menubar.tools add command -label "IPv4 address pool" -underline 0 \ + -command { + set w .entry1 + catch {destroy $w} + toplevel $w + wm title $w "IPv4 autonumbering address pool" + wm iconname $w "IPv4 address pool" + + label $w.msg -wraplength 5i -justify left -text "IPv4 address range:" + pack $w.msg -side top + + frame $w.buttons + pack $w.buttons -side bottom -fill x -pady 2m + button $w.buttons.print -text "Apply" -command "IPv4AddrApply $w" + button $w.buttons.cancel -text "Cancel" -command "destroy $w" + pack $w.buttons.print $w.buttons.cancel -side left -expand 1 + + + entry $w.e1 -bg white -validate focus -invcmd "focusAndFlash %W" + $w.e1 insert 0 $ipv4 + pack $w.e1 -side top -pady 5 -padx 10 -fill x + + $w.e1 configure -vcmd {checkIPv4Net %P} +} +.menubar.tools add separator .menubar.tools add command -label "ns2imunes converter" \ -underline 0 -command { toplevel .ns2im-dialog diff --git a/ipv4.tcl b/ipv4.tcl index 39432fe..dade18c 100755 --- a/ipv4.tcl +++ b/ipv4.tcl @@ -26,7 +26,7 @@ # and Technology through the research contract #IP-2003-143. # -# $Id: ipv4.tcl,v 1.15 2008/01/02 12:08:46 marko Exp $ +# $Id: ipv4.tcl,v 1.16 2008/05/17 01:57:02 marko Exp $ #****h* imunes/ipv4.tcl @@ -34,6 +34,58 @@ # ipv4.tcl -- file for handeling IPv4 #**** +set ipv4 10.0.0.0/24 +set numbits [lindex [split $ipv4 /] 1] +set control 0 +set changeAddrRange 0 + +proc IPv4AddrApply { w } { + global ipv4 + global numbits + global changed + global control + + set newipv4 [$w.e1 get] + + if { [checkIPv4Net $newipv4] == 0 } { + focusAndFlash .entry1.e1 + return + } + destroy $w + + if { $newipv4 != $ipv4 } { + set changed 1 + set control 1 + } + set ipv4 $newipv4 + set numbits [lindex [split $ipv4 /] 1] +} + +proc dec2bin {dec} { + set res "" + while {$dec > 0} { + set res [expr {$dec % 2}]$res + set dec [expr {$dec / 2}] + } + if {$res == ""} {set res 0} + if {[string length $res] < 8} { + set n [expr {8-[string length $res]}] + for {set i 0} {$i < $n} {incr i} { + set res 0$res + } + } + return $res +} + +proc bin2dec {bin} { + set res 0 + foreach i $bin { + set res [expr {$res*2 + $i}] + } + return $res +} + + #****f* ipv4.tcl/findFreeIPv4Net # NAME # findFreeIPv4Net -- find free IPv4 network @@ -45,29 +97,118 @@ # INPUTS # * mask -- this parameter is left unused for now # RESULT -# * ipnet -- returns the free IPv4 network address in the form 10.a.b -#**** - +# * ipnet -- returns the free IPv4 network address in the form a.b.c.d +#**** + proc findFreeIPv4Net { mask } { upvar 0 ::cf::[set ::curcfg]::node_list node_list + global ipv4 + global numbits + + set numbits $mask + + set addr [lindex [split $ipv4 /] 0] + + set a [dec2bin [lindex [split $addr .] 0]] + set b [dec2bin [lindex [split $addr .] 1]] + set c [dec2bin [lindex [split $addr .] 2]] + set d [dec2bin [lindex [split $addr .] 3]] + + set addr_bin $a$b$c$d + + set host_id [string range $addr_bin $numbits end] + + while {[string first 1 $host_id] != -1} { + set i [string first 1 $host_id] + set host_id [string replace $host_id $i $i 0] + } + + set net_id [string range $addr_bin 0 [expr {$numbits-1}]] + + set sub_addr $net_id$host_id + + if {$numbits == 8 || $numbits == 16 || $numbits == 24} { + set pot 0 + } else { + set pot [expr {8 - ($numbits % 8)}] + } + + set step [expr {1 << $pot}] + set ipnets {} + foreach node $node_list { foreach ifc [ifcList $node] { - set ipnet [lrange [split [getIfcIPv4addr $node $ifc] .] 0 2] + if {$numbits <= 8} { + set ipnet [lindex [split [getIfcIPv4addr $node $ifc] .] 0] + } elseif {$numbits > 8 && $numbits <=16} { + set ipnet [lrange [split [getIfcIPv4addr $node $ifc] .] 0 1] + } elseif {$numbits > 16 && $numbits <=24} { + set ipnet [lrange [split [getIfcIPv4addr $node $ifc] .] 0 2] + } elseif {$numbits > 24} { + set ifcaddr [lindex [split [getIfcIPv4addr $node $ifc] /] 0] + if {[lindex [split $ifcaddr .] 3] != ""} { + set x [expr {[lindex [split $ifcaddr .] 3] - \ + ([lindex [split $ifcaddr .] 3] % $step)}] + set ipnet [split $ifcaddr .] + lset ipnet 3 $x + } else { + set ipnet {} + } + } if {[lsearch $ipnets $ipnet] == -1} { lappend ipnets $ipnet } } } - for { set i 0 } { $i <= 255 } { incr i } { - for { set j 0 } { $j <= 255 } { incr j } { - if {[lsearch $ipnets "10 $i $j"] == -1} { - set ipnet "10.$i.$j" + + set a_sub [bin2dec [split [string range $sub_addr 0 7] {}]] + set b_sub [bin2dec [split [string range $sub_addr 8 15] {}]] + set c_sub [bin2dec [split [string range $sub_addr 16 23] {}]] + set d_sub [bin2dec [split [string range $sub_addr 24 31] {}]] + + if {$numbits <= 8} { + for { set i $a_sub } { $i <= 255 } { incr i $step } { + if {[lsearch $ipnets "$i"] == -1} { + set ipnet "$i" return $ipnet + } + } + } elseif {$numbits > 8 && $numbits <=16} { + for { set i $a_sub } { $i <= 255 } { incr i } { + for { set j $b_sub } { $j <= 255 } { incr j $step } { + if {[lsearch $ipnets "$i $j"] == -1} { + set ipnet "$i.$j" + return $ipnet + } } } - } + } elseif {$numbits > 16 && $numbits <=24} { + for { set i $a_sub } { $i <= 255 } { incr i } { + for { set j $b_sub } { $j <= 255 } { incr j } { + for { set k $c_sub } { $k <= 255 } { incr k $step } { + if {[lsearch $ipnets "$i $j $k"] == -1} { + set ipnet "$i.$j.$k" + return $ipnet + } + } + } + } + } elseif {$numbits > 24} { + for { set i $a_sub } { $i <= 255 } { incr i } { + for { set j $b_sub } { $j <= 255 } { incr j } { + for { set k $c_sub } { $k <= 255 } { incr k } { + for { set l $d_sub } { $l <= 255 } { incr l $step } { + if {[lsearch $ipnets "$i $j $k $l"] == -1} { + set ipnet "$i.$j.$k.$l" + return $ipnet + } + } + } + } + } + } } #****f* ipv4.tcl/autoIPv4addr @@ -86,6 +227,11 @@ proc findFreeIPv4Net { mask } { #**** proc autoIPv4addr { node iface } { + + global numbits + global changeAddrRange + global control + set peer_ip4addrs {} if { [[typemodel $node].layer] != "NETWORK" } { @@ -99,7 +245,7 @@ proc autoIPv4addr { node iface } { set peer_node [logicalPeerByIfc $node $iface] - if { [[typemodel $peer_node].layer] == "LINK" } { + if { [[typemodel $peer_node].layer] == "LINK" && $control == 0 } { foreach l2node [listLANnodes $peer_node {}] { foreach ifc [ifcList $l2node] { set peer [logicalPeerByIfc $l2node $ifc] @@ -110,11 +256,12 @@ proc autoIPv4addr { node iface } { } } } - } else { + } elseif {[[typemodel $peer_node].layer] != "LINK"} { set peer_if [ifcByLogicalPeer $peer_node $node] set peer_ip4addr [getIfcIPv4addr $peer_node $peer_if] set peer_ip4addrs [lindex [split $peer_ip4addr /] 0] } + switch -exact -- [nodeType $node] { router { set targetbyte 1 @@ -126,17 +273,61 @@ proc autoIPv4addr { node iface } { set targetbyte 20 } } - if { $peer_ip4addrs != "" } { - set ipnums [split [lindex $peer_ip4addrs 0] .] - set net "[lindex $ipnums 0].[lindex $ipnums 1].[lindex $ipnums 2]" - set ipaddr $net.$targetbyte - while { [lsearch $peer_ip4addrs $ipaddr] >= 0 } { - incr targetbyte - set ipaddr $net.$targetbyte - } - setIfcIPv4addr $node $iface "$ipaddr/24" + + set targetbyte2 0 + + if { $peer_ip4addrs != "" && $changeAddrRange == 0 } { + set ipnums [split [lindex $peer_ip4addrs 0] .] + + set targetbyte3 [expr {[lindex $ipnums 3] + 1}] + + if {$numbits <= 8} { + set net "[lindex $ipnums 0]" + set ipaddr $net.$targetbyte2.$targetbyte2.$targetbyte + while { [lsearch $peer_ip4addrs $ipaddr] >= 0 } { + incr targetbyte + set ipaddr $net.$targetbyte2.$targetbyte2.$targetbyte + } + } elseif {$numbits > 8 && $numbits <=16} { + set net "[lindex $ipnums 0].[lindex $ipnums 1]" + set ipaddr $net.$targetbyte2.$targetbyte + set x [lindex [split $net .] 1] + while { [lsearch $peer_ip4addrs $ipaddr] >= 0 } { + incr targetbyte + set ipaddr $net.$targetbyte2.$targetbyte + } + } elseif {$numbits > 16 && $numbits <=24} { + set net "[lindex $ipnums 0].[lindex $ipnums 1].[lindex $ipnums 2]" + set ipaddr $net.$targetbyte + while { [lsearch $peer_ip4addrs $ipaddr] >= 0 } { + incr targetbyte + set ipaddr $net.$targetbyte + } + } elseif {$numbits > 24} { + set first3bytes \ + "[lindex $ipnums 0].[lindex $ipnums 1].[lindex $ipnums 2]" + set ipaddr $first3bytes.$targetbyte3 + while { [lsearch $peer_ip4addrs $ipaddr] >= 0 } { + incr targetbyte3 + set ipaddr $first3bytes.$targetbyte3 + } + } + + setIfcIPv4addr $node $iface "$ipaddr/$numbits" + } else { - setIfcIPv4addr $node $iface "[findFreeIPv4Net 24].$targetbyte/24" + if {$numbits <= 8} { + setIfcIPv4addr $node $iface "[findFreeIPv4Net $numbits].$targetbyte2.$targetbyte2.$targetbyte/$numbits" + } elseif {$numbits > 8 && $numbits <=16} { + setIfcIPv4addr $node $iface "[findFreeIPv4Net $numbits].$targetbyte2.$targetbyte/$numbits" + } elseif {$numbits > 16 && $numbits <=24} { + setIfcIPv4addr $node $iface "[findFreeIPv4Net $numbits].$targetbyte/$numbits" + } elseif {$numbits > 24} { + set lastbyte [lindex [split [findFreeIPv4Net $numbits] .] 3] + set first3bytes [join [lrange [split [findFreeIPv4Net $numbits] .] 0 2] .] + set targetbyte3 [expr {$lastbyte + 1}] + setIfcIPv4addr $node $iface "$first3bytes.$targetbyte3/$numbits" + } } }