aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Subiron <maethor@subiron.org>2016-03-15 10:31:21 +0100
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2016-03-15 10:35:14 +0100
commitb3959704906192a29bd863bd8cdf30be3ed2aca0 (patch)
tree03ad1f158930bf185f1567bfcc374b8d8c1716fc
parent59ec4a16cee98e0103d008f5d49ea0236ac49bbd (diff)
downloadslirp-b3959704906192a29bd863bd8cdf30be3ed2aca0.zip
slirp-b3959704906192a29bd863bd8cdf30be3ed2aca0.tar.gz
slirp-b3959704906192a29bd863bd8cdf30be3ed2aca0.tar.bz2
slirp: Generalizing and neutralizing various TCP functions before adding IPv6 stuff
Basically, this patch adds some switch in various TCP functions to prepare them for the IPv6 case. To have something to "switch" in tcp_input() and tcp_respond(), a new argument is used to give them the sa_family of the addresses they are working on. This patch does not include the entailed reindentation, to make proofread easier. Reindentation is adressed in the following no-op patch. Signed-off-by: Guillaume Subiron <maethor@subiron.org> Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org> Reviewed-by: Thomas Huth <thuth@redhat.com>
-rw-r--r--ip_input.c2
-rw-r--r--slirp.c6
-rw-r--r--slirp.h4
-rw-r--r--tcp_input.c168
-rw-r--r--tcp_output.c36
-rw-r--r--tcp_subr.c83
-rw-r--r--tcp_timer.c2
7 files changed, 188 insertions, 113 deletions
diff --git a/ip_input.c b/ip_input.c
index 7bfcbf8..67ab677 100644
--- a/ip_input.c
+++ b/ip_input.c
@@ -196,7 +196,7 @@ void ip_input(struct mbuf *m)
*/
switch (ip->ip_p) {
case IPPROTO_TCP:
- tcp_input(m, hlen, (struct socket *)NULL);
+ tcp_input(m, hlen, (struct socket *)NULL, AF_INET);
break;
case IPPROTO_UDP:
udp_input(m, hlen);
diff --git a/slirp.c b/slirp.c
index 65b4a22..72cc033 100644
--- a/slirp.c
+++ b/slirp.c
@@ -583,7 +583,8 @@ void slirp_pollfds_poll(GArray *pollfds, int select_error)
/*
* Continue tcp_input
*/
- tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
+ tcp_input((struct mbuf *)NULL, sizeof(struct ip), so,
+ so->so_ffamily);
/* continue; */
} else {
ret = sowrite(so);
@@ -631,7 +632,8 @@ void slirp_pollfds_poll(GArray *pollfds, int select_error)
so->so_state &= ~SS_ISFCONNECTING;
}
}
- tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
+ tcp_input((struct mbuf *)NULL, sizeof(struct ip), so,
+ so->so_ffamily);
} /* SS_ISFCONNECTING */
#endif
}
diff --git a/slirp.h b/slirp.h
index c50827b..1e9a788 100644
--- a/slirp.h
+++ b/slirp.h
@@ -329,7 +329,7 @@ void ip6_input(struct mbuf *);
int ip6_output(struct socket *, struct mbuf *, int fast);
/* tcp_input.c */
-void tcp_input(register struct mbuf *, int, struct socket *);
+void tcp_input(register struct mbuf *, int, struct socket *, unsigned short af);
int tcp_mss(register struct tcpcb *, u_int);
/* tcp_output.c */
@@ -341,7 +341,7 @@ void tcp_init(Slirp *);
void tcp_cleanup(Slirp *);
void tcp_template(struct tcpcb *);
void tcp_respond(struct tcpcb *, register struct tcpiphdr *,
- register struct mbuf *, tcp_seq, tcp_seq, int);
+ register struct mbuf *, tcp_seq, tcp_seq, int, unsigned short);
struct tcpcb *tcp_newtcpcb(struct socket *);
struct tcpcb *tcp_close(register struct tcpcb *);
void tcp_sockclosed(struct tcpcb *);
diff --git a/tcp_input.c b/tcp_input.c
index 3b02559..7450f7b 100644
--- a/tcp_input.c
+++ b/tcp_input.c
@@ -215,7 +215,8 @@ present:
* TCP input routine, follows pages 65-76 of the
* protocol specification dated September, 1981 very closely.
*/
-void tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
+void tcp_input(struct mbuf *m, int iphlen, struct socket *inso,
+ unsigned short af)
{
struct ip save_ip, *ip;
register struct tcpiphdr *ti;
@@ -256,46 +257,53 @@ void tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
}
slirp = m->slirp;
- if (iphlen > sizeof(struct ip)) {
- ip_stripoptions(m, (struct mbuf *)0);
- iphlen = sizeof(struct ip);
- }
- /* XXX Check if too short */
+ switch (af) {
+ case AF_INET:
+ if (iphlen > sizeof(struct ip)) {
+ ip_stripoptions(m, (struct mbuf *)0);
+ iphlen = sizeof(struct ip);
+ }
+ /* XXX Check if too short */
- /*
- * Save a copy of the IP header in case we want restore it
- * for sending an ICMP error message in response.
- */
- ip = mtod(m, struct ip *);
- save_ip = *ip;
- save_ip.ip_len += iphlen;
+ /*
+ * Save a copy of the IP header in case we want restore it
+ * for sending an ICMP error message in response.
+ */
+ ip = mtod(m, struct ip *);
+ save_ip = *ip;
+ save_ip.ip_len += iphlen;
- /*
- * Get IP and TCP header together in first mbuf.
- * Note: IP leaves IP header in first mbuf.
- */
- m->m_data -=
- sizeof(struct tcpiphdr) - sizeof(struct ip) - sizeof(struct tcphdr);
- m->m_len +=
- sizeof(struct tcpiphdr) - sizeof(struct ip) - sizeof(struct tcphdr);
- ti = mtod(m, struct tcpiphdr *);
+ /*
+ * Get IP and TCP header together in first mbuf.
+ * Note: IP leaves IP header in first mbuf.
+ */
+ m->m_data -=
+ sizeof(struct tcpiphdr) - sizeof(struct ip) - sizeof(struct tcphdr);
+ m->m_len +=
+ sizeof(struct tcpiphdr) - sizeof(struct ip) - sizeof(struct tcphdr);
+ ti = mtod(m, struct tcpiphdr *);
- /*
- * Checksum extended TCP header and data.
- */
- tlen = ip->ip_len;
- tcpiphdr2qlink(ti)->next = tcpiphdr2qlink(ti)->prev = NULL;
- memset(&ti->ih_mbuf, 0, sizeof(struct mbuf_ptr));
- memset(&ti->ti, 0, sizeof(ti->ti));
- ti->ti_x0 = 0;
- ti->ti_src = save_ip.ip_src;
- ti->ti_dst = save_ip.ip_dst;
- ti->ti_pr = save_ip.ip_p;
- ti->ti_len = htons((uint16_t)tlen);
- len = ((sizeof(struct tcpiphdr) - sizeof(struct tcphdr)) + tlen);
- if (cksum(m, len)) {
- goto drop;
+ /*
+ * Checksum extended TCP header and data.
+ */
+ tlen = ip->ip_len;
+ tcpiphdr2qlink(ti)->next = tcpiphdr2qlink(ti)->prev = NULL;
+ memset(&ti->ih_mbuf, 0, sizeof(struct mbuf_ptr));
+ memset(&ti->ti, 0, sizeof(ti->ti));
+ ti->ti_x0 = 0;
+ ti->ti_src = save_ip.ip_src;
+ ti->ti_dst = save_ip.ip_dst;
+ ti->ti_pr = save_ip.ip_p;
+ ti->ti_len = htons((uint16_t)tlen);
+ len = ((sizeof(struct tcpiphdr) - sizeof(struct tcphdr)) + tlen);
+ if (cksum(m, len)) {
+ goto drop;
+ }
+ break;
+
+ default:
+ g_assert_not_reached();
}
/*
@@ -332,14 +340,20 @@ void tcp_input(struct mbuf *m, int iphlen, struct socket *inso)
* Locate pcb for segment.
*/
findso:
- lhost.ss_family = AF_INET;
- lhost4 = (struct sockaddr_in *)&lhost;
- lhost4->sin_addr = ti->ti_src;
- lhost4->sin_port = ti->ti_sport;
- fhost.ss_family = AF_INET;
- fhost4 = (struct sockaddr_in *)&fhost;
- fhost4->sin_addr = ti->ti_dst;
- fhost4->sin_port = ti->ti_dport;
+ lhost.ss_family = af;
+ fhost.ss_family = af;
+ switch (af) {
+ case AF_INET:
+ lhost4 = (struct sockaddr_in *)&lhost;
+ lhost4->sin_addr = ti->ti_src;
+ lhost4->sin_port = ti->ti_sport;
+ fhost4 = (struct sockaddr_in *)&fhost;
+ fhost4->sin_addr = ti->ti_dst;
+ fhost4->sin_port = ti->ti_dport;
+ break;
+ default:
+ g_assert_not_reached();
+ }
so = solookup(&slirp->tcp_last_so, &slirp->tcb, &lhost, &fhost);
@@ -389,8 +403,16 @@ findso:
so->lhost.ss = lhost;
so->fhost.ss = fhost;
- if ((so->so_iptos = tcp_tos(so)) == 0)
- so->so_iptos = ((struct ip *)ti)->ip_tos;
+ so->so_iptos = tcp_tos(so);
+ if (so->so_iptos == 0) {
+ switch (af) {
+ case AF_INET:
+ so->so_iptos = ((struct ip *)ti)->ip_tos;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ }
tp = sototcpcb(so);
tp->t_state = TCPS_LISTEN;
@@ -566,8 +588,9 @@ findso:
* If this is destined for the control address, then flag to
* tcp_ctl once connected, otherwise connect
*/
- if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
- slirp->vnetwork_addr.s_addr) {
+ if (af == AF_INET &&
+ (so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
+ slirp->vnetwork_addr.s_addr) {
if (so->so_faddr.s_addr != slirp->vhost_addr.s_addr &&
so->so_faddr.s_addr != slirp->vnameserver_addr.s_addr) {
/* May be an add exec */
@@ -593,16 +616,24 @@ findso:
if ((tcp_fconnect(so, so->so_ffamily) == -1) &&
(errno != EINPROGRESS) && (errno != EWOULDBLOCK)) {
- u_char code = ICMP_UNREACH_NET;
+ uint8_t code;
DEBUG_MISC(
(dfd, " tcp fconnect errno = %d-%s\n", errno, strerror(errno)));
if (errno == ECONNREFUSED) {
/* ACK the SYN, send RST to refuse the connection */
tcp_respond(tp, ti, m, ti->ti_seq + 1, (tcp_seq)0,
- TH_RST | TH_ACK);
+ TH_RST | TH_ACK, af);
} else {
- if (errno == EHOSTUNREACH)
- code = ICMP_UNREACH_HOST;
+ switch (af) {
+ case AF_INET:
+ code = ICMP_UNREACH_NET;
+ if (errno == EHOSTUNREACH) {
+ code = ICMP_UNREACH_HOST;
+ }
+ break;
+ default:
+ g_assert_not_reached();
+ }
HTONL(ti->ti_seq); /* restore tcp header */
HTONL(ti->ti_ack);
HTONS(ti->ti_win);
@@ -611,12 +642,18 @@ findso:
sizeof(struct tcpiphdr) + off - sizeof(struct tcphdr);
m->m_len +=
sizeof(struct tcpiphdr) + off - sizeof(struct tcphdr);
- m->m_data += sizeof(struct tcpiphdr) - sizeof(struct ip) -
- sizeof(struct tcphdr);
- m->m_len -= sizeof(struct tcpiphdr) - sizeof(struct ip) -
- sizeof(struct tcphdr);
- *ip = save_ip;
- icmp_send_error(m, ICMP_UNREACH, code, 0, strerror(errno));
+ switch (af) {
+ case AF_INET:
+ m->m_data += sizeof(struct tcpiphdr) - sizeof(struct ip) -
+ sizeof(struct tcphdr);
+ m->m_len -= sizeof(struct tcpiphdr) - sizeof(struct ip) -
+ sizeof(struct tcphdr);
+ *ip = save_ip;
+ icmp_send_error(m, ICMP_UNREACH, code, 0, strerror(errno));
+ break;
+ default:
+ g_assert_not_reached();
+ }
}
tcp_close(tp);
m_free(m);
@@ -1279,12 +1316,12 @@ dropafterack:
dropwithreset:
/* reuses m if m!=NULL, m_free() unnecessary */
if (tiflags & TH_ACK)
- tcp_respond(tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST);
+ tcp_respond(tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST, af);
else {
if (tiflags & TH_SYN)
ti->ti_len++;
tcp_respond(tp, ti, m, ti->ti_seq + ti->ti_len, (tcp_seq)0,
- TH_RST | TH_ACK);
+ TH_RST | TH_ACK, af);
}
return;
@@ -1470,7 +1507,14 @@ int tcp_mss(struct tcpcb *tp, u_int offer)
DEBUG_ARG("tp = %p", tp);
DEBUG_ARG("offer = %d", offer);
- mss = min(IF_MTU, IF_MRU) - sizeof(struct tcphdr) + sizeof(struct ip);
+ switch (so->so_ffamily) {
+ case AF_INET:
+ mss = min(IF_MTU, IF_MRU) - sizeof(struct tcphdr) + sizeof(struct ip);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
if (offer)
mss = min(mss, offer);
mss = max(mss, 32);
diff --git a/tcp_output.c b/tcp_output.c
index 808df35..fa80496 100644
--- a/tcp_output.c
+++ b/tcp_output.c
@@ -60,7 +60,8 @@ int tcp_output(struct tcpcb *tp)
register long len, win;
int off, flags, error;
register struct mbuf *m;
- register struct tcpiphdr *ti;
+ register struct tcpiphdr *ti, tcpiph_save;
+ struct ip *ip;
u_char opt[MAX_TCPOPTLEN];
unsigned optlen, hdrlen;
int idle, sendalot;
@@ -443,23 +444,30 @@ send:
* the template, but need a way to checksum without them.
*/
m->m_len = hdrlen + len; /* XXX Needed? m_len should be correct */
+ tcpiph_save = *mtod(m, struct tcpiphdr *);
- struct tcpiphdr tcpiph_save = *(mtod(m, struct tcpiphdr *));
- m->m_data +=
- sizeof(struct tcpiphdr) - sizeof(struct tcphdr) - sizeof(struct ip);
- m->m_len -=
- sizeof(struct tcpiphdr) - sizeof(struct tcphdr) - sizeof(struct ip);
- struct ip *ip = mtod(m, struct ip *);
+ switch (so->so_ffamily) {
+ case AF_INET:
+ m->m_data +=
+ sizeof(struct tcpiphdr) - sizeof(struct tcphdr) - sizeof(struct ip);
+ m->m_len -=
+ sizeof(struct tcpiphdr) - sizeof(struct tcphdr) - sizeof(struct ip);
+ ip = mtod(m, struct ip *);
- ip->ip_len = m->m_len;
- ip->ip_dst = tcpiph_save.ti_dst;
- ip->ip_src = tcpiph_save.ti_src;
- ip->ip_p = tcpiph_save.ti_pr;
+ ip->ip_len = m->m_len;
+ ip->ip_dst = tcpiph_save.ti_dst;
+ ip->ip_src = tcpiph_save.ti_src;
+ ip->ip_p = tcpiph_save.ti_pr;
- ip->ip_ttl = IPDEFTTL;
- ip->ip_tos = so->so_iptos;
+ ip->ip_ttl = IPDEFTTL;
+ ip->ip_tos = so->so_iptos;
- error = ip_output(so, m);
+ error = ip_output(so, m);
+ break;
+
+ default:
+ g_assert_not_reached();
+ }
if (error) {
out:
diff --git a/tcp_subr.c b/tcp_subr.c
index 8a4a6e7..0dae1da 100644
--- a/tcp_subr.c
+++ b/tcp_subr.c
@@ -76,12 +76,19 @@ void tcp_template(struct tcpcb *tp)
n->ti_mbuf = NULL;
memset(&n->ti, 0, sizeof(n->ti));
n->ti_x0 = 0;
- n->ti_pr = IPPROTO_TCP;
- n->ti_len = htons(sizeof(struct tcphdr));
- n->ti_src = so->so_faddr;
- n->ti_dst = so->so_laddr;
- n->ti_sport = so->so_fport;
- n->ti_dport = so->so_lport;
+ switch (so->so_ffamily) {
+ case AF_INET:
+ n->ti_pr = IPPROTO_TCP;
+ n->ti_len = htons(sizeof(struct tcphdr));
+ n->ti_src = so->so_faddr;
+ n->ti_dst = so->so_laddr;
+ n->ti_sport = so->so_fport;
+ n->ti_dport = so->so_lport;
+ break;
+
+ default:
+ g_assert_not_reached();
+ }
n->ti_seq = 0;
n->ti_ack = 0;
@@ -107,7 +114,7 @@ void tcp_template(struct tcpcb *tp)
* segment are as specified by the parameters.
*/
void tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m,
- tcp_seq ack, tcp_seq seq, int flags)
+ tcp_seq ack, tcp_seq seq, int flags, unsigned short af)
{
register int tlen;
int win = 0;
@@ -147,8 +154,14 @@ void tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m,
a = b; \
b = t; \
}
- xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, uint32_t);
- xchg(ti->ti_dport, ti->ti_sport, uint16_t);
+ switch (af) {
+ case AF_INET:
+ xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, uint32_t);
+ xchg(ti->ti_dport, ti->ti_sport, uint16_t);
+ break;
+ default:
+ g_assert_not_reached();
+ }
#undef xchg
}
ti->ti_len = htons((u_short)(sizeof(struct tcphdr) + tlen));
@@ -171,23 +184,32 @@ void tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m,
ti->ti_sum = cksum(m, tlen);
struct tcpiphdr tcpiph_save = *(mtod(m, struct tcpiphdr *));
- m->m_data +=
- sizeof(struct tcpiphdr) - sizeof(struct tcphdr) - sizeof(struct ip);
- m->m_len -=
- sizeof(struct tcpiphdr) - sizeof(struct tcphdr) - sizeof(struct ip);
- struct ip *ip = mtod(m, struct ip *);
- ip->ip_len = tlen;
- ip->ip_dst = tcpiph_save.ti_dst;
- ip->ip_src = tcpiph_save.ti_src;
- ip->ip_p = tcpiph_save.ti_pr;
-
- if (flags & TH_RST) {
- ip->ip_ttl = MAXTTL;
- } else {
- ip->ip_ttl = IPDEFTTL;
- }
+ struct ip *ip;
+
+ switch (af) {
+ case AF_INET:
+ m->m_data +=
+ sizeof(struct tcpiphdr) - sizeof(struct tcphdr) - sizeof(struct ip);
+ m->m_len -=
+ sizeof(struct tcpiphdr) - sizeof(struct tcphdr) - sizeof(struct ip);
+ ip = mtod(m, struct ip *);
+ ip->ip_len = tlen;
+ ip->ip_dst = tcpiph_save.ti_dst;
+ ip->ip_src = tcpiph_save.ti_src;
+ ip->ip_p = tcpiph_save.ti_pr;
+
+ if (flags & TH_RST) {
+ ip->ip_ttl = MAXTTL;
+ } else {
+ ip->ip_ttl = IPDEFTTL;
+ }
+
+ (void)ip_output((struct socket *)0, m);
+ break;
- (void)ip_output((struct socket *)0, m);
+ default:
+ g_assert_not_reached();
+ }
}
/*
@@ -386,8 +408,8 @@ void tcp_connect(struct socket *inso)
{
Slirp *slirp = inso->slirp;
struct socket *so;
- struct sockaddr_in addr;
- socklen_t addrlen = sizeof(struct sockaddr_in);
+ struct sockaddr_storage addr;
+ socklen_t addrlen = sizeof(struct sockaddr_storage);
struct tcpcb *tp;
int s, opt;
@@ -412,9 +434,8 @@ void tcp_connect(struct socket *inso)
free(so); /* NOT sofree */
return;
}
- so->so_lfamily = AF_INET;
- so->so_laddr = inso->so_laddr;
- so->so_lport = inso->so_lport;
+ so->lhost = inso->lhost;
+ so->so_ffamily = inso->so_ffamily;
}
tcp_mss(sototcpcb(so), 0);
@@ -430,7 +451,7 @@ void tcp_connect(struct socket *inso)
qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
socket_set_nodelay(s);
- so->fhost.sin = addr;
+ so->fhost.ss = addr;
sotranslate_accept(so);
/* Close the accept() socket, set right state */
diff --git a/tcp_timer.c b/tcp_timer.c
index 13db569..a264d9e 100644
--- a/tcp_timer.c
+++ b/tcp_timer.c
@@ -271,7 +271,7 @@ static struct tcpcb *tcp_timers(register struct tcpcb *tp, int timer)
* correspondent TCP to respond.
*/
tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL, tp->rcv_nxt,
- tp->snd_una - 1, 0);
+ tp->snd_una - 1, 0, tp->t_socket->so_ffamily);
tp->t_timer[TCPT_KEEP] = TCPTV_KEEPINTVL;
} else
tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_IDLE;