Kea DHCP Hooks开发
来源:互联网 发布:绘声绘色软件怎么使用 编辑:程序博客网 时间:2024/06/06 02:29
目录
摘要
开发环境要求
Hook开发需求
Hook代码编写
Hook代码编译
Hook Kea配置
总结
参考文献
附录
摘要
简单Kea DHCP开发案例教程。通过本篇文章使读者能够对Hook开发有一个大致轮廓。主要侧重操作,对于概念的说明请查看官网。申明:本篇使用的是官方文档案例
开发环境要求
- Ubuntu
- gcc编译环境
apt install gcc
- vim编辑器
- Kea相关Hook开发库(安装Kea即可)
Hook开发需求
Kea DHCPv4用于分配IPv4地址给客户端(也会传给客户端其他信息,比如DNS服务器地址)。假设需要根据客户硬件地址和客户请求IPv4地址进行分类,且记录感兴趣的客户端硬件地址和已分配IP地址。
Hook代码编写
- version - Hook代码被编译时Kea代码使用的版本
- load - 当Hook被服务器加载时调用
- unload - 当Hook被服务器卸载是调用
version函数
用于检查Hook是否兼容当前正在运行的Kea服务器。
源码
// version.cc#include <hooks/hooks.h>extern "C" { int version() { return (KEA_HOOKS_VERSION); }}
load和unload函数
- load肯定被调用,unload不一定被调用,比如系统异常关闭。
- 这两个函数主要用于资源的分配和关闭。
- load函数可以注册自定义callout名字,比如如下代码:
int load(LibraryHandle& libhandle) { // Register the callouts on the hooks. We assume that a header file declares the "classify" and "write_data" functions. libhandle.registerCallout("pkt4_receive", classify); libhandle.registerCallout("pkt4_send", write_data); // Open the log file interesting.open("/tmp/interesting.log", std::fstream::out | std::fstream::app); return (interesting ? 0 : 1);}
源码
- 将创建两个文件,分别为library_common.h和load_unload.cc,library_common.h用于文件处理器声明。load_unload.cc用于定义load和unload函数。
// library_common.h#ifndef LIBRARY_COMMON_H#define LIBRARY_COMMON_H#include <fstream>// 日志文件处理器声明extern std::fstream interesting;#endif // LIBRARY_COMMON_H
- 定义load和unload函数源文件。==interesting.open的文件必须保证文件夹是存在的==,否则加载会失败
// load_unload.cc#include <hooks/hooks.h>#include "library_common.h"using namespace isc::hooks;// 日志文件处理器定义std::fstream interesting;extern "C" { int load(LibraryHandle&) { interesting.open("/tmp/interesting.log",std::fstream::out | std::fstream::app); return (interesting ? 0 : 1); } int unload() { if (interesting) { interesting.close(); } return (0); }}
Callout函数
这里的Callout是所有Hook point的统称。并不是真的叫callout这个名字。
callout签名
返回0表示成功,非0表示失败。
extern "C" { int callout(CalloutHandle& handle);}
callout参数
CalloutHandle对象提供2个方法getArgument和setArgument,获取和设置参数。下面的举例如何使用
// 服务端代码片段,演示设置参数int count = 10;boost::shared_ptr<Pkt4> pktptr = ... // Set to appropriate value// 假设handle对象已经创建handle.setArgument("data_count", count);handle.setArgument("inpacket", pktptr);// 调用 callouts...// 获取修改的值handle.getArgument("data_count", count);handle.getArgument("inpacket", pktptr);
源码
// pkt4_receive.cc#include <hooks/hooks.h>#include <dhcp/pkt4.h>#include "library_common.h"#include <string>using namespace isc::dhcp;using namespace isc::hooks;using namespace std;extern "C" {// 在pkt4_receive时调用该函数int pkt4_receive(CalloutHandle& handle) { // A pointer to the packet is passed to the callout via a "boost" smart // pointer. The include file "pkt4.h" typedefs a pointer to the Pkt4 // object as Pkt4Ptr. Retrieve a pointer to the object. Pkt4Ptr query4_ptr; handle.getArgument("query4", query4_ptr); // Point to the hardware address. HWAddrPtr hwaddr_ptr = query4_ptr->getHWAddr(); // The hardware address is held in a public member variable. We'll classify // it as interesting if the sum of all the bytes in it is divisible by 4. // (This is a contrived example after all!) long sum = 0; for (int i = 0; i < hwaddr_ptr->hwaddr_.size(); ++i) { sum += hwaddr_ptr->hwaddr_[i]; } // Classify it. if (sum % 4 == 0) { // Store the text form of the hardware address in the context to pass // to the next callout. string hwaddr = hwaddr_ptr->toText(); handle.setContext("hwaddr", hwaddr); } return (0);};}
// pkt4_send.cc#include <hooks/hooks.h>#include <dhcp/pkt4.h>#include "library_common.h"#include <string>using namespace isc::dhcp;using namespace isc::hooks;using namespace std;extern "C" {// 在pkt4_send hook的时候调用int pkt4_send(CalloutHandle& handle) { // Obtain the hardware address of the "interesting" client. We have to // use a try...catch block here because if the client was not interesting, // no information would be set and getArgument would thrown an exception. string hwaddr; try { handle.getContext("hwaddr", hwaddr); // getContext didn't throw so the client is interesting. Get a pointer // to the reply. Pkt4Ptr response4_ptr; handle.getArgument("response4", response4_ptr); // Get the string form of the IP address. string ipaddr = response4_ptr->getYiaddr().toText(); // Write the information to the log file. interesting << hwaddr << " " << ipaddr << "\n"; // ... and to guard against a crash, we'll flush the output stream. flush(interesting); } catch (const NoSuchCalloutContext&) { // No such element in the per-request context with the name "hwaddr". // This means that the request was not an interesting, so do nothing // and dismiss the exception. } return (0);}}
Hook代码编译
根据上面的操作,完整的文件列表如下:
编译
g++ -I <install-dir>/include/kea -L <install-dir>/lib -fpic -shared -o example.so load_unload.cc pkt4_receive.cc pkt4_send.cc version.cc -lkea-dhcpsrv -lkea-dhcp++ -lkea-hooks -lkea-log -lkea-util -lkea-exceptions
上面编译成功后会在编译目录下,看到 example.so
指向kea安装时的目录,除非你安装时指定–prefix,否则默认为/usr/local
Hook Kea配置
复制
复制Hook库到/usr/local/lib/hooks/下(根据你的喜好你可以放置在任意位置)
编辑
编辑vim /usr/local/etc/kea/kea-dhcp4.conf,在文件的Dhcp4节点下添加如下配置
"hooks-libraries": [{ "library" : "/usr/local/lib/hooks/example.so"}]
重启
重启后,运行测试工具,成功的话可以在/tmp/interesting.log目录如下输出:
总结
Kea如何测试测试,请查阅Karaf教程之Config Admin服务的使用。
参考文献
Hooks Developer’s Guide
Hooks Libraries
Linux共享对象之编译参数fPIC
附录
源码附件
阅读全文
0 0
- Kea DHCP Hooks开发
- Kea DHCP服务器安装教程(Ubuntu)
- Kea DHCP配置介绍和基本使用
- Ubuntu搭建dhcpv4+dhcpv6服务器(Kea DHCP Server V1.2.0)
- Ubuntu IPv6 pppoe服务器搭建(基于Kea DHCP Server V1.2.0)
- Hooks
- Git Hooks实现开发部署任务自动化
- Kea!X问题
- kea预装软件
- K60学习 KEA学习
- WordPress 插件开发教程 – Part-3 – 钩子( hooks )
- 使用Git Hooks实现开发部署任务自动化
- 使用Git Hooks实现开发部署任务自动化
- 使用Git Hooks实现开发部署任务自动化
- 使用Git Hooks实现开发部署任务自动化
- DHCP
- DHCP+
- DHCP
- uploadify上传附件传参
- 全栈HTML5工程师养成记—多终端浏览器兼容
- 第一次使用tensorflow编写程序
- Crypto++的安装及使用
- 扫描识别工具Dynamic Web TWAIN使用教程:如何将本地图像加载到查看器中
- Kea DHCP Hooks开发
- Nginx负载均衡的详细配置及使用案例详解.
- CheckedListBox 中添加带 Text 和 Value 的 CheckBox
- BigDecimal 加减乘除
- docker push 过程 distribution源码 分析
- 用类和函数做装饰器-class decorator and function decorator
- 安装zabbix
- python脚本批量执行shell,使用queue、threading库
- 值得期待:Go对WebAssmbly的完全支持