Skip to content

Instantly share code, notes, and snippets.

@mattpascoe
Last active November 29, 2018 23:20
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save mattpascoe/4039747 to your computer and use it in GitHub Desktop.
Save mattpascoe/4039747 to your computer and use it in GitHub Desktop.
An AWK script to parse ISC dhcpd configuration files into dcm.pl output to load into OpenNetAdmin
#!/usr/bin/awk -f
#
# Author: Matt Pascoe - matt@opennetadmin.com
#
# This awk script is used to extract relavant information from a dhcpd.conf
# config file and build dcm.pl output with appropriate fields. This can be
# used to bootstrap a new database from existing site data.
# As usual, inspect the output for accuracy.
# Also you will get three types of output, subnet,pool,host. You must
# add the subnet information first, then pool, then host.
# Note that for hosts, it will try a reverse lookup on the IP address
# to determine an appropriate dns name
#
# USAGE:
# make this script executable with `chmod +x dhcpparse.awk` and then
#
# cat dhcpd.conf|./dhcpparse.awk|sort
# set the RECORD SEPARATOR, RS, to "}" ... records span multiple lines
BEGIN {RS="}"}
# TODO: figure out how to skip comment lines without having to use sed first
length($0) > 5 { total++
for(i=1;i<=NF;i++) {
counter[total] = total
# if this field matches the word "host"
if($i ~ /^host$/) {
type[total] = "host"
hostname[total]=$(i+1)
# Remove the trailing { that might be there
gsub(/{/, "", hostname[total])
}
# if this field matches the word "hardware"
else if($i ~ /^hardware$/) {
# get rid of the trailing semi-colon
split($(i+2),arr,";")
mac[total]=arr[1]
}
# if this field matches the word "hardware"
else if($i ~ /^fixed-address$/) {
# get rid of the trailing semi-colon
split($(i+1),arr,";")
ip[total]=arr[1]
}
# if this field matches the word "subnet"
else if($i ~ /^subnet$/) {
type[total] = "subnet"
# get rid of the enclosing quotes
split($(i+1),arr,"\"")
subnetip[total]=arr[1]
}
# if this field matches the word "netmask"
else if($i ~ /^netmask$/) {
subnetmask[total]=$(i+1)
}
# if this field matches the word "range"
else if($i ~ /^range$/) {
total++
type[total] = "pool"
poolstart[total]=$(i+1)
# get rid of the trailing semi-colon
split($(i+2),arr,";")
poolend[total]=arr[1]
}
# if this field matches the word "failover"
if($i ~ /^#failover$/) {
# get rid of the enclosing quotes
split($(i+2),arr,"\"")
failover[total]=arr[2]
}
}
# do a host command reverse lookup on the IP to try and find a dns name
if( length(ip[total]) > 0 ) {
command = ("host " ip[total])
command | getline tmpname
close(command)
split(tmpname,n,"pointer")
# trim off leading spaces etc
gsub(/^[ \t]+/, "", n[2])
name[total] = substr(n[2],0,length(n[2])-1)
}
if( length(name[total]) == 0 ) {
gsub(/\./, "-", hostname[total])
# This option turns the ip into a fake name
#name[total]="dhcpload-" ip[total]
# This option just uses the text found in the conf for host
name[total]=hostname[total]
}
}
# for every entry we captured, display its appropriate info
END { for(entry in counter) {
if(type[entry] == "subnet") {
printf("dcm.pl -r %s_add ip=%s netmask=%s name='DHCPLOAD-%s' type='LAN'\n",\
type[entry],subnetip[entry],subnetmask[entry],subnetip[entry])
}
if(type[entry] == "pool") {
printf("dcm.pl -r dhcp_pool_add start=%s end=%s\n",\
poolstart[entry],poolend[entry])
}
if(type[entry] == "host") {
printf("dcm.pl -r %s_add ip=%s mac=%s host=%s type='Unknown, Unknown (Manually loaded)'\n",\
type[entry],ip[entry],mac[entry],name[entry])
}
}
}
@fxpottier
Copy link

Hi Matt

I forked your script here : https://gist.github.com/fxpottier/d96f41f17b2132df1d15

with an addition to include the comments in the csv file so that we can store in the comments in ONA for example.

You can also choose to simply exclude the comments found

@k0ste
Copy link

k0ste commented Apr 29, 2015

Forked to YAML generator to use with Ansible : https://gist.github.com/k0ste/d830cde9a14a1acba1c7
From usual dhcpd.conf parser generates ready-to-use YAML configuration.

@mattpascoe
Copy link
Author

My latest update now outputs direct dcm.pl command output instead of csv. There are goods and bads of both but the dcm.pl output seemed the most direct and simple for new users to understand and deal with. I also am defaulting hosts to the name field as defined in the dhcp.conf file. You can choose to switch to an IP mode here instead by adjusting comment lines at about line 112.

@crlsgms
Copy link

crlsgms commented Apr 11, 2016

Thanks very much matt on the troubleshooting and line of though using the import script. Ill test up the parse update and give some feedback asap.

@crlsgms
Copy link

crlsgms commented Apr 13, 2016

well, I managed to get the script running, but nothing appeared on the interface, besides the DHCP Pools. So I tried to run one line at a time to troubleshoot where it stopped. After adding the pools, on the first host it prompts the syntaxe, maybe its something wrong on the host_add line:


dcm.pl -r host_add ip=20.14.11.11 mac=00:22:71:69:85:40 name=AP01_AD2_S11

host_add-v1.11
Add a new host

  Synopsis: host_add [KEY=VALUE] ...

  Required:
    host=NAME[.DOMAIN]        Hostname for new DNS record
    type=TYPE or ID           Device/model type or ID
    ip=ADDRESS                IP address (numeric or dotted)

  Optional:
    notes=NOTES               Textual notes
    location=REF              Reference of location
    device=NAME|ID            The device this host is associated with

  Optional, add an interface too:
    mac=ADDRESS               Mac address (most formats are ok)
    name=NAME                 Interface name (i.e. "FastEthernet0/1.100")
    description=TEXT          Brief description of the interface
    addptr=Y|N                Auto add a PTR record for new host/IP (default: Y)


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment