static int tftp_session_allocate(Slirp *slirp, struct tftp_t *tp) { struct tftp_session *spt; int k; for (k = 0; k < TFTP_SESSIONS_MAX; k++) { spt = &slirp->tftp_sessions[k]; if (!tftp_session_in_use(spt)) goto found; /* sessions time out after 5 inactive seconds */ if ((int)(curtime - spt->timestamp) > 5000) { qemu_free(spt->filename); goto found; } } return -1; found: memset(spt, 0, sizeof(*spt)); memcpy(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip)); spt->client_port = tp->udp.uh_sport; spt->slirp = slirp; tftp_session_update(spt); return k; }
static int tftp_send_data(struct tftp_session *spt, u_int16_t block_nr, struct tftp_t *recv_tp) { struct sockaddr_in saddr, daddr; struct mbuf *m; struct tftp_t *tp; int nobytes; if (block_nr < 1) { return -1; } m = m_get(spt->slirp); if (!m) { return -1; } 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->tp_op = htons(TFTP_DATA); tp->x.tp_data.tp_block_nr = htons(block_nr); 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, block_nr - 1, tp->x.tp_data.tp_buf, 512); if (nobytes < 0) { m_free(m); /* send "file not found" error back */ tftp_send_error(spt, 1, "File not found", tp); return -1; } m->m_len = sizeof(struct tftp_t) - (512 - nobytes) - sizeof(struct ip) - sizeof(struct udphdr); udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); if (nobytes == 512) { tftp_session_update(spt); } else { tftp_session_terminate(spt); } return 0; }
static int tftp_session_allocate(Slirp *slirp, struct sockaddr_storage *srcsas, struct tftp_t *tp) { struct tftp_session *spt; int k; for (k = 0; k < TFTP_SESSIONS_MAX; k++) { spt = &slirp->tftp_sessions[k]; if (!tftp_session_in_use(spt)) goto found; /* sessions time out after 5 inactive seconds */ if ((int)(curtime - spt->timestamp) > 5000) { tftp_session_terminate(spt); goto found; } } return -1; found: memset(spt, 0, sizeof(*spt)); spt->client_addr = *srcsas; spt->fd = -1; spt->client_port = tp->udp.uh_sport; spt->slirp = slirp; tftp_session_update(spt); return k; }
static int tftp_session_allocate(PNATState pData, struct tftp_t *tp) { struct tftp_session *spt; int k; for (k = 0; k < TFTP_SESSIONS_MAX; k++) { spt = &tftp_sessions[k]; if (!spt->in_use) goto found; /* sessions time out after 5 inactive seconds */ if ((int)(curtime - spt->timestamp) > 5000) goto found; } return -1; found: memset(spt, 0, sizeof(*spt)); memcpy(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip)); spt->client_port = tp->udp.uh_sport; tftp_session_update(pData, spt); return k; }
static int tftp_send_data(PNATState pData, struct tftp_session *spt, u_int16_t block_nr, struct tftp_t *recv_tp) { struct sockaddr_in saddr, daddr; struct mbuf *m; struct tftp_t *tp; int nobytes; if (block_nr < 1) return -1; m = slirpTftpMbufAlloc(pData); if (!m) return -1; m->m_data += if_maxlinkhdr; m->m_pkthdr.header = mtod(m, void *); tp = mtod(m, void *); m->m_data += sizeof(struct udpiphdr); tp->tp_op = RT_H2N_U16_C(TFTP_DATA); tp->x.tp_data.tp_block_nr = RT_H2N_U16(block_nr); 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(pData, spt, block_nr - 1, tp->x.tp_data.tp_buf, 512); if (nobytes < 0) { m_freem(pData, m); /* send "file not found" error back */ tftp_send_error(pData, spt, 1, "File not found", tp); return -1; } m->m_len = sizeof(struct tftp_t) - (512 - nobytes) - sizeof(struct ip) - sizeof(struct udphdr); udp_output2(pData, NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); if (nobytes == 512) tftp_session_update(pData, spt); else tftp_session_terminate(spt); return 0; }
static void tftp_send_next_block(struct tftp_session *spt, struct tftp_t *recv_tp) { struct mbuf *m; struct tftp_t *tp; int nobytes; m = m_get(spt->slirp); if (!m) { return; } 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); nobytes = tftp_read_data(spt, spt->block_nr, tp->x.tp_data.tp_buf, spt->block_size); if (nobytes < 0) { m_free(m); /* send "file not found" error back */ tftp_send_error(spt, 1, "File not found", tp); return; } m->m_len = sizeof(struct tftp_t) - (TFTP_BLOCKSIZE_MAX - nobytes) - sizeof(struct udphdr); tftp_udp_output(spt, m, recv_tp); if (nobytes == spt->block_size) { tftp_session_update(spt); } else { tftp_session_terminate(spt); } spt->block_nr++; }