1: #!/usr/bin/tcl -n 2: set DIRECTORY "/var/named/dyn" 3: set passfile "$DIRECTORY/passwd" 4: set PORT 32766 5: set HOSTNAME [id host] 6: set VERSION "0.2.1-Tcl" 7: set USERFILE "$DIRECTORY/\$user.zone" 8: set SUFIX ".dyn.n-f-d.com. 600" 9: set INCLUDESFILE "$DIRECTORY/dynamic_ips.conf" 10: set SERIALFILE "$DIRECTORY/serial.conf" 11: set HEADERFILE "$DIRECTORY/header.conf" 12: set USER "dns" 13: set GROUP "dns" 14: 15: 16: proc DoHUP {} { 17: global passfile 18: loadpasswords $passfile 19: } 20: 21: proc loadpasswords {passfile} { 22: global passwords 23: catch { unset passwords } 24: catch { 25: set passId [open $passfile r] 26: } 27: if {![info exists passId]} { 28: puts "Could not read passwd file ($passfile)" 29: exit 30: } 31: while {![eof $passId]} { 32: gets $passId ln 33: if {[llength $ln]==2 && [string index $ln 0]!="#"} { 34: set passwords([lindex $ln 0]) [lindex $ln 1] 35: } 36: } 37: return 38: } 39: 40: proc putsock {sockId text} { 41: puts $sockId $text 42: flush $sockId 43: } 44: 45: proc crypt {pass} { 46: return $pass 47: } 48: 49: proc CreateIncludes {} { 50: global INCLUDESFILE DIRECTORY USERFILE HEADERFILE SERIALFILE passwords serial 51: catch { 52: set fileId [open $INCLUDESFILE w] 53: } 54: if {![info exists fileId]} { return 0 } 55: catch { set headId [open $HEADERFILE r] } 56: if {[info exists headId]} { 57: set serId [open $SERIALFILE r] 58: gets $serId serial 59: close $serId 60: while {![eof $headId]} { 61: gets $headId ln 62: catch { 63: puts $fileId [subst $ln] 64: } 65: } 66: close $headId 67: } 68: foreach user [array names passwords] { 69: set file [subst $USERFILE] 70: puts $fileId "\$include \"$file\";" 71: } 72: close $fileId 73: return 1 74: } 75: 76: proc updateIP {user ip} { 77: global USERFILE SUFIX SERIALFILE 78: set wrk [split $ip .] 79: if {[llength $wrk]!=4} { return 0} 80: set ip "" 81: for {set i 0} {$i<4} {incr i} { 82: set tmp [lindex $wrk $i] 83: if {$tmp>254 || $tmp<0} { return 0 } 84: if {[catch { set tmp [expr $tmp/1] }]} { return 0 } 85: set ip "$ip.$tmp" 86: } 87: set ip [string range $ip 1 end] 88: catch { 89: set fileId [open [subst $USERFILE] r] 90: } 91: set newstring "$user$SUFIX IN A $ip" 92: if {[info exists fileId]} { 93: gets $fileId ln 94: if {$ln==$newstring} { return -1 } 95: close $fileId 96: unset fileId 97: } 98: catch { 99: set fileId [open [subst $USERFILE] w] 100: } 101: if {![info exists fileId]} { return 0 } 102: puts $fileId $newstring 103: close $fileId 104: CreateIncludes 105: unset fileId 106: catch { 107: set fileId [open $SERIALFILE r] 108: } 109: gets $fileId ln 110: close $fileId 111: set fileId [open $SERIALFILE w] 112: puts $fileId [expr $ln +1] 113: close $fileId 114: exec /bin/killall -HUP named 115: return 1 116: } 117: 118: 119: proc GotConnection {sockId addr port} { 120: global passwords HOSTNAME VERSION 121: if {[fork]!=0} { 122: close $sockId 123: wait 124: return 125: } 126: if {[fork]!=0} { exit } 127: putsock $sockId "220 $HOSTNAME NFD-DYNDNS $VERSION Ready." 128: set state 0 129: while {![eof $sockId]} { 130: set cmd "" 131: set arg "" 132: gets $sockId ln 133: catch { 134: set cmd [string tolower [lindex $ln 0]] 135: set arg [lindex $ln 1] 136: } 137: switch -- $cmd { 138: "user" { 139: set username [string tolower $arg] 140: set state 1 141: putsock $sockId "331 Password Required" 142: flush $sockId 143: } 144: "pass" { 145: if {$state==1} { 146: set password [crypt $arg] 147: if {[info exists passwords($username)]} { 148: if {$passwords($username)==$password} { set fail 0 } else { set fail 1 } 149: } else { 150: set fail 1 151: } 152: if {!$fail} { 153: putsock $sockId "230 Password Accepted" 154: set state 2 155: } else { 156: putsock $sockId "530 Login incorrect" 157: } 158: } else { 159: putsock $sockid "503 Send USER first" 160: } 161: } 162: "seti" { 163: if {$state==2} { 164: if {[updateIP $username $arg]!=0} { 165: putsock $sockId "220 Updated" 166: } else { 167: putsock $sockId "420 Database Error" 168: } 169: } else { 170: putsock $sockId "530 Login with USER and PASS" 171: } 172: } 173: "quit" { 174: putsock $sockId "221 Bye." 175: close $sockId 176: exit 177: } 178: default { 179: putsock $sockId "500 '[string toupper $cmd]': Command not recognized." 180: } 181: } 182: } 183: exit 184: } 185: 186: id group $GROUP 187: id user $USER 188: loadpasswords $passfile 189: signal trap SIGHUP DoHUP 190: if {[fork]!=0} { exit } 191: socket -server GotConnection $PORT 192: vwait forever |