static int tftp_send_oack(struct tftp_session *spt, const char *keys[], uint32_t values[], int nb, struct tftp_t *recv_tp) { struct mbuf *m; struct tftp_t *tp; int i, n = 0; m = m_get(spt->slirp); if (!m) return -1; tp = tftp_prep_mbuf_data(spt, m); tp->tp_op = htons(TFTP_OACK); for (i = 0; i < nb; i++) { n += snprintf(tp->x.tp_buf + n, sizeof(tp->x.tp_buf) - n, "%s", keys[i]) + 1; n += snprintf(tp->x.tp_buf + n, sizeof(tp->x.tp_buf) - n, "%u", values[i]) + 1; } m->m_len = sizeof(struct tftp_t) - 514 + n - sizeof(struct udphdr); tftp_udp_output(spt, m, recv_tp); return 0; }
static void tftp_send_error(struct tftp_session *spt, uint16_t errorcode, const char *msg, struct tftp_t *recv_tp) { struct mbuf *m; struct tftp_t *tp; m = m_get(spt->slirp); if (!m) { goto out; } 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); 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); }
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++; }