odhcpd.awk (6207B)
1 #!/usr/bin/awk 2 ############################################################################## 3 # 4 # This program is free software; you can redistribute it and/or modify 5 # it under the terms of the GNU General Public License version 2 as 6 # published by the Free Software Foundation. 7 # 8 # This program is distributed in the hope that it will be useful, 9 # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 # GNU General Public License for more details. 12 # 13 # Copyright (C) 2016 Eric Luehrsen 14 # 15 ############################################################################## 16 # 17 # Turn DHCP records into meaningful A, AAAA, and PTR records. Also lift a 18 # function from dnsmasq and use DHCPv4 MAC to find IPV6 SLAAC hosts. 19 # 20 # External Parameters 21 # "hostfile" = where this script will cache host DNS data 22 # "domain" = text domain suffix 23 # "bslaac" = boolean, use DHCPv4 MAC to find GA and ULA IPV6 SLAAC 24 # "bisolt" = boolean, format <host>.<network>.<domain>. so you can isolate 25 # "bconf" = boolean, write conf file format rather than pipe records 26 # 27 ############################################################################## 28 29 /^#/ { 30 # We need to pick out DHCP v4 or v6 records 31 net = $2 ; id = $3 ; cls = $4 ; hst = $5 ; adr = $9 ; adr2 = $10 32 cdr = adr ; 33 cdr2 = adr2 ; 34 sub( /\/.*/, "", adr ) ; 35 sub( /.*\//, "", cdr ) ; 36 sub( /\/.*/, "", adr2 ) ; 37 sub( /.*\//, "", cdr2 ) ; 38 39 40 if ( bisolt == 1 ) { 41 # TODO: this might be better with a substituion option, 42 # or per DHCP pool do-not-DNS option, but its getting busy here. 43 fqdn = net 44 fqdn = sub( /\./, "-", fqdn ) ; 45 fqdn = tolower( hst "." fqdn "." domain ) ; 46 } 47 48 else { 49 fqdn = tolower( hst "." domain ) ; 50 } 51 52 53 if ( cls == "ipv4" ) { 54 if ( NF == 8 ) { 55 # odhcpd errata in field format without host name 56 adr = $8 ; hst = "-" ; cdr = adr ; 57 sub( /\/.*/, "", adr ) ; 58 sub( /.*\//, "", cdr ) ; 59 } 60 61 62 if (( cdr == 32 ) && ( hst != "-" )) { 63 # only for provided hostnames and full /32 assignments 64 ptr = adr ; qpr = "" ; split( ptr, ptr, "." ) ; 65 slaac = slaac_eui64( id ) ; 66 67 68 if ( bconf == 1 ) { 69 x = ( "local-data: \"" fqdn ". 120 IN A " adr "\"" ) ; 70 y = ( "local-data-ptr: \"" adr " 120 " fqdn "\"" ) ; 71 print ( x "\n" y ) > hostfile ; 72 } 73 74 else { 75 for( i=1; i<=4; i++ ) { qpr = ( ptr[i] "." qpr) ; } 76 x = ( fqdn ". 120 IN A " adr ) ; 77 y = ( qpr "in-addr.arpa. 120 IN PTR " fqdn ) ; 78 print ( x "\n" y ) > hostfile ; 79 } 80 81 82 if (( bslaac == 1 ) && ( slaac != 0 )) { 83 # UCI option to discover IPV6 routed SLAAC addresses 84 # NOT TODO - ping probe take too long when added in awk-rule loop 85 cmd = ( "ip -6 --oneline route show dev " net ) ; 86 87 88 while ( ( cmd | getline adr ) > 0 ) { 89 if (( substr( adr, 1, 5 ) <= "fd00:" ) \ 90 && ( index( adr, "via" ) == 0 )) { 91 # GA or ULA routed addresses only (not LL or MC) 92 sub( /\/.*/, "", adr ) ; 93 adr = ( adr slaac ) ; 94 95 96 if ( split( adr, tmp0, ":" ) >= 8 ) { 97 sub( "::", ":", adr ) ; 98 } 99 100 101 if ( bconf == 1 ) { 102 x = ( "local-data: \"" fqdn ". 120 IN AAAA " adr "\"" ) ; 103 y = ( "local-data-ptr: \"" adr " 120 " fqdn "\"" ) ; 104 print ( x "\n" y ) > hostfile ; 105 } 106 107 else { 108 qpr = ipv6_ptr( adr ) ; 109 x = ( fqdn ". 120 IN AAAA " adr ) ; 110 y = ( qpr ". 120 IN PTR " fqdn ) ; 111 print ( x "\n" y ) > hostfile ; 112 } 113 } 114 } 115 116 117 close( cmd ) ; 118 } 119 } 120 } 121 122 else { 123 if (( cdr == 128 ) && ( hst != "-" )) { 124 if ( bconf == 1 ) { 125 x = ( "local-data: \"" fqdn ". 120 IN AAAA " adr "\"" ) ; 126 y = ( "local-data-ptr: \"" adr " 120 " fqdn "\"" ) ; 127 print ( x "\n" y ) > hostfile ; 128 } 129 130 else { 131 # only for provided hostnames and full /128 assignments 132 qpr = ipv6_ptr( adr ) ; 133 x = ( fqdn ". 120 IN AAAA " adr ) ; 134 y = ( qpr ". 120 IN PTR " fqdn ) ; 135 print ( x "\n" y ) > hostfile ; 136 } 137 } 138 139 if (( cdr2 == 128 ) && ( hst != "-" )) { 140 if ( bconf == 1 ) { 141 x = ( "local-data: \"" fqdn ". 120 IN AAAA " adr2 "\"" ) ; 142 y = ( "local-data-ptr: \"" adr2 " 120 " fqdn "\"" ) ; 143 print ( x "\n" y ) > hostfile ; 144 } 145 146 else { 147 # odhcp puts GA and ULA on the same line (position 9 and 10) 148 qpr2 = ipv6_ptr( adr2 ) ; 149 x = ( fqdn ". 120 IN AAAA " adr2 ) ; 150 y = ( qpr2 ". 120 IN PTR " fqdn ) ; 151 print ( x "\n" y ) > hostfile ; 152 } 153 } 154 } 155 } 156 157 ############################################################################## 158 159 function ipv6_ptr( ipv6, arpa, ary, end, i, j, new6, sz, start ) { 160 # IPV6 colon flexibility is a challenge when creating [ptr].ip6.arpa. 161 sz = split( ipv6, ary, ":" ) ; end = 9 - sz ; 162 163 164 for( i=1; i<=sz; i++ ) { 165 if( length(ary[i]) == 0 ) { 166 for( j=1; j<=end; j++ ) { ary[i] = ( ary[i] "0000" ) ; } 167 } 168 169 else { 170 ary[i] = substr( ( "0000" ary[i] ), length( ary[i] )+5-4 ) ; 171 } 172 } 173 174 175 new6 = ary[1] ; 176 for( i = 2; i <= sz; i++ ) { new6 = ( new6 ary[i] ) ; } 177 start = length( new6 ) ; 178 for( i=start; i>0; i-- ) { arpa = ( arpa substr( new6, i, 1 ) ) ; } ; 179 gsub( /./, "&\.", arpa ) ; arpa = ( arpa "ip6.arpa" ) ; 180 181 return arpa ; 182 } 183 184 ############################################################################## 185 186 function slaac_eui64( mac, ary, glbit, eui64 ) { 187 if ( length(mac) >= 12 ) { 188 # RFC2373 and use DHCPv4 registered MAC to find SLAAC addresses 189 split( mac , ary , "" ) ; 190 glbit = ( "0x" ary[2] ) ; 191 glbit = sprintf( "%d", glbit ) ; 192 glbit = or( glbit, 2 ) ; 193 ary[2] = sprintf( "%x", glbit ) ; 194 eui64 = ( ary[1] ary[2] ary[3] ary[4] ":" ary[5] ary[6] "ff:fe" ) ; 195 eui64 = ( eui64 ary[7] ary[8] ":" ary[9] ary[10] ary[11] ary[12] ) ; 196 } 197 198 else { 199 eui64 = 0 ; 200 } 201 202 203 return eui64 ; 204 } 205 206 ############################################################################## 207