2 ##############################################################################
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.
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.
13 # Copyright (C) 2016 Eric Luehrsen
15 ##############################################################################
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.
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
27 ##############################################################################
30 # We need to pick out DHCP v4 or v6 records
31 net = $
2 ; id = $
3 ; cls = $
4 ; hst = $
5 ; adr = $
9 ; adr2 = $
10
34 sub( /\
/.
*/, "", adr
) ;
35 sub( /.
*\
//, "", cdr
) ;
36 sub( /\
/.
*/, "", adr2
) ;
37 sub( /.
*\
//, "", cdr2
) ;
41 # TODO: this might be better with a substituion option,
42 # or per DHCP pool do-not-DNS option, but its getting busy here.
44 fqdn =
sub( /\.
/, "-", fqdn
) ;
45 fqdn =
tolower( hst
"." fqdn
"." domain
) ;
49 fqdn =
tolower( hst
"." domain
) ;
53 if ( cls ==
"ipv4" ) {
55 # odhcpd errata in field format without host name
56 adr = $
8 ; hst =
"-" ; cdr = adr
;
57 sub( /\
/.
*/, "", adr
) ;
58 sub( /.
*\
//, "", cdr
) ;
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
) ;
69 x =
( "local-data: \"" fqdn
". 120 IN A " adr
"\"" ) ;
70 y =
( "local-data-ptr: \"" adr
" 120 " fqdn
"\"" ) ;
71 print ( x
"\n" y
) > hostfile
;
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
;
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
) ;
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
) ;
96 if ( split( adr
, tmp0
, ":" ) >=
8 ) {
97 sub( "::", ":", adr
) ;
102 x =
( "local-data: \"" fqdn
". 120 IN AAAA " adr
"\"" ) ;
103 y =
( "local-data-ptr: \"" adr
" 120 " fqdn
"\"" ) ;
104 print ( x
"\n" y
) > hostfile
;
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
;
123 if (( cdr ==
128 ) && ( hst
!= "-" )) {
125 x =
( "local-data: \"" fqdn
". 120 IN AAAA " adr
"\"" ) ;
126 y =
( "local-data-ptr: \"" adr
" 120 " fqdn
"\"" ) ;
127 print ( x
"\n" y
) > hostfile
;
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
;
139 if (( cdr2 ==
128 ) && ( hst
!= "-" )) {
141 x =
( "local-data: \"" fqdn
". 120 IN AAAA " adr2
"\"" ) ;
142 y =
( "local-data-ptr: \"" adr2
" 120 " fqdn
"\"" ) ;
143 print ( x
"\n" y
) > hostfile
;
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
;
157 ##############################################################################
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
;
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" ) ; }
170 ary
[i
] =
substr( ( "0000" ary
[i
] ), length( ary
[i
] )+5-4 ) ;
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" ) ;
184 ##############################################################################
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] ) ;
206 ##############################################################################