Esempio n. 1
0
File: tftp.c Progetto: ryenus/vbox
DECLINLINE(int) tftpSendError(PNATState pData,
                              PTFTPSESSION pTftpSession,
                              uint16_t errorcode,
                              const char *msg,
                              PCTFTPIPHDR pcTftpIpHeaderRecv)
{
    struct mbuf *m = NULL;
    PTFTPIPHDR pTftpIpHeader = NULL;

    LogFlowFunc(("ENTER: errorcode: %RX16, msg: %s\n", errorcode, msg));
    m = slirpTftpMbufAlloc(pData);
    if (!m)
    {
        LogFlowFunc(("LEAVE: Can't allocate mbuf\n"));
        return -1;
    }

    m->m_data += if_maxlinkhdr;
    m->m_len = sizeof(TFTPIPHDR)
             + strlen(msg) + 1; /* ending zero */
    m->m_pkthdr.header = mtod(m, void *);
    pTftpIpHeader = mtod(m, PTFTPIPHDR);

    pTftpIpHeader->u16TftpOpType = RT_H2N_U16_C(TFTP_ERROR);
    pTftpIpHeader->Core.u16TftpOpCode = RT_H2N_U16(errorcode);

    m_copyback(pData, m, sizeof(TFTPIPHDR), strlen(msg) + 1 /* copy ending zerro*/, (c_caddr_t)msg);

    tftpSend(pData, pTftpSession, m, pcTftpIpHeaderRecv);

    tftpSessionTerminate(pTftpSession);

    LogFlowFuncLeave();
    return 0;
}
Esempio n. 2
0
static int tftp_send_oack(PNATState pData,
                          struct tftp_session *spt,
                          const char *key, uint32_t value,
                          struct tftp_t *recv_tp)
{
    struct sockaddr_in saddr, daddr;
    struct mbuf *m;
    struct tftp_t *tp;
    int n = 0;

    m = slirpTftpMbufAlloc(pData);
    if (!m)
        return -1;

    m->m_data += if_maxlinkhdr;
    m->m_pkthdr.header = mtod(m, void *);
    tp = (void *)m->m_data;
    m->m_data += sizeof(struct udpiphdr);

    tp->tp_op = RT_H2N_U16_C(TFTP_OACK);
    n += RTStrPrintf((char *)tp->x.tp_buf + n, M_TRAILINGSPACE(m), "%s", key) + 1;
    n += RTStrPrintf((char *)tp->x.tp_buf + n, M_TRAILINGSPACE(m), "%u", value) + 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_output2(pData, NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);

    return 0;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
File: tftp.c Progetto: ryenus/vbox
static int tftpSendData(PNATState pData,
                          PTFTPSESSION pTftpSession,
                          uint16_t u16Block,
                          PCTFTPIPHDR pcTftpIpHeaderRecv)
{
    struct mbuf *m;
    PTFTPIPHDR pTftpIpHeader;
    int cbRead = 0;
    int rc = VINF_SUCCESS;

    if (u16Block == pTftpSession->cTftpAck)
        pTftpSession->cTftpAck++;
    else
    {
        tftpSendError(pData, pTftpSession, 6, "ACK is wrong", pcTftpIpHeaderRecv);
        tftpSessionTerminate(pTftpSession);
        return -1;
    }

    m = slirpTftpMbufAlloc(pData);
    if (!m)
        return -1;

    m->m_data += if_maxlinkhdr;
    m->m_pkthdr.header = mtod(m, void *);
    pTftpIpHeader = mtod(m, PTFTPIPHDR);
    m->m_len = sizeof(TFTPIPHDR);

    pTftpIpHeader->u16TftpOpType = RT_H2N_U16_C(TFTP_DATA);
    pTftpIpHeader->Core.u16TftpOpCode = RT_H2N_U16(pTftpSession->cTftpAck);

    rc = tftpReadDataBlock(pData, pTftpSession, (uint8_t *)&pTftpIpHeader->Core.u16TftpOpCode + sizeof(uint16_t), &cbRead);

    if (RT_SUCCESS(rc))
    {
        pTftpSession->cbTransfered += cbRead;
        m->m_len += cbRead;
        tftpSend(pData, pTftpSession, m, pcTftpIpHeaderRecv);
        if (cbRead > 0)
            tftpSessionUpdate(pData, pTftpSession);
        else
            tftpSessionTerminate(pTftpSession);
    }
    else
    {
        m_freem(pData, m);
        tftpSendError(pData, pTftpSession, 1, "File not found", pcTftpIpHeaderRecv);
        /* send "file not found" error back */
        return -1;
    }

    return 0;
}
Esempio n. 5
0
static int tftp_send_error(PNATState pData,
                           struct tftp_session *spt,
                           u_int16_t errorcode, const char *msg,
                           struct tftp_t *recv_tp)
{
    struct sockaddr_in saddr, daddr;
    struct mbuf *m;
    struct tftp_t *tp;
    int nobytes;

    m = slirpTftpMbufAlloc(pData);
    if (!m)
        return -1;

    m->m_data += if_maxlinkhdr;
    m->m_pkthdr.header = mtod(m, void *);
    tp = (void *)m->m_data;
    m->m_data += sizeof(struct udpiphdr);

    tp->tp_op = RT_H2N_U16_C(TFTP_ERROR);
    tp->x.tp_error.tp_error_code = RT_H2N_U16(errorcode);
    strcpy((char *)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;

    nobytes = 2;

    m->m_len = sizeof(struct tftp_t)
             - 514
             + 3
             + strlen(msg)
             - sizeof(struct ip)
             - sizeof(struct udphdr);

    udp_output2(pData, NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);

    tftp_session_terminate(spt);

    return 0;
}
Esempio n. 6
0
File: tftp.c Progetto: ryenus/vbox
DECLINLINE(int) tftpSendOACK(PNATState pData,
                          PTFTPSESSION pTftpSession,
                          PCTFTPIPHDR pcTftpIpHeaderRecv)
{
    struct mbuf *m;
    PTFTPIPHDR pTftpIpHeader;
    int rc = VINF_SUCCESS;

    rc = tftpSessionEvaluateOptions(pData, pTftpSession);
    if (RT_FAILURE(rc))
    {
        tftpSendError(pData, pTftpSession, 2, "Internal Error (blksize evaluation)", pcTftpIpHeaderRecv);
        LogFlowFuncLeave();
        return -1;
    }

    m = slirpTftpMbufAlloc(pData);
    if (!m)
        return -1;



    m->m_data += if_maxlinkhdr;
    m->m_pkthdr.header = mtod(m, void *);
    pTftpIpHeader = mtod(m, PTFTPIPHDR);
    m->m_len = sizeof(TFTPIPHDR) - sizeof(uint16_t); /* no u16TftpOpCode */

    pTftpIpHeader->u16TftpOpType = RT_H2N_U16_C(TFTP_OACK);

    if (pTftpSession->OptionBlkSize.fRequested)
    {
        if (pTftpSession->OptionBlkSize.u64Value > UINT16_MAX)
            rc = VERR_INVALID_PARAMETER;
        else
            rc = tftpAddOptionToOACK(pData, m, "blksize", pTftpSession->OptionBlkSize.u64Value);
    }
    if (   RT_SUCCESS(rc)
        && pTftpSession->OptionTSize.fRequested)
        rc = tftpAddOptionToOACK(pData, m, "tsize", pTftpSession->OptionTSize.u64Value);

    rc = tftpSend(pData, pTftpSession, m, pcTftpIpHeaderRecv);
    return RT_SUCCESS(rc) ? 0 : -1;
}