<commit_before>/*
 * H.323 connection tracking helper
 *
 * Copyright (c) 2006 <NAME> <<EMAIL>>
 *
 * This source code is licensed under General Public License version 2.
 *
 * Based on the 'brute force' H.323 connection tracking module by
 * <NAME> <<EMAIL>>
 *
 * For more information, please see http://nath323.sourceforge.net/
 */

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/ctype.h>
#include <linux/inet.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/slab.h>
#include <linux/udp.h>
#include <linux/tcp.h>
#include <linux/skbuff.h>
#include <net/route.h>
#include <net/ip6_route.h>

#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_conntrack_tuple.h>
#include <net/netfilter/nf_conntrack_expect.h>
#include <net/netfilter/nf_conntrack_ecache.h>
#include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_zones.h>
#include <linux/netfilter/nf_conntrack_h323.h>

/* Parameters */
static unsigned int default_rrq_ttl __read_mostly = 300;
module_param(default_rrq_ttl, uint, 0600);
MODULE_PARM_DESC(default_rrq_ttl, "use this TTL if it's missing in RRQ");

static int gkrouted_only __read_mostly = 1;
module_param(gkrouted_only, int, 0600);
MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper");

static int callforward_filter __read_mostly = 1;
module_param(callforward_filter, bool, 0600);
MODULE_PARM_DESC(callforward_filter, "only create call forwarding expectations "
				     "if both endpoints are on different sides "
				     "(determined by routing information)");

/* Hooks for NAT */
int (*set_h245_addr_hook) (struct sk_buff *skb,
			   unsigned char **data, int dataoff,
			   H245_TransportAddress *taddr,
			   union nf_inet_addr *addr, __be16 port)
			   __read_mostly;
int (*set_h225_addr_hook) (struct sk_buff *skb,
			   unsigned char **data, int dataoff,
			   TransportAddress *taddr,
			   union nf_inet_addr *addr, __be16 port)
			   __read_mostly;
int (*set_sig_addr_hook) (struct sk_buff *skb,
			  struct nf_conn *ct,
			  enum ip_conntrack_info ctinfo,
			  unsigned char **data,
			  TransportAddress *taddr, int count) __read_mostly;
int (*set_ras_addr_hook) (struct sk_buff *skb,
			  struct nf_conn *ct,
			  enum ip_conntrack_info ctinfo,
			  unsigned char **data,
			  TransportAddress *taddr, int count) __read_mostly;
int (*nat_rtp_rtcp_hook) (struct sk_buff *skb,
			  struct nf_conn *ct,
			  enum ip_conntrack_info ctinfo,
			  unsigned char **data, int dataoff,
			  H245_TransportAddress *taddr,
			  __be16 port, __be16 rtp_port,
			  struct nf_conntrack_expect *rtp_exp,
			  struct nf_conntrack_expect *rtcp_exp) __read_mostly;
int (*nat_t120_hook) (struct sk_buff *skb,
		      struct nf_conn *ct,
		      enum ip_conntrack_info ctinfo,
		      unsigned char **data, int dataoff,
		      H245_TransportAddress *taddr, __be16 port,
		      struct nf_conntrack_expect *exp) __read_mostly;
int (*nat_h245_hook) (struct sk_buff *skb,
		      struct nf_conn *ct,
		      enum ip_conntrack_info ctinfo,
		      unsigned char **data, int dataoff,
		      TransportAddress *taddr, __be16 port,
		      struct nf_conntrack_expect *exp) __read_mostly;
int (*nat_callforwarding_hook) (struct sk_buff *skb,
				struct nf_conn *ct,
				enum ip_conntrack_info ctinfo,
				unsigned char **data, int dataoff,
				TransportAddress *taddr, __be16 port,
				struct nf_conntrack_expect *exp) __read_mostly;
int (*nat_q931_hook) (struct sk_buff *skb,
		      struct nf_conn *ct,
		      enum ip_conntrack_info ctinfo,
		      unsigned char **data, TransportAddress *taddr, int idx,
		      __be16 port, struct nf_conntrack_expect *exp)
		      __read_mostly;

static DEFINE_SPINLOCK(nf_h323_lock);
static char *h323_buffer;

static struct nf_conntrack_helper nf_conntrack_helper_h245;
static struct nf_conntrack_helper nf_conntrack_helper_q931[];
static struct nf_conntrack_helper nf_conntrack_helper_ras[];

/****************************************************************************/
static int get_tpkt_data(struct sk_buff *skb, unsigned int protoff,
			 struct nf_conn *ct, enum ip_conntrack_info ctinfo,
			 unsigned char **data, int *datalen, int *dataoff)
{
	struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
	int dir = CTINFO2DIR(ctinfo);
	const struct tcphdr *th;
	struct tcphdr _tcph;
	int tcpdatalen;
	int tcpdataoff;
	unsigned char *tpkt;
	int tpktlen;
	int tpktoff;

	/* Get TCP header */
	th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
	if (th == NULL)
		return 0;

	/* Get TCP data offset */
	tcpdataoff = protoff + th->doff * 4;

	/* Get TCP data length */
	tcpdatalen = skb->len - tcpdataoff;
	if (tcpdatalen <= 0)	/* No TCP data */
		goto clear_out;

	if (*data == NULL) {	/* first TPKT */
		/* Get first TPKT pointer */
		tpkt = skb_header_pointer(skb, tcpdataoff, tcpdatalen,
					  h323_buffer);
		BUG_ON(tpkt == NULL);

		/* Validate TPKT identifier */
		if (tcpdatalen < 4 || tpkt[0] != 0x03 || tpkt[1] != 0) {
			/* Netmeeting sends TPKT header and data separately */
			if (info->tpkt_len[dir] > 0) {
				pr_debug("nf_ct_h323: previous packet "
					 "indicated separate TPKT data of %hu "
					 "bytes\n", info->tpkt_len[dir]);
				if (info->tpkt_len[dir] <= tcpdatalen) {
					/* Yes, there was a TPKT header
					 * received */
					*data = tpkt;
					*datalen = info->tpkt_len[dir];
					*dataoff = 0;
					goto out;
				}

				/* Fragmented TPKT */
				pr_debug("nf_ct_h323: fragmented TPKT\n");
				goto clear_out;
			}

			/* It is not even a TPKT */
			return 0;
		}
		tpktoff = 0;
	} else {		/* Next TPKT */
		tpktoff = *dataoff + *datalen;
		tcpdatalen -= tpktoff;
		if (tcpdatalen <= 4)	/* No more TPKT */
			goto clear_out;
		tpkt = *data + *datalen;

		/* Validate TPKT identifier */
		if (tpkt[0] != 0x03 || tpkt[1] != 0)
			goto clear_out;
	}

	/* Validate TPKT length */
	tpktlen = tpkt[2] * 256 + tpkt[3];
	if (tpktlen < 4)
		goto clear_out;
	if (tpktlen > tcpdatalen) {
		if (tcpdatalen == 4) {	/* Separate TPKT header */
			/* Netmeeting sends TPKT header and data separately */
			pr_debug("nf_ct_h323: separate TPKT header indicates "
				 "there will be TPKT data of %hu bytes\n",
				 tpktlen - 4);
			info->tpkt_len[dir] = tpktlen - 4;
			return 0;
		}

		if (net_ratelimit())
			printk("nf_ct_h323: incomplete TPKT (fragmented?)\n");
		goto clear_out;
	}

	/* This is the encapsulated data */
	*data = tpkt + 4;
	*datalen = tpktlen - 4;
	*dataoff = tpktoff + 4;

      out:
	/* Clear TPKT length */
	info->tpkt_len[dir] = 0;
	return 1;

      clear_out:
	info->tpkt_len[dir] = 0;
	return 0;
}

/****************************************************************************/
static int get_h245_addr(struct nf_conn *ct, const unsigned char *data,
			 H245_TransportAddress *taddr,
			 union nf_inet_addr *addr, __be16 *port)
{
	const unsigned char *p;
	int len;

	if (taddr->choice != eH245_TransportAddress_unicastAddress)
		return 0;<commit_msg>netfilter: nf_ct_h323: switch "incomplete TPKT" message to pr_debug()<commit_after>/*
 * H.323 connection tracking helper
 *
 * Copyright (c) 2006 <NAME> <<EMAIL>>
 *
 * This source code is licensed under General Public License version 2.
 *
 * Based on the 'brute force' H.323 connection tracking module by
 * <NAME> <<EMAIL>>
 *
 * For more information, please see http://nath323.sourceforge.net/
 */

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/ctype.h>
#include <linux/inet.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/slab.h>
#include <linux/udp.h>
#include <linux/tcp.h>
#include <linux/skbuff.h>
#include <net/route.h>
#include <net/ip6_route.h>

#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_conntrack_tuple.h>
#include <net/netfilter/nf_conntrack_expect.h>
#include <net/netfilter/nf_conntrack_ecache.h>
#include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_zones.h>
#include <linux/netfilter/nf_conntrack_h323.h>

/* Parameters */
static unsigned int default_rrq_ttl __read_mostly = 300;
module_param(default_rrq_ttl, uint, 0600);
MODULE_PARM_DESC(default_rrq_ttl, "use this TTL if it's missing in RRQ");

static int gkrouted_only __read_mostly = 1;
module_param(gkrouted_only, int, 0600);
MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper");

static int callforward_filter __read_mostly = 1;
module_param(callforward_filter, bool, 0600);
MODULE_PARM_DESC(callforward_filter, "only create call forwarding expectations "
				     "if both endpoints are on different sides "
				     "(determined by routing information)");

/* Hooks for NAT */
int (*set_h245_addr_hook) (struct sk_buff *skb,
			   unsigned char **data, int dataoff,
			   H245_TransportAddress *taddr,
			   union nf_inet_addr *addr, __be16 port)
			   __read_mostly;
int (*set_h225_addr_hook) (struct sk_buff *skb,
			   unsigned char **data, int dataoff,
			   TransportAddress *taddr,
			   union nf_inet_addr *addr, __be16 port)
			   __read_mostly;
int (*set_sig_addr_hook) (struct sk_buff *skb,
			  struct nf_conn *ct,
			  enum ip_conntrack_info ctinfo,
			  unsigned char **data,
			  TransportAddress *taddr, int count) __read_mostly;
int (*set_ras_addr_hook) (struct sk_buff *skb,
			  struct nf_conn *ct,
			  enum ip_conntrack_info ctinfo,
			  unsigned char **data,
			  TransportAddress *taddr, int count) __read_mostly;
int (*nat_rtp_rtcp_hook) (struct sk_buff *skb,
			  struct nf_conn *ct,
			  enum ip_conntrack_info ctinfo,
			  unsigned char **data, int dataoff,
			  H245_TransportAddress *taddr,
			  __be16 port, __be16 rtp_port,
			  struct nf_conntrack_expect *rtp_exp,
			  struct nf_conntrack_expect *rtcp_exp) __read_mostly;
int (*nat_t120_hook) (struct sk_buff *skb,
		      struct nf_conn *ct,
		      enum ip_conntrack_info ctinfo,
		      unsigned char **data, int dataoff,
		      H245_TransportAddress *taddr, __be16 port,
		      struct nf_conntrack_expect *exp) __read_mostly;
int (*nat_h245_hook) (struct sk_buff *skb,
		      struct nf_conn *ct,
		      enum ip_conntrack_info ctinfo,
		      unsigned char **data, int dataoff,
		      TransportAddress *taddr, __be16 port,
		      struct nf_conntrack_expect *exp) __read_mostly;
int (*nat_callforwarding_hook) (struct sk_buff *skb,
				struct nf_conn *ct,
				enum ip_conntrack_info ctinfo,
				unsigned char **data, int dataoff,
				TransportAddress *taddr, __be16 port,
				struct nf_conntrack_expect *exp) __read_mostly;
int (*nat_q931_hook) (struct sk_buff *skb,
		      struct nf_conn *ct,
		      enum ip_conntrack_info ctinfo,
		      unsigned char **data, TransportAddress *taddr, int idx,
		      __be16 port, struct nf_conntrack_expect *exp)
		      __read_mostly;

static DEFINE_SPINLOCK(nf_h323_lock);
static char *h323_buffer;

static struct nf_conntrack_helper nf_conntrack_helper_h245;
static struct nf_conntrack_helper nf_conntrack_helper_q931[];
static struct nf_conntrack_helper nf_conntrack_helper_ras[];

/****************************************************************************/
static int get_tpkt_data(struct sk_buff *skb, unsigned int protoff,
			 struct nf_conn *ct, enum ip_conntrack_info ctinfo,
			 unsigned char **data, int *datalen, int *dataoff)
{
	struct nf_ct_h323_master *info = &nfct_help(ct)->help.ct_h323_info;
	int dir = CTINFO2DIR(ctinfo);
	const struct tcphdr *th;
	struct tcphdr _tcph;
	int tcpdatalen;
	int tcpdataoff;
	unsigned char *tpkt;
	int tpktlen;
	int tpktoff;

	/* Get TCP header */
	th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
	if (th == NULL)
		return 0;

	/* Get TCP data offset */
	tcpdataoff = protoff + th->doff * 4;

	/* Get TCP data length */
	tcpdatalen = skb->len - tcpdataoff;
	if (tcpdatalen <= 0)	/* No TCP data */
		goto clear_out;

	if (*data == NULL) {	/* first TPKT */
		/* Get first TPKT pointer */
		tpkt = skb_header_pointer(skb, tcpdataoff, tcpdatalen,
					  h323_buffer);
		BUG_ON(tpkt == NULL);

		/* Validate TPKT identifier */
		if (tcpdatalen < 4 || tpkt[0] != 0x03 || tpkt[1] != 0) {
			/* Netmeeting sends TPKT header and data separately */
			if (info->tpkt_len[dir] > 0) {
				pr_debug("nf_ct_h323: previous packet "
					 "indicated separate TPKT data of %hu "
					 "bytes\n", info->tpkt_len[dir]);
				if (info->tpkt_len[dir] <= tcpdatalen) {
					/* Yes, there was a TPKT header
					 * received */
					*data = tpkt;
					*datalen = info->tpkt_len[dir];
					*dataoff = 0;
					goto out;
				}

				/* Fragmented TPKT */
				pr_debug("nf_ct_h323: fragmented TPKT\n");
				goto clear_out;
			}

			/* It is not even a TPKT */
			return 0;
		}
		tpktoff = 0;
	} else {		/* Next TPKT */
		tpktoff = *dataoff + *datalen;
		tcpdatalen -= tpktoff;
		if (tcpdatalen <= 4)	/* No more TPKT */
			goto clear_out;
		tpkt = *data + *datalen;

		/* Validate TPKT identifier */
		if (tpkt[0] != 0x03 || tpkt[1] != 0)
			goto clear_out;
	}

	/* Validate TPKT length */
	tpktlen = tpkt[2] * 256 + tpkt[3];
	if (tpktlen < 4)
		goto clear_out;
	if (tpktlen > tcpdatalen) {
		if (tcpdatalen == 4) {	/* Separate TPKT header */
			/* Netmeeting sends TPKT header and data separately */
			pr_debug("nf_ct_h323: separate TPKT header indicates "
				 "there will be TPKT data of %hu bytes\n",
				 tpktlen - 4);
			info->tpkt_len[dir] = tpktlen - 4;
			return 0;
		}

		pr_debug("nf_ct_h323: incomplete TPKT (fragmented?)\n");
		goto clear_out;
	}

	/* This is the encapsulated data */
	*data = tpkt + 4;
	*datalen = tpktlen - 4;
	*dataoff = tpktoff + 4;

      out:
	/* Clear TPKT length */
	info->tpkt_len[dir] = 0;
	return 1;

      clear_out:
	info->tpkt_len[dir] = 0;
	return 0;
}

/****************************************************************************/
static int get_h245_addr(struct nf_conn *ct, const unsigned char *data,
			 H245_TransportAddress *taddr,
			 union nf_inet_addr *addr, __be16 *port)
{
	const unsigned char *p;
	int len;

	if (taddr->choice != eH245_TransportAddress_unicastAddress)
		return 0;
{'fraction_non_alphanumeric': 0.13117789488676826, 'fraction_numerical': 0.022859991454208802, 'mean_word_length': 3.807600136939404, 'pattern_counts': {'":': 0, '<': 65, '<?xml version=': 0, '>': 81, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6330033', 'n_tokens_mistral': 5859, 'n_tokens_neox': 5079, 'n_words': 1322}