summaryrefslogtreecommitdiffstats
path: root/vnfs/vCPE/kea-sdnc-notify-mod
diff options
context:
space:
mode:
authorBrian Freeman <bf1936@att.com>2017-08-04 17:14:28 +0000
committerBrian Freeman <bf1936@att.com>2017-08-04 17:52:27 +0000
commitf08fe6bfad6f9d044512142f104609d5c092a4f1 (patch)
tree30d185bc402e6954331e740375491e31da700269 /vnfs/vCPE/kea-sdnc-notify-mod
parent7ef5928d077cedf46b1e0cd9c40f4443bb640706 (diff)
Initial KEA DHCP Hook
Change-Id: I21c8184c8845e620400d0c2419b6ff16c7ffecc9 Signed-off-by: Brian Freeman <bf1936@att.com>
Diffstat (limited to 'vnfs/vCPE/kea-sdnc-notify-mod')
-rw-r--r--vnfs/vCPE/kea-sdnc-notify-mod/.gitignore2
-rw-r--r--vnfs/vCPE/kea-sdnc-notify-mod/LICENSE.TXT22
-rw-r--r--vnfs/vCPE/kea-sdnc-notify-mod/README.md68
-rwxr-xr-xvnfs/vCPE/kea-sdnc-notify-mod/build.sh6
-rw-r--r--vnfs/vCPE/kea-sdnc-notify-mod/etc/kea-dhcp4.conf.example64
-rw-r--r--vnfs/vCPE/kea-sdnc-notify-mod/etc/kea-sdnc-notify.conf3
-rw-r--r--vnfs/vCPE/kea-sdnc-notify-mod/pom.xml86
-rw-r--r--vnfs/vCPE/kea-sdnc-notify-mod/src/assembly/dep.xml28
-rw-r--r--vnfs/vCPE/kea-sdnc-notify-mod/src/library_common.h35
-rw-r--r--vnfs/vCPE/kea-sdnc-notify-mod/src/load_unload.cc47
-rw-r--r--vnfs/vCPE/kea-sdnc-notify-mod/src/pkt4_send.cc181
-rw-r--r--vnfs/vCPE/kea-sdnc-notify-mod/src/version.cc26
-rw-r--r--vnfs/vCPE/kea-sdnc-notify-mod/test/README.md16
-rw-r--r--vnfs/vCPE/kea-sdnc-notify-mod/test/sdnc.php32
14 files changed, 616 insertions, 0 deletions
diff --git a/vnfs/vCPE/kea-sdnc-notify-mod/.gitignore b/vnfs/vCPE/kea-sdnc-notify-mod/.gitignore
new file mode 100644
index 00000000..b00a8b97
--- /dev/null
+++ b/vnfs/vCPE/kea-sdnc-notify-mod/.gitignore
@@ -0,0 +1,2 @@
+build/*
+target/*
diff --git a/vnfs/vCPE/kea-sdnc-notify-mod/LICENSE.TXT b/vnfs/vCPE/kea-sdnc-notify-mod/LICENSE.TXT
new file mode 100644
index 00000000..34422812
--- /dev/null
+++ b/vnfs/vCPE/kea-sdnc-notify-mod/LICENSE.TXT
@@ -0,0 +1,22 @@
+/*
+ * ============LICENSE_START==========================================
+ * ===================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ *
+ * ECOMP and OpenECOMP are trademarks
+ * and service marks of AT&T Intellectual Property.
+ *
+ */
diff --git a/vnfs/vCPE/kea-sdnc-notify-mod/README.md b/vnfs/vCPE/kea-sdnc-notify-mod/README.md
new file mode 100644
index 00000000..cee91073
--- /dev/null
+++ b/vnfs/vCPE/kea-sdnc-notify-mod/README.md
@@ -0,0 +1,68 @@
+#
+# kea-sdnc-notify-mod
+
+Kea module utilizing hooks api to notify SDNC of macaddr, yiaddr, dhcp-msg-name via HTTP POST request.
+
+# ONAP installation of vDHCP will intall and configure on the vDHCP VM
+#
+# for local development/testing follow these steps.
+#
+
+#
+# install kea on ubuntu
+apt-get install kea-dhcp4-server
+
+
+#
+# Usage
+Install the compiled library from the ./build direction to /usr/local/lib/kea-sdnc-notify.so
+
+Configure /etc/kea/kea-sdnc-notify.conf using the ./etc example
+
+Configure /etc/kea/kea-dhcp4.conf usign the ./etc example
+
+The hook will POST json from the the variables from the DHCP Acknowledgement message to the SDNC "url" in the form of "url+macaddr"
+"url": "http://localhost/sdnc.php?macaddr="
+
+Example: http://localhost/sdnc.php?macaddr=aa:bb:cc:dd:ee:ff
+
+In the ONAP installation instead of localhost it will be to either a DMaaP Topic or to SDNC directly.
+
+
+## START DHCP
+[as root]
+cd /etc/init.d
+./kea-dhcp4-server start or
+./kea-dhcp4-server restart
+
+./kea-dhcp4-server stop
+
+## logs are in
+/var/log/kea-dhcp4.log
+
+## Build requirements
+This software has been developed on Ubuntu 16.04.
+
+apt-get install g++ libcurl4-gnutls-dev libboost-dev kea-dev
+
+./build.sh
+
+## Intallation in ONAP
+The vdhcp install scripts for ONAP will do the build on the vDHCP VM from these source files and copy the resulting library into /usr/local/lib and the configuration files into /etc/kea
+
+## Testing locally
+
+#### USE THIS ON OPENSTACK UBUNTU 16.04 GUEST VM
+
+Create a veth pair:
+
+ip link add veth0 type veth peer name veth1
+
+ip link set veth0 up && ip link set veth1 up
+
+ip address add dev veth0 10.3.0.1/24
+
+dhclient -d -v veth1
+
+dhclient -d -v veth1 -r (to release)
+
diff --git a/vnfs/vCPE/kea-sdnc-notify-mod/build.sh b/vnfs/vCPE/kea-sdnc-notify-mod/build.sh
new file mode 100755
index 00000000..70abbd8a
--- /dev/null
+++ b/vnfs/vCPE/kea-sdnc-notify-mod/build.sh
@@ -0,0 +1,6 @@
+rm -rf ./build
+mkdir ./build
+g++ -ggdb -I /usr/include/kea -L /usr/lib/kea/lib -fpic -shared -o ./build/kea-sdnc-notify.so \
+ src/load_unload.cc src/pkt4_send.cc src/version.cc \
+ -lkea-dhcpsrv -lkea-dhcp++ -lkea-hooks -lkea-log -lkea-util \
+ -lkea-exceptions -lcurl
diff --git a/vnfs/vCPE/kea-sdnc-notify-mod/etc/kea-dhcp4.conf.example b/vnfs/vCPE/kea-sdnc-notify-mod/etc/kea-dhcp4.conf.example
new file mode 100644
index 00000000..b3149af1
--- /dev/null
+++ b/vnfs/vCPE/kea-sdnc-notify-mod/etc/kea-dhcp4.conf.example
@@ -0,0 +1,64 @@
+{
+"Dhcp4":
+ {
+# For testing, you can use veth pair as described in README.md
+ "interfaces-config": {
+ "interfaces": ["veth0" ]
+ },
+
+# How to load the hook library.
+ "hooks-libraries": [
+ {"library": "/usr/local/lib/kea-sdnc-notify.so"}
+ ],
+
+ "lease-database": {
+ "type": "memfile"
+ },
+
+ "expired-leases-processing": {
+ "reclaim-timer-wait-time": 10,
+ "flush-reclaimed-timer-wait-time": 25,
+ "hold-reclaimed-time": 3600,
+ "max-reclaim-leases": 100,
+ "max-reclaim-time": 250,
+ "unwarned-reclaim-cycles": 5
+ },
+
+ "valid-lifetime": 300,
+
+# Ensure you set some sensible defaults for the siaddr and option-data,
+# otherwise the options won't be added at all.
+# Also keep in mind that if kea doesn't receive the desired values for some
+# reason, these values will be sent to the client.
+ "subnet4": [
+ { "subnet": "10.3.0.0/24",
+ "pools" : [ { "pool": "10.3.0.2 - 10.3.0.255"} ],
+ "next-server": "10.3.0.1",
+ "option-data": [
+ {"name": "tftp-server-name",
+ "data": "10.4.0.1"},
+ {"name": "boot-file-name",
+ "data": "/dev/null"}
+ ]
+ }
+ ]
+
+},
+
+"Logging":
+{
+ "loggers": [
+ {
+ "name": "kea-dhcp4",
+ "output_options": [
+ {
+ "output": "/var/log/kea-dhcp4.log"
+ }
+ ],
+ "severity": "DEBUG",
+ "debuglevel": 0
+ },
+ ]
+}
+
+}
diff --git a/vnfs/vCPE/kea-sdnc-notify-mod/etc/kea-sdnc-notify.conf b/vnfs/vCPE/kea-sdnc-notify-mod/etc/kea-sdnc-notify.conf
new file mode 100644
index 00000000..1a8ee2e3
--- /dev/null
+++ b/vnfs/vCPE/kea-sdnc-notify-mod/etc/kea-sdnc-notify.conf
@@ -0,0 +1,3 @@
+{"url": "http://localhost/sdnc.php?macaddr=",
+ "siaddr": "siaddr"
+}
diff --git a/vnfs/vCPE/kea-sdnc-notify-mod/pom.xml b/vnfs/vCPE/kea-sdnc-notify-mod/pom.xml
new file mode 100644
index 00000000..737da797
--- /dev/null
+++ b/vnfs/vCPE/kea-sdnc-notify-mod/pom.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ ============LICENSE_START==========================================
+ ===================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ ===================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END============================================
+
+ ECOMP and OpenECOMP are trademarks
+ and service marks of AT&T Intellectual Property.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.onap.demo.vnf</groupId>
+ <artifactId>demo-aggregator</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ <relativePath>../../../pom.xml</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.onap.demo.vnf.vCPE</groupId>
+ <artifactId>kea-sdnc-notify-mod</artifactId>
+
+ <build>
+ <plugins>
+
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.3.2</version>
+ <executions>
+ <execution>
+ <id>default-jar</id>
+ <phase>never</phase>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>2.5.3</version>
+ <configuration>
+ <descriptor>src/assembly/dep.xml</descriptor>
+ </configuration>
+ <executions>
+ <execution>
+ <id>create-archive</id>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>none</phase>
+ </execution>
+ </executions>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+
+ </plugins>
+ </build>
+
+</project>
diff --git a/vnfs/vCPE/kea-sdnc-notify-mod/src/assembly/dep.xml b/vnfs/vCPE/kea-sdnc-notify-mod/src/assembly/dep.xml
new file mode 100644
index 00000000..d938e10a
--- /dev/null
+++ b/vnfs/vCPE/kea-sdnc-notify-mod/src/assembly/dep.xml
@@ -0,0 +1,28 @@
+<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
+ <id>demo</id>
+ <formats>
+ <format>tar.gz</format>
+ </formats>
+ <fileSets>
+
+ <fileSet>
+ <directory>${project.basedir}</directory>
+ <outputDirectory>/</outputDirectory>
+ <includes>
+ <include>**/*.md</include>
+ <include>**/*.cc</include>
+ <include>**/*.h</include>
+ <include>**/*.conf</include>
+ <include>**/*.sh</include>
+ <include>**/*.TXT</include>
+ </includes>
+ <excludes>
+ <exclude>build/*</exclude>
+ <exclude>test/*</exclude>
+ </excludes>
+ </fileSet>
+
+ </fileSets>
+</assembly>
diff --git a/vnfs/vCPE/kea-sdnc-notify-mod/src/library_common.h b/vnfs/vCPE/kea-sdnc-notify-mod/src/library_common.h
new file mode 100644
index 00000000..9b33b95e
--- /dev/null
+++ b/vnfs/vCPE/kea-sdnc-notify-mod/src/library_common.h
@@ -0,0 +1,35 @@
+/**************************************************************************//**
+* @file
+* common headers
+*
+*
+* License
+* -------
+*
+* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+****************************************************************************/
+
+
+
+#ifndef LIBRARY_COMMON_H
+#define LIBRARY_COMMON_H
+#include <string>
+#include <iostream>
+#include <hooks/hooks.h>
+#include <boost/property_tree/ptree.hpp>
+#include <boost/property_tree/json_parser.hpp>
+
+extern std::string json_params[3];
+#endif
diff --git a/vnfs/vCPE/kea-sdnc-notify-mod/src/load_unload.cc b/vnfs/vCPE/kea-sdnc-notify-mod/src/load_unload.cc
new file mode 100644
index 00000000..2296379c
--- /dev/null
+++ b/vnfs/vCPE/kea-sdnc-notify-mod/src/load_unload.cc
@@ -0,0 +1,47 @@
+/**************************************************************************//**
+* @file
+* load_unload the module in kea
+*
+*
+* License
+* -------
+*
+* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+****************************************************************************/
+
+
+#include "library_common.h"
+
+using namespace isc::hooks;
+namespace pt = boost::property_tree;
+
+std::string param_url;
+std::string json_params[3];
+
+extern "C" {
+int load(LibraryHandle& handle) {
+ pt::ptree root;
+ pt::read_json("/etc/kea/kea-sdnc-notify.conf", root);
+
+ json_params[0] = (root.get<std::string>("url"));
+ json_params[1] = (root.get<std::string>("siaddr"));
+
+ std::cout << "kea-sdnc-notify.so loaded\n" << std::endl;
+ return 0;
+}
+int unload() {
+ return (0);
+}
+}
diff --git a/vnfs/vCPE/kea-sdnc-notify-mod/src/pkt4_send.cc b/vnfs/vCPE/kea-sdnc-notify-mod/src/pkt4_send.cc
new file mode 100644
index 00000000..231a0a8b
--- /dev/null
+++ b/vnfs/vCPE/kea-sdnc-notify-mod/src/pkt4_send.cc
@@ -0,0 +1,181 @@
+/*****************************************************************************
+* @file
+* main function to process ipv4 packets
+* -------
+*
+* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+****************************************************************************/
+
+#include <dhcp/pkt4.h>
+#include <log/logger.h>
+#include <log/macros.h>
+#include <log/message_initializer.h>
+#include "library_common.h"
+#include <curl/curl.h>
+#include <sstream>
+
+using namespace isc::dhcp;
+using namespace isc::hooks;
+using namespace std;
+using namespace isc::log;
+namespace pt = boost::property_tree;
+
+
+isc::log::Logger logger("sdnc-notify-logger");
+const char* log_messages[] = {
+ "SNL_BASE", "message: %1",
+ "SNL_PKT_SEND", "Outgoing packet: \n%1",
+ "SNL_CURL_RECEIVED", "Received: \n%1",
+ "SNL_CURL_FAILED", "Unable to receive data from %1",
+ NULL
+};
+
+/// Initializer for log messages.
+const MessageInitializer message_initializer(log_messages);
+
+extern "C" {
+int pkt4_send(CalloutHandle& handle) {
+
+ // Curl variables
+ CURL *curl;
+ CURLcode res;
+ struct curl_slist *list=NULL;
+ bool perform_updates = 0;
+ int curl_opt_res = 0;
+
+ // "C" variables.
+ char *bp;
+ size_t size;
+ FILE *response_memfile;
+
+ // String variables
+ string hwaddr;
+ string final_url;
+ string msg_name;
+ string yiaddr;
+ string post_data;
+
+
+ // Pkt4 variables.
+ Pkt4Ptr response4_ptr;
+ HWAddrPtr hwaddr_ptr;
+
+ // Boost / json related variables.
+ pt::ptree root;
+ std::stringstream ss;
+ boost::optional<std::string> siaddr_json_field;
+
+ /* Begin Code */
+ handle.getArgument("response4", response4_ptr);
+ hwaddr_ptr = response4_ptr->getHWAddr();
+ isc::asiolink::IOAddress new_yiaddr(response4_ptr->getYiaddr());
+ hwaddr = hwaddr_ptr->toText(false);
+ yiaddr = new_yiaddr.toText();
+ msg_name = response4_ptr->getName();
+ post_data = "{ macaddr=" + hwaddr + "&yiaddr=" + yiaddr + "&msg=" + msg_name + "}";
+ final_url = json_params[0] + hwaddr;
+ LOG_DEBUG(logger, 0, "SNL_BASE").arg(final_url);
+ LOG_DEBUG(logger, 0, "SNL_BASE").arg(yiaddr);
+
+
+ if ( msg_name == "DHCPACK")
+ perform_updates = 1;
+
+ if (!perform_updates) {
+ LOG_WARN(logger, "SNL_BASE").arg("Nothing to update.");
+ return(0);
+ }
+
+ curl_global_init(CURL_GLOBAL_DEFAULT);
+ curl = curl_easy_init();
+ if(!curl) {
+ curl_global_cleanup();
+ LOG_ERROR(logger, "SNL_BASE").arg("Could not initialize curl");
+ return(1);
+ }
+
+ list = curl_slist_append(list, "Accept: application/json");
+ if (list == NULL) {
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+ LOG_ERROR(logger, "SNL_BASE").arg("Could not create curl slist.");
+ return(1);
+ }
+
+ response_memfile = open_memstream (&bp, &size);
+ if (response_memfile == NULL) {
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+ LOG_ERROR(logger, "SNL_BASE").arg("Could not create memfile.");
+ return(1);
+ }
+
+ // DEBUGGING
+ curl_opt_res += curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+ curl_opt_res += curl_easy_setopt(curl, CURLOPT_HEADER, 1L);
+
+ // If we don't set a timeout, curl will try for 300 seconds by default.
+ curl_opt_res += curl_easy_setopt(curl, CURLOPT_TIMEOUT, 1L);
+ curl_opt_res += curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 1L);
+ // libcurl's docs say to cast as void, don't blame me.
+ curl_opt_res += curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)response_memfile);
+ // CURLOPT_URL takes a char*
+ curl_opt_res += curl_easy_setopt(curl, CURLOPT_URL, (final_url).c_str());
+
+ // let curl use strlen
+ curl_opt_res += curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, -1L );
+ curl_opt_res += curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data.c_str() );
+ curl_opt_res += curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
+
+ #ifdef SKIP_PEER_VERIFICATION
+ curl_opt_res += curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
+ #endif
+
+ #ifdef SKIP_HOSTNAME_VERIFICATION
+ curl_opt_res += curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
+ #endif
+ if (curl_opt_res > 0) {
+ fclose(response_memfile);
+ free(bp);
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+ LOG_ERROR(logger, "SNL_BASE").arg("Error setting curl options.");
+ return(1);
+ }
+ res = curl_easy_perform(curl);
+ /* Check for errors */
+ if(res != CURLE_OK) {
+ fclose(response_memfile);
+ free(bp);
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+ LOG_ERROR(logger, "SNL_CURL_FAILED").arg(ss.str());
+ return(1);
+ }
+ // make bp available for reading.
+ fclose(response_memfile);
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+ ss << bp;
+ free(bp);
+ LOG_DEBUG(logger, 0, "SNL_CURL_RECEIVED").arg(ss.str());
+ // Load the json file in this ptree
+
+
+ LOG_DEBUG(logger, 0, "SNL_PKT_SEND").arg(response4_ptr->toText());
+
+ return(0);
+}
+}
diff --git a/vnfs/vCPE/kea-sdnc-notify-mod/src/version.cc b/vnfs/vCPE/kea-sdnc-notify-mod/src/version.cc
new file mode 100644
index 00000000..ce71d758
--- /dev/null
+++ b/vnfs/vCPE/kea-sdnc-notify-mod/src/version.cc
@@ -0,0 +1,26 @@
+/****************************************************************************
+* @file
+* add hook
+* -------
+*
+* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+****************************************************************************/
+
+#include <hooks/hooks.h>
+extern "C" {
+int version() {
+ return (KEA_HOOKS_VERSION);
+}
+}
diff --git a/vnfs/vCPE/kea-sdnc-notify-mod/test/README.md b/vnfs/vCPE/kea-sdnc-notify-mod/test/README.md
new file mode 100644
index 00000000..90076945
--- /dev/null
+++ b/vnfs/vCPE/kea-sdnc-notify-mod/test/README.md
@@ -0,0 +1,16 @@
+
+
+
+# sdnc emulator
+# install in /var/www/html with standard apache2 and php install
+# create /var/log/onap directoy
+# set owner to 'www-data' on /var/log/onap and /var/log/onap/macaddr.log
+
+# test with curl http://localhost/sdnc.php?macaddr=11:22:33:44
+# or
+# curl -H "Content-Type: application/json" -X POST -d '{"username":"xyz","password":"xyz"}' http://localhost/sdnc.php?macaddr=12:34:56:66
+#
+# response is {"succes"}
+#
+# macaddr.log should record the data submitted
+
diff --git a/vnfs/vCPE/kea-sdnc-notify-mod/test/sdnc.php b/vnfs/vCPE/kea-sdnc-notify-mod/test/sdnc.php
new file mode 100644
index 00000000..85c59a66
--- /dev/null
+++ b/vnfs/vCPE/kea-sdnc-notify-mod/test/sdnc.php
@@ -0,0 +1,32 @@
+###################################################################################
+# simple php script to act as sdnc emulator for testing DHCP notifications
+#
+# License
+# -------
+#
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+###################################################################################
+
+<?php
+header('Content-type: application/json');
+$date = new DateTime();
+$date = $date->format("y:m:d h:i:s");
+$req_dump = print_r( $_REQUEST, true );
+$fp = file_put_contents( '/var/log/onap/macaddr.log', $date . "|" . $req_dump . "|" ,FILE_APPEND | LOCK_EX );
+$fp = file_put_contents( '/var/log/onap/macaddr.log', file_get_contents('php://input'),FILE_APPEND | LOCK_EX );
+$fp = file_put_contents( '/var/log/onap/macaddr.log', "\n",FILE_APPEND | LOCK_EX );
+
+print "{\"succes\"}";
+?>