Project Home
Project Home
Wiki
Wiki
Discussion Forums
Discussions
Project Information
Project Info
Forum Topic - io-pkt pfil hook: (9 Items)
   
io-pkt pfil hook  
I have a packet filter implemented using the pfil interface which I am mounting into the io-pkt . In both the input and 
output hooks , how do I extract information such as source & destination ip-address , port no of the packets ? 

the hooks have signature : hook(void *arg, struct mbuf **m, struct ifnet *ifp, int dir)

how can I get all the relevant packet data coming in / going out inside these hooks functions which are getting called ?


Any information / sample code would be useful .
Re: io-pkt pfil hook  
The packet is a struct mbuf * located in *m. It is going to depend on the parameters you passed to pfil_add_hook() on 
whether you just have the IP layer or a full layer 2 packet (e.g. Ethernet layer). Also you need to watch out for 
whether you have the full packet in one mbuf or whether it is distributed along a chain of mbufs requiring you to walk 
the chain whilst traversing the packet.

Once you've got these things sorted out, you can just mtod() it and extract the fields directly.
Re: io-pkt pfil hook  
Hey Nick ,
               thnx for ur reply ... i tried few things on mbuf today but without any success .

I have registered my output_hook as : 
pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
pfil_add_hook(output_hook, NULL, PFIL_OUT | PFIL_WAITOK,pfh_inet);

So I am expecting IP layer data in my mbuf . The only data structure containing struct sock_addr inside struct mbuf is 
pkthdr_data.rcvif of struct ifnet type . So i was trying to access this member to get port & ip information but its empty .
Also in my traversal i follow the next packet link but if  i follow the next buffer link of same chain I get segmentation issues . Below is a code snippet of the hook function . Any pointers as to what I am doing wrong wud be very useful .

static int output_hook(void *arg, struct mbuf **m,
                       struct ifnet *ifp, int dir)
{
    out_bytes += (*m)->m_len;
    struct mbuf* trav = (*m);
do{
	short mbuf_type = trav->m_type;
    int mbuf_length = trav->m_len;

    int mbuf_flags = trav->m_flags;
    struct	pkthdr pkthdr_data = trav->m_pkthdr;
    struct	ifnet *if_data = NULL;

     slogf( _SLOG_SETCODE(_SLOGC_TEST, 2),
            	           _SLOG_ERROR,
            	           "in our output_hook() mbuf len:%d type:%d flags:%d",
            	           	   	   	   	   mbuf_length,mbuf_type,mbuf_flags);

    slogf( _SLOG_SETCODE(_SLOGC_TEST, 2),
            	           _SLOG_ERROR,
            	           "in our output_hook() packet hdr len:%d csumflags:%d csumdata:%u segsize:%u",
            	           pkthdr_data.len,pkthdr_data.csum_flags,pkthdr_data.csum_data,pkthdr_data.segsz);

    if_data = pkthdr_data.rcvif;
    if(if_data)
    {
    	struct sockaddr *dest_sa = NULL;
    	int fam = -1;
    	int port = -1;
       	if(if_data->if_dl && if_data->if_dl->ifa_dstaddr)
       	{
       		dest_sa = if_data->if_dl->ifa_dstaddr;
			if(dest_sa){
				port = ntohs(((struct sockaddr_in*)dest_sa)->sin_port);
				fam = ((struct sockaddr_in*)dest_sa)->sin_family;
			}
       	}
       	slogf( _SLOG_SETCODE(_SLOGC_TEST, 2),
       	    	           _SLOG_ERROR,
       	    	           "in our output_hook() socket info:%d %d",port,fam);
    }
    // go to next packet
    trav=trav->m_nextpkt;
}while(NULL != trav);

   return 0; // 0 means allow, 1 means block
}

TIA 
Atish
Re: io-pkt pfil hook  
I had some success in walking thru the mbufs constituting the packet with some code modifications . The 1st mbuf is the 
header foloowed by the data mbufs . I am able to traverse thru the mbufs and extract some info related to length of data
 & packet . But I cant figure out the location of the ip layer information inside the data mbufs . when I access some of the char sequence members of the mbuf such as MH_databuf & M_databuf using mtod I get some sequence of chars . Am I looking in the wrong place ?
Pls give me some pointers . 

Below is the code of the hook for reference : 

static int output_hook(void *arg, struct mbuf **m,
                       struct ifnet *ifp, int dir)
{
    out_bytes += (*m)->m_len;
    struct mbuf* trav = (*m);
do{
	short mbuf_type = trav->m_type;
    int mbuf_length = trav->m_len;
    int mbuf_flags = trav->m_flags;

    //char * mbuf_hdrdata = (*m)->m_data;
    //struct	mowner * mbuf_owner = (*m)->m_owner;
    //char * mbuf_data = (*m)->m_dat;
    //char *mdata = (char *)malloc(mbuf_length+1);
    //strncpy(mdata,mbuf_hdrdata,mbuf_length);
    //mdata[mbuf_length]='\0';

    slogf( _SLOG_SETCODE(_SLOGC_TEST, 2),
            	           _SLOG_ERROR,
            	           "in our output_hook() mbuf len:%d type:%d flags:%d",
            	           	   	   	   	   	   mbuf_length,mbuf_type,mbuf_flags);

    // found a packet header mbuf
    if(M_PKTHDR == mbuf_flags)
    {
    	struct	pkthdr pkthdr_data = trav->m_pkthdr;
    	slogf( _SLOG_SETCODE(_SLOGC_TEST, 2),
							   _SLOG_ERROR,
							   "in our output_hook() packet hdr len:%d csumflags:%d csumdata:%u segsize:%u",
							   pkthdr_data.len,pkthdr_data.csum_flags,pkthdr_data.csum_data,pkthdr_data.segsz);

    	struct	ifnet *if_data = NULL;
	    if_data = pkthdr_data.rcvif;
		if(if_data)
		{
			struct sockaddr *dest_sa = NULL;
			int fam = -1;
			int port = -1;
			if(if_data->if_dl && if_data->if_dl->ifa_dstaddr)
			{
				dest_sa = if_data->if_dl->ifa_dstaddr;
				if(dest_sa){
					port = ntohs(((struct sockaddr_in*)dest_sa)->sin_port);
					fam = ((struct sockaddr_in*)dest_sa)->sin_family;
				}
			}
			slogf( _SLOG_SETCODE(_SLOGC_TEST, 2),
							   _SLOG_ERROR,
							   "in our output_hook() socket info:%d %d",port,fam);
		}
    }
    // found a data packet mbuf but where is it ???
    else if(MT_DATA == mbuf_type )
    {
    	//char databuffer[MLEN]= {0};
    	//strcpy(databuffer,trav->m_dat);
    	//char * databuffer = trav->m_dat;
		//char *pdata = (char *)malloc(mbuf_length+1);
		//strncpy(pdata,databuffer,mbuf_length);
		//pdata[mbuf_length]='\0';

    	slogf( _SLOG_SETCODE(_SLOGC_TEST, 2),_SLOG_ERROR,
    						"in our output_hook() i m databuffer");
    }
    // go to next buf in chain
    trav=trav->m_next;
}while(NULL != trav);

    return 0; // 0 means allow, 1 means block
}
Re: io-pkt pfil hook  
The mbuf contains the data on the wire, nothing to do with sockaddr. You need to do something like:

#include <netinet/ip.h>


struct ip *ip;

  ip = mtod(*m, struct ip *);

Then you have the addresses in ip->ip_src, ip->ip_dst. The protocol in ip->ip_p will tell you what to cast the next 
bunch of bytes to in order to decode them.
Re: io-pkt pfil hook  
Forgot to mention, watch out that on output you may have a chain, always check (*m)->m_len before doing the mtod() to 
make sure you have enough data there.
Re: io-pkt pfil hook  
Hey Nick ,
                ur info helped a lot ... now I am able to read the IP header from mbuf & extract source & dest ip 
address from the structure . I also need to read the TCp header & read port numbers . I tried offesetting to TCp header 
from the IP header if the IP protocol value is 6 (TCP) & read port nos . but I am not sure I am getting proper values . 
I want to filter out any http requests by detecting the destination port no = 80 , but right now I am mever getting the 
value 80 after I invoke a http request using the browser . Below is the code snippet I have used ... any pointers as to 
what might be wrong wud  b immensely helpful .

struct ip *ipheader = NULL;
    	ipheader = mtod(trav,struct ip *);
        slogf( _SLOG_SETCODE(_SLOGC_TEST, 2),_SLOG_ERROR,
                	    						"in our output_hook() mtod done for ip");
        // lookout for TCP packets
        if(ipheader && (6 == ipheader->ip_p))
        {
        	
        	slogf( _SLOG_SETCODE(_SLOGC_TEST, 2),_SLOG_ERROR,
        	    						"in our output_hook() source ip : %d:%d:%d:%d",
        	    						(int)(ipheader->ip_src.s_addr&0xFF),
        	    						(int)((ipheader->ip_src.s_addr&0xFF00)>>8),
        	    						(int)((ipheader->ip_src.s_addr&0xFF0000)>>16),
        	    						(int)((ipheader->ip_src.s_addr&0xFF000000)>>24));


        	slogf( _SLOG_SETCODE(_SLOGC_TEST, 2),_SLOG_ERROR,
        	        	    	 	"in our output_hook() dest ip : %d:%d:%d:%d",
        	        	    	 	(int)(ipheader->ip_dst.s_addr&0xFF),
									(int)((ipheader->ip_dst.s_addr&0xFF00)>>8),
									(int)((ipheader->ip_dst.s_addr&0xFF0000)>>16),
									(int)((ipheader->ip_dst.s_addr&0xFF000000)>>24));

        	slogf( _SLOG_SETCODE(_SLOGC_TEST, 2),_SLOG_ERROR,
        	        	        	    	 	"in our output_hook() version : %d hdrl : %d length : %d",
        	        	        	    	 	ipheader->ip_v,ipheader->ip_hl,ipheader->ip_len);

        	struct tcphdr *tcpheader = NULL;
        	tcpheader= (struct tcphdr *)(ipheader + (ipheader->ip_hl*4));
        	slogf( _SLOG_SETCODE(_SLOGC_TEST, 2),_SLOG_ERROR,
        	                	    						"in our output_hook() mtod done for tcp");
        	if(tcpheader)
        	{
        		
        		slogf( _SLOG_SETCODE(_SLOGC_TEST, 2),_SLOG_ERROR,
        		        	"in our output_hook() source port : %04x dest port : %04x",
        		        									tcpheader->th_sport,
        		        									tcpheader->th_dport);
        	}
        }

TIA
Atish
Re: io-pkt pfil hook  
Hey Nick ,
               with the help of ur info now I am able to read the port nos. inside the tcp header . I am getting the 
port nos for qconn & phrelay Qnx services which are running but I am not getting the port no 80 corresponding to http request when I invoke the browser . Can u pls help if anything else needs to be done for http packets . Below is the code snippet which reads ip header & tcp header from mbuf in the outgoing hook : 

if(mbuf_length > 0 )
    {
    	slogf( _SLOG_SETCODE(_SLOGC_TEST, 2),_SLOG_ERROR,
    	        	    						"in our output_hook() i m databuffer");
    	struct ip *ipheader = NULL;
    	ipheader = mtod(trav,struct ip *);

        // lookout for TCP packets
        if(ipheader && (6 == ipheader->ip_p))
        {
        	slogf( _SLOG_SETCODE(_SLOGC_TEST, 2),_SLOG_ERROR,
        	    						"in our output_hook() source ip : %d:%d:%d:%d",
        	    						(int)(ipheader->ip_src.s_addr&0xFF),
        	    						(int)((ipheader->ip_src.s_addr&0xFF00)>>8),
        	    						(int)((ipheader->ip_src.s_addr&0xFF0000)>>16),
        	    						(int)((ipheader->ip_src.s_addr&0xFF000000)>>24));


        	slogf( _SLOG_SETCODE(_SLOGC_TEST, 2),_SLOG_ERROR,
        	        	    	 	"in our output_hook() dest ip : %d:%d:%d:%d",
        	        	    	 	(int)(ipheader->ip_dst.s_addr&0xFF),
									(int)((ipheader->ip_dst.s_addr&0xFF00)>>8),
									(int)((ipheader->ip_dst.s_addr&0xFF0000)>>16),
									(int)((ipheader->ip_dst.s_addr&0xFF000000)>>24));

        	slogf( _SLOG_SETCODE(_SLOGC_TEST, 2),_SLOG_ERROR,
        	        	        	    	 	"in our output_hook() version : %d hdrl : %d length : %d",
        	        	        	    	 	ipheader->ip_v,ipheader->ip_hl,ipheader->ip_len);


        	// offset to the tcp header which follows the ip header
        	struct tcphdr *tcpheader = NULL;
        	//tcpheader = mtod(trav,struct tcphdr *);
        	int iphdrsize = sizeof(struct ip);
        	tcpheader= (struct tcphdr *)((void *)ipheader + iphdrsize);



            slogf( _SLOG_SETCODE(_SLOGC_TEST, 2),_SLOG_ERROR,
                    	        "in our output_hook() ip header size : %d",iphdrsize);
            slogf( _SLOG_SETCODE(_SLOGC_TEST, 2),_SLOG_ERROR,
                                	        "in our output_hook() ip header location : %p",(void *)ipheader);
            slogf( _SLOG_SETCODE(_SLOGC_TEST, 2),_SLOG_ERROR,
                                            "in our output_hook() tcp header location : %p",(void *)tcpheader);
            if(tcpheader)
        	{
        		slogf( _SLOG_SETCODE(_SLOGC_TEST, 2),_SLOG_ERROR,
        		        	"in our output_hook() source port : %04x dest port : %04x",
        		        						tcpheader->th_sport,tcpheader->th_dport);
        	}
        }
    }

TIA 
Atish
Re: io-pkt pfil hook  
Hi Nick ,
            I am able to extract data from IP & TCP headers .I am able to intercept all the phrelay/qconn packets being 
exchanged . But I am not able to intercept any http packet when I invoke the browser and open any webpage . Please 
provide any pointers as to whats required to intercept a http request packet .

Regards
Atish