待整理...
一、user-mode 网络 包过滤
1、winsock分层service provider
参照Microsoft Platform SDK上有关文档和例子
(http://www.microsoft.com/msdownload/platformsdk/sdkupdate/)
这里有好几个microsoft lsp 例子,最新(可能最bug-free)的经常在这里能找到。需要知道的是可以通过TDI调用核心TCPIP驱动,而且可以完全绕开WINSOCK,在大多 数情况下这不是一个问题。例如:QOS的实现可以在WINSOCK LSP上。
然而,这样做的话, 程序 必须察看和操作每个包,而不能依靠WINSOCK LSP,他们要以一种接近核心态的方法来实现。
2、win2000包过滤接口
WIN2000包过滤接口提供了一种机制,这种机制允许用户态程序或者服务指定一系列的"过滤原则",这些过滤原则会被低层的TCPIP实现用来过滤包。这种过滤工主要是对IP原地址、目标地址、端口号(或者端口号范围)进行pass或者drop操作。
Windows Developer's Journal
《用iphlpapi.dll进行包过滤》作者:Ton plooy,October,2000,Volume 11, Number 10。
WIN2000提供了一个较好对TCPIP的可编程控制,其中包括包过滤。不幸的是,有关这个新的API的文档并不是很容易能找到。这篇文章向你演示了怎样对特定IP地址或者特定TCP端口的包进行阻塞的编程。
链接:www.wdj.com
上面这个例子的下载:ftp://ftp.wdj.com/pub/webzip/1110/plooy.zip
Hollis 的解决方案:
HTS W2K IpHook例子演示了IP过滤和它的HOOK API,包含原文件,而且是免费的,需要HtsCpp运行时库(免费),下载地址:http://www.hollistech.com/
3、winsock替代DLL
在使用WINSOCK LSP之前,唯一的办法是用自己的DLL取代微软的WINSOCK DLL,假如实现顺利的话,自己的DLL会接收用户的WINSOCK调用请求,然后还可以调用原来的WINSOCK DLL来处理。
不过这样的实现是比较费力的,其中有个困难就是微软的WINSOCK DLL里面经常有一些未公开的内部使用的函数,一个WINSOCK代替DLL至少要处理其中的一些未公开函数。
随着WINDOWS系统结构的变化,有些方面得到了加强,比如系统文件保护,这使得这种技术变得不太可行。总的说来,使用WINSOCK DLL替换不是一个坏主意。(Xfilter就是用的这种技术,原代码可能在网上有流传,我以前看到过的)
二、kernel-mode网络包过滤
1、Transport Data Interface (TDI)
这主要是一个直接在核心TCPIP驱动上面的一层过滤驱动。在WINXP上TDI驱动是一种传统的NT 风格 的驱动,使用了基于IRP的API,这里有两种方法来实现。
A、使用核心模式服务的IoAttachDeviceXYZ函数族在TDI上实现一个过滤。
B、对TDI驱动IRP DISPATCH表进行过滤。
IoAttachDeviceXYZ函数在许多WINNT驱动开发的书上提到。这两种技术都需要对WINNT驱动开发编程技术十分了解,对TDI函数也要相当的了解。
2、NDIS中间层(IM)
具体请看NDIS IM FAQ:http://www.pcausa.com/resources/ndisimfaq.htm
3、WIN2000 FILTER-HOOK
请参照有关DDK文档,系统中只能有一个 活动 的Filter-Hook存在,这点使这种技术的使用有严重的限制。(平时所见的drvipflt就是用的这个)
4、WIN2000 FIREWALL-HOOK
Firewall-Hook Driver函数在文档里介绍得很少,而且在有些win2000版本中不可用。请参照微软有关文档:http: //msdn.microsoft.com/library/default.asp?url=/library/en-us/network/hh/network/firewall_3wfb.asp
5、NDIS-HOOKING (费尔防火墙就是用的这种技术吧,据我所知,虽然我没看过原码。)
NDIS-Hooking驱动拦截或者叫"HOOK"一些由NDIS封装程序导出的函数。虽然从实现手段上来说有些不正规,但一个有系统的NDIS-Hooking过滤会非常有效。
另外:NDIS-Hooking过滤驱动有下面的好处:
A、容易安装(可以动态装卸,不过有时候会出问题,里面有些情况现在还未知。)
B、支持拨号-ppp适配器。
Ndis-Hooking技术在98和ME系统下非常有效和实用。在这些平台上,DDK文档和provided services都能很有用的帮你HOOK由Ndis wrapper导出的函数。
Ndis-Hooking技术在NT,2000和XP上同样有效和实用。这种技术很像核心 模式 的调试器。文档支持较少,而且基本上不会被WHQL认证。
PCAUSA提供了一套NDIS PIM驱动例子,这些例子能在现有的WIN平台上运行成功(从95到XP)。地址:http://www.pcausa.com/ndispim/Default.htm
其他:
Network操作和进程信息:
有许多人想知道网络上的操作和WIN进程(就是应用程序啦)之间怎样联系起来,举例来说,可能会想知道是哪个进程在一个特定的IP端口上发送或接收数据。
先不考虑这种技术是否有用,或者是否可靠, 我们 认 为核心模式TCPIP驱动上层的过滤程序可以处理这个问题。而TCPIP驱动下层的过滤程序根本看不到进程信息。特别要注意的是有些网络服务操作生成一个 新的进程attach到系统进程上的。在这种情况下进程信息并不能告诉我们原先是哪个进程生成的。特别是单独在核心模式下的WIN服务(TDI客户)
最后,有必要看看下面的资料United States Patent 5,987,611; "System and methodology for managing internet access on a per application basis for client computers connected to the internet "
我们并不知道这项专利的价值,也不知道他是否能用在包过滤上。详情请参阅:http://www.uspto.gov/patft/index.html
www.pcausa.com
============================================
drvipflt具体解析,就是上面所提到的吧(2-3就是说的这东东)。
假定大家对驱动框架已经有了一定的理解。IRP分配程序如下:
NTSTATUS DrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
...
switch (irpStack->MajorFunction)
{
...
case IRP_MJ_DEVICE_CONTROL:
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
switch (ioControlCode)
{
// ioctl code to start filtering
//这里可以从用户模式程序发送这样的请求。
//直接用DeviceIoControl这个函数,就像下面这样调用就可以了吧,我想。
//DeviceIoControl(drivehandle,START_IP_HOOK,NULL,0,NULL,0,&bytereturned,NULL)
case START_IP_HOOK:
{
//这个应该是最主要的函数了。
SetFilterFunction(cbFilterFunction);
break;
}
// ioctl to stop filtering
case STOP_IP_HOOK:
{
SetFilterFunction(NULL);
break;
}
// ioctl to add a filter rule
case ADD_FILTER:
{
if(inputBufferLength == sizeof(IPFilter))
{
IPFilter *nf;
nf = (IPFilter *)ioBuffer;
AddFilterToList(nf);
}
break;
}
// ioctl to free filter rule list
case CLEAR_FILTER:
{
ClearFilterList();
break;
}
default:
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
break;
}
break;
...
}
SetFilterFunction(cbFilterFunction)可能是最重要的一个程序了。具体如下:
实际上这个做法相当在系统中注册了一个回调函数。
NTSTATUS SetFilterFunction(PacketFilterExtensionPtr filterFunction)
{
NTSTATUS status = STATUS_SUCCESS, waitStatus=STATUS_SUCCESS;
UNICODE_STRING filterName;
PDEVICE_OBJECT ipDeviceObject=NULL;
PFILE_OBJECT ipFileObject=NULL;
PF_SET_EXTENSION_HOOK_INFO filterData;
KEVENT event;
IO_STATUS_BLOCK ioStatus;
PIRP irp;
//首先获得一个 设备 指针。
//first of all, we have to get a pointer to IpFilterDriver Device
RtlInitUnicodeString(&filterName, DD_IPFLTRDRVR_DEVICE_NAME);
status = IoGetDeviceObjectPointer(&filterName,STANDARD_RIGHTS_ALL, &ipFileObject, &ipDeviceObject);
if(NT_SUCCESS(status))
{
//一些初始化工作,填充filterData。
//initialize the struct with functions parameters
filterData.ExtensionPointer = filterFunction;
//we need initialize the event used later by the IpFilterDriver to signal us
//when it finished its work
KeInitializeEvent(&event, NotificationEvent, FALSE);
//这个就是最重要的注册回调函数过程。DDK中具体讲述是这样的
//IOCTL_PF_SET_EXTENSION_POINTER registers filter-hook callback functions to the IP filter driver
//to inform the IP filter driver to call those filter hook callbacks for every IP packet
//that is received or transmitted. Also, IOCTL_PF_SET_EXTENSION_POINTER clears filter-hook
//callback functions from the IP filter driver. (看到了吧,最后一句话,注册新的回调函数,就将原先的清除掉了,
//所以说系统中只存在一个这样的驱动有用。)
//we build the irp needed to establish fitler function这个地方仅仅是生成这样的IRP,并没有注册
irp = IoBuildDeviceIoControlRequest(IOCTL_PF_SET_EXTENSION_POINTER,
ipDeviceObject,
(PVOID) &filterData,
sizeof(PF_SET_EXTENSION_HOOK_INFO),
NULL,
0,
FALSE,
&event,
&ioStatus);
if(irp != NULL)
{
// we send the IRP
//这个地方才是真正的注册呀。
status = IoCallDriver(ipDeviceObject, irp);
//and finally, we wait for "acknowledge" of IpDriverFilter
if (status == STATUS_PENDING)
{
waitStatus = KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
if (waitStatus != STATUS_SUCCESS ) {}
}
status = ioStatus.Status;
if(!NT_SUCCESS(status)){}
}
else
{
//if we cant allocate the space, we return the corresponding code error
status = STATUS_INSUFFICIENT_RESOURCES;
}
if(ipFileObject != NULL)
ObDereferenceObject(ipFileObject);
ipFileObject = NULL;
ipDeviceObject = NULL;
}
else
return status;
}
//真正的过滤函数是这个,在最早的IRPdispatch里面传递的这个函数。
//这个函数就是系统传递了一个包头和包内容和包长度之类的东西,你可以在里面进行一些处理,
//假如你想让这个包通过的话,就返回PF_FORWARD,或者你不想让包通过的话,就返回PF_DROP就拦住了。是不是
//听起来很简单,
PF_FORWARD_ACTION cbFilterFunction(IN unsigned char *PacketHeader,IN unsigned char *Packet, IN unsigned int PacketLength, IN unsigned int RecvInterfaceIndex, IN unsigned int SendInterfaceIndex, IN unsigned long RecvLinkNextHop, IN unsigned long SendLinkNextHop)
{
IPPacket *ipp;
TCPHeader *tcph;
UDPHeader *udph;
int countRule=0;
struct filterList *aux = first;
//we "extract" the ip Header
ipp=(IPPacket *)PacketHeader;
// dprintf("Source: %x/nDestination: %x/nProtocol: %d", ipp->ipSource, ipp->ipDestination, ipp->ipProtocol);
//TCP -> protocol = 6
//we accept all packets of established connections
if(ipp->ipProtocol == 6)
{
tcph=(TCPHeader *)Packet;
// dprintf("FLAGS: %x/n", tcph->flags);
//if we havent the bit SYN activate, we pass the packets
if(!(tcph->flags & 0x02))
return PF_FORWARD;
}
//otherwise, we compare the packet with our rules
while(aux != NULL)
{
// dprintf("Comparing with Rule %d", countRule);
//if protocol is the same....
if(aux->ipf.protocol == 0 || ipp->ipProtocol == aux->ipf.protocol)
{
//we look in source Address
if(aux->ipf.sourceIp != 0 && (ipp->ipSource & aux->ipf.sourceMask) != aux->ipf.sourceIp)
{
aux=aux->next;
countRule++;
continue;
}
// we look in destination address
if(aux->ipf.destinationIp != 0 && (ipp->ipDestination & aux->ipf.destinationMask) != aux->ipf.destinationIp)
{
aux=aux->next;
countRule++;
continue;
}
//if we have a tcp packet, we look in ports
//tcp, protocol = 6
if(ipp->ipProtocol == 6)
{
if(aux->ipf.sourcePort == 0 || tcph->sourcePort == aux->ipf.sourcePort)
{
if(aux->ipf.destinationPort == 0 || tcph->destinationPort == aux->ipf.destinationPort) //puerto tcp destino
{
//now we decided what to do with the packet
if(aux->ipf.drop)
return PF_DROP;
else
return PF_FORWARD;
}
}
}
//udp, protocol = 17
else if(ipp->ipProtocol == 17)
{
udph=(UDPHeader *)Packet;
if(aux->ipf.sourcePort == 0 || udph->sourcePort == aux->ipf.sourcePort)
{
if(aux->ipf.destinationPort == 0 || udph->destinationPort == aux->ipf.destinationPort)
{
//now we decided what to do with the packet
if(aux->ipf.drop)
return PF_DROP;
else
return PF_FORWARD;
}
}
}
else
{
//for other packet we dont look more and ....
//now we decided what to do with the packet
if(aux->ipf.drop)
return PF_DROP;
else
return PF_FORWARD;
}
}
//compare with the next rule
countRule++;
aux=aux->next;
}
//we accept all not registered
return PF_FORWARD;
}
一、user-mode 网络 包过滤
1、winsock分层service provider
参照Microsoft Platform SDK上有关文档和例子
(http://www.microsoft.com/msdownload/platformsdk/sdkupdate/)
这里有好几个microsoft lsp 例子,最新(可能最bug-free)的经常在这里能找到。需要知道的是可以通过TDI调用核心TCPIP驱动,而且可以完全绕开WINSOCK,在大多 数情况下这不是一个问题。例如:QOS的实现可以在WINSOCK LSP上。
然而,这样做的话, 程序 必须察看和操作每个包,而不能依靠WINSOCK LSP,他们要以一种接近核心态的方法来实现。
2、win2000包过滤接口
WIN2000包过滤接口提供了一种机制,这种机制允许用户态程序或者服务指定一系列的"过滤原则",这些过滤原则会被低层的TCPIP实现用来过滤包。这种过滤工主要是对IP原地址、目标地址、端口号(或者端口号范围)进行pass或者drop操作。
Windows Developer's Journal
《用iphlpapi.dll进行包过滤》作者:Ton plooy,October,2000,Volume 11, Number 10。
WIN2000提供了一个较好对TCPIP的可编程控制,其中包括包过滤。不幸的是,有关这个新的API的文档并不是很容易能找到。这篇文章向你演示了怎样对特定IP地址或者特定TCP端口的包进行阻塞的编程。
链接:www.wdj.com
上面这个例子的下载:ftp://ftp.wdj.com/pub/webzip/1110/plooy.zip
Hollis 的解决方案:
HTS W2K IpHook例子演示了IP过滤和它的HOOK API,包含原文件,而且是免费的,需要HtsCpp运行时库(免费),下载地址:http://www.hollistech.com/
3、winsock替代DLL
在使用WINSOCK LSP之前,唯一的办法是用自己的DLL取代微软的WINSOCK DLL,假如实现顺利的话,自己的DLL会接收用户的WINSOCK调用请求,然后还可以调用原来的WINSOCK DLL来处理。
不过这样的实现是比较费力的,其中有个困难就是微软的WINSOCK DLL里面经常有一些未公开的内部使用的函数,一个WINSOCK代替DLL至少要处理其中的一些未公开函数。
随着WINDOWS系统结构的变化,有些方面得到了加强,比如系统文件保护,这使得这种技术变得不太可行。总的说来,使用WINSOCK DLL替换不是一个坏主意。(Xfilter就是用的这种技术,原代码可能在网上有流传,我以前看到过的)
二、kernel-mode网络包过滤
1、Transport Data Interface (TDI)
这主要是一个直接在核心TCPIP驱动上面的一层过滤驱动。在WINXP上TDI驱动是一种传统的NT 风格 的驱动,使用了基于IRP的API,这里有两种方法来实现。
A、使用核心模式服务的IoAttachDeviceXYZ函数族在TDI上实现一个过滤。
B、对TDI驱动IRP DISPATCH表进行过滤。
IoAttachDeviceXYZ函数在许多WINNT驱动开发的书上提到。这两种技术都需要对WINNT驱动开发编程技术十分了解,对TDI函数也要相当的了解。
2、NDIS中间层(IM)
具体请看NDIS IM FAQ:http://www.pcausa.com/resources/ndisimfaq.htm
3、WIN2000 FILTER-HOOK
请参照有关DDK文档,系统中只能有一个 活动 的Filter-Hook存在,这点使这种技术的使用有严重的限制。(平时所见的drvipflt就是用的这个)
4、WIN2000 FIREWALL-HOOK
Firewall-Hook Driver函数在文档里介绍得很少,而且在有些win2000版本中不可用。请参照微软有关文档:http: //msdn.microsoft.com/library/default.asp?url=/library/en-us/network/hh/network/firewall_3wfb.asp
5、NDIS-HOOKING (费尔防火墙就是用的这种技术吧,据我所知,虽然我没看过原码。)
NDIS-Hooking驱动拦截或者叫"HOOK"一些由NDIS封装程序导出的函数。虽然从实现手段上来说有些不正规,但一个有系统的NDIS-Hooking过滤会非常有效。
另外:NDIS-Hooking过滤驱动有下面的好处:
A、容易安装(可以动态装卸,不过有时候会出问题,里面有些情况现在还未知。)
B、支持拨号-ppp适配器。
Ndis-Hooking技术在98和ME系统下非常有效和实用。在这些平台上,DDK文档和provided services都能很有用的帮你HOOK由Ndis wrapper导出的函数。
Ndis-Hooking技术在NT,2000和XP上同样有效和实用。这种技术很像核心 模式 的调试器。文档支持较少,而且基本上不会被WHQL认证。
PCAUSA提供了一套NDIS PIM驱动例子,这些例子能在现有的WIN平台上运行成功(从95到XP)。地址:http://www.pcausa.com/ndispim/Default.htm
其他:
Network操作和进程信息:
有许多人想知道网络上的操作和WIN进程(就是应用程序啦)之间怎样联系起来,举例来说,可能会想知道是哪个进程在一个特定的IP端口上发送或接收数据。
先不考虑这种技术是否有用,或者是否可靠, 我们 认 为核心模式TCPIP驱动上层的过滤程序可以处理这个问题。而TCPIP驱动下层的过滤程序根本看不到进程信息。特别要注意的是有些网络服务操作生成一个 新的进程attach到系统进程上的。在这种情况下进程信息并不能告诉我们原先是哪个进程生成的。特别是单独在核心模式下的WIN服务(TDI客户)
最后,有必要看看下面的资料United States Patent 5,987,611; "System and methodology for managing internet access on a per application basis for client computers connected to the internet "
我们并不知道这项专利的价值,也不知道他是否能用在包过滤上。详情请参阅:http://www.uspto.gov/patft/index.html
www.pcausa.com
============================================
drvipflt具体解析,就是上面所提到的吧(2-3就是说的这东东)。
假定大家对驱动框架已经有了一定的理解。IRP分配程序如下:
NTSTATUS DrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
...
switch (irpStack->MajorFunction)
{
...
case IRP_MJ_DEVICE_CONTROL:
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
switch (ioControlCode)
{
// ioctl code to start filtering
//这里可以从用户模式程序发送这样的请求。
//直接用DeviceIoControl这个函数,就像下面这样调用就可以了吧,我想。
//DeviceIoControl(drivehandle,START_IP_HOOK,NULL,0,NULL,0,&bytereturned,NULL)
case START_IP_HOOK:
{
//这个应该是最主要的函数了。
SetFilterFunction(cbFilterFunction);
break;
}
// ioctl to stop filtering
case STOP_IP_HOOK:
{
SetFilterFunction(NULL);
break;
}
// ioctl to add a filter rule
case ADD_FILTER:
{
if(inputBufferLength == sizeof(IPFilter))
{
IPFilter *nf;
nf = (IPFilter *)ioBuffer;
AddFilterToList(nf);
}
break;
}
// ioctl to free filter rule list
case CLEAR_FILTER:
{
ClearFilterList();
break;
}
default:
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
break;
}
break;
...
}
SetFilterFunction(cbFilterFunction)可能是最重要的一个程序了。具体如下:
实际上这个做法相当在系统中注册了一个回调函数。
NTSTATUS SetFilterFunction(PacketFilterExtensionPtr filterFunction)
{
NTSTATUS status = STATUS_SUCCESS, waitStatus=STATUS_SUCCESS;
UNICODE_STRING filterName;
PDEVICE_OBJECT ipDeviceObject=NULL;
PFILE_OBJECT ipFileObject=NULL;
PF_SET_EXTENSION_HOOK_INFO filterData;
KEVENT event;
IO_STATUS_BLOCK ioStatus;
PIRP irp;
//首先获得一个 设备 指针。
//first of all, we have to get a pointer to IpFilterDriver Device
RtlInitUnicodeString(&filterName, DD_IPFLTRDRVR_DEVICE_NAME);
status = IoGetDeviceObjectPointer(&filterName,STANDARD_RIGHTS_ALL, &ipFileObject, &ipDeviceObject);
if(NT_SUCCESS(status))
{
//一些初始化工作,填充filterData。
//initialize the struct with functions parameters
filterData.ExtensionPointer = filterFunction;
//we need initialize the event used later by the IpFilterDriver to signal us
//when it finished its work
KeInitializeEvent(&event, NotificationEvent, FALSE);
//这个就是最重要的注册回调函数过程。DDK中具体讲述是这样的
//IOCTL_PF_SET_EXTENSION_POINTER registers filter-hook callback functions to the IP filter driver
//to inform the IP filter driver to call those filter hook callbacks for every IP packet
//that is received or transmitted. Also, IOCTL_PF_SET_EXTENSION_POINTER clears filter-hook
//callback functions from the IP filter driver. (看到了吧,最后一句话,注册新的回调函数,就将原先的清除掉了,
//所以说系统中只存在一个这样的驱动有用。)
//we build the irp needed to establish fitler function这个地方仅仅是生成这样的IRP,并没有注册
irp = IoBuildDeviceIoControlRequest(IOCTL_PF_SET_EXTENSION_POINTER,
ipDeviceObject,
(PVOID) &filterData,
sizeof(PF_SET_EXTENSION_HOOK_INFO),
NULL,
0,
FALSE,
&event,
&ioStatus);
if(irp != NULL)
{
// we send the IRP
//这个地方才是真正的注册呀。
status = IoCallDriver(ipDeviceObject, irp);
//and finally, we wait for "acknowledge" of IpDriverFilter
if (status == STATUS_PENDING)
{
waitStatus = KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
if (waitStatus != STATUS_SUCCESS ) {}
}
status = ioStatus.Status;
if(!NT_SUCCESS(status)){}
}
else
{
//if we cant allocate the space, we return the corresponding code error
status = STATUS_INSUFFICIENT_RESOURCES;
}
if(ipFileObject != NULL)
ObDereferenceObject(ipFileObject);
ipFileObject = NULL;
ipDeviceObject = NULL;
}
else
return status;
}
//真正的过滤函数是这个,在最早的IRPdispatch里面传递的这个函数。
//这个函数就是系统传递了一个包头和包内容和包长度之类的东西,你可以在里面进行一些处理,
//假如你想让这个包通过的话,就返回PF_FORWARD,或者你不想让包通过的话,就返回PF_DROP就拦住了。是不是
//听起来很简单,
PF_FORWARD_ACTION cbFilterFunction(IN unsigned char *PacketHeader,IN unsigned char *Packet, IN unsigned int PacketLength, IN unsigned int RecvInterfaceIndex, IN unsigned int SendInterfaceIndex, IN unsigned long RecvLinkNextHop, IN unsigned long SendLinkNextHop)
{
IPPacket *ipp;
TCPHeader *tcph;
UDPHeader *udph;
int countRule=0;
struct filterList *aux = first;
//we "extract" the ip Header
ipp=(IPPacket *)PacketHeader;
// dprintf("Source: %x/nDestination: %x/nProtocol: %d", ipp->ipSource, ipp->ipDestination, ipp->ipProtocol);
//TCP -> protocol = 6
//we accept all packets of established connections
if(ipp->ipProtocol == 6)
{
tcph=(TCPHeader *)Packet;
// dprintf("FLAGS: %x/n", tcph->flags);
//if we havent the bit SYN activate, we pass the packets
if(!(tcph->flags & 0x02))
return PF_FORWARD;
}
//otherwise, we compare the packet with our rules
while(aux != NULL)
{
// dprintf("Comparing with Rule %d", countRule);
//if protocol is the same....
if(aux->ipf.protocol == 0 || ipp->ipProtocol == aux->ipf.protocol)
{
//we look in source Address
if(aux->ipf.sourceIp != 0 && (ipp->ipSource & aux->ipf.sourceMask) != aux->ipf.sourceIp)
{
aux=aux->next;
countRule++;
continue;
}
// we look in destination address
if(aux->ipf.destinationIp != 0 && (ipp->ipDestination & aux->ipf.destinationMask) != aux->ipf.destinationIp)
{
aux=aux->next;
countRule++;
continue;
}
//if we have a tcp packet, we look in ports
//tcp, protocol = 6
if(ipp->ipProtocol == 6)
{
if(aux->ipf.sourcePort == 0 || tcph->sourcePort == aux->ipf.sourcePort)
{
if(aux->ipf.destinationPort == 0 || tcph->destinationPort == aux->ipf.destinationPort) //puerto tcp destino
{
//now we decided what to do with the packet
if(aux->ipf.drop)
return PF_DROP;
else
return PF_FORWARD;
}
}
}
//udp, protocol = 17
else if(ipp->ipProtocol == 17)
{
udph=(UDPHeader *)Packet;
if(aux->ipf.sourcePort == 0 || udph->sourcePort == aux->ipf.sourcePort)
{
if(aux->ipf.destinationPort == 0 || udph->destinationPort == aux->ipf.destinationPort)
{
//now we decided what to do with the packet
if(aux->ipf.drop)
return PF_DROP;
else
return PF_FORWARD;
}
}
}
else
{
//for other packet we dont look more and ....
//now we decided what to do with the packet
if(aux->ipf.drop)
return PF_DROP;
else
return PF_FORWARD;
}
}
//compare with the next rule
countRule++;
aux=aux->next;
}
//we accept all not registered
return PF_FORWARD;
}