Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 1 Jan 2001 17:47:19 +0100
From:      Danny Pansters <danny@ricin.com>
To:        Brent Kearney <brent@kearneys.ca>
Cc:        freebsd-questions@freebsd.org
Subject:   Re: hope for H323/natd
Message-ID:  <01010117471902.25486@ricin.localnet>
In-Reply-To: <20001230211532.A49774@kearneys.ca>
References:  <20001230211532.A49774@kearneys.ca>

next in thread | previous in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
On Sunday 31 December 2000 06:15, you wrote:
> http://www.coritel.it/projects/sofia/nat.html
>
> Anyone up for porting this to *BSD?

Trouble is, its a linux kernel module and therefore probably not that easily 
"ported" to BSD. The sad thing is that I've used it (with linux) in the past 
and it worked great (albeit very noisy as it threw any output to the 
console). It's limited to one video (h245) connection at a time. You could 
try gatekeeper instead but I didn't get it to properly work yet :-(

AFAIK it's really a crazy protocol (from an IP angle) as it wants to connect 
to random ports > 1024. Not easy with firewalls either. Would be great though 
if someone more knowledgeable than me would write a module for it, maybe as 
an extension to natd or ipf, because - please don't flame me - gatekeeper 
didn't get me anything further to correctly NAT this type of traffic and I've 
given up on it for the time being. I know that my partner would like to be 
able to do netmeeting and currently this is still somewhat of an Achilles' 
heel in my defending switching my boxes from linux to fBSD... 

I am not a programmer, but I assume that the hard part would be to think up 
some notion of statefulness for h323 connections including the other 
protocols encapsulated by h323 so that its possible to, once identified as a 
valid h323 two way connection, have it bypass any filtering. Maybe the linux 
module source can be modified to use BSD kernel calls instead because the 
algorithm itself seems to work, but really I don't know sh*t about how to do
that.

For those readers who like to give it a try, the source is rather small, has 
lots of commented-out code, is GPL'ed and attached below. I'll be more than 
happy to test it.



Danny



[-- Attachment #2 --]
/*
 *              IP_MASQ_H323, H.323 masquerading module 
 *
 *
 * Version:     1.0 beta, Feb 25 2000 
 *
 * Author:      Rajkumar. S
 *              Archana V. S.
 *              Sheenarani I.
 *
 *              ____Modified on  28 Mar 2000 by CoRiTeL (www.coritel.it)___

 *              Luca Veltri (veltri@coritel.it)
 *              Stefano Giacometti
 *
 *              to work on kernel 2.2.12 and NetMeeting 3.01
 *
 *              official site: http://www.coritel.it/projects/sofia/nat.html
 *
 *      This program is free software; you can redistribute it and/or
 *      modify it under the terms of the GNU General Public License
 *      as published by the Free Software Foundation; either version
 *      2 of the License, or (at your option) any later version.
 *
 *
 */
#include <linux/module.h>
#include <asm/system.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <net/protocol.h>
#include <net/tcp.h>
#include <net/ip_masq.h>

#ifndef DEBUG_CONFIG_IP_MASQ_H323
#define DEBUG_CONFIG_IP_MASQ_H323 1
#endif

/* 
 *  port_h323 is set to the default h.323 port (1720)
 */
int port_h323 = 1720; 
struct ip_masq_app *masq_incarnation;


/*@@@@@ private comments (CoRiTeL)...
some notes: 
  1) every h.323 session regists a new 'h245 application' to handle with a new h.245 session, this 'h245 appl.' is always registered with the same ip_masq_h245 structure (see point (1)); for this reason only one h245 session can be handled in the same time;
  2) for this reason, when a new h245 session is needed, the old one is deregistrated and the 'attach' value is set to zero; 
*/


int h245registered=0;


/**********  Start of H.245 masq app functions ******************/

static int
masq_h245_init_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
{
  MOD_INC_USE_COUNT;
  printk("masq_h245_init_1: IP masq app 245 init\n");
  return 0;
}

static int
masq_h245_done_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
{
  MOD_DEC_USE_COUNT;
  printk("masq_h245_done_1: IP masq app 245 done\n");
  return 0;
}


int
masq_h245_in (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, __u32 maddr)
{
//	printk("masq_h245_in\n");
	return 0;
}


int
masq_h245_out (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, __u32 maddr)
{

//@@@@@ (CoRiTeL): private comments
//  'mapp' punta all'info sul protocollo da mascherare (in pratica h245)
//  'ms' punta la tabella di masheramento
//  'sk_buff' punta una struttura che contiene anche il pacchetto IP completo
//  'maddr' e' una copia del masq IP address (mi sembra nelle prove identico a 'ms->maddr')

  struct sk_buff *skb; 
  struct iphdr *iph; 
  struct tcphdr *th; 
  unsigned char *data, *data_limit;
  unsigned char *skbuff_p;
  __u16 port, *rtp_port; 
  __u32 ip,temp_ip, *rtp_ip;
  struct ip_masq * n_ms_rtp;
  unsigned char p1,p2;


  skb = *skb_p; 
  iph = skb->h.ipiph;  //'skbuff_p' points the IP header of the packet to be processed
  th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]); 
  data = skb->data; 
  data_limit = skb->tail; 
  skbuff_p = data+12;

  printk("masq_h245_out: tcp/ip_packet: h245_data: ");
       data+=iph->ihl*4+th->doff*4; 
  while(data<data_limit){ 
      printk("%02x ",*data); 
      data++; 
  }
  printk("\n");

  //@@@@@ CoRiTeL: analisys of h245 msg
  data=skb->data; //@@@@@ CoRiTeL: start of IP pkt
  data+=iph->ihl*4+th->doff*4; //@@@@@ CoRiTeL: jumps headres
  ip=ntohl(ms->saddr); //@@@@@ CoRiTeL: to find=source IP address
  while((data+5)<data_limit)
  { temp_ip= (((*data) << 24) + (*(data+1)<< 16) + (*(data+2) << 8) + (*(data+3)));
    if (temp_ip==ip)
	{ p1=*(data+4); 
      p2=*(data+5); 
      port=(p1<<8)+p2; 

      printk("masq_h245_out: <-- RTCP/RTP_dest_addr: %08x\n",ip);
      printk("masq_h245_out: <-- RTCP/RTP_dest_port: %04x\n",port);

      //printk("masq_h245_out: mapp->n_attach (before 'ip_masq_new') = %d\n",mapp->n_attach);
      n_ms_rtp = ip_masq_new( 
      IPPROTO_UDP, maddr,0,            //@@@@@ CoRiTeL:  masq addr
      htonl(ip), htons(port),          //@@@@@ CoRiTeL:  pck source
      iph->daddr, 0,                   //@@@@@ CoRiTeL:  pck dest
      IP_MASQ_F_NO_DPORT); 
      if(n_ms_rtp==NULL)
        printk("masq_h245_out: RTCP/RTP masq entry not made\n"); 
      else { 


             rtp_ip=data; 
             rtp_port=data+4; 
             *rtp_ip=n_ms_rtp->maddr;     //@@@@@ CoRiTeL:  change IP
             *rtp_port=n_ms_rtp->mport;   //@@@@@ CoRiTeL:  change port
             printk("masq_h245_out: RTCP/RTP masquerated: maddr=%08x , mport=%u\n", n_ms_rtp->maddr,n_ms_rtp->mport);
             //printk("masq_h245_out: mapp->n_attach (after 'ip_masq_new') = %d\n",mapp->n_attach);
           }

    }
    
    data++; 
  }

  return 0;	
}


/***********End of H.245 app functions *******************/


struct ip_masq_app  ip_masq_h245_template = {
        NULL,			/* next */
        "h245",			/* name */
        0,                      /* type */
        0,                      /* n_attach */
        masq_h245_init_1,        /* ip_masq_init_1 */
        masq_h245_done_1,        /* ip_masq_done_1 */
        masq_h245_out,           /* pkt_out */
        masq_h245_in,            /* pkt_in */
};



struct ip_masq_app * ip_masq_h245;

static int
masq_h323_init_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
{ printk("masq_h323_init_1\n");
        MOD_INC_USE_COUNT;
  if (h245registered) { 
  	  //printk("masq_h323_init_1: found an old ip_masq_app entry for h245, I'm trying to delete it....\n");
      
      //@@@@@ CoRiTeL: set n_attach to zero to unregister the old h245 app
      ip_masq_h245->n_attach=0;
      printk("masq_h323_init_1: found an old  h245 app; n_attach forced to 0\n");

  	  if(unregister_ip_masq_app(ip_masq_h245)) 
  	    { //kfree(ip_masq_h245); //@@@@@ CoRiTeL: otherwise it frees mem not to be malloced before being reused
          printk("masq_h323_init_1: error unregistering the old h245 app!\n");
        } else printk("masq_h323_init_1: the old h245 app is successfully unregistered.\n");
	  h245registered=0;
  	} 
 return 0;
}

static int
masq_h323_done_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
{
  printk("masq_h323_done_1\n");
  printk("masq_h323: h245 status (0=unregistered, 1=registered) = %d\n",h245registered); //@@@@@ CoRiTeL: debug
  MOD_DEC_USE_COUNT;
  return 0;
}

int
masq_h323_out (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, __u32 maddr)
{
//  printk("masq_h323_out: does do nothing!!!\n");
  return 0;
}


int
masq_h323_in (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, __u32 maddr)
{
  struct sk_buff *skb;
  struct iphdr *iph;
  struct tcphdr *th;
  unsigned char *data, *data_limit;
  __u32 ip;
  __u16 port;
  __u32 temp_ip;
  unsigned char * skbuff_p;
  unsigned char p1,p2;
  int j;


    skb = *skb_p;
	iph = skb->h.ipiph;
        th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
	data = skb->data;
        data_limit = skb->tail;
	skbuff_p = data+12;
	ip= (((*skbuff_p) << 24) + (*(skbuff_p+1)<< 16) + (*(skbuff_p+2) << 8) + (*(skbuff_p+3))); 
	skbuff_p=skbuff_p+4;
	temp_ip= (((*skbuff_p) << 24) + (*(skbuff_p+1)<< 16) + (*(skbuff_p+2) << 8) + (*(skbuff_p+3))); 
	while(((skbuff_p+6)< data_limit) && (temp_ip !=ip)){
	  skbuff_p++;
	  temp_ip= (((*skbuff_p) << 24) + (*(skbuff_p+1)<< 16) + (*(skbuff_p+2) << 8) + (*(skbuff_p+3))); 
	}
	if(temp_ip==ip){
	p1=*(skbuff_p+4);
	p2=*(skbuff_p+5);
	port=(p1<<8)+p2;
	if (h245registered==1) 
	{ printk("masq_h323_in: ATTENTION!!! found a previous ip_masq_app entry, deleting....\n");
      unregister_ip_masq_app(ip_masq_h245);
	  h245registered=0;
	}
    printk("masq_h323_in: H.245 Port is at: %u\n",port);
	if (!(j = register_ip_masq_app(ip_masq_h245, IPPROTO_TCP, port))) 
    { h245registered = 1;
	} else printk("masq_h323_in: ATTENTION: H245 messages will not be captured!!!\n");
	
	
	}
return 0;	
}
struct ip_masq_app ip_masq_h323 = {
        NULL,			/* next */
	"h323",			/* name */
        0,                      /* type */
        0,                      /* n_attach */ //
        masq_h323_init_1,        /* ip_masq_init_1 */
        masq_h323_done_1,        /* ip_masq_done_1 */
        masq_h323_out,           /* pkt_out */
        masq_h323_in,            /* pkt_in */
};

/*
 * 	ip_masq_h323 initialization
 */

int ip_masq_h323_init(void)
{
	int j;

//	printk("ip_masq_h323_init\n"); 
	ip_masq_h245 = NULL;
		
	if ((masq_incarnation = kmalloc(sizeof(struct ip_masq_app), GFP_KERNEL)) == NULL)
	  return -ENOMEM;
	memcpy(masq_incarnation, &ip_masq_h323, sizeof(struct ip_masq_app));
	        
    if ((ip_masq_h245 = kmalloc(sizeof(struct ip_masq_app),GFP_KERNEL)) == NULL)
	  return -ENOMEM;	  
    memcpy(ip_masq_h245, &ip_masq_h245_template, sizeof(struct ip_masq_app));
			
    if ((j = register_ip_masq_app(masq_incarnation, IPPROTO_TCP, port_h323)))
	  return j;
        

#if DEBUG_CONF_IG_IP_MASQ_H323
			printk("ip_masq_h323_init: H323: loaded support on port = %d\n", port_h323);
#endif
    return 0;
}

/*
 * 	ip_masq_h323 fin.
 */

int ip_masq_h323_done(void)
{
	int k;

	k=0;

	printk("ip_masq_h323_done\n"); 

	if (masq_incarnation) {
	    if ((k = unregister_ip_masq_app(masq_incarnation))) {
	    } else {
	      kfree(masq_incarnation);
	      masq_incarnation = NULL;
#if DEBUG_CONFIG_IP_MASQ_H323
	      printk("ip_masq_h323_done: H323: unloaded support on port = %d\n", port_h323);
#endif
	    }
	  }

	if (h245registered) { 
  	  printk("ip_masq_h323_done: removing the masq app entry\n"); 
  	  if(unregister_ip_masq_app(ip_masq_h245)) 
  	    kfree(ip_masq_h245); 
	  h245registered=0;
  	} 
	return k;
}

#ifdef MODULE

int init_module(void)
{
  printk("Init module\n");  
  if (ip_masq_h323_init() != 0)
    return -EIO;
  return 0;
}

void cleanup_module(void)
{
        if (ip_masq_h323_done() != 0)
                printk("ip_masq_h323: can't remove module\n");
}

#endif /* MODULE */

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?01010117471902.25486>