- 浏览: 182377 次
- 性别:
- 来自: 成都
文章分类
最新评论
-
行动与思考:
你好!请问GraphicString这个类型是什么类型呀?怎么 ...
ACSE-1 (osi 8650-1)abstract syntax -
gaozon:
楼主,你好,请问用lua能编写这样一种插件吗:我想更改网络层i ...
编程语言 Lua -
langzhe:
percept:profile("test.dat& ...
erlang r12 新增加Percept并发性能调测模块 -
mryufeng:
解释epmd等2进制协议是erlang的拿手呀
Use Erlang NIF to snoop, capture packets(in Windows XP), in OTP-R13B04 -
xumingyong:
GeoffCant在git clone git://git.e ...
Use Erlang NIF to snoop, capture packets(in Windows XP), in OTP-R13B04
Use Erlang NIF to snoop, capture packets(in Windows XP), in OTP-R13B04
- 博客分类:
- Erlang
1. 介绍
在上一篇博文http://xumingyong.iteye.com/blog/586743中,我在Erlang/OTP-R13B03中,用nif实现了抓网络包功能,但是由于在R13B04版本中,NIF接口形式发生了变化(见下一段在线文档摘要),所以我的源码也做了相应修改。
---------------------------------------------------------------------------------
The NIF concept was introduced in R13B03 as an EXPERIMENTAL feature. The interfaces may be changed in any way in coming releases. The plan is however to lift the experimental label and maintain interface backward compatibility from R14B.
Incompatible changes in R13B04:
- The function prototypes of the NIFs have changed to expect argc and argv arguments. The arity of a NIF is by that no longer limited to 3.
- enif_get_data renamed as enif_priv_data.
- enif_make_string got a third argument for character encoding.
----------------------------------------------------------------------------------
2. nif_R13B04.c
主要是nif函数的声明形式发生了变化。
/* This file used to create a Erlang NIF which sniffer network packets. */ #include "nif.h" pcap_t *devHandler = NULL; static ERL_NIF_TERM lookup(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { int i = 0; char errbuf[PCAP_ERRBUF_SIZE], str[1024], str1[1024], num[6]; pcap_if_t *alldevs, *d; memset(errbuf, 0, PCAP_ERRBUF_SIZE); memset(str, 0, 1024); memset(str1, 0, 1024); if (pcap_findalldevs_ex("rpcap://", NULL /* auth is not needed */, &alldevs, errbuf) == -1) return enif_make_string(env, errbuf, ERL_NIF_LATIN1); for(d= alldevs; d != NULL; d= d->next) { strcat(str, "{"); itoa(++i, num, 10); strcat(str, num); strcat(str, ", "); strcat(str, d->name); strcat(str, ", "); if (d->description) strcat(str, d->description); else strcat(str,"null"); strcat(str, "}, "); } pcap_freealldevs(alldevs); return enif_make_string(env, str, ERL_NIF_LATIN1); } static ERL_NIF_TERM opendevice(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { /* char dev[64]; */ char dev[1024]; int ip, res, i, j; char errbuf[PCAP_ERRBUF_SIZE]; pcap_if_t *alldevs, *d; memset(errbuf, 0, PCAP_ERRBUF_SIZE); memset(dev, 0, 1024); /* argv[0] = interface index */ res = enif_get_int(env, argv[0], &ip); if(res < 0) { return enif_make_string(env, "error argument", ERL_NIF_LATIN1); } if (pcap_findalldevs_ex("rpcap://", NULL /* auth is not needed */, &alldevs, errbuf) == -1) return enif_make_string(env, errbuf, ERL_NIF_LATIN1); for(d = alldevs, i = 1; d != NULL; d = d->next, i++) { if(i == ip) strcpy(dev, d->name); } pcap_freealldevs(alldevs); /* Parms: dev,snaplen,promisc,timeout_ms,errbuf * to_ms=0 means wait enough packet to arrive. */ devHandler = pcap_open_live(dev, 65535, 1, 0, errbuf); if(devHandler != NULL) return enif_make_atom(env, "ok"); else return enif_make_string(env, errbuf, ERL_NIF_LATIN1); } static ERL_NIF_TERM capture(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { int i, res; struct pcap_pkthdr *pkthdr; const u_char *packet = NULL; ErlNifBinary bin; res = pcap_next_ex(devHandler, &pkthdr, &packet); if(res > 0) { enif_alloc_binary(env, pkthdr->len, &bin); for(i = 0; i < pkthdr->len; i++) { bin.data[i] = packet[i]; } bin.size = pkthdr->len; return enif_make_binary(env, &bin); } else if(res == 0) { return enif_make_string(env, "Timeout", ERL_NIF_LATIN1); } else if(res == -1) { return enif_make_string(env, pcap_geterr(devHandler), ERL_NIF_LATIN1); } else { return enif_make_string(env, "Unknown error", ERL_NIF_LATIN1); } } static ErlNifFunc funcs[] = { {"lookup", 0, lookup}, {"capture", 0, capture}, {"opendevice", 1, opendevice} }; ERL_NIF_INIT(nif,funcs,NULL,NULL,NULL,NULL)
3. nif.h
#include "erl_nif.h" #include "stdio.h" #include "pcap.h" #include "string.h" #include "ctype.h" #include "stdlib.h" #ifndef NIF_H #define NIF_H #ifdef __cplusplus extern "C" { #endif static ERL_NIF_TERM opendevice(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM capture(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM lookup(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); #ifdef __cplusplus } #endif #endif
4. Makefile
# by xumingyong@gmail.com all: nif_dll nif.beam # for win32 dll compiler # CFLAGS -g used for to generate debug info, used by gdb command. CC = gcc CFLAGS = -shared INPUT = nif_R13B04.c wpcap.lib nif_dll: nif.h $(CC) $(CFLAGS) -o nif.dll $(INPUT) # for erlang beam compiler ERL = erlc .SUFFIXES: .erl .beam .erl.beam: $(ERL) $< clean: del *.beam *.dll erl_crash.dump
5. nif.erl
主要变化是:在R13B03中on_load函数的返回值必须是true,在R13B04中不需要了。
%%% nif sniffer -module(nif). -on_load(on_load/0). -compile(export_all). %%============================================================ %% Automatically loaded when load the module. on_load() -> ok = erlang:load_nif("./nif", 0). start(InterfaceIndex, CaptureNum) -> case opendevice(InterfaceIndex) of ok -> loop(CaptureNum); _Any -> {error, opendevice_fail} end. %% return a tuple, with{id, name, description}... lookup() -> error. %check the lookup() return, here use the Interface id, e.g. 1, 2 or ... opendevice(_Interface) -> error. capture() -> error. loop(0) -> io:format("Time:~w ", [time()]); loop(Count) -> Pkt = capture(), parser(Pkt), loop(Count-1). %%============================================================ parser(Pkt) when is_binary(Pkt) -> <<_Addr:12/binary-little, TypeOrLen:2/binary-little, _Res/binary-little>> = Pkt, case (TypeOrLen > <<16#05, 16#DC>>) of true -> parser(ethernet, Pkt); false -> parser(ieee, Pkt) end; parser(Pkt) when not(is_binary(Pkt)) -> io:format("---Not a binary data-------------------------------~n"), io:format("\t~p~n", [Pkt]). parser(ethernet, Pkt) -> <<Dst:6/binary-little, Src:6/binary-little, Type:2/binary-little, Res/binary-little>> = Pkt, io:format("---Ethernet II frame-------------------------------"), io:format("~nDst MAC:\t"), printHex(Dst), io:format("~nSrc MAC:\t"), printHex(Src), io:format("~nType:\t\t"), printHex(Type), printEthernetIIType(Type), io:format("~nData:\t\t"), printHex(Res), io:format("~n~n"); parser(ieee, Pkt) -> <<Dst:6/binary-little, Src:6/binary-little, Len:2/binary-little, DSAP:1/binary-little, SSAP:1/binary-little, Ctrl:1/binary-little, % ieee802.2 class 1, connectionless type. Normally be 0x03. Res/binary-little>> = Pkt, io:format("---IEEE802.3 frame-------------------------------"), io:format("~nDst MAC:\t"), printHex(Dst), io:format("~nSrc MAC:\t"), printHex(Src), io:format("~nTotal Length:\t"), printHex(Len), io:format("~nDSAP:\t\t"), printHex(DSAP), printIeeeDSAP(DSAP), io:format("~nSSAP:\t\t"), printHex(SSAP), printIeeeSSAP(SSAP), io:format("~nControl:\t"), printHex(Ctrl), io:format("~nData:\t\t"), printHex(Res), io:format("~n~n"). printHex(Bin) -> [io:format("~2.16.0B ",[X]) || X <- binary_to_list(Bin)]. printEthernetIIType(Type) -> case Type of <<16#08, 16#06>> -> io:format("\t= ARP"); <<16#08, 16#00>> -> io:format("\t= IP"); <<16#02, 16#00>> -> io:format("\t= PUP"); <<16#80, 16#35>> -> io:format("\t= RARP"); <<16#86, 16#DD>> -> io:format("\t= IPv6"); <<16#88, 16#63>> -> io:format("\t= PPPOE Discovery"); <<16#88, 16#64>> -> io:format("\t= PPPoE Session"); <<16#88, 16#47>> -> io:format("\t= MPLS Unicast"); <<16#88, 16#48>> -> io:format("\t= MPLS Multicast"); <<16#81, 16#37>> -> io:format("\t= IPX/SPX"); <<16#80, 16#00>> -> io:format("\t= IS-IS"); <<16#88, 16#09>> -> io:format("\t= LACP"); <<16#88, 16#8E>> -> io:format("\t= 802.1x"); <<16#81, 16#4C>> -> io:format("\t= SNMP"); <<16#88, 16#0B>> -> io:format("\t= PPP"); <<16#88, 16#A7>> -> io:format("\t= Cluster"); <<16#90, 16#00>> -> io:format("\t= Loopback"); <<16#90, 16#10>> -> io:format("\t= Vlan Tag"); <<16#90, 16#20>> -> io:format("\t= Vlan Tag"); _Any -> io:format("\t= unknown") end. printIeeeDSAP(Dsap) -> <<IG>> = Dsap, case IG bsr 7 of 0 -> io:format("\t I/G=0 (Individual address)"); 1 -> io:format("\t I/G=1 (Group address)") end. printIeeeSSAP(Ssap) -> <<CR>> = Ssap, case CR bsr 7 of 0 -> io:format("\t C/R=0 (Command)"); 1 -> io:format("\t C/R=1 (Response)") end.
6. 测试
省略,见上一篇博文http://xumingyong.iteye.com/blog/586743。
另外:需要注意的是,R13B04的lib\tools-2.6.5.1\emacs目录下,缺少了erlang-skels.el和erlang-skels-old.el两个文件,导致EMACS不能正常进行语法高亮显示,可在源码中将这两个文件拷贝到该目录下即可。一个小小的bug。
评论
erlsnoop是用纯C实现的,用erl应该会更简单,只是要实现一个完整的EPMD协议还是挺麻烦的。
发表评论
-
又一本ERLANG书:Erlang and OTP in Action
2010-03-30 15:46 1195在网上找了很久,终于通过twitter-->> ... -
使用一个Makefile文件同时编译dll和beam文件
2010-02-09 11:28 15481. 测试环境 - Windows XP SP3 ... -
Use Erlang NIF to snoop, capture packets(in Windows XP)
2010-02-03 15:02 39551. Overview In my last blog ... -
Use Erlang NIF to snoop, capture packets.
2010-02-01 17:43 25641. Overview In Erlang/OT ... -
New features of NIF in Erlang/OTP R13B04
2010-01-31 15:34 1107From: http://archive.netbsd.se/ ... -
Another erlang nif test
2010-01-31 11:30 1261from http://www.davispj.com/200 ... -
转载:UBUNTU下安装Erlang的两种方法
2010-01-28 21:04 2405================第一种============ ... -
在SOLARIS x86下编译安装ERLANG的另一种方法(失败)
2010-01-04 12:48 1058尝试另一种方法。 1. 安装环境 ... -
在SOLARIS x86下成功编译安装ERLANG
2009-12-25 22:35 10401. 系统环境 在http://www.sunfr ... -
ERLANG编辑环境IDE配置
2009-11-18 08:41 37081. 概述 erlang的IDE有很多种,包括EMACS, ... -
Erlang文件I/O性能测评
2009-08-23 15:31 1398转载:http://chaoslawful.ite ... -
erlang网络编程的几个性能调优和注意点
2009-08-23 10:38 1220转载:http://www.lupaworld.com/act ... -
用Erlang实现领域特定语言
2009-08-13 13:13 1005用Erlang实现领域特定语言 http://cools ... -
ERLANG mnesia:create_table/2问题
2009-06-11 14:27 1280我测试发现mnesia:create_table()有这样几个 ... -
ERLANG的OS_MON应用程序
2009-06-10 23:03 1657在ERLANG在线手册中,凡是看到〔Application〕字 ... -
erlang/OTP for TCP资源
2009-05-24 00:02 1131a-generalized-tcp-server ... -
ERLANG网上的资源
2009-04-29 15:05 1099http://www.erlang.org/ 是官方 ... -
erlang:split_binary(Bin, N)的BUG
2009-04-23 23:52 5092OS运行平台: root ... -
当你net_adm:ping(Node)的时候发生了什么?流程复杂 但是对理解dist工作原理至关重
2009-04-09 16:31 1437当你net_adm:ping(Node)的时候发生 ... -
erlang的crash_core_dump解读
2009-04-09 16:27 2006正常情况下 当erlang进程发生错误没有catch的时候 e ...
相关推荐
在给定的压缩包文件"otp-OTP-20.0.tar.gz"中,我们可以推测这包含了OTP的版本20.0,这是一个针对Erlang语言的重要版本更新。 Erlang是一种静态类型、函数式编程语言,特别适合构建高并发、低延迟和容错性强的系统,...
**OTP (Open Telecom Platform) for Windows 64位 25.0.1 版本:ErLang 下载** ErLang是一种高级并发编程语言,由瑞典电信设备制造商Ericsson开发,用于构建高度可靠和可扩展的分布式系统。OTP(Open Telecom ...
在Windows操作系统上,Erlang OTP通常提供为预编译的64位版本,如"erlang-otp-win64位 25.3版本",这确保了它能在Windows 64位环境下高效运行。 Erlang OTP(Open Telephony Platform)是一个开放源码的软件框架,...
【标题】:“rustler编写erlang nif” 在Erlang生态系统中,Native Implemented Functions (NIFs) 是一种机制,允许开发者用其他语言(如C、C++或Rust)编写性能关键部分的代码,然后在Erlang虚拟机(VM)中调用。...
Erlang NIF(Native Implemented Functions)是Erlang虚拟机提供的一种机制,允许开发者用C语言或者其他低级语言编写性能关键部分的代码,并在Erlang系统中无缝调用。这种方式可以充分利用C语言的高效性,同时保持...
标题中的"otp-win64-25.1.2"指的是Erlang OTP(Open Telephony Platform)的一个64位Windows版本,版本号为25.1.2。Erlang OTP是一个开源平台,主要用于构建高可用性、分布式和实时系统。它提供了强大的并发处理、...
在本案例中,我们讨论的是RabbitMQ的Windows 64位版本,即rabbitmq-server-3.12.4.exe,以及配套的Erlang环境 otp-win64-26.0.exe。Erlang是一种面向并发的编程语言,是RabbitMQ的基础,因为RabbitMQ是用Erlang编写...
Erlang OTP(Open Telephony Platform)是一种由Ericsson公司开发的编程语言Erlang的扩展框架,主要用于构建高可用性、容错性和分布式系统。Erlang OTP 19.0是该平台的一个重要版本,它包含了Erlang R19.1,这是一个...
Win10安装erlang,高版本,官网下载速度比较慢,网上资料大多名副其实,挂羊头卖狗肉,花费很长时间从官网下载的最新版本otp_win64_24.0,拿出来与大家分享
Windows上安装RabbitMQ服务,依赖的Erlang语言安装包:otp_win64_25.2.1.exe 重要:Erlang安装程序必须【以管理员身份运行】,否则RabbitMQ安装程序相关信息不会在注册表项中不存在。
标题中的"otp-src-21.3.zip"指的是Erlang编程语言的源代码压缩包,版本为21.3。OTP(Open Telephony Platform)是Erlang的核心部分,包含了许多用于构建可靠、分布式系统的基础库和工具。Erlang因其在处理并发和容错...
此“Erlang-OTP-API 离线查询英文全手册”是Erlang OTP的官方文档,包含了所有API的详细信息,是学习和开发Erlang OTP应用的重要资源。手册内容广泛,包括了以下几个核心部分: 1. **模块和函数**:手册详细列出了...
标题中的"otp-win64_20.1 64位"指的是Erlang的 OTP (Open Telecom Platform) 的一个特定版本,适用于64位Windows操作系统。OTP是Erlang编程语言的核心部分,提供了一个强大的并发框架、分布式计算支持以及故障恢复...
用于linux下安装RabbitMQ ,首先安装Erlang环境,并且要注意rabbitmq版本和Erlang需版本对应 我安装的RabbitMQ 3.10.25和Erlang 23.2; Erlang 25.1(下载 地址:https://www.erlang.org/patches/otp-23.2.7.5) ...
OTP的核心是Erlang编程语言,它提供了强大的并发处理能力和容错机制,使得在分布式系统中实现高可用性成为可能。 在OTP 19.3版本中,我们看到的是一个经过精心设计和优化的版本,它包含了Erlang VM(BEAM)的改进...
标题中的"otp-win64-25.3.exe"是一个针对Windows 64位操作系统的 OTP(Open Telecom Platform)软件的可执行文件。OTP是由Ericsson开发的一个开源框架,主要用于构建高度可靠、可扩展和可维护的分布式系统,尤其是...
This section covers the installation process for the Erlang/OTP binary release on UNIX or Windows environments. ##### UNIX Installation **Introduction** The OTP system is distributed as a single ...
OTP(Open Telephony Platform)是爱立信公司开发的一个开源软件框架,主要为构建高度可靠、可扩展且具有容错能力的分布式系统提供基础。它以其内置的编程语言Erlang为核心,Erlang是一种静态类型、函数式编程语言,...
EMQX,全称为Erlang MQTT Broker,是一款基于Erlang OTP开发的开源MQTT消息代理,专门针对物联网(IoT)设计。这个“emqx-4.4.3-otp24.2.1-windows-amd64.zip”压缩包文件包含了EMQ X Broker的4.4.3版本,适配于运行...
otp_win64_26.0安装包