]> git.entuzijast.net Git - imunes.git/commitdiff
Introduce support for automated IPv4 address renumbering, and
authormarko <marko>
Sat, 17 May 2008 01:57:02 +0000 (01:57 +0000)
committermarko <marko>
Sat, 17 May 2008 01:57:02 +0000 (01:57 +0000)
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 <Sanja.Marjanovic at fer.hr>
Reviewed by:
Approved by:
Obtained from:

editor.tcl
initgui.tcl
ipv4.tcl

index 8b1642486b2c4c54120b71ef01e1c78c00b81776..330ed2e7e8eab0b2f6ed1de70c811a4cbf480fa3 100755 (executable)
@@ -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
+}
+
index 0b0d6540931aad6675625ba1b1c8d2ba736c141f..488cd7d61a65910dd1ffd1f931daeb3ef481f548 100755 (executable)
@@ -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
index 39432fe87b04d44f00f9eb230b761608bf1656ab..dade18cb99b156b75a7224428cfe8aa5b8a5a453 100755 (executable)
--- 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
 #   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
 # 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"
+        }
     }
 }