Ejemplo n.º 1
0
static int talk_help_response(struct ip_conntrack *ct,
			      struct ip_conntrack_expect *exp,
			      struct sk_buff **pskb,
		              u_char type,
		              u_char answer,
		              struct talk_addr *addr)
{
	u_int32_t newip;
	u_int16_t port;
	struct ip_conntrack_tuple t;
	struct ip_ct_talk_expect *ct_talk_info;

	DEBUGP("ip_nat_talk_help_response: addr: %u.%u.%u.%u:%u, type %d answer %d\n",
		NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
		type, answer);
	
	LOCK_BH(&ip_talk_lock);
	ct_talk_info = &exp->help.exp_talk_info;

	if (!(answer == SUCCESS 
	      && (type == LOOK_UP || type == ANNOUNCE)
	      && exp != NULL)) {
		UNLOCK_BH(&ip_talk_lock);
		return NF_ACCEPT;
	}
		
	DEBUGP("ip_nat_talk_help_response: talkinfo port %u (%s)\n", 
		ntohs(ct_talk_info->port), 
		type == LOOK_UP ? "LOOK_UP" : "ANNOUNCE");

	/* Change address inside packet to match way we're mapping
	   this connection. */
	newip = ct->tuplehash[type == LOOK_UP ? IP_CT_DIR_ORIGINAL : 
						IP_CT_DIR_REPLY].tuple.dst.ip;
	/* We can read expect here without conntrack lock, since it's
	   only set in ip_conntrack_talk , with ip_talk_lock held
	   writable */ 
	t = exp->tuple;
	t.dst.ip = newip;

	/* Try to get same port: if not, try to change it. */
	for (port = ntohs(ct_talk_info->port); port != 0; port++) {
		if (type == LOOK_UP)
			t.dst.u.tcp.port = htons(port);
		else
			t.dst.u.udp.port = htons(port);

		if (ip_conntrack_change_expect(exp, &t) == 0) {
			DEBUGP("ip_nat_talk_help_response: using %u.%u.%u.%u:%u\n", NIPQUAD(newip), port);
			break;
		}
	}
	UNLOCK_BH(&ip_talk_lock);

	if (port == 0 || !mangle_packet(pskb, ct, newip, htons(port), addr, NULL))
		return NF_DROP;
	
	return NF_ACCEPT;
}
Ejemplo n.º 2
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));
}
Ejemplo n.º 3
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;
}