enum {
TCP_ESTABLISHED = 1,
TCP_SYN_SENT,
TCP_SYN_RECV,
TCP_FIN_WAIT1,
TCP_FIN_WAIT2,
TCP_TIME_WAIT,
TCP_CLOSE,
TCP_CLOSE_WAIT,
TCP_LAST_ACK,
TCP_LISTEN,
TCP_CLOSING, /* Now a valid state */
TCP_NEW_SYN_RECV,
TCP_MAX_STATES /* Leave at the end! */
};
staticvoid test_sock_checkpoint_queue(int sk, int queue, int qlen, struct tcp_sock_queue *q)
{
socklen_t len; int ret;
if (setsockopt(sk, SOL_TCP, TCP_REPAIR_QUEUE, &queue, sizeof(queue)))
test_error("setsockopt(TCP_REPAIR_QUEUE)");
len = sizeof(q->seq);
ret = getsockopt(sk, SOL_TCP, TCP_QUEUE_SEQ, &q->seq, &len); if (ret || len != sizeof(q->seq))
test_error("getsockopt(TCP_QUEUE_SEQ): %d", (int)len);
if (!qlen) {
q->buf = NULL; return;
}
q->buf = malloc(qlen); if (q->buf == NULL)
test_error("malloc()");
ret = recv(sk, q->buf, qlen, MSG_PEEK | MSG_DONTWAIT); if (ret != qlen)
test_error("recv(%d): %d", qlen, ret);
}
void __test_sock_checkpoint(int sk, struct tcp_sock_state *state, void *addr, size_t addr_size)
{
socklen_t len = sizeof(state->info); int ret;
memset(state, 0, sizeof(*state));
ret = getsockopt(sk, SOL_TCP, TCP_INFO, &state->info, &len); if (ret || len != sizeof(state->info))
test_error("getsockopt(TCP_INFO): %d", (int)len);
len = addr_size; if (getsockname(sk, addr, &len) || len != addr_size)
test_error("getsockname(): %d", (int)len);
len = sizeof(state->trw);
ret = getsockopt(sk, SOL_TCP, TCP_REPAIR_WINDOW, &state->trw, &len); if (ret || len != sizeof(state->trw))
test_error("getsockopt(TCP_REPAIR_WINDOW): %d", (int)len);
if (ioctl(sk, SIOCOUTQ, &state->outq_len))
test_error("ioctl(SIOCOUTQ)");
if (ioctl(sk, SIOCOUTQNSD, &state->outq_nsd_len))
test_error("ioctl(SIOCOUTQNSD)");
test_sock_checkpoint_queue(sk, TCP_SEND_QUEUE, state->outq_len, &state->out);
if (ioctl(sk, SIOCINQ, &state->inq_len))
test_error("ioctl(SIOCINQ)");
test_sock_checkpoint_queue(sk, TCP_RECV_QUEUE, state->inq_len, &state->in);
if (state->info.tcpi_state == TCP_CLOSE)
state->outq_len = state->outq_nsd_len = 0;
len = sizeof(state->mss);
ret = getsockopt(sk, SOL_TCP, TCP_MAXSEG, &state->mss, &len); if (ret || len != sizeof(state->mss))
test_error("getsockopt(TCP_MAXSEG): %d", (int)len);
len = sizeof(state->timestamp);
ret = getsockopt(sk, SOL_TCP, TCP_TIMESTAMP, &state->timestamp, &len); if (ret || len != sizeof(state->timestamp))
test_error("getsockopt(TCP_TIMESTAMP): %d", (int)len);
}
void test_ao_checkpoint(int sk, struct tcp_ao_repair *state)
{
socklen_t len = sizeof(*state); int ret;
memset(state, 0, sizeof(*state));
ret = getsockopt(sk, SOL_TCP, TCP_AO_REPAIR, state, &len); if (ret || len != sizeof(*state))
test_error("getsockopt(TCP_AO_REPAIR): %d", (int)len);
}
staticvoid test_sock_restore_seq(int sk, int queue, uint32_t seq)
{ if (setsockopt(sk, SOL_TCP, TCP_REPAIR_QUEUE, &queue, sizeof(queue)))
test_error("setsockopt(TCP_REPAIR_QUEUE)");
if (setsockopt(sk, SOL_TCP, TCP_QUEUE_SEQ, &seq, sizeof(seq)))
test_error("setsockopt(TCP_QUEUE_SEQ)");
}
staticvoid test_sock_restore_queue(int sk, int queue, void *buf, int len)
{ int chunk = len;
size_t off = 0;
if (len == 0) return;
if (setsockopt(sk, SOL_TCP, TCP_REPAIR_QUEUE, &queue, sizeof(queue)))
test_error("setsockopt(TCP_REPAIR_QUEUE)");
do { int ret;
ret = send(sk, buf + off, chunk, 0); if (ret <= 0) { if (chunk > 1024) {
chunk >>= 1; continue;
}
test_error("send()");
}
off += ret;
len -= ret;
} while (len > 0);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.