Пример #1
0
static int irc_data_fixup(const struct ip_ct_irc_expect *exp_irc_info,
			  struct ip_conntrack *ct,
			  struct sk_buff **pskb,
			  enum ip_conntrack_info ctinfo,
			  struct ip_conntrack_expect *expect)
{
	u_int32_t newip;
	struct ip_conntrack_tuple t;
	struct iphdr *iph = (*pskb)->nh.iph;
	struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
	u_int16_t port;

	/* "4294967296 65635 " */
	char buffer[18];

	DEBUGP("IRC_NAT: info (seq %u + %u) in %u\n",
	       expect->seq, exp_irc_info->len,
	       ntohl(tcph->seq));

	newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;

	/* Alter conntrack's expectations. */
	t = expect->tuple;
	t.dst.ip = newip;
	for (port = exp_irc_info->port; port != 0; port++) {
		t.dst.u.tcp.port = htons(port);
		if (ip_conntrack_change_expect(expect, &t) == 0) {
			DEBUGP("using port %d", port);
			break;
		}

	}
	if (port == 0)
		return 0;

	/*      strlen("\1DCC CHAT chat AAAAAAAA P\1\n")=27
	 *      strlen("\1DCC SCHAT chat AAAAAAAA P\1\n")=28
	 *      strlen("\1DCC SEND F AAAAAAAA P S\1\n")=26
	 *      strlen("\1DCC MOVE F AAAAAAAA P S\1\n")=26
	 *      strlen("\1DCC TSEND F AAAAAAAA P S\1\n")=27
	 *              AAAAAAAAA: bound addr (1.0.0.0==16777216, min 8 digits,
	 *                      255.255.255.255==4294967296, 10 digits)
	 *              P:         bound port (min 1 d, max 5d (65635))
	 *              F:         filename   (min 1 d )
	 *              S:         size       (min 1 d )
	 *              0x01, \n:  terminators
	 */

	sprintf(buffer, "%u %u", ntohl(newip), port);
	DEBUGP("ip_nat_irc: Inserting '%s' == %u.%u.%u.%u, port %u\n",
	       buffer, NIPQUAD(newip), port);

	return ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
					expect->seq - ntohl(tcph->seq),
					exp_irc_info->len, buffer, 
					strlen(buffer));
}
static int set_addr(struct sk_buff **pskb,
		    unsigned char **data, int dataoff,
		    unsigned int addroff, __be32 ip, u_int16_t port)
{
	enum ip_conntrack_info ctinfo;
	struct ip_conntrack *ct = ip_conntrack_get(*pskb, &ctinfo);
	struct {
		__be32 ip;
		__be16 port;
	} __attribute__ ((__packed__)) buf;
	struct tcphdr _tcph, *th;

	buf.ip = ip;
	buf.port = htons(port);
	addroff += dataoff;

	if ((*pskb)->nh.iph->protocol == IPPROTO_TCP) {
		if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
					      addroff, sizeof(buf),
					      (char *) &buf, sizeof(buf))) {
			if (net_ratelimit())
				printk("ip_nat_h323: ip_nat_mangle_tcp_packet"
				       " error\n");
			return -1;
		}

		/* Relocate data pointer */
		th = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl * 4,
					sizeof(_tcph), &_tcph);
		if (th == NULL)
			return -1;
		*data = (*pskb)->data + (*pskb)->nh.iph->ihl * 4 +
		    th->doff * 4 + dataoff;
	} else {
		if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
					      addroff, sizeof(buf),
					      (char *) &buf, sizeof(buf))) {
			if (net_ratelimit())
				printk("ip_nat_h323: ip_nat_mangle_udp_packet"
				       " error\n");
			return -1;
		}
		/* ip_nat_mangle_udp_packet uses skb_make_writable() to copy
		 * or pull everything in a linear buffer, so we can safely
		 * use the skb pointers now */
		*data = (*pskb)->data + (*pskb)->nh.iph->ihl * 4 +
		    sizeof(struct udphdr);
	}

	return 0;
}
Пример #3
0
static int sl_remove_port(struct sk_buff **pskb,
                          struct ip_conntrack *ct,
               	          enum   ip_conntrack_info ctinfo,
                	      unsigned int host_offset,
                	      unsigned int dataoff,
                	      unsigned int datalen,
			              unsigned int end_of_host,
        	              unsigned char *user_data)
{
    
    if (strncmp(search[PORT].string, 
	&user_data[end_of_host-search[PORT].len+search[NEWLINE].len],
	search[PORT].len)) {

#ifdef SL_DEBUG
        printk(KERN_DEBUG "no port rewrite found in packet strncmp\n");
	printk(KERN_DEBUG "end of host packet dump:\n%s\n",
		(unsigned char *)((unsigned int)user_data+end_of_host-search[PORT].len+search[NEWLINE].len));
#endif
	return 0;
    }


#ifdef SL_DEBUG
    printk(KERN_DEBUG "remove_port found a port at offset %u\n",
	end_of_host-search[PORT].len+search[NEWLINE].len );
#endif

    /* remove the port */
    if (!ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
        end_of_host-search[PORT].len+search[NEWLINE].len,
        search[PORT].len-(search[NEWLINE].len*2), // subtract \r\n
	NULL,
	0))
    {
        printk(KERN_ERR "unable to remove port needle\n");
	// we've already found the port, so we return 1 regardless
        return 1;
    }

#ifdef SL_DEBUG
    printk(KERN_DEBUG "port removed ok, new packet\n%s\n",
	(unsigned char *)user_data);

#endif

    return 1; 
}
Пример #4
0
static int
mangle_packet(struct sk_buff **pskb,
		     u_int32_t newip,
		     unsigned int matchoff,
		     unsigned int matchlen,
		     struct ip_conntrack *ct,
		     enum ip_conntrack_info ctinfo)
{
	unsigned char buffer[4];

	MUST_BE_LOCKED(&ip_sc_lock);

	*((u_int32_t *)(buffer)) = htonl(newip);

	DEBUGP("calling ip_nat_mangle_tcp_packet\n");

	return ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff, matchlen, buffer, 4);
}
/* |1|132.235.1.2|6275| */
static int
mangle_epsv_packet(struct sk_buff **pskb,
		   u_int32_t newip,
		   u_int16_t port,
		   unsigned int matchoff,
		   unsigned int matchlen,
		   struct ip_conntrack *ct,
		   enum ip_conntrack_info ctinfo,
		   u32 *seq)
{
	char buffer[sizeof("|||65535|")];

	sprintf(buffer, "|||%u|", port);

	DEBUGP("calling ip_nat_mangle_tcp_packet\n");

	*seq += strlen(buffer) - matchlen;
	return ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff, 
					matchlen, buffer, strlen(buffer));
}
static int
mangle_rfc959_packet(struct sk_buff **pskb,
		     u_int32_t newip,
		     u_int16_t port,
		     unsigned int matchoff,
		     unsigned int matchlen,
		     struct ip_conntrack *ct,
		     enum ip_conntrack_info ctinfo,
		     u32 *seq)
{
	char buffer[sizeof("nnn,nnn,nnn,nnn,nnn,nnn")];

	sprintf(buffer, "%u,%u,%u,%u,%u,%u",
		NIPQUAD(newip), port>>8, port&0xFF);

	DEBUGP("calling ip_nat_mangle_tcp_packet\n");

	*seq += strlen(buffer) - matchlen;
	return ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, matchoff, 
					matchlen, buffer, strlen(buffer));
}
Пример #7
0
/* inbound packets == from PAC to PNS */
static int
pptp_inbound_pkt(struct sk_buff **pskb,
		 struct ip_conntrack *ct,
		 enum ip_conntrack_info ctinfo,
		 struct PptpControlHeader *ctlh,
		 union pptp_ctrl_union *pptpReq)
{
	struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;
	u_int16_t msg, new_cid = 0, new_pcid;
	unsigned int pcid_off, cid_off = 0;

	int ret = NF_ACCEPT, rv;

	new_pcid = htons(nat_pptp_info->pns_call_id);

	switch (msg = ntohs(ctlh->messageType)) {
	case PPTP_OUT_CALL_REPLY:
		pcid_off = offsetof(union pptp_ctrl_union, ocack.peersCallID);
		cid_off = offsetof(union pptp_ctrl_union, ocack.callID);
		break;
	case PPTP_IN_CALL_CONNECT:
		pcid_off = offsetof(union pptp_ctrl_union, iccon.peersCallID);
		break;
	case PPTP_IN_CALL_REQUEST:
		/* only need to nat in case PAC is behind NAT box */
		return NF_ACCEPT;
	case PPTP_WAN_ERROR_NOTIFY:
		pcid_off = offsetof(union pptp_ctrl_union, wanerr.peersCallID);
		break;
	case PPTP_CALL_DISCONNECT_NOTIFY:
		pcid_off = offsetof(union pptp_ctrl_union, disc.callID);
		break;
	case PPTP_SET_LINK_INFO:
		pcid_off = offsetof(union pptp_ctrl_union, setlink.peersCallID);
		break;

	default:
		DEBUGP("unknown inbound packet %s\n",
			(msg <= PPTP_MSG_MAX)? strMName[msg]:strMName[0]);
		/* fall through */

	case PPTP_START_SESSION_REQUEST:
	case PPTP_START_SESSION_REPLY:
	case PPTP_STOP_SESSION_REQUEST:
	case PPTP_STOP_SESSION_REPLY:
	case PPTP_ECHO_REQUEST:
	case PPTP_ECHO_REPLY:
		/* no need to alter packet */
		return NF_ACCEPT;
	}

	/* only OUT_CALL_REPLY, IN_CALL_CONNECT, IN_CALL_REQUEST,
	 * WAN_ERROR_NOTIFY, CALL_DISCONNECT_NOTIFY pass down here */

	/* mangle packet */
	IP_NF_ASSERT(pcid);
	DEBUGP("altering peer call id from 0x%04x to 0x%04x\n",
		ntohs(*(u_int16_t *)pptpReq + pcid_off), ntohs(new_pcid));
	
	rv = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
	                              pcid_off + sizeof(struct pptp_pkt_hdr) +
				      sizeof(struct PptpControlHeader),
				      sizeof(new_pcid), (char *)&new_pcid, 
				      sizeof(new_pcid));
	if (rv != NF_ACCEPT) 
		return rv;

	if (new_cid) {
 		DEBUGP("altering call id from 0x%04x to 0x%04x\n",
			ntohs(*(u_int16_t *)pptpReq + cid_off), ntohs(new_cid));
		rv = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
		                              cid_off + sizeof(struct pptp_pkt_hdr) +
					      sizeof(struct PptpControlHeader),
					      sizeof(new_cid), (char *)&new_cid, 
					      sizeof(new_cid));
		if (rv != NF_ACCEPT)
			return rv;
	}

	/* check for earlier return value of 'switch' above */
	if (ret != NF_ACCEPT)
		return ret;

	/* great, at least we don't need to resize packets */
	return NF_ACCEPT;
}
Пример #8
0
/* outbound packets == from PNS to PAC */
static int
pptp_outbound_pkt(struct sk_buff **pskb,
		  struct ip_conntrack *ct,
		  enum ip_conntrack_info ctinfo,
		  struct PptpControlHeader *ctlh,
		  union pptp_ctrl_union *pptpReq)

{
	struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info;
	struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;

	u_int16_t msg, new_callid;
	unsigned int cid_off;

	new_callid = htons(ct_pptp_info->pns_call_id);
	
	switch (msg = ntohs(ctlh->messageType)) {
		case PPTP_OUT_CALL_REQUEST:
			cid_off = offsetof(union pptp_ctrl_union, ocreq.callID);
			/* FIXME: ideally we would want to reserve a call ID
			 * here.  current netfilter NAT core is not able to do
			 * this :( For now we use TCP source port. This breaks
			 * multiple calls within one control session */

			/* save original call ID in nat_info */
			nat_pptp_info->pns_call_id = ct_pptp_info->pns_call_id;

			/* don't use tcph->source since we are at a DSTmanip
			 * hook (e.g. PREROUTING) and pkt is not mangled yet */
			new_callid = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.tcp.port;

			/* save new call ID in ct info */
			ct_pptp_info->pns_call_id = ntohs(new_callid);
			break;
		case PPTP_IN_CALL_REPLY:
			cid_off = offsetof(union pptp_ctrl_union, icreq.callID);
			break;
		case PPTP_CALL_CLEAR_REQUEST:
			cid_off = offsetof(union pptp_ctrl_union, clrreq.callID);
			break;
		default:
			DEBUGP("unknown outbound packet 0x%04x:%s\n", msg,
			      (msg <= PPTP_MSG_MAX)? strMName[msg]:strMName[0]);
			/* fall through */

		case PPTP_SET_LINK_INFO:
			/* only need to NAT in case PAC is behind NAT box */
		case PPTP_START_SESSION_REQUEST:
		case PPTP_START_SESSION_REPLY:
		case PPTP_STOP_SESSION_REQUEST:
		case PPTP_STOP_SESSION_REPLY:
		case PPTP_ECHO_REQUEST:
		case PPTP_ECHO_REPLY:
			/* no need to alter packet */
			return NF_ACCEPT;
	}

	/* only OUT_CALL_REQUEST, IN_CALL_REPLY, CALL_CLEAR_REQUEST pass
	 * down to here */

	IP_NF_ASSERT(cid);

	DEBUGP("altering call id from 0x%04x to 0x%04x\n",
		ntohs(*(u_int16_t *)pptpReq + cid_off), ntohs(new_callid));

	/* mangle packet */
	if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo,
	                             cid_off + sizeof(struct pptp_pkt_hdr) +
	                             sizeof(struct PptpControlHeader),
	                             sizeof(new_callid), (char *)&new_callid,
	                             sizeof(new_callid)) == 0)
		return NF_DROP;

	return NF_ACCEPT;
}
Пример #9
0
static unsigned int help(struct sk_buff **pskb,
                         enum ip_conntrack_info ctinfo,
                         unsigned int matchoff,
                         unsigned int matchlen,
                         struct ip_conntrack_expect *exp)
{
    u_int16_t port;
    unsigned int ret;

    /* "4294967296 65635 " */
    char buffer[18];

    DEBUGP("IRC_NAT: info (seq %u + %u) in %u\n",
           expect->seq, exp_irc_info->len,
           ntohl(tcph->seq));

    /* Reply comes from server. */
    exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
    exp->dir = IP_CT_DIR_REPLY;

    /* When you see the packet, we need to NAT it the same as the
     * this one. */
    exp->expectfn = ip_nat_follow_master;

    /* Try to get same port: if not, try to change it. */
    for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
        exp->tuple.dst.u.tcp.port = htons(port);
        if (ip_conntrack_expect_related(exp) == 0)
            break;
    }

    if (port == 0)
        return NF_DROP;

    /*      strlen("\1DCC CHAT chat AAAAAAAA P\1\n")=27
     *      strlen("\1DCC SCHAT chat AAAAAAAA P\1\n")=28
     *      strlen("\1DCC SEND F AAAAAAAA P S\1\n")=26
     *      strlen("\1DCC MOVE F AAAAAAAA P S\1\n")=26
     *      strlen("\1DCC TSEND F AAAAAAAA P S\1\n")=27
     *              AAAAAAAAA: bound addr (1.0.0.0==16777216, min 8 digits,
     *                      255.255.255.255==4294967296, 10 digits)
     *              P:         bound port (min 1 d, max 5d (65635))
     *              F:         filename   (min 1 d )
     *              S:         size       (min 1 d )
     *              0x01, \n:  terminators
     */

    /* AAA = "us", ie. where server normally talks to. */
    sprintf(buffer, "%u %u",
            ntohl(exp->master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
            port);
    DEBUGP("ip_nat_irc: Inserting '%s' == %u.%u.%u.%u, port %u\n",
           buffer, NIPQUAD(exp->tuple.src.ip), port);

    ret = ip_nat_mangle_tcp_packet(pskb, exp->master, ctinfo,
                                   matchoff, matchlen, buffer,
                                   strlen(buffer));
    if (ret != NF_ACCEPT)
        ip_conntrack_unexpect_related(exp);
    return ret;
}
Пример #10
0
static int mms_data_fixup(const struct ip_ct_mms_expect *ct_mms_info,
                          struct ip_conntrack *ct,
                          struct sk_buff **pskb,
                          enum ip_conntrack_info ctinfo,
                          struct ip_conntrack_expect *expect)
{
	u_int32_t newip;
	struct ip_conntrack_tuple t;
	struct iphdr *iph = (*pskb)->nh.iph;
	struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
	char *data = (char *)tcph + tcph->doff * 4;
	int i, j, k, port;
	u_int16_t mms_proto;

	u_int32_t *mms_chunkLenLV    = (u_int32_t *)(data + MMS_SRV_CHUNKLENLV_OFFSET);
	u_int32_t *mms_chunkLenLM    = (u_int32_t *)(data + MMS_SRV_CHUNKLENLM_OFFSET);
	u_int32_t *mms_messageLength = (u_int32_t *)(data + MMS_SRV_MESSAGELENGTH_OFFSET);

	int zero_padding;

	char buffer[28];         /* "\\255.255.255.255\UDP\65635" * 2 (for unicode) */
	char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
	char proto_string[6];
	
	/* what was the protocol again ? */
	mms_proto = expect->tuple.dst.protonum;
	sprintf(proto_string, "%u", mms_proto);
	
	DEBUGP("ip_nat_mms: mms_data_fixup: info (seq %u + %u) in %u, proto %s\n",
	       expect->seq, ct_mms_info->len, ntohl(tcph->seq),
	       mms_proto == IPPROTO_UDP ? "UDP"
	       : mms_proto == IPPROTO_TCP ? "TCP":proto_string);
	
	newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;

	/* Alter conntrack's expectations. */
	t = expect->tuple;
	t.dst.ip = newip;
	for (port = ct_mms_info->port; port != 0; port++) {
		t.dst.u.tcp.port = htons(port);
		if (ip_conntrack_change_expect(expect, &t) == 0) {
			DEBUGP("ip_nat_mms: mms_data_fixup: using port %d\n", port);
			break;
		}
	}
	
	if(port == 0)
		return 0;

	sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
	        NIPQUAD(newip),
		expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
		: expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
		port);
	DEBUGP("ip_nat_mms: new unicode string=%s\n", buffer);
	
	memset(unicode_buffer, 0, sizeof(char)*75);

	for (i=0; i<strlen(buffer); ++i)
		*(unicode_buffer+i*2)=*(buffer+i);
	
	DEBUGP("ip_nat_mms: mms_data_fixup: padding: %u len: %u\n", ct_mms_info->padding, ct_mms_info->len);
	DEBUGP("ip_nat_mms: mms_data_fixup: offset: %u\n", MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len);
	DUMP_BYTES(data+MMS_SRV_UNICODE_STRING_OFFSET, 60);
	
	/* add end of packet to it */
	for (j=0; j<ct_mms_info->padding; ++j) {
		DEBUGP("ip_nat_mms: mms_data_fixup: i=%u j=%u byte=%u\n", 
		       i, j, (u8)*(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j));
		*(unicode_buffer+i*2+j) = *(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j);
	}

	/* pad with zeroes at the end ? see explanation of weird math below */
	zero_padding = (8-(strlen(buffer)*2 + ct_mms_info->padding + 4)%8)%8;
	for (k=0; k<zero_padding; ++k)
		*(unicode_buffer+i*2+j+k)= (char)0;
	
	DEBUGP("ip_nat_mms: mms_data_fixup: zero_padding = %u\n", zero_padding);
	DEBUGP("ip_nat_mms: original=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
	       *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
	
	/* explanation, before I forget what I did:
	   strlen(buffer)*2 + ct_mms_info->padding + 4 must be divisable by 8;
	   divide by 8 and add 3 to compute the mms_chunkLenLM field,
	   but note that things may have to be padded with zeroes to align by 8 
	   bytes, hence we add 7 and divide by 8 to get the correct length */ 
	*mms_chunkLenLM    = (u_int32_t) (3+(strlen(buffer)*2+ct_mms_info->padding+11)/8);
	*mms_chunkLenLV    = *mms_chunkLenLM+2;
	*mms_messageLength = *mms_chunkLenLV*8;
	
	DEBUGP("ip_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
	       *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
	
	ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
	                         expect->seq - ntohl(tcph->seq),
	                         ct_mms_info->len + ct_mms_info->padding, unicode_buffer,
	                         strlen(buffer)*2 + ct_mms_info->padding + zero_padding);
	DUMP_BYTES(unicode_buffer, 60);
	
	return 1;
}
Пример #11
0
static unsigned int add_sl_header(struct sk_buff **pskb,
                                  struct ip_conntrack *ct, 
                                  enum ip_conntrack_info ctinfo,
      				              unsigned int host_offset, 
                                  unsigned int dataoff, 
                                  unsigned int datalen,
                                  unsigned int end_of_host,
                                  unsigned char *user_data)
{                      
       
    unsigned int jhashed, slheader_len;
    char src_string[MACADDR_SIZE], slheader[SL_HEADER_LEN];
    struct ethhdr *bigmac = eth_hdr(*pskb);

    /* first make sure there is room */
    if ( (*pskb)->len >= ( MAX_PACKET_LEN - SL_HEADER_LEN ) ) {

#ifdef SL_DEBUG
        printk(KERN_DEBUG "packet too large for sl_header, length: %d\n", (*pskb)->len);
#endif
        return 0;
    }


    /* next make sure an x-slr header is not already present */
    if (!strncmp(xslr,(unsigned char *)((unsigned int)user_data+end_of_host+1),
		 XSLR_LEN)) {
#ifdef SL_DEBUG
    	printk(KERN_DEBUG "pkt x-slr already present\n");
#endif
    	return 0;
    }

#ifdef SL_DEBUG
        printk(KERN_DEBUG "no x-slr header present, adding\n");
#endif

    /* create the X-SLR Header */        
#ifdef SL_DEBUG
    printk(KERN_DEBUG "source mac found: %02x%02x%02x%02x%02x%02x\n",
            bigmac->h_source[0],
            bigmac->h_source[1],
            bigmac->h_source[2],
            bigmac->h_source[3],
            bigmac->h_source[4],
            bigmac->h_source[5]);
#endif        

    sprintf(src_string, "%02x%02x%02x%02x%02x%02x",
            bigmac->h_source[0],
            bigmac->h_source[1],
            bigmac->h_source[2],
            bigmac->h_source[3],
            bigmac->h_source[4],
            bigmac->h_source[5]);

    /********************************************/
    /* create the http header */
    /* jenkins hash obfuscation of source mac */
    jhashed = jhash((void *)src_string, MACADDR_SIZE, JHASH_SALT);
    slheader_len = sprintf(slheader, "X-SLR: %08x|%s\r\n", jhashed, sl_device);

    /* handle sprintf failure */
   if (slheader_len != SL_HEADER_LEN) {
        printk(KERN_ERR "exp header %s len %d doesnt match calc len %d\n",
               (char *)slheader, SL_HEADER_LEN, slheader_len );
        return 0;
    }

#ifdef SL_DEBUG
    printk(KERN_DEBUG "xslr %s, len %d\n", slheader, slheader_len);
#endif        


    /********************************************/
    /* insert the slheader into the http headers */
    if (!ip_nat_mangle_tcp_packet( pskb,
                                   ct, 
                                   ctinfo,
                                   end_of_host + search[NEWLINE].len,
                                   0, 
                                   slheader,
                                   slheader_len)) {  

        printk(KERN_ERR " failed to mangle packet\n");
	return 0;
    }

#ifdef SL_DEBUG
        printk(KERN_DEBUG "packet mangled ok:\n%s\n",
		(unsigned char *)((unsigned int)user_data));
#endif        

    return 1;
}