コード例 #1
0
ファイル: tsession6_chain.c プロジェクト: millken/zhuxianB30
int tse6_seq_adjust(struct sk_buff **pskb,
		  struct nf_conn *ct,
		  enum ip_conntrack_info ctinfo)
{
	struct tcphdr *tcph;
	int dir;
	int protoff = 0;
	__be32 newseq, newack;
	u8 pnum = (*pskb)->nh.ipv6h->nexthdr;
	struct nf_conn_nat *nat = &ct->nat;
	struct nf_nat_seq *this_way, *other_way;

	dir = CTINFO2DIR(ctinfo);

	this_way = &nat->info.seq[dir];
	other_way = &nat->info.seq[!dir];

	protoff = tse6_skip_exthdr(*pskb, sizeof(struct ipv6hdr), &pnum, (*pskb)->len - sizeof(struct ipv6hdr));
	if ((protoff < 0) || (protoff > (*pskb)->len) || (pnum != IPPROTO_TCP)) {
		return -NF_ACCEPT;
	}
	tcph = (void *)(*pskb)->nh.ipv6h + protoff;


	if (!skb_make_writable(pskb, protoff+sizeof(*tcph)))
		return 0;

	tcph = (void *)(*pskb)->data + protoff;
	if (after(ntohl(tcph->seq), this_way->correction_pos))
		newseq = htonl(ntohl(tcph->seq) + this_way->offset_after);
	else
		newseq = htonl(ntohl(tcph->seq) + this_way->offset_before);

	if (after(ntohl(tcph->ack_seq) - other_way->offset_before,
		  other_way->correction_pos))
		newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_after);
	else
		newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_before);

	nf_proto_csum_replace4(&tcph->check, *pskb, tcph->seq, newseq, 0);
	nf_proto_csum_replace4(&tcph->check, *pskb, tcph->ack_seq, newack, 0);

	tcph->seq = newseq;
	tcph->ack_seq = newack;

	if (!tse6_sack_adjust(pskb, tcph, ct, ctinfo, protoff)) {
		return 0;
	}

	nf_conntrack_tcp_update(*pskb, protoff, ct, dir);

	return 1;
}
コード例 #2
0
/* Generic function for mangling variable-length address changes inside
 * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX
 * command in FTP).
 *
 * Takes care about all the nasty sequence number changes, checksumming,
 * skb enlargement, ...
 *
 * */
int
nf_nat_mangle_tcp_packet(struct sk_buff **pskb,
			 struct nf_conn *ct,
			 enum ip_conntrack_info ctinfo,
			 unsigned int match_offset,
			 unsigned int match_len,
			 const char *rep_buffer,
			 unsigned int rep_len)
{
	struct iphdr *iph;
	struct tcphdr *tcph;
	int oldlen, datalen;

	if (!skb_make_writable(pskb, (*pskb)->len))
		return 0;

	if (rep_len > match_len &&
	    rep_len - match_len > skb_tailroom(*pskb) &&
	    !enlarge_skb(pskb, rep_len - match_len))
		return 0;

	SKB_LINEAR_ASSERT(*pskb);

	iph = (*pskb)->nh.iph;
	tcph = (void *)iph + iph->ihl*4;

	oldlen = (*pskb)->len - iph->ihl*4;
	mangle_contents(*pskb, iph->ihl*4 + tcph->doff*4,
			match_offset, match_len, rep_buffer, rep_len);

	datalen = (*pskb)->len - iph->ihl*4;
	if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
		tcph->check = 0;
		tcph->check = tcp_v4_check(datalen,
					   iph->saddr, iph->daddr,
					   csum_partial((char *)tcph,
							datalen, 0));
	} else
		nf_proto_csum_replace2(&tcph->check, *pskb,
				       htons(oldlen), htons(datalen), 1);

	if (rep_len != match_len) {
		set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
		adjust_tcp_sequence(ntohl(tcph->seq),
				    (int)rep_len - (int)match_len,
				    ct, ctinfo);
		/* Tell TCP window tracking about seq change */
		nf_conntrack_tcp_update(*pskb, (*pskb)->nh.iph->ihl*4,
					ct, CTINFO2DIR(ctinfo));
	}
	return 1;
}
コード例 #3
0
/* TCP sequence number adjustment.  Returns 1 on success, 0 on failure */
int
nf_nat_seq_adjust(struct sk_buff **pskb,
		  struct nf_conn *ct,
		  enum ip_conntrack_info ctinfo)
{
	struct tcphdr *tcph;
	int dir;
	__be32 newseq, newack;
	struct nf_conn_nat *nat = nfct_nat(ct);
	struct nf_nat_seq *this_way, *other_way;

	dir = CTINFO2DIR(ctinfo);

	this_way = &nat->info.seq[dir];
	other_way = &nat->info.seq[!dir];

	if (!skb_make_writable(pskb, (*pskb)->nh.iph->ihl*4+sizeof(*tcph)))
		return 0;

	tcph = (void *)(*pskb)->data + (*pskb)->nh.iph->ihl*4;
	if (after(ntohl(tcph->seq), this_way->correction_pos))
		newseq = htonl(ntohl(tcph->seq) + this_way->offset_after);
	else
		newseq = htonl(ntohl(tcph->seq) + this_way->offset_before);

	if (after(ntohl(tcph->ack_seq) - other_way->offset_before,
		  other_way->correction_pos))
		newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_after);
	else
		newack = htonl(ntohl(tcph->ack_seq) - other_way->offset_before);

	nf_proto_csum_replace4(&tcph->check, *pskb, tcph->seq, newseq, 0);
	nf_proto_csum_replace4(&tcph->check, *pskb, tcph->ack_seq, newack, 0);

	DEBUGP("Adjusting sequence number from %u->%u, ack from %u->%u\n",
		ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq),
		ntohl(newack));

	tcph->seq = newseq;
	tcph->ack_seq = newack;

	if (!nf_nat_sack_adjust(pskb, tcph, ct, ctinfo))
		return 0;

	nf_conntrack_tcp_update(*pskb, (*pskb)->nh.iph->ihl*4, ct, dir);

	return 1;
}