Beispiel #1
0
/**@brief Sends UDP data in Request format described in description above.
 *
 * @details Sends UDP data in Request of size 8 in format described in description above.
 */
static void udp_data_send(void)
{
    struct pbuf * p_send_buf;
    uint8_t     * p_udp_data;

    APPL_LOG ("[APPL]: >> UDP Data Tx\r\n");
    m_sequence_number++;

    p_send_buf = pbuf_alloc (PBUF_TRANSPORT, UDP_DATA_SIZE, PBUF_RAM);
    ASSERT(p_send_buf != NULL);

    p_send_buf->len = UDP_DATA_SIZE;
    p_udp_data = p_send_buf->payload;

    p_udp_data[0] = (uint8_t )((m_sequence_number >> 24) & 0x000000FF);
    p_udp_data[1] = (uint8_t )((m_sequence_number >> 16) & 0x000000FF);
    p_udp_data[2] = (uint8_t )((m_sequence_number >> 8) & 0x000000FF);
    p_udp_data[3] = (uint8_t )(m_sequence_number & 0x000000FF);

    p_udp_data[4] = 'P';
    p_udp_data[5] = 'i';
    p_udp_data[6] = 'n';
    p_udp_data[7] = 'g';

    //Send UDP Data packet.
    err_t err = udp_sendto_ip6(mp_udp_port, p_send_buf, &m_remote_addr, UDP_SERVER_PORT);
    if (err != ERR_OK)
    {
        APPL_LOG ("[APPL]: Failed to send UDP packet, reason %d\r\n", err);
        m_sequence_number--;
    }

    APPL_DUMP(p_send_buf->payload,p_send_buf->len);
    APPL_LOG ("[APPL]: << UDP Data Tx, %d len %d\r\n", err, p_send_buf->len);

    UNUSED_VARIABLE(pbuf_free(p_send_buf));

}
static void
dhcp6ds_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p,
             ip6_addr_t *addr, u16_t port)
{
    u8_t msg_header[4];
    unsigned int msg_type, msg_tid;
    int copied;
    size_t roff;
    struct pbuf *q;
    err_t error;

    LWIP_UNUSED_ARG(arg);
    LWIP_ASSERT1(p != NULL);

    copied = pbuf_copy_partial(p, msg_header, sizeof(msg_header), 0);
    if (copied != sizeof(msg_header)) {
        DPRINTF(("%s: message header truncated\n", __func__));
        pbuf_free(p);
        return;
    }
    pbuf_header(p, -(s16_t)sizeof(msg_header));

    msg_type = msg_header[0];
    msg_tid = (msg_header[1] << 16) | (msg_header[2] << 8) | msg_header[3];
    DPRINTF(("%s: type %u, tid 0x%6x\n", __func__, msg_type, msg_tid));
    if (msg_type != DHCP6_INFORMATION_REQUEST) { /* TODO:? RELAY_FORW */
        pbuf_free(p);
        return;
    }

    roff = 0;

    msg_header[0] = DHCP6_REPLY;
    memcpy(dhcp6ds_reply_buf + roff, msg_header, sizeof(msg_header));
    roff += sizeof(msg_header);


    /* loop over options */
    while (p->tot_len > 0) {
        u16_t opt, optlen;

        /* fetch option code */
        copied = pbuf_copy_partial(p, &opt, sizeof(opt), 0);
        if (copied != sizeof(opt)) {
            DPRINTF(("%s: option header truncated\n", __func__));
            pbuf_free(p);
            return;
        }
        pbuf_header(p, -(s16_t)sizeof(opt));
        opt = ntohs(opt);

        /* fetch option length */
        copied = pbuf_copy_partial(p, &optlen, sizeof(optlen), 0);
        if (copied != sizeof(optlen)) {
            DPRINTF(("%s: option %u length truncated\n", __func__, opt));
            pbuf_free(p);
            return;
        }
        pbuf_header(p, -(s16_t)sizeof(optlen));
        optlen = ntohs(optlen);

        /* enough data? */
        if (optlen > p->tot_len) {
            DPRINTF(("%s: option %u truncated: expect %u, got %u\n",
                     __func__, opt, optlen, p->tot_len));
            pbuf_free(p);
            return;
        }

        DPRINTF2(("%s: option %u length %u\n", __func__, opt, optlen));

        if (opt == DHCP6_OPTION_CLIENTID) {
            u16_t s;

            /* "A DUID can be no more than 128 octets long (not
               including the type code)." */
            if (optlen > 130) {
                DPRINTF(("%s: client DUID too long: %u\n", __func__, optlen));
                pbuf_free(p);
                return;
            }

            s = PP_HTONS(DHCP6_OPTION_CLIENTID);
            memcpy(dhcp6ds_reply_buf + roff, &s, sizeof(s));
            roff += sizeof(s);

            s = ntohs(optlen);
            memcpy(dhcp6ds_reply_buf + roff, &s, sizeof(s));
            roff += sizeof(s);

            pbuf_copy_partial(p, dhcp6ds_reply_buf + roff, optlen, 0);
            roff += optlen;
        }
        else if (opt == DHCP6_OPTION_ORO) {
            u16_t *opts;
            int i, nopts;

            if (optlen % 2 != 0) {
                DPRINTF2(("%s: Option Request of odd length\n", __func__));
                goto bad_oro;
            }
            nopts = optlen / 2;

            opts = (u16_t *)malloc(optlen);
            if (opts == NULL) {
                DPRINTF2(("%s: failed to allocate space for Option Request\n",
                          __func__));
                goto bad_oro;
            }

            pbuf_copy_partial(p, opts, optlen, 0);
            for (i = 0; i < nopts; ++i) {
                opt = ntohs(opts[i]);
                DPRINTF2(("> request option %u\n", opt));
            };
            free(opts);

          bad_oro: /* empty */;
        }

        pbuf_header(p, -optlen); /* go to next option */
    }
    pbuf_free(p);               /* done */


    memcpy(dhcp6ds_reply_buf + roff, dhcp6ds_serverid, sizeof(dhcp6ds_serverid));
    roff += sizeof(dhcp6ds_serverid);

    memcpy(dhcp6ds_reply_buf + roff, dhcp6ds_dns, sizeof(dhcp6ds_dns));
    roff += sizeof(dhcp6ds_dns);

    q = pbuf_alloc(PBUF_RAW, roff, PBUF_RAM);
    if (q == NULL) {
        DPRINTF(("%s: pbuf_alloc(%d) failed\n", __func__, (int)roff));
        return;
    }

    error = pbuf_take(q, dhcp6ds_reply_buf, roff);
    if (error != ERR_OK) {
        DPRINTF(("%s: pbuf_take(%d) failed: %s\n",
                 __func__, (int)roff, proxy_lwip_strerr(error)));
        pbuf_free(q);
        return;
    }

    error = udp_sendto_ip6(pcb, q, addr, port);
    if (error != ERR_OK) {
        DPRINTF(("%s: udp_sendto failed: %s\n",
                 __func__, proxy_lwip_strerr(error)));
    }

    pbuf_free(q);
}