- 浏览: 175799 次
- 性别:
- 来自: 成都
文章分类
最新评论
-
行动与思考:
你好!请问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 1123在网上找了很久,终于通过twitter-->> ... -
使用一个Makefile文件同时编译dll和beam文件
2010-02-09 11:28 14841. 测试环境 - Windows XP SP3 ... -
Use Erlang NIF to snoop, capture packets(in Windows XP)
2010-02-03 15:02 38741. Overview In my last blog ... -
Use Erlang NIF to snoop, capture packets.
2010-02-01 17:43 25131. Overview In Erlang/OT ... -
New features of NIF in Erlang/OTP R13B04
2010-01-31 15:34 1036From: http://archive.netbsd.se/ ... -
Another erlang nif test
2010-01-31 11:30 1187from http://www.davispj.com/200 ... -
转载:UBUNTU下安装Erlang的两种方法
2010-01-28 21:04 2312================第一种============ ... -
在SOLARIS x86下编译安装ERLANG的另一种方法(失败)
2010-01-04 12:48 998尝试另一种方法。 1. 安装环境 ... -
在SOLARIS x86下成功编译安装ERLANG
2009-12-25 22:35 9731. 系统环境 在http://www.sunfr ... -
ERLANG编辑环境IDE配置
2009-11-18 08:41 36721. 概述 erlang的IDE有很多种,包括EMACS, ... -
Erlang文件I/O性能测评
2009-08-23 15:31 1344转载:http://chaoslawful.ite ... -
erlang网络编程的几个性能调优和注意点
2009-08-23 10:38 1162转载:http://www.lupaworld.com/act ... -
用Erlang实现领域特定语言
2009-08-13 13:13 906用Erlang实现领域特定语言 http://cools ... -
ERLANG mnesia:create_table/2问题
2009-06-11 14:27 1223我测试发现mnesia:create_table()有这样几个 ... -
ERLANG的OS_MON应用程序
2009-06-10 23:03 1582在ERLANG在线手册中,凡是看到〔Application〕字 ... -
erlang/OTP for TCP资源
2009-05-24 00:02 1060a-generalized-tcp-server ... -
ERLANG网上的资源
2009-04-29 15:05 1042http://www.erlang.org/ 是官方 ... -
erlang:split_binary(Bin, N)的BUG
2009-04-23 23:52 5036OS运行平台: root ... -
当你net_adm:ping(Node)的时候发生了什么?流程复杂 但是对理解dist工作原理至关重
2009-04-09 16:31 1335当你net_adm:ping(Node)的时候发生 ... -
erlang的crash_core_dump解读
2009-04-09 16:27 1940正常情况下 当erlang进程发生错误没有catch的时候 e ...
相关推荐
erlang nif test demo
ErLang Windows 25.0.1版本 ErLang 为RabbitMQ必要软件
Windows上安装RabbitMQ服务,依赖的Erlang语言安装包:otp_win64_25.2.1.exe 重要:Erlang安装程序必须【以管理员身份运行】,否则RabbitMQ安装程序相关信息不会在注册表项中不存在。
开发语言Erlang R19.1发布下载。 这种语言目前主要比较著名的开源应用有RabbitMQ,CouchDB,Riak等..它的命名规则也比较特别,这是新的产品系列19.0的第一个补丁版。
Erlang OTP 20.1 Windows 64-bit Binary File 下载地址:http://www.erlang.org/downloads
erlang otp25 win安装包
windows64位操作系统 rabbit mq3.12.4及配套的Erlang/OTP26.0 安装包。官方资源不好下载
OTP是开放电信平台的简称,包含了erlang语言环境。 erlang是函数式语言,提供了9个9的稳定性和超高并发并发性能。 OTP是高并发分布式服务器的最理想平台。
rabbitmq erlang otp_win64_26.0.1.exe windows版本,以管理员安装
Windows下使用NIF扩展Erlang完整例子,包含nif工程项目,erlang引用例子。 配套文章:http://blog.csdn.net/mycwq/article/details/17527485
otp-win32_20.1 32位,里面时安装文件,自己找的时候方便一些
完整Erlang的APi查询手册,和官网上的一样,绝对没有差误,解压后有140M的大的,所有的ErlangOPT都可以查询
otp-23.1 rabbitmq-server-3.8.9 RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件)。RabbitMQ服务器是用Erlang语言编写的,而集群和故障转移是构建在开放电信平台框架上的。...
otp-win64_20.1 64位,里面时安装文件,自己找的时候方便一些
Erlang最新版本 25.0.3 windows 安装文件 解压直接安装 5个币-----------------------------------------------------------------------------------------------------------------------------------------------...
最新版erlang安装包,最新版erlang安装包,最新版erlang安装包,最新版erlang安装包,最新版erlang安装包,最新版erlang安装包,最新版erlang安装包,最新版erlang安装包,最新版erlang安装包,最新版erlang安装包,...
erlang_otp_20.3_man开发手册,erlang_otp_20.3_man开发手册,erlang_otp_20.3_man开发手册
Erlang and OTP in Action
Erlang otp_src_20.3.tar.gz linux centos otp-OTP-20.0.tar.gz 可兼容rabbitmq3.7.0
erlang的otp官方文档,详细介绍了erlang的otp系统的方方面面。