From: Samuel Thibault <samuel.thibault@gnu.org>
To: Thomas Huth <thuth@redhat.com>
Cc: jan.kiszka@siemens.com, jasowang@redhat.com, qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH v2] slirp: Add IPv6 support to the TFTP code
Date: Wed, 17 Feb 2016 09:42:25 +0100 [thread overview]
Message-ID: <20160217084225.GO2656@var.home> (raw)
In-Reply-To: <1455698410-13191-1-git-send-email-thuth@redhat.com>
Thomas Huth, on Wed 17 Feb 2016 09:40:10 +0100, wrote:
> Add the handler code for incoming TFTP packets to udp6_input(),
> and make sure that the TFTP code can send packets with both,
> udp_output() and udp6_output() by introducing a wrapper function
> called tftp_udp_output().
>
> Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
> ---
> v2: Changes according to the review of Samuel Thibault:
> - Use the "slirp" parameter as the first parameter
> - Use structure assignments instead of memcpy()
>
> This patch has to be applied on top of Samuel's "slirp: Adding IPv6
> support to Qemu -net user mode" patch series.
> Samuel, if you respin your patch series and if you think this patch
> is ok, feel free to also include it in your series.
>
> Code has been tested with network booting in SLOF:
>
> qemu-system-ppc64 -vga none -device virtio-net,netdev=mynet \
> -netdev user,id=mynet,tftp=/home/thuth/tmp/tftp -nographic
>
> ... and then, at the Open Firmware prompt, type:
>
> boot net:ipv6,fec0::2,zImage,fec0::1234
> ---
> slirp/tftp.c | 133 +++++++++++++++++++++++++++++++++--------------------------
> slirp/tftp.h | 7 ++--
> slirp/udp.c | 16 ++++---
> slirp/udp6.c | 16 +++++--
> 4 files changed, 100 insertions(+), 72 deletions(-)
>
> diff --git a/slirp/tftp.c b/slirp/tftp.c
> index abb0106..7d70504 100644
> --- a/slirp/tftp.c
> +++ b/slirp/tftp.c
> @@ -46,7 +46,8 @@ static void tftp_session_terminate(struct tftp_session *spt)
> spt->slirp = NULL;
> }
>
> -static int tftp_session_allocate(Slirp *slirp, struct tftp_t *tp)
> +static int tftp_session_allocate(Slirp *slirp, struct sockaddr_storage *srcsas,
> + struct tftp_t *tp)
> {
> struct tftp_session *spt;
> int k;
> @@ -68,7 +69,7 @@ static int tftp_session_allocate(Slirp *slirp, struct tftp_t *tp)
>
> found:
> memset(spt, 0, sizeof(*spt));
> - memcpy(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip));
> + spt->client_addr = *srcsas;
> spt->fd = -1;
> spt->client_port = tp->udp.uh_sport;
> spt->slirp = slirp;
> @@ -78,7 +79,8 @@ static int tftp_session_allocate(Slirp *slirp, struct tftp_t *tp)
> return k;
> }
>
> -static int tftp_session_find(Slirp *slirp, struct tftp_t *tp)
> +static int tftp_session_find(Slirp *slirp, struct sockaddr_storage *srcsas,
> + struct tftp_t *tp)
> {
> struct tftp_session *spt;
> int k;
> @@ -87,7 +89,7 @@ static int tftp_session_find(Slirp *slirp, struct tftp_t *tp)
> spt = &slirp->tftp_sessions[k];
>
> if (tftp_session_in_use(spt)) {
> - if (!memcmp(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip))) {
> + if (sockaddr_equal(&spt->client_addr, srcsas)) {
> if (spt->client_port == tp->udp.uh_sport) {
> return k;
> }
> @@ -120,11 +122,53 @@ static int tftp_read_data(struct tftp_session *spt, uint32_t block_nr,
> return bytes_read;
> }
>
> +static struct tftp_t *tftp_prep_mbuf_data(struct tftp_session *spt,
> + struct mbuf *m)
> +{
> + struct tftp_t *tp;
> +
> + memset(m->m_data, 0, m->m_size);
> +
> + m->m_data += IF_MAXLINKHDR;
> + if (spt->client_addr.ss_family == AF_INET6) {
> + m->m_data += sizeof(struct ip6);
> + } else {
> + m->m_data += sizeof(struct ip);
> + }
> + tp = (void *)m->m_data;
> + m->m_data += sizeof(struct udphdr);
> +
> + return tp;
> +}
> +
> +static void tftp_udp_output(struct tftp_session *spt, struct mbuf *m,
> + struct tftp_t *recv_tp)
> +{
> + if (spt->client_addr.ss_family == AF_INET6) {
> + struct sockaddr_in6 sa6, da6;
> +
> + sa6.sin6_addr = spt->slirp->vhost_addr6;
> + sa6.sin6_port = recv_tp->udp.uh_dport;
> + da6.sin6_addr = ((struct sockaddr_in6 *)&spt->client_addr)->sin6_addr;
> + da6.sin6_port = spt->client_port;
> +
> + udp6_output(NULL, m, &sa6, &da6);
> + } else {
> + struct sockaddr_in sa4, da4;
> +
> + sa4.sin_addr = spt->slirp->vhost_addr;
> + sa4.sin_port = recv_tp->udp.uh_dport;
> + da4.sin_addr = ((struct sockaddr_in *)&spt->client_addr)->sin_addr;
> + da4.sin_port = spt->client_port;
> +
> + udp_output(NULL, m, &sa4, &da4, IPTOS_LOWDELAY);
> + }
> +}
> +
> static int tftp_send_oack(struct tftp_session *spt,
> const char *keys[], uint32_t values[], int nb,
> struct tftp_t *recv_tp)
> {
> - struct sockaddr_in saddr, daddr;
> struct mbuf *m;
> struct tftp_t *tp;
> int i, n = 0;
> @@ -132,13 +176,9 @@ static int tftp_send_oack(struct tftp_session *spt,
> m = m_get(spt->slirp);
>
> if (!m)
> - return -1;
> -
> - memset(m->m_data, 0, m->m_size);
> + return -1;
>
> - m->m_data += IF_MAXLINKHDR;
> - tp = (void *)m->m_data;
> - m->m_data += sizeof(struct udpiphdr);
> + tp = tftp_prep_mbuf_data(spt, m);
>
> tp->tp_op = htons(TFTP_OACK);
> for (i = 0; i < nb; i++) {
> @@ -148,15 +188,8 @@ static int tftp_send_oack(struct tftp_session *spt,
> values[i]) + 1;
> }
>
> - saddr.sin_addr = recv_tp->ip.ip_dst;
> - saddr.sin_port = recv_tp->udp.uh_dport;
> -
> - daddr.sin_addr = spt->client_ip;
> - daddr.sin_port = spt->client_port;
> -
> - m->m_len = sizeof(struct tftp_t) - 514 + n -
> - sizeof(struct ip) - sizeof(struct udphdr);
> - udp_output(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
> + m->m_len = sizeof(struct tftp_t) - 514 + n - sizeof(struct udphdr);
> + tftp_udp_output(spt, m, recv_tp);
>
> return 0;
> }
> @@ -165,7 +198,6 @@ static void tftp_send_error(struct tftp_session *spt,
> uint16_t errorcode, const char *msg,
> struct tftp_t *recv_tp)
> {
> - struct sockaddr_in saddr, daddr;
> struct mbuf *m;
> struct tftp_t *tp;
>
> @@ -177,24 +209,15 @@ static void tftp_send_error(struct tftp_session *spt,
>
> memset(m->m_data, 0, m->m_size);
>
> - m->m_data += IF_MAXLINKHDR;
> - tp = (void *)m->m_data;
> - m->m_data += sizeof(struct udpiphdr);
> + tp = tftp_prep_mbuf_data(spt, m);
>
> tp->tp_op = htons(TFTP_ERROR);
> tp->x.tp_error.tp_error_code = htons(errorcode);
> pstrcpy((char *)tp->x.tp_error.tp_msg, sizeof(tp->x.tp_error.tp_msg), msg);
>
> - saddr.sin_addr = recv_tp->ip.ip_dst;
> - saddr.sin_port = recv_tp->udp.uh_dport;
> -
> - daddr.sin_addr = spt->client_ip;
> - daddr.sin_port = spt->client_port;
> -
> - m->m_len = sizeof(struct tftp_t) - 514 + 3 + strlen(msg) -
> - sizeof(struct ip) - sizeof(struct udphdr);
> -
> - udp_output(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
> + m->m_len = sizeof(struct tftp_t) - 514 + 3 + strlen(msg)
> + - sizeof(struct udphdr);
> + tftp_udp_output(spt, m, recv_tp);
>
> out:
> tftp_session_terminate(spt);
> @@ -203,7 +226,6 @@ out:
> static void tftp_send_next_block(struct tftp_session *spt,
> struct tftp_t *recv_tp)
> {
> - struct sockaddr_in saddr, daddr;
> struct mbuf *m;
> struct tftp_t *tp;
> int nobytes;
> @@ -216,19 +238,11 @@ static void tftp_send_next_block(struct tftp_session *spt,
>
> memset(m->m_data, 0, m->m_size);
>
> - m->m_data += IF_MAXLINKHDR;
> - tp = (void *)m->m_data;
> - m->m_data += sizeof(struct udpiphdr);
> + tp = tftp_prep_mbuf_data(spt, m);
>
> tp->tp_op = htons(TFTP_DATA);
> tp->x.tp_data.tp_block_nr = htons((spt->block_nr + 1) & 0xffff);
>
> - saddr.sin_addr = recv_tp->ip.ip_dst;
> - saddr.sin_port = recv_tp->udp.uh_dport;
> -
> - daddr.sin_addr = spt->client_ip;
> - daddr.sin_port = spt->client_port;
> -
> nobytes = tftp_read_data(spt, spt->block_nr, tp->x.tp_data.tp_buf, 512);
>
> if (nobytes < 0) {
> @@ -241,10 +255,8 @@ static void tftp_send_next_block(struct tftp_session *spt,
> return;
> }
>
> - m->m_len = sizeof(struct tftp_t) - (512 - nobytes) -
> - sizeof(struct ip) - sizeof(struct udphdr);
> -
> - udp_output(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
> + m->m_len = sizeof(struct tftp_t) - (512 - nobytes) - sizeof(struct udphdr);
> + tftp_udp_output(spt, m, recv_tp);
>
> if (nobytes == 512) {
> tftp_session_update(spt);
> @@ -256,7 +268,8 @@ static void tftp_send_next_block(struct tftp_session *spt,
> spt->block_nr++;
> }
>
> -static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen)
> +static void tftp_handle_rrq(Slirp *slirp, struct sockaddr_storage *srcsas,
> + struct tftp_t *tp, int pktlen)
> {
> struct tftp_session *spt;
> int s, k;
> @@ -267,12 +280,12 @@ static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen)
> int nb_options = 0;
>
> /* check if a session already exists and if so terminate it */
> - s = tftp_session_find(slirp, tp);
> + s = tftp_session_find(slirp, srcsas, tp);
> if (s >= 0) {
> tftp_session_terminate(&slirp->tftp_sessions[s]);
> }
>
> - s = tftp_session_allocate(slirp, tp);
> + s = tftp_session_allocate(slirp, srcsas, tp);
>
> if (s < 0) {
> return;
> @@ -397,11 +410,12 @@ static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen)
> tftp_send_next_block(spt, tp);
> }
>
> -static void tftp_handle_ack(Slirp *slirp, struct tftp_t *tp, int pktlen)
> +static void tftp_handle_ack(Slirp *slirp, struct sockaddr_storage *srcsas,
> + struct tftp_t *tp, int pktlen)
> {
> int s;
>
> - s = tftp_session_find(slirp, tp);
> + s = tftp_session_find(slirp, srcsas, tp);
>
> if (s < 0) {
> return;
> @@ -410,11 +424,12 @@ static void tftp_handle_ack(Slirp *slirp, struct tftp_t *tp, int pktlen)
> tftp_send_next_block(&slirp->tftp_sessions[s], tp);
> }
>
> -static void tftp_handle_error(Slirp *slirp, struct tftp_t *tp, int pktlen)
> +static void tftp_handle_error(Slirp *slirp, struct sockaddr_storage *srcsas,
> + struct tftp_t *tp, int pktlen)
> {
> int s;
>
> - s = tftp_session_find(slirp, tp);
> + s = tftp_session_find(slirp, srcsas, tp);
>
> if (s < 0) {
> return;
> @@ -423,21 +438,21 @@ static void tftp_handle_error(Slirp *slirp, struct tftp_t *tp, int pktlen)
> tftp_session_terminate(&slirp->tftp_sessions[s]);
> }
>
> -void tftp_input(struct mbuf *m)
> +void tftp_input(struct sockaddr_storage *srcsas, struct mbuf *m)
> {
> struct tftp_t *tp = (struct tftp_t *)m->m_data;
>
> switch(ntohs(tp->tp_op)) {
> case TFTP_RRQ:
> - tftp_handle_rrq(m->slirp, tp, m->m_len);
> + tftp_handle_rrq(m->slirp, srcsas, tp, m->m_len);
> break;
>
> case TFTP_ACK:
> - tftp_handle_ack(m->slirp, tp, m->m_len);
> + tftp_handle_ack(m->slirp, srcsas, tp, m->m_len);
> break;
>
> case TFTP_ERROR:
> - tftp_handle_error(m->slirp, tp, m->m_len);
> + tftp_handle_error(m->slirp, srcsas, tp, m->m_len);
> break;
> }
> }
> diff --git a/slirp/tftp.h b/slirp/tftp.h
> index e1cc24b..1cb1adf 100644
> --- a/slirp/tftp.h
> +++ b/slirp/tftp.h
> @@ -16,7 +16,6 @@
> #define TFTP_FILENAME_MAX 512
>
> struct tftp_t {
> - struct ip ip;
> struct udphdr udp;
> uint16_t tp_op;
> union {
> @@ -30,20 +29,20 @@ struct tftp_t {
> } tp_error;
> char tp_buf[512 + 2];
> } x;
> -};
> +} __attribute__((packed));
>
> struct tftp_session {
> Slirp *slirp;
> char *filename;
> int fd;
>
> - struct in_addr client_ip;
> + struct sockaddr_storage client_addr;
> uint16_t client_port;
> uint32_t block_nr;
>
> int timestamp;
> };
>
> -void tftp_input(struct mbuf *m);
> +void tftp_input(struct sockaddr_storage *srcsas, struct mbuf *m);
>
> #endif
> diff --git a/slirp/udp.c b/slirp/udp.c
> index be012fb..247024f 100644
> --- a/slirp/udp.c
> +++ b/slirp/udp.c
> @@ -128,6 +128,11 @@ udp_input(register struct mbuf *m, int iphlen)
> }
> }
>
> + lhost.ss_family = AF_INET;
> + lhost4 = (struct sockaddr_in *) &lhost;
> + lhost4->sin_addr = ip->ip_src;
> + lhost4->sin_port = uh->uh_sport;
> +
> /*
> * handle DHCP/BOOTP
> */
> @@ -143,7 +148,11 @@ udp_input(register struct mbuf *m, int iphlen)
> */
> if (ntohs(uh->uh_dport) == TFTP_SERVER &&
> ip->ip_dst.s_addr == slirp->vhost_addr.s_addr) {
> - tftp_input(m);
> + m->m_data += iphlen;
> + m->m_len -= iphlen;
> + tftp_input(&lhost, m);
> + m->m_data -= iphlen;
> + m->m_len += iphlen;
> goto bad;
> }
>
> @@ -154,11 +163,6 @@ udp_input(register struct mbuf *m, int iphlen)
> /*
> * Locate pcb for datagram.
> */
> - lhost.ss_family = AF_INET;
> - lhost4 = (struct sockaddr_in *) &lhost;
> - lhost4->sin_addr = ip->ip_src;
> - lhost4->sin_port = uh->uh_sport;
> -
> so = solookup(&slirp->udp_last_so, &slirp->udb, &lhost, NULL);
>
> if (so == NULL) {
> diff --git a/slirp/udp6.c b/slirp/udp6.c
> index 6c0d55f..820192a 100644
> --- a/slirp/udp6.c
> +++ b/slirp/udp6.c
> @@ -55,14 +55,24 @@ void udp6_input(struct mbuf *m)
> */
> save_ip = *ip;
>
> - /* TODO handle DHCP/BOOTP */
> - /* TODO handle TFTP */
> -
> /* Locate pcb for datagram. */
> lhost.sin6_family = AF_INET6;
> lhost.sin6_addr = ip->ip_src;
> lhost.sin6_port = uh->uh_sport;
>
> + /* TODO handle DHCP/BOOTP */
> +
> + /* handle TFTP */
> + if (ntohs(uh->uh_dport) == TFTP_SERVER &&
> + !memcmp(ip->ip_dst.s6_addr, slirp->vhost_addr6.s6_addr, 16)) {
> + m->m_data += hlen;
> + m->m_len -= hlen;
> + tftp_input((struct sockaddr_storage *)&lhost, m);
> + m->m_data -= hlen;
> + m->m_len += hlen;
> + goto bad;
> + }
> +
> so = solookup(&slirp->udp_last_so, &slirp->udb,
> (struct sockaddr_storage *) &lhost, NULL);
>
> --
> 1.8.3.1
>
--
Samuel
In mutt, type cthis
Dans mutt, taper cceci
prev parent reply other threads:[~2016-02-17 8:42 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-02-14 17:47 [Qemu-devel] [PATCHv8 0/9] slirp: Adding IPv6 support to Qemu -net user mode Samuel Thibault
2016-02-14 17:47 ` [Qemu-devel] [PATCHv7 1/9] slirp: Adding IPv6, ICMPv6 Echo and NDP autoconfiguration Samuel Thibault
2016-02-16 11:36 ` Thomas Huth
2016-02-19 13:57 ` Thomas Huth
2016-02-14 17:47 ` [Qemu-devel] [PATCHv7 2/9] slirp: Adding ICMPv6 error sending Samuel Thibault
2016-02-16 12:21 ` Thomas Huth
2016-02-14 17:47 ` [Qemu-devel] [PATCHv7 3/9] slirp: Adding IPv6 UDP support Samuel Thibault
2016-02-16 12:28 ` Thomas Huth
2016-02-14 17:47 ` [Qemu-devel] [PATCHv7 4/9] slirp: Factorizing tcpiphdr structure with an union Samuel Thibault
2016-02-19 0:36 ` Samuel Thibault
2016-02-19 13:44 ` Thomas Huth
2016-02-22 1:48 ` Samuel Thibault
2016-02-22 7:56 ` Thomas Huth
2016-02-22 10:20 ` Samuel Thibault
2016-02-14 17:47 ` [Qemu-devel] [PATCHv7 5/9] slirp: Generalizing and neutralizing various TCP functions before adding IPv6 stuff Samuel Thibault
2016-02-17 8:25 ` Thomas Huth
2016-02-14 17:47 ` [Qemu-devel] [PATCHv7 6/9] slirp: Reindent after refactoring Samuel Thibault
2016-02-17 9:03 ` Thomas Huth
2016-02-14 17:47 ` [Qemu-devel] [PATCHv7 7/9] slirp: Handle IPv6 in TCP functions Samuel Thibault
2016-02-17 9:18 ` Thomas Huth
2016-02-17 9:30 ` Samuel Thibault
2016-02-14 17:47 ` [Qemu-devel] [PATCHv7 8/9] slirp: Adding IPv6 address for DNS relay Samuel Thibault
2016-02-17 9:28 ` Thomas Huth
2016-02-17 9:36 ` Samuel Thibault
2016-02-19 0:26 ` Samuel Thibault
2016-02-14 17:47 ` [Qemu-devel] [PATCHv7 9/9] qapi-schema, qemu-options & slirp: Adding Qemu options for IPv6 addresses Samuel Thibault
2016-02-17 11:59 ` Thomas Huth
2016-02-19 0:35 ` Samuel Thibault
2016-02-16 8:47 ` [Qemu-devel] [PATCH] slirp: Add IPv6 support to the TFTP code Thomas Huth
2016-02-16 10:30 ` Samuel Thibault
2016-02-16 12:09 ` Thomas Huth
2016-02-17 8:40 ` [Qemu-devel] [PATCH v2] " Thomas Huth
2016-02-17 8:42 ` Samuel Thibault [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20160217084225.GO2656@var.home \
--to=samuel.thibault@gnu.org \
--cc=jan.kiszka@siemens.com \
--cc=jasowang@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=thuth@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).