Exemple #1
0
/* data has been encrypted before */
static gint packet_send_out(PurpleConnection *gc, guint16 cmd, guint16 seq, guint8 *data, gint data_len)
{
	qq_data *qd;
	guint8 *buf;
	gint buf_len;
	gint bytes_sent;

	g_return_val_if_fail(gc != NULL && gc->proto_data != NULL, -1);
	qd = (qq_data *)gc->proto_data;
	g_return_val_if_fail(data != NULL && data_len > 0, -1);

	buf = g_newa(guint8, MAX_PACKET_SIZE);
	memset(buf, 0, MAX_PACKET_SIZE);
	/* encapsulate */
	buf_len = packet_encap(qd, buf, MAX_PACKET_SIZE, cmd, seq, data, data_len);
	if (buf_len <= 0) {
		return -1;
	}

	qd->net_stat.sent++;
	if (qd->use_tcp) {
		bytes_sent = tcp_send_out(gc, buf, buf_len);
	} else {
		bytes_sent = udp_send_out(gc, buf, buf_len);
	}

	return bytes_sent;
}
Exemple #2
0
int tcp_send_text(struct tcp_sock *tsk, void *buf, int len)
{
	struct pkbuf *pkb;
	int slen = 0;
	int segsize = tsk->sk.sk_dst->rt_dev->net_mtu - IP_HRD_SZ - TCP_HRD_SZ;
	len = min(len, (int)tsk->snd_wnd);
	while (slen < len) {
		/* TODO: handle silly window syndrome */
		segsize = min(segsize, len - slen);
		pkb = alloc_pkb(ETH_HRD_SZ + IP_HRD_SZ + TCP_HRD_SZ + segsize);
		tcp_init_text(tsk, pkb, buf + slen, segsize);
		slen += segsize;
		if (slen >= len)
			pkb2tcp(pkb)->psh = 1;
		tcp_send_out(tsk, pkb, NULL);
	}

	/* zero window: request window update */
	if (!slen) {
		/* TODO: persist timer */
		tcp_send_ack(tsk, NULL);
		slen = -1;
	}
	return slen;
}
Exemple #3
0
/*
 * Reset algorithm is not stated directly in RFC 793,
 * but we can conclude it according to all reset generation.
 * NOTE: maybe @tsk is NULL
 */
void tcp_send_reset(struct tcp_sock *tsk, struct tcp_segment *seg)
{
	struct tcp *otcp, *tcphdr = seg->tcphdr;
	struct pkbuf *opkb;

	if (tcphdr->rst)
		return;
	opkb = alloc_pkb(ETH_HRD_SZ + IP_HRD_SZ + TCP_HRD_SZ);
	/* fill tcp head */
	otcp = (struct tcp *)pkb2ip(opkb)->ip_data;
	otcp->src = tcphdr->dst;
	otcp->dst = tcphdr->src;
	if (tcphdr->ack) {
		/*
		 * Should we set ack?
		 * -Yes for xinu, it always set ack to seq+len
		 * +No for Linux
		 * +No for tapip
		 */
		otcp->seq = tcphdr->ackn;
	} else {
		otcp->ackn = _htonl(seg->seq + seg->len);
		otcp->ack = 1;
	}
	otcp->doff = TCP_HRD_DOFF;
	otcp->rst = 1;
	tcpdbg("send RESET from "IPFMT":%d to "IPFMT":%d",
			ipfmt(seg->iphdr->ip_dst), _ntohs(otcp->src),
			ipfmt(seg->iphdr->ip_src), _ntohs(otcp->dst));
	tcp_send_out(NULL, opkb, seg);
}
Exemple #4
0
void tcp_send_fin(struct tcp_sock *tsk)
{
	struct tcp *otcp;
	struct pkbuf *opkb;

	opkb = alloc_pkb(ETH_HRD_SZ + IP_HRD_SZ + TCP_HRD_SZ);
	/* fill tcp head */
	otcp = (struct tcp *)pkb2ip(opkb)->ip_data;
	otcp->src = tsk->sk.sk_sport;
	otcp->dst = tsk->sk.sk_dport;
	otcp->doff = TCP_HRD_DOFF;
	otcp->seq = _htonl(tsk->snd_nxt);
	otcp->window = _htons(tsk->rcv_wnd);
	otcp->fin = 1;
	/*
	 * Should we send an ACK?
	 * Yes, tcp stack will drop packet if it has no ACK bit
	 * according to RFC 793 #SEGMENT RECEIVE
	 */
	otcp->ackn = _htonl(tsk->rcv_nxt);
	otcp->ack = 1;
	tcpdbg("send FIN(%u)/ACK(%u) [WIN %d] to "IPFMT":%d",
			_ntohl(otcp->seq), _ntohl(otcp->ackn),
			_ntohs(otcp->window), ipfmt(tsk->sk.sk_daddr),
			_ntohs(otcp->dst));
	tcp_send_out(tsk, opkb, NULL);
}
Exemple #5
0
void tcp_send_synack(struct tcp_sock *tsk, struct tcp_segment *seg)
{
	/*
	 * LISTEN :
	 * SYN-SENT:
	 *         SEG: SYN, no ACK, no RST
	 *         <SEQ=ISS><ACK=RCV.NXT><CTL=SYN,ACK>
	 *         (ISS == SND.NXT)
	 */
	struct tcp *otcp, *tcphdr = seg->tcphdr;
	struct pkbuf *opkb;

	if (tcphdr->rst)
		return;
	opkb = alloc_pkb(ETH_HRD_SZ + IP_HRD_SZ + TCP_HRD_SZ);
	/* fill tcp head */
	otcp = (struct tcp *)pkb2ip(opkb)->ip_data;
	otcp->src = tcphdr->dst;
	otcp->dst = tcphdr->src;
	otcp->doff = TCP_HRD_DOFF;
	otcp->seq = _htonl(tsk->iss);
	otcp->ackn = _htonl(tsk->rcv_nxt);
	otcp->syn = 1;
	otcp->ack = 1;
	otcp->window = _htons(tsk->rcv_wnd);
	tcpdbg("send SYN(%u)/ACK(%u) [WIN %d] to "IPFMT":%d",
			_ntohl(otcp->seq), _ntohs(otcp->window),
			_ntohl(otcp->ackn), ipfmt(seg->iphdr->ip_dst),
			_ntohs(otcp->dst));
	tcp_send_out(tsk, opkb, seg);
}
Exemple #6
0
void tcp_send_syn(struct tcp_sock *tsk, struct tcp_segment *seg)
{
	/*
	 * SYN-SENT:
	 */
	struct tcp *otcp;
	struct pkbuf *opkb;

	opkb = alloc_pkb(ETH_HRD_SZ + IP_HRD_SZ + TCP_HRD_SZ);
	/* fill tcp head */
	otcp = (struct tcp *)pkb2ip(opkb)->ip_data;
	otcp->src = tsk->sk.sk_sport;
	otcp->dst = tsk->sk.sk_dport;
	otcp->doff = TCP_HRD_DOFF;
	otcp->seq = _htonl(tsk->iss);
	otcp->syn = 1;
	otcp->window = _htons(tsk->rcv_wnd);
	tcpdbg("send SYN(%u) [WIN %d] to "IPFMT":%d",
			_ntohl(otcp->seq), _ntohs(otcp->window),
			ipfmt(tsk->sk.sk_daddr), _ntohs(otcp->dst));
	tcp_send_out(tsk, opkb, seg);
}
Exemple #7
0
/*
 * Acknowledgment algorithm is not stated directly in RFC 793,
 * but we can conclude it from all acknowledgment situation.
 */
void tcp_send_ack(struct tcp_sock *tsk, struct tcp_segment *seg)
{
	/*
	 * SYN-SENT :
	 *         SEG: SYN, acceptable ACK, no RST   (SND.NXT = SEG.SEQ+1)
	 *         <SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>
	 * SYN-RECEIVED / ESTABLISHED  / FIN-WAIT-1   / FIN-WAIT-2   /
	 * CLOSE-WAIT   / CLOSING      / LAST-ACK     / TIME-WAIT    :
	 *         SEG: no RST, ??ACK, ??SYN        (segment is not acceptable)
	 *         <SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>
	 * ESTABLISHED  / FIN-WAIT-1  / FIN-WAIT-2  / process the segment text:
	 *         SEG: ACK, no RST
	 *         <SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK>
	 *         (This acknowledgment should be piggybacked on a segment being
	 *          transmitted if possible without incurring undue delay.)
	 */
	struct tcp *otcp, *tcphdr = seg->tcphdr;
	struct pkbuf *opkb;

	if (tcphdr->rst)
		return;
	opkb = alloc_pkb(ETH_HRD_SZ + IP_HRD_SZ + TCP_HRD_SZ);
	/* fill tcp head */
	otcp = (struct tcp *)pkb2ip(opkb)->ip_data;
	otcp->src = tcphdr->dst;
	otcp->dst = tcphdr->src;
	otcp->doff = TCP_HRD_DOFF;
	otcp->seq = _htonl(tsk->snd_nxt);
	otcp->ackn = _htonl(tsk->rcv_nxt);
	otcp->ack = 1;
	otcp->window = _htons(tsk->rcv_wnd);
	tcpdbg("send ACK(%u) [WIN %d] to "IPFMT":%d",
			_ntohl(otcp->ackn), _ntohs(otcp->window),
			ipfmt(seg->iphdr->ip_src), _ntohs(otcp->dst));
	tcp_send_out(tsk, opkb, seg);
}